From 21e86fbfa1416679b8031f578fbabf33dd101896 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Mar 2013 21:15:55 +0000 Subject: [PATCH 0001/1215] Add a library for manipulating stack traces. Review URL: https://codereview.chromium.org//13102003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20582 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/README.md | 57 +++++++++ pkgs/stack_trace/lib/src/frame.dart | 88 ++++++++++++++ pkgs/stack_trace/lib/src/trace.dart | 127 ++++++++++++++++++++ pkgs/stack_trace/lib/stack_trace.dart | 11 ++ pkgs/stack_trace/pubspec.yaml | 11 ++ pkgs/stack_trace/test/frame_test.dart | 159 ++++++++++++++++++++++++++ pkgs/stack_trace/test/trace_test.dart | 134 ++++++++++++++++++++++ 7 files changed, 587 insertions(+) create mode 100644 pkgs/stack_trace/README.md create mode 100644 pkgs/stack_trace/lib/src/frame.dart create mode 100644 pkgs/stack_trace/lib/src/trace.dart create mode 100644 pkgs/stack_trace/lib/stack_trace.dart create mode 100644 pkgs/stack_trace/pubspec.yaml create mode 100644 pkgs/stack_trace/test/frame_test.dart create mode 100644 pkgs/stack_trace/test/trace_test.dart diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md new file mode 100644 index 000000000..6a8112a55 --- /dev/null +++ b/pkgs/stack_trace/README.md @@ -0,0 +1,57 @@ +This library provides the ability to parse, inspect, and manipulate stack traces +produced by the underlying Dart implementation. It also provides functions to +produce string representations of stack traces in a more readable format than +the native [StackTrace] implementation. + +`Trace`s can be parsed from native [StackTrace]s using `Trace.from`, or captured +using `Trace.current`. Native [StackTrace]s can also be directly converted to +human-readable strings using `Trace.format`. + +[StackTrace]: http://api.dartlang.org/docs/releases/latest/dart_core/StackTrace.html + +Here's an example native stack trace from debugging this library: + + #0 Object.noSuchMethod (dart:core-patch:1884:25) + #1 Trace.terse. (file:///usr/local/google-old/home/goog/dart/dart/pkg/stack_trace/lib/src/trace.dart:47:21) + #2 IterableMixinWorkaround.reduce (dart:collection:29:29) + #3 List.reduce (dart:core-patch:1247:42) + #4 Trace.terse (file:///usr/local/google-old/home/goog/dart/dart/pkg/stack_trace/lib/src/trace.dart:40:35) + #5 format (file:///usr/local/google-old/home/goog/dart/dart/pkg/stack_trace/lib/stack_trace.dart:24:28) + #6 main. (file:///usr/local/google-old/home/goog/dart/dart/test.dart:21:29) + #7 _CatchErrorFuture._sendError (dart:async:525:24) + #8 _FutureImpl._setErrorWithoutAsyncTrace (dart:async:393:26) + #9 _FutureImpl._setError (dart:async:378:31) + #10 _ThenFuture._sendValue (dart:async:490:16) + #11 _FutureImpl._handleValue. (dart:async:349:28) + #12 Timer.run. (dart:async:2402:21) + #13 Timer.Timer. (dart:async-patch:15:15) + +and its human-readable representation: + + dart:core-patch Object.noSuchMethod + pkg/stack_trace/lib/src/trace.dart 47:21 Trace.terse. + dart:collection IterableMixinWorkaround.reduce + dart:core-patch List.reduce + pkg/stack_trace/lib/src/trace.dart 40:35 Trace.terse + pkg/stack_trace/lib/stack_trace.dart 24:28 format + test.dart 21:29 main. + dart:async _CatchErrorFuture._sendError + dart:async _FutureImpl._setErrorWithoutAsyncTrace + dart:async _FutureImpl._setError + dart:async _ThenFuture._sendValue + dart:async _FutureImpl._handleValue. + dart:async Timer.run. + dart:async-patch Timer.Timer. + +You can further clean up the stack trace using `Trace.terse`. This folds +together multiple stack frames from the Dart core libraries, so that only the +core library method that was directly called from user code is visible. For +example: + + dart:core Object.noSuchMethod + pkg/stack_trace/lib/src/trace.dart 47:21 Trace.terse. + dart:core List.reduce + pkg/stack_trace/lib/src/trace.dart 40:35 Trace.terse + pkg/stack_trace/lib/stack_trace.dart 24:28 format + test.dart 21:29 main. + dart:async Timer.Timer. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart new file mode 100644 index 000000000..fdf4fe0d5 --- /dev/null +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -0,0 +1,88 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library frame; + +import 'dart:uri'; + +import 'package:pathos/path.dart' as path; + +import 'trace.dart'; + +final _nativeFrameRegExp = new RegExp( + r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); + +/// A single stack frame. Each frame points to a precise location in Dart code. +class Frame { + /// The URI of the file in which the code is located. + /// + /// This URI will usually have the scheme `dart`, `file`, `http`, or `https`. + final Uri uri; + + /// The line number on which the code location is located. + final int line; + + /// The column number of the code location. + final int column; + + /// The name of the member in which the code location occurs. + /// + /// Anonymous closures are represented as `` in this member string. + final String member; + + /// Whether this stack frame comes from the Dart core libraries. + bool get isCore => uri.scheme == 'dart'; + + /// Returns a human-friendly description of the library that this stack frame + /// comes from. + /// + /// This will usually be the string form of [uri], but a relative path will be + /// used if possible. + String get library { + // TODO(nweiz): handle relative URIs here as well once pathos supports that. + if (uri.scheme != 'file') return uri.toString(); + return path.relative(uri.path); + } + + /// A human-friendly description of the code location. + /// + /// For Dart core libraries, this will omit the line and column information, + /// since those are useless for baked-in libraries. + String get location { + if (isCore) return library; + return '$library $line:$column'; + } + + /// Returns a single frame of the current stack. + /// + /// By default, this will return the frame above the current method. If + /// [level] is `0`, it will return the current method's frame; if [level] is + /// higher than `1`, it will return higher frames. + factory Frame.caller([int level=1]) { + if (level < 0) { + throw new ArgumentError("Argument [level] must be greater than or equal " + "to 0."); + } + + return new Trace.current(level + 1).frames.first; + } + + /// Parses a string representation of a stack frame. + /// + /// [frame] should be formatted in the same way as a native stack trace frame. + factory Frame.parse(String frame) { + var match = _nativeFrameRegExp.firstMatch(frame); + if (match == null) { + throw new FormatException("Couldn't parse stack trace line '$frame'."); + } + + var uri = new Uri.fromString(match[2]); + var member = match[1].replaceAll("", ""); + return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); + } + + Frame(this.uri, this.line, this.column, this.member); + + String toString() => '$location in $member'; +} diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart new file mode 100644 index 000000000..1ab7695b9 --- /dev/null +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -0,0 +1,127 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library trace; + +import 'dart:uri'; + +import 'frame.dart'; + +final _patchRegExp = new RegExp(r"-patch$"); + +/// A stack trace, comprised of a list of stack frames. +class Trace implements StackTrace { + // TODO(nweiz): make this read-only once issue 8321 is fixed. + /// The stack frames that comprise this stack trace. + final List frames; + + /// Returns a human-readable representation of [stackTrace]. If [terse] is + /// set, this folds together multiple stack frames from the Dart core + /// libraries, so that only the core library method directly called from user + /// code is visible (see [Trace.terse]). + static String format(StackTrace stackTrace, {bool terse: true}) { + var trace = new Trace.from(stackTrace); + if (terse) trace = trace.terse; + return trace.toString(); + } + + /// Returns the current stack trace. + /// + /// By default, the first frame of this trace will be the line where + /// [Trace.current] is called. If [level] is passed, the trace will start that + /// many frames up instead. + factory Trace.current([int level=0]) { + if (level < 0) { + throw new ArgumentError("Argument [level] must be greater than or equal " + "to 0."); + } + + try { + throw ''; + } catch (_, nativeTrace) { + var trace = new Trace.from(nativeTrace); + return new Trace(trace.frames.skip(level + 1)); + } + } + + /// Returns a new stack trace containing the same data as [trace]. + /// + /// If [trace] is a native [StackTrace], its data will be parsed out; if it's + /// a [Trace], it will be returned as-is. + factory Trace.from(StackTrace trace) { + if (trace is Trace) return trace; + return new Trace.parse(trace.fullStackTrace); + } + + /// Parses a string representation of a stack trace. + /// + /// [trace] should be formatted in the same way as native stack traces. + Trace.parse(String trace) + : this(trace.trim().split("\n").map((line) => new Frame.parse(line))); + + /// Returns a new [Trace] comprised of [frames]. + Trace(Iterable frames) + : frames = frames.toList(); + + // TODO(nweiz): Keep track of which [Frame]s are part of the partial stack + // trace and only print them. + /// Returns a string representation of this stack trace. + /// + /// This is identical to [toString]. It will not be formatted in the manner of + /// native stack traces. + String get stackTrace => toString(); + + /// Returns a string representation of this stack trace. + /// + /// This is identical to [toString]. It will not be formatted in the manner of + /// native stack traces. + String get fullStackTrace => toString(); + + /// Returns a terser version of [this]. This is accomplished by folding + /// together multiple stack frames from the core library. If multiple such + /// frames appear in a row, only the last (the one directly called by user + /// code) is kept. Core library patches are also renamed to remove their + /// `-patch` suffix. + Trace get terse { + var newFrames = []; + for (var frame in frames.reversed) { + if (!frame.isCore) { + newFrames.add(frame); + } else if (newFrames.isEmpty || !newFrames.last.isCore) { + var library = frame.library.replaceAll(_patchRegExp, ''); + newFrames.add(new Frame( + Uri.parse(library), frame.line, frame.column, frame.member)); + } + } + + return new Trace(newFrames.reversed); + } + + /// Returns a human-readable string representation of [this]. + String toString() { + if (frames.length == '') return ''; + + // Figure out the longest path so we know how much to pad. + var longest = frames.map((frame) => frame.location.length).max(); + + // Print out the stack trace nicely formatted. + return frames.map((frame) { + return '${_padRight(frame.location, longest)} ${frame.member}\n'; + }).join(); + } +} + +/// Returns [string] with enough spaces added to the end to make it [length] +/// characters long. +String _padRight(String string, int length) { + if (string.length >= length) return string; + + var result = new StringBuffer(); + result.write(string); + for (var i = 0; i < length - string.length; i++) { + result.write(' '); + } + + return result.toString(); +} diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart new file mode 100644 index 000000000..455dd57ae --- /dev/null +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace; + +import 'src/trace.dart'; +import 'src/frame.dart'; + +export 'src/trace.dart'; +export 'src/frame.dart'; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml new file mode 100644 index 000000000..3a679a826 --- /dev/null +++ b/pkgs/stack_trace/pubspec.yaml @@ -0,0 +1,11 @@ +name: stack_trace +author: "Dart Team " +homepage: http://www.dartlang.org +description: > + A package for manipulating stack traces and printing them readably. + +dependencies: + pathos: any + +dev_dependencies: + unittest: any diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart new file mode 100644 index 000000000..66dee6ace --- /dev/null +++ b/pkgs/stack_trace/test/frame_test.dart @@ -0,0 +1,159 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library frame_test; + +import 'dart:uri'; + +import 'package:pathos/path.dart' as path; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +String getStackFrame() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString().split("\n").first; + } +} + +Frame getCaller([int level]) { + if (level == null) return new Frame.caller(); + return new Frame.caller(level); +} + +Frame nestedGetCaller(int level) => getCaller(level); + +void main() { + test('parses a stack frame correctly', () { + var frame = new Frame.parse("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart:42:21)"); + expect(frame.uri, + equals(new Uri.fromString("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, equals(42)); + expect(frame.column, equals(21)); + expect(frame.member, equals('Foo._bar')); + }); + + test('parses a real stack frame correctly', () { + var frame = new Frame.parse(getStackFrame()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(frame.uri.path), equals('frame_test.dart')); + expect(frame.line, equals(15)); + expect(frame.column, equals(5)); + expect(frame.member, equals('getStackFrame')); + }); + + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parse('#0 $member (foo:0:0)').member; + + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); + + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parse(''), throwsFormatException); + expect(() => new Frame.parse('#1'), throwsFormatException); + expect(() => new Frame.parse('#1 Foo'), throwsFormatException); + expect(() => new Frame.parse('#1 Foo (dart:async)'), + throwsFormatException); + expect(() => new Frame.parse('#1 Foo (dart:async:10)'), + throwsFormatException); + expect(() => new Frame.parse('#1 (dart:async:10:15)'), + throwsFormatException); + expect(() => new Frame.parse('Foo (dart:async:10:15)'), + throwsFormatException); + }); + + test('only considers dart URIs to be core', () { + bool isCore(String library) => + new Frame.parse('#0 Foo ($library:0:0)').isCore; + + expect(isCore('dart:core'), isTrue); + expect(isCore('dart:async'), isTrue); + expect(isCore('bart:core'), isFalse); + expect(isCore('sdart:core'), isFalse); + expect(isCore('darty:core'), isFalse); + }); + + group('.caller()', () { + test('with no argument returns the parent frame', () { + expect(getCaller().member, equals('main..')); + }); + + test('at level 0 returns the current frame', () { + expect(getCaller(0).member, equals('getCaller')); + }); + + test('at level 1 returns the current frame', () { + expect(getCaller(1).member, equals('main..')); + }); + + test('at level 2 returns the grandparent frame', () { + expect(nestedGetCaller(2).member, equals('main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Frame.caller(-1), throwsArgumentError); + }); + }); + + group('.library', () { + test('returns the URI string for non-file URIs', () { + expect(new Frame.parse('#0 Foo (dart:async:0:0)').library, + equals('dart:async')); + expect(new Frame.parse('#0 Foo ' + '(http://dartlang.org/stuff/thing.dart:0:0)').library, + equals('http://dartlang.org/stuff/thing.dart')); + }); + + test('returns the relative path for file URIs', () { + var absolute = path.absolute(path.join('foo', 'bar.dart')); + expect(new Frame.parse('#0 Foo (file://$absolute:0:0)').library, + equals(path.join('foo', 'bar.dart'))); + }); + }); + + group('.location', () { + test('returns the library and line/column numbers for non-core ' + 'libraries', () { + expect(new Frame.parse('#0 Foo ' + '(http://dartlang.org/thing.dart:5:10)').location, + equals('http://dartlang.org/thing.dart 5:10')); + var absolute = path.absolute(path.join('foo', 'bar.dart')); + expect(new Frame.parse('#0 Foo (file://$absolute:1:2)').location, + equals('${path.join('foo', 'bar.dart')} 1:2')); + }); + + test('just returns the library for core libraries', () { + expect(new Frame.parse('#0 Foo (dart:core:5:10)').location, + equals('dart:core')); + expect(new Frame.parse('#0 Foo (dart:async-patch:1:2)').location, + equals('dart:async-patch')); + }); + }); + + group('.toString()', () { + test('returns the library and line/column numbers for non-core ' + 'libraries', () { + expect(new Frame.parse('#0 Foo (http://dartlang.org/thing.dart:5:10)') + .toString(), + equals('http://dartlang.org/thing.dart 5:10 in Foo')); + }); + + test('just returns the library for core libraries', () { + expect(new Frame.parse('#0 Foo (dart:core:5:10)').toString(), + equals('dart:core in Foo')); + }); + + test('converts "" to ""', () { + expect(new Frame.parse('#0 Foo. (dart:core:5:10)') + .toString(), + equals('dart:core in Foo.')); + }); + }); +} diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart new file mode 100644 index 000000000..711a41276 --- /dev/null +++ b/pkgs/stack_trace/test/trace_test.dart @@ -0,0 +1,134 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library trace_test; + +import 'dart:uri'; + +import 'package:pathos/path.dart' as path; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +String getStackTraceString() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString(); + } +} + +StackTrace getStackTraceObject() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace; + } +} + +Trace getCurrentTrace([int level]) => new Trace.current(level); + +Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); + +void main() { + test('parses a stack trace correctly', () { + var trace = new Trace.parse(''' +#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) +#1 zip..zap (dart:async:0:2) +#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) +'''); + + expect(trace.frames[0].uri, + equals(new Uri.fromString("file:///home/nweiz/code/stuff.dart"))); + expect(trace.frames[1].uri, equals(new Uri.fromString("dart:async"))); + expect(trace.frames[2].uri, + equals(new Uri.fromString("http://pub.dartlang.org/thing.dart"))); + }); + + test('parses a real stack trace correctly', () { + var trace = new Trace.parse(getStackTraceString()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(trace.frames.first.uri.path), + equals('trace_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceString')); + }); + + test('converts from a native stack trace correctly', () { + var trace = new Trace.from(getStackTraceObject()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(trace.frames.first.uri.path), + equals('trace_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceObject')); + }); + + group('.current()', () { + test('with no argument returns a trace starting at the current frame', () { + var trace = new Trace.current(); + expect(trace.frames.first.member, equals('main..')); + }); + + test('at level 0 returns a trace starting at the current frame', () { + var trace = new Trace.current(0); + expect(trace.frames.first.member, equals('main..')); + }); + + test('at level 1 returns a trace starting at the parent frame', () { + var trace = getCurrentTrace(1); + expect(trace.frames.first.member, equals('main..')); + }); + + test('at level 2 returns a trace starting at the grandparent frame', () { + var trace = nestedGetCurrentTrace(2); + expect(trace.frames.first.member, equals('main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Trace.current(-1), throwsArgumentError); + }); + }); + + test('.toString() nicely formats the stack trace', () { + var absolute = path.absolute(path.join('foo', 'bar.dart')); + var trace = new Trace.parse(''' +#0 Foo._bar (file://$absolute:42:21) +#1 zip..zap (dart:async:0:2) +#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) +'''); + + expect(trace.toString(), equals(''' +${path.join('foo', 'bar.dart')} 42:21 Foo._bar +dart:async zip..zap +http://pub.dartlang.org/thing.dart 1:100 zip..zap +''')); + }); + + test('.stackTrace forwards to .toString()', () { + var trace = new Trace.current(); + expect(trace.stackTrace, equals(trace.toString())); + }); + + test('.fullStackTrace forwards to .toString()', () { + var trace = new Trace.current(); + expect(trace.fullStackTrace, equals(trace.toString())); + }); + + test('.terse folds core frames together bottom-up', () { + var trace = new Trace.parse(''' +#0 notCore (foo.dart:42:21) +#1 top (dart:async:0:2) +#2 bottom (dart:core:1:100) +#3 alsoNotCore (bar.dart:10:20) +#4 top (dart:io:5:10) +#5 bottom (dart:async-patch:9:11) +'''); + + expect(trace.terse.toString(), equals(''' +foo.dart 42:21 notCore +dart:core bottom +bar.dart 10:20 alsoNotCore +dart:async bottom +''')); + }); +} From 9da325eab1b281f6b65ae03d2215e6d6a402aeb0 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Mar 2013 21:37:20 +0000 Subject: [PATCH 0002/1215] Fix Frame.location on Windows in pkg/stack_trace. Review URL: https://codereview.chromium.org//12545080 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20586 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/frame_test.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 66dee6ace..5c5a32ed9 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -4,6 +4,7 @@ library frame_test; +import 'dart:io'; import 'dart:uri'; import 'package:pathos/path.dart' as path; @@ -41,7 +42,7 @@ void main() { // TODO(nweiz): use URL-style paths when such a thing exists. var builder = new path.Builder(style: path.Style.posix); expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(15)); + expect(frame.line, equals(16)); expect(frame.column, equals(5)); expect(frame.member, equals('getStackFrame')); }); @@ -112,8 +113,8 @@ void main() { }); test('returns the relative path for file URIs', () { - var absolute = path.absolute(path.join('foo', 'bar.dart')); - expect(new Frame.parse('#0 Foo (file://$absolute:0:0)').library, + var uri = _pathToFileUri(path.join('foo', 'bar.dart')); + expect(new Frame.parse('#0 Foo ($uri:0:0)').library, equals(path.join('foo', 'bar.dart'))); }); }); @@ -124,8 +125,8 @@ void main() { expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - var absolute = path.absolute(path.join('foo', 'bar.dart')); - expect(new Frame.parse('#0 Foo (file://$absolute:1:2)').location, + var uri = _pathToFileUri(path.join('foo', 'bar.dart')); + expect(new Frame.parse('#0 Foo ($uri:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); @@ -157,3 +158,9 @@ void main() { }); }); } + +String _pathToFileUri(String pathString) { + pathString = path.absolute(pathString); + if (Platform.operatingSystem != 'windows') return 'file://$pathString'; + return 'file:///${pathString.replaceAll("\\", "/")}'; +} From 3ad56b01cd3241a99db594f24267ad2686e22a31 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Mar 2013 21:57:31 +0000 Subject: [PATCH 0003/1215] Fix the stack_trace frame test on Windows as well. Review URL: https://codereview.chromium.org//12681036 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20588 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/trace_test.dart | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 711a41276..2cbe48d12 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -4,6 +4,7 @@ library trace_test; +import 'dart:io'; import 'dart:uri'; import 'package:pathos/path.dart' as path; @@ -90,9 +91,9 @@ void main() { }); test('.toString() nicely formats the stack trace', () { - var absolute = path.absolute(path.join('foo', 'bar.dart')); + var uri = _pathToFileUri(path.join('foo', 'bar.dart')); var trace = new Trace.parse(''' -#0 Foo._bar (file://$absolute:42:21) +#0 Foo._bar ($uri:42:21) #1 zip..zap (dart:async:0:2) #2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) '''); @@ -132,3 +133,9 @@ dart:async bottom ''')); }); } + +String _pathToFileUri(String pathString) { + pathString = path.absolute(pathString); + if (Platform.operatingSystem != 'windows') return 'file://$pathString'; + return 'file:///${pathString.replaceAll("\\", "/")}'; +} From 91e238e1660d80d00c703b00d9cc38f7f7ff317d Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 30 Mar 2013 00:36:38 +0000 Subject: [PATCH 0004/1215] Be more careful about converting between file URIs and paths. This happened to work on Windows because it interprets forward slashes as directory separators. Review URL: https://codereview.chromium.org//13191011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20708 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 3 ++- pkgs/stack_trace/test/frame_test.dart | 13 ++++--------- pkgs/stack_trace/test/trace_test.dart | 9 ++------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index fdf4fe0d5..5f0777c16 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -9,6 +9,7 @@ import 'dart:uri'; import 'package:pathos/path.dart' as path; import 'trace.dart'; +import 'utils.dart'; final _nativeFrameRegExp = new RegExp( r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); @@ -42,7 +43,7 @@ class Frame { String get library { // TODO(nweiz): handle relative URIs here as well once pathos supports that. if (uri.scheme != 'file') return uri.toString(); - return path.relative(uri.path); + return path.relative(fileUriToPath(uri)); } /// A human-friendly description of the code location. diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 5c5a32ed9..c65f39559 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'dart:uri'; import 'package:pathos/path.dart' as path; +import 'package:stack_trace/src/utils.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -42,7 +43,7 @@ void main() { // TODO(nweiz): use URL-style paths when such a thing exists. var builder = new path.Builder(style: path.Style.posix); expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(16)); + expect(frame.line, equals(17)); expect(frame.column, equals(5)); expect(frame.member, equals('getStackFrame')); }); @@ -113,7 +114,7 @@ void main() { }); test('returns the relative path for file URIs', () { - var uri = _pathToFileUri(path.join('foo', 'bar.dart')); + var uri = pathToFileUri(path.join('foo', 'bar.dart')); expect(new Frame.parse('#0 Foo ($uri:0:0)').library, equals(path.join('foo', 'bar.dart'))); }); @@ -125,7 +126,7 @@ void main() { expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - var uri = _pathToFileUri(path.join('foo', 'bar.dart')); + var uri = pathToFileUri(path.join('foo', 'bar.dart')); expect(new Frame.parse('#0 Foo ($uri:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); @@ -158,9 +159,3 @@ void main() { }); }); } - -String _pathToFileUri(String pathString) { - pathString = path.absolute(pathString); - if (Platform.operatingSystem != 'windows') return 'file://$pathString'; - return 'file:///${pathString.replaceAll("\\", "/")}'; -} diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 2cbe48d12..ed8fa6b03 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'dart:uri'; import 'package:pathos/path.dart' as path; +import 'package:stack_trace/src/utils.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -91,7 +92,7 @@ void main() { }); test('.toString() nicely formats the stack trace', () { - var uri = _pathToFileUri(path.join('foo', 'bar.dart')); + var uri = pathToFileUri(path.join('foo', 'bar.dart')); var trace = new Trace.parse(''' #0 Foo._bar ($uri:42:21) #1 zip..zap (dart:async:0:2) @@ -133,9 +134,3 @@ dart:async bottom ''')); }); } - -String _pathToFileUri(String pathString) { - pathString = path.absolute(pathString); - if (Platform.operatingSystem != 'windows') return 'file://$pathString'; - return 'file:///${pathString.replaceAll("\\", "/")}'; -} From b04479baccda08a4b15b48dc699483f3f845ba0c Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 30 Mar 2013 00:47:33 +0000 Subject: [PATCH 0005/1215] Check in pkg/stack_trace/lib/src/utils.dart. Review URL: https://codereview.chromium.org//13371002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20710 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/utils.dart | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 pkgs/stack_trace/lib/src/utils.dart diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart new file mode 100644 index 000000000..790dec88b --- /dev/null +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library utils; + +import 'dart:io'; +import 'dart:uri'; + +import 'package:pathos/path.dart' as path; + +/// Converts a `file:` [Uri] to a local path string. +String fileUriToPath(Uri uri) { + if (uri.scheme != 'file') { + throw new ArgumentError("Uri $uri must have scheme 'file:'."); + } + if (Platform.operatingSystem != 'windows') return uri.path; + return uri.path.replaceFirst("/", "").replaceAll("/", "\\"); +} + +/// Converts a local path string to a `file:` [Uri]. +Uri pathToFileUri(String pathString) { + pathString = path.absolute(pathString); + if (Platform.operatingSystem != 'windows') { + return Uri.parse('file://$pathString'); + } else { + return Uri.parse('file:///${pathString.replaceAll("\\", "/")}'); + } +} From 74570bfb1d39bbc80fe69f5ab99491b630fcc9f9 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 1 Apr 2013 20:46:15 +0000 Subject: [PATCH 0006/1215] Use the stack_trace library in scheduled_test. This also adds a couple features to stack_trace. Review URL: https://codereview.chromium.org//13157004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@20752 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 7 +++++++ pkgs/stack_trace/lib/src/trace.dart | 29 +++++++++++++++++++-------- pkgs/stack_trace/test/frame_test.dart | 16 +++++++++++++++ pkgs/stack_trace/test/trace_test.dart | 19 ++++++++++++++++++ 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 5f0777c16..f05b46928 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -46,6 +46,13 @@ class Frame { return path.relative(fileUriToPath(uri)); } + /// Returns the name of the package this stack frame comes from, or `null` if + /// this stack frame doesn't come from a `package:` URL. + String get package { + if (uri.scheme != 'package') return null; + return uri.path.split('/').first; + } + /// A human-friendly description of the code location. /// /// For Dart core libraries, this will omit the line and column information, diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 1ab7695b9..43a598c87 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -79,19 +79,32 @@ class Trace implements StackTrace { String get fullStackTrace => toString(); /// Returns a terser version of [this]. This is accomplished by folding - /// together multiple stack frames from the core library. If multiple such - /// frames appear in a row, only the last (the one directly called by user - /// code) is kept. Core library patches are also renamed to remove their - /// `-patch` suffix. + /// together multiple stack frames from the core library, as in [foldFrames]. + /// Core library patches are also renamed to remove their `-patch` suffix. Trace get terse { + return new Trace(foldFrames((frame) => frame.isCore).frames.map((frame) { + if (!frame.isCore) return frame; + var library = frame.library.replaceAll(_patchRegExp, ''); + return new Frame( + Uri.parse(library), frame.line, frame.column, frame.member); + })); + } + + /// Returns a new [Trace] based on [this] where multiple stack frames matching + /// [predicate] are folded together. This means that whenever there are + /// multiple frames in a row that match [predicate], only the last one is + /// kept. + /// + /// This is useful for limiting the amount of library code that appears in a + /// stack trace by only showing user code and code that's called by user code. + Trace foldFrames(bool predicate(frame)) { var newFrames = []; for (var frame in frames.reversed) { - if (!frame.isCore) { + if (!predicate(frame)) { newFrames.add(frame); - } else if (newFrames.isEmpty || !newFrames.last.isCore) { - var library = frame.library.replaceAll(_patchRegExp, ''); + } else if (newFrames.isEmpty || !predicate(newFrames.last)) { newFrames.add(new Frame( - Uri.parse(library), frame.line, frame.column, frame.member)); + frame.uri, frame.line, frame.column, frame.member)); } } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index c65f39559..02bec6834 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -139,6 +139,22 @@ void main() { }); }); + group('.package', () { + test('returns null for non-package URIs', () { + expect(new Frame.parse('#0 Foo (dart:async:0:0)').package, isNull); + expect(new Frame.parse('#0 Foo ' + '(http://dartlang.org/stuff/thing.dart:0:0)').package, + isNull); + }); + + test('returns the package name for package: URIs', () { + expect(new Frame.parse('#0 Foo (package:foo/foo.dart:0:0)').package, + equals('foo')); + expect(new Frame.parse('#0 Foo (package:foo/zap/bar.dart:0:0)').package, + equals('foo')); + }); + }); + group('.toString()', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index ed8fa6b03..cbbf90bd1 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -131,6 +131,25 @@ foo.dart 42:21 notCore dart:core bottom bar.dart 10:20 alsoNotCore dart:async bottom +''')); + }); + + test('.foldFrames folds frames together bottom-up', () { + var trace = new Trace.parse(''' +#0 notFoo (foo.dart:42:21) +#1 fooTop (bar.dart:0:2) +#2 fooBottom (foo.dart:1:100) +#3 alsoNotFoo (bar.dart:10:20) +#4 fooTop (dart:io:5:10) +#5 fooBottom (dart:async-patch:9:11) +'''); + + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); + expect(folded.toString(), equals(''' +foo.dart 42:21 notFoo +foo.dart 1:100 fooBottom +bar.dart 10:20 alsoNotFoo +dart:async-patch fooBottom ''')); }); } From 80e75ec4cdb4a875e79585ea36b4cfec3201553c Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 8 Apr 2013 19:39:30 +0000 Subject: [PATCH 0007/1215] Normalize packages' library names. This makes the library names play nicer with dartdoc. Review URL: https://codereview.chromium.org//13674024 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21106 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/stack_trace.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index 455dd57ae..5747b85b9 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -4,8 +4,5 @@ library stack_trace; -import 'src/trace.dart'; -import 'src/frame.dart'; - export 'src/trace.dart'; export 'src/frame.dart'; From 39955275a4769107c436db299b21aedef2a1462c Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Thu, 11 Apr 2013 08:32:31 +0000 Subject: [PATCH 0008/1215] Added new version of reduce. Removed min/max and uses of min/max. Review URL: https://codereview.chromium.org//14071002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21258 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 43a598c87..bed1d5d89 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -5,6 +5,7 @@ library trace; import 'dart:uri'; +import 'dart:math'; import 'frame.dart'; @@ -116,7 +117,7 @@ class Trace implements StackTrace { if (frames.length == '') return ''; // Figure out the longest path so we know how much to pad. - var longest = frames.map((frame) => frame.location.length).max(); + var longest = frames.map((frame) => frame.location.length).reduce(max); // Print out the stack trace nicely formatted. return frames.map((frame) { From 10ae21e43ca7e48dd95ee4d6707131dbd3dfb903 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Sat, 13 Apr 2013 13:17:13 +0000 Subject: [PATCH 0009/1215] Import math library with a prefix. Review URL: https://codereview.chromium.org//14111004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21406 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index bed1d5d89..33b2dd422 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -5,7 +5,7 @@ library trace; import 'dart:uri'; -import 'dart:math'; +import 'dart:math' as math; import 'frame.dart'; @@ -117,7 +117,7 @@ class Trace implements StackTrace { if (frames.length == '') return ''; // Figure out the longest path so we know how much to pad. - var longest = frames.map((frame) => frame.location.length).reduce(max); + var longest = frames.map((frame) => frame.location.length).reduce(math.max); // Print out the stack trace nicely formatted. return frames.map((frame) { From 87fa964ea4aa258322e4405b32874458bf3f6b17 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" Date: Mon, 15 Apr 2013 11:44:30 +0000 Subject: [PATCH 0010/1215] Remove methods on StackTrace class. The API is not ready for finalization, so we remove it for further development after M4. Makes dart2js's StackTrace object implement dart:core's StackTrace. Marks dart2js stack-trace tests as Fail instead of Skip. Review URL: https://codereview.chromium.org//14009004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21437 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 33b2dd422..fa0c313c6 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -52,7 +52,7 @@ class Trace implements StackTrace { /// a [Trace], it will be returned as-is. factory Trace.from(StackTrace trace) { if (trace is Trace) return trace; - return new Trace.parse(trace.fullStackTrace); + return new Trace.parse(trace.toString()); } /// Parses a string representation of a stack trace. From 2ea21e15067519c1b5ee0ce59ad7a9971ff2aef1 Mon Sep 17 00:00:00 2001 From: "sethladd@google.com" Date: Fri, 19 Apr 2013 20:51:10 +0000 Subject: [PATCH 0011/1215] add installation instructions to pkg packages BUG= Review URL: https://codereview.chromium.org//14188048 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21770 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/stack_trace.dart | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index 5747b85b9..f031f956b 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -2,6 +2,23 @@ // 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. +/** + * ## Installing ## + * + * Use [pub][] to install this package. Add the following to your `pubspec.yaml` + * file. + * + * dependencies: + * stack_trace: any + * + * Then run `pub install`. + * + * For more information, see the + * [stack_trace package on pub.dartlang.org][pkg]. + * + * [pub]: http://pub.dartlang.org + * [pkg]: http://pub.dartlang.org/packages/stack_trace + */ library stack_trace; export 'src/trace.dart'; From 4aa6dbf366235633ac36764af542500b30583284 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 22 Apr 2013 23:05:30 +0000 Subject: [PATCH 0012/1215] Use UnmodifiableListView to expose read-only lists. Review URL: https://codereview.chromium.org//14394003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21855 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index fa0c313c6..54f99db57 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -4,6 +4,7 @@ library trace; +import 'dart:collection'; import 'dart:uri'; import 'dart:math' as math; @@ -13,7 +14,6 @@ final _patchRegExp = new RegExp(r"-patch$"); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { - // TODO(nweiz): make this read-only once issue 8321 is fixed. /// The stack frames that comprise this stack trace. final List frames; @@ -63,7 +63,7 @@ class Trace implements StackTrace { /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) - : frames = frames.toList(); + : frames = new UnmodifiableListView(frames.toList()); // TODO(nweiz): Keep track of which [Frame]s are part of the partial stack // trace and only print them. From b35b3f85a664ebee4c69815164dbec1aaef61106 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 23 Apr 2013 23:55:46 +0000 Subject: [PATCH 0013/1215] Clean up various ways we find paths in pub. This makes it so that it's never necessary to pass in DART_SDK. Review URL: https://codereview.chromium.org//14449004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21914 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/utils.dart | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 790dec88b..ec764e598 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -15,7 +15,14 @@ String fileUriToPath(Uri uri) { throw new ArgumentError("Uri $uri must have scheme 'file:'."); } if (Platform.operatingSystem != 'windows') return uri.path; - return uri.path.replaceFirst("/", "").replaceAll("/", "\\"); + if (uri.path.startsWith("/")) { + // Drive-letter paths look like "file:///C:/path/to/file". The replaceFirst + // removes the extra initial slash. + return uri.path.replaceFirst("/", "").replaceAll("/", "\\"); + } else { + // Network paths look like "file://hostname/path/to/file". + return "\\\\${uri.path.replaceAll("/", "\\")}"; + } } /// Converts a local path string to a `file:` [Uri]. @@ -23,7 +30,11 @@ Uri pathToFileUri(String pathString) { pathString = path.absolute(pathString); if (Platform.operatingSystem != 'windows') { return Uri.parse('file://$pathString'); + } else if (path.rootPrefix(path).startsWith('\\\\')) { + // Network paths become "file://hostname/path/to/file". + return Uri.parse('file:${pathString.replaceAll("\\", "/")}'); } else { + // Drive-letter paths become "file:///C:/path/to/file". return Uri.parse('file:///${pathString.replaceAll("\\", "/")}'); } } From 3991fdfa57aca1530973d4faa2fece0d8293f386 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 24 Apr 2013 01:00:03 +0000 Subject: [PATCH 0014/1215] Fix a bug in pathToFileUri. TBR Review URL: https://codereview.chromium.org//14287003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@21916 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index ec764e598..50ccab3f1 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -30,7 +30,7 @@ Uri pathToFileUri(String pathString) { pathString = path.absolute(pathString); if (Platform.operatingSystem != 'windows') { return Uri.parse('file://$pathString'); - } else if (path.rootPrefix(path).startsWith('\\\\')) { + } else if (path.rootPrefix(pathString).startsWith('\\\\')) { // Network paths become "file://hostname/path/to/file". return Uri.parse('file:${pathString.replaceAll("\\", "/")}'); } else { From c1fd44901f9e67bca6f54ab81562c34f12ac3260 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 30 Apr 2013 21:34:08 +0000 Subject: [PATCH 0015/1215] Be lazier when capturing stack traces. It turns out that capturing stack traces is cheap; converting them to strings is what's so expensive. R=rnystrom@google.com Review URL: https://codereview.chromium.org//14647003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@22205 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/lazy_trace.dart | 34 ++++++++++++++++++++++++ pkgs/stack_trace/lib/src/trace.dart | 5 ++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 pkgs/stack_trace/lib/src/lazy_trace.dart diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart new file mode 100644 index 000000000..8c4482971 --- /dev/null +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library lazy_trace; + +import 'frame.dart'; +import 'trace.dart'; + +/// A thunk for lazily constructing a [Trace]. +typedef Trace TraceThunk(); + +/// A wrapper around a [TraceThunk]. This works around issue 9579 by avoiding +/// the conversion of native [StackTrace]s to strings until it's absolutely +/// necessary. +class LazyTrace implements Trace { + final TraceThunk _thunk; + Trace _inner; + + LazyTrace(this._thunk); + + Trace get _trace { + if (_inner == null) _inner = _thunk(); + return _inner; + } + + List get frames => _trace.frames; + String get stackTrace => _trace.stackTrace; + String get fullStackTrace => _trace.fullStackTrace; + Trace get terse => new LazyTrace(() => _trace.terse); + Trace foldFrames(bool predicate(frame)) => + new LazyTrace(() => _trace.foldFrames(predicate)); + String toString() => _trace.toString(); +} diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 54f99db57..ffea4986c 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -9,6 +9,7 @@ import 'dart:uri'; import 'dart:math' as math; import 'frame.dart'; +import 'lazy_trace.dart'; final _patchRegExp = new RegExp(r"-patch$"); @@ -42,7 +43,7 @@ class Trace implements StackTrace { throw ''; } catch (_, nativeTrace) { var trace = new Trace.from(nativeTrace); - return new Trace(trace.frames.skip(level + 1)); + return new LazyTrace(() => new Trace(trace.frames.skip(level + 1))); } } @@ -52,7 +53,7 @@ class Trace implements StackTrace { /// a [Trace], it will be returned as-is. factory Trace.from(StackTrace trace) { if (trace is Trace) return trace; - return new Trace.parse(trace.toString()); + return new LazyTrace(() => new Trace.parse(trace.toString())); } /// Parses a string representation of a stack trace. From e95049037d80c7e1d59217753151629f40a3d3f4 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 1 May 2013 09:27:50 +0000 Subject: [PATCH 0016/1215] Enable parsing of IPv6 form addresse (see rfc2373 and rfc2732). This also wraps the 'domain' component in toString with [...], if it contains any ':' characters. BUG= R=floitsch@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//14753005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@22228 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 2 +- pkgs/stack_trace/test/frame_test.dart | 3 +-- pkgs/stack_trace/test/trace_test.dart | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index f05b46928..cb7d65630 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -85,7 +85,7 @@ class Frame { throw new FormatException("Couldn't parse stack trace line '$frame'."); } - var uri = new Uri.fromString(match[2]); + var uri = Uri.parse(match[2]); var member = match[1].replaceAll("", ""); return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 02bec6834..826bad7bf 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -31,8 +31,7 @@ void main() { test('parses a stack frame correctly', () { var frame = new Frame.parse("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:42:21)"); - expect(frame.uri, - equals(new Uri.fromString("file:///home/nweiz/code/stuff.dart"))); + expect(frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); expect(frame.line, equals(42)); expect(frame.column, equals(21)); expect(frame.member, equals('Foo._bar')); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index cbbf90bd1..d3fa56ea6 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -41,10 +41,10 @@ void main() { '''); expect(trace.frames[0].uri, - equals(new Uri.fromString("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(new Uri.fromString("dart:async"))); + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(trace.frames[1].uri, equals(Uri.parse("dart:async"))); expect(trace.frames[2].uri, - equals(new Uri.fromString("http://pub.dartlang.org/thing.dart"))); + equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); }); test('parses a real stack trace correctly', () { From d5a4fedbba3e8ecb2701a35dbd7261a6f5a57c01 Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" Date: Tue, 28 May 2013 13:35:01 +0000 Subject: [PATCH 0017/1215] Merge the dart:uri library into dart:core and update the Uri class This merges the dart:uri library into dart:core removing the dart:uri library. Besides moving the library the Url class has been changed. * Removed existing Uri constructor as it was equivalent with Uri.parse * Remamed constructor Uri.fromComponents to Uri * Moved toplevel function encodeUriComponent to static method Uri.encodeComponent * Moved toplevel function decodeUriComponent to static method Uri.decodeComponent * Moved toplevel function encodeUri to static method Uri.encodeFull * Moved toplevel function decodeUri to static method Uri.decodeFull * Rename domain to host * Added static methods Uri.encodeQueryComponent and Uri.decodeQueryComponent * Added support for path generation and splitting * Added support for query generation and splitting * Added some level of normalization R=floitsch@google.com, lrn@google.com, nweiz@google.com, scheglov@google.com BUG= Review URL: https://codereview.chromium.org//16019002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@23266 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 1 - pkgs/stack_trace/lib/src/trace.dart | 1 - pkgs/stack_trace/lib/src/utils.dart | 1 - pkgs/stack_trace/test/frame_test.dart | 3 +-- pkgs/stack_trace/test/trace_test.dart | 1 - 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index cb7d65630..335bfbab3 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -4,7 +4,6 @@ library frame; -import 'dart:uri'; import 'package:pathos/path.dart' as path; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index ffea4986c..4ed1563fe 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -5,7 +5,6 @@ library trace; import 'dart:collection'; -import 'dart:uri'; import 'dart:math' as math; import 'frame.dart'; diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 50ccab3f1..30a43bcc3 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -5,7 +5,6 @@ library utils; import 'dart:io'; -import 'dart:uri'; import 'package:pathos/path.dart' as path; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 826bad7bf..512f6d0a2 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -5,7 +5,6 @@ library frame_test; import 'dart:io'; -import 'dart:uri'; import 'package:pathos/path.dart' as path; import 'package:stack_trace/src/utils.dart'; @@ -42,7 +41,7 @@ void main() { // TODO(nweiz): use URL-style paths when such a thing exists. var builder = new path.Builder(style: path.Style.posix); expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(17)); + expect(frame.line, equals(16)); expect(frame.column, equals(5)); expect(frame.member, equals('getStackFrame')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index d3fa56ea6..afd570097 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -5,7 +5,6 @@ library trace_test; import 'dart:io'; -import 'dart:uri'; import 'package:pathos/path.dart' as path; import 'package:stack_trace/src/utils.dart'; From cae4ed5e2c4d9216d648565d6bbd3115ec240003 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 4 Jun 2013 23:36:31 +0000 Subject: [PATCH 0018/1215] Make the StackTrace library better handle core library frames. Core library stack frames now have libraries and meaningful line numbers, so in general we should preserve those. However, terse stack traces don't care about the internal workings of the core libraries, so they now explicitly remove the library and line number information. R=rnystrom@google.com Review URL: https://codereview.chromium.org//16097012 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@23621 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 11 +++++--- pkgs/stack_trace/lib/src/trace.dart | 15 +++++------ pkgs/stack_trace/test/frame_test.dart | 36 +++++++++++---------------- pkgs/stack_trace/test/trace_test.dart | 26 +++++++++---------- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 335bfbab3..8f1931bc2 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -21,9 +21,15 @@ class Frame { final Uri uri; /// The line number on which the code location is located. + /// + /// This can be null, indicating that the line number is unknown or + /// unimportant. final int line; /// The column number of the code location. + /// + /// This can be null, indicating that the column number is unknown or + /// unimportant. final int column; /// The name of the member in which the code location occurs. @@ -53,11 +59,8 @@ class Frame { } /// A human-friendly description of the code location. - /// - /// For Dart core libraries, this will omit the line and column information, - /// since those are useless for baked-in libraries. String get location { - if (isCore) return library; + if (line == null || column == null) return library; return '$library $line:$column'; } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 4ed1563fe..db0e70ba2 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -10,7 +10,7 @@ import 'dart:math' as math; import 'frame.dart'; import 'lazy_trace.dart'; -final _patchRegExp = new RegExp(r"-patch$"); +final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { @@ -79,15 +79,16 @@ class Trace implements StackTrace { /// native stack traces. String get fullStackTrace => toString(); - /// Returns a terser version of [this]. This is accomplished by folding - /// together multiple stack frames from the core library, as in [foldFrames]. - /// Core library patches are also renamed to remove their `-patch` suffix. + /// Returns a terser version of [this]. + /// + /// This is accomplished by folding together multiple stack frames from the + /// core library, as in [foldFrames]. Remaining core library frames have their + /// libraries, "-patch" suffixes, and line numbers removed. Trace get terse { return new Trace(foldFrames((frame) => frame.isCore).frames.map((frame) { if (!frame.isCore) return frame; - var library = frame.library.replaceAll(_patchRegExp, ''); - return new Frame( - Uri.parse(library), frame.line, frame.column, frame.member); + var library = frame.library.replaceAll(_terseRegExp, ''); + return new Frame(Uri.parse(library), null, null, frame.member); })); } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 512f6d0a2..d1f53f604 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -59,13 +59,13 @@ void main() { expect(() => new Frame.parse(''), throwsFormatException); expect(() => new Frame.parse('#1'), throwsFormatException); expect(() => new Frame.parse('#1 Foo'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async)'), + expect(() => new Frame.parse('#1 Foo (dart:async/future.dart)'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async:10)'), + expect(() => new Frame.parse('#1 Foo (dart:async/future.dart:10)'), throwsFormatException); - expect(() => new Frame.parse('#1 (dart:async:10:15)'), + expect(() => new Frame.parse('#1 (dart:async/future.dart:10:15)'), throwsFormatException); - expect(() => new Frame.parse('Foo (dart:async:10:15)'), + expect(() => new Frame.parse('Foo (dart:async/future.dart:10:15)'), throwsFormatException); }); @@ -75,9 +75,12 @@ void main() { expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); + expect(isCore('dart:core/uri.dart'), isTrue); + expect(isCore('dart:async/future.dart'), isTrue); expect(isCore('bart:core'), isFalse); expect(isCore('sdart:core'), isFalse); expect(isCore('darty:core'), isFalse); + expect(isCore('bart:core/uri.dart'), isFalse); }); group('.caller()', () { @@ -104,8 +107,8 @@ void main() { group('.library', () { test('returns the URI string for non-file URIs', () { - expect(new Frame.parse('#0 Foo (dart:async:0:0)').library, - equals('dart:async')); + expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').library, + equals('dart:async/future.dart')); expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').library, equals('http://dartlang.org/stuff/thing.dart')); @@ -128,18 +131,12 @@ void main() { expect(new Frame.parse('#0 Foo ($uri:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); - - test('just returns the library for core libraries', () { - expect(new Frame.parse('#0 Foo (dart:core:5:10)').location, - equals('dart:core')); - expect(new Frame.parse('#0 Foo (dart:async-patch:1:2)').location, - equals('dart:async-patch')); - }); }); group('.package', () { test('returns null for non-package URIs', () { - expect(new Frame.parse('#0 Foo (dart:async:0:0)').package, isNull); + expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').package, + isNull); expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').package, isNull); @@ -161,15 +158,10 @@ void main() { equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); - test('just returns the library for core libraries', () { - expect(new Frame.parse('#0 Foo (dart:core:5:10)').toString(), - equals('dart:core in Foo')); - }); - test('converts "" to ""', () { - expect(new Frame.parse('#0 Foo. (dart:core:5:10)') - .toString(), - equals('dart:core in Foo.')); + expect(new Frame.parse('#0 Foo. ' + '(dart:core/uri.dart:5:10)').toString(), + equals('dart:core/uri.dart 5:10 in Foo.')); }); }); } diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index afd570097..902ae80d0 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -35,13 +35,13 @@ void main() { test('parses a stack trace correctly', () { var trace = new Trace.parse(''' #0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) -#1 zip..zap (dart:async:0:2) +#1 zip..zap (dart:async/future.dart:0:2) #2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) '''); expect(trace.frames[0].uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(Uri.parse("dart:async"))); + expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); }); @@ -94,13 +94,13 @@ void main() { var uri = pathToFileUri(path.join('foo', 'bar.dart')); var trace = new Trace.parse(''' #0 Foo._bar ($uri:42:21) -#1 zip..zap (dart:async:0:2) +#1 zip..zap (dart:async/future.dart:0:2) #2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) '''); expect(trace.toString(), equals(''' ${path.join('foo', 'bar.dart')} 42:21 Foo._bar -dart:async zip..zap +dart:async/future.dart 0:2 zip..zap http://pub.dartlang.org/thing.dart 1:100 zip..zap ''')); }); @@ -118,11 +118,11 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap test('.terse folds core frames together bottom-up', () { var trace = new Trace.parse(''' #0 notCore (foo.dart:42:21) -#1 top (dart:async:0:2) -#2 bottom (dart:core:1:100) +#1 top (dart:async/future.dart:0:2) +#2 bottom (dart:core/uri.dart:1:100) #3 alsoNotCore (bar.dart:10:20) #4 top (dart:io:5:10) -#5 bottom (dart:async-patch:9:11) +#5 bottom (dart:async-patch/future.dart:9:11) '''); expect(trace.terse.toString(), equals(''' @@ -139,16 +139,16 @@ dart:async bottom #1 fooTop (bar.dart:0:2) #2 fooBottom (foo.dart:1:100) #3 alsoNotFoo (bar.dart:10:20) -#4 fooTop (dart:io:5:10) -#5 fooBottom (dart:async-patch:9:11) +#4 fooTop (dart:io/socket.dart:5:10) +#5 fooBottom (dart:async-patch/future.dart:9:11) '''); var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); expect(folded.toString(), equals(''' -foo.dart 42:21 notFoo -foo.dart 1:100 fooBottom -bar.dart 10:20 alsoNotFoo -dart:async-patch fooBottom +foo.dart 42:21 notFoo +foo.dart 1:100 fooBottom +bar.dart 10:20 alsoNotFoo +dart:async-patch/future.dart 9:11 fooBottom ''')); }); } From 75bc0effa2eba7c64c22955203aab8c54e6b1126 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 19 Jun 2013 19:06:19 +0000 Subject: [PATCH 0019/1215] Add toUri and fromUri functions to pathos. This also replaces the ubiqutous pathToFileUri/fileUriToPath functions. R=rnystrom@google.com Review URL: https://codereview.chromium.org//16848002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24196 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 4 +-- pkgs/stack_trace/lib/src/utils.dart | 39 --------------------------- pkgs/stack_trace/test/frame_test.dart | 7 +++-- pkgs/stack_trace/test/trace_test.dart | 3 +-- 4 files changed, 5 insertions(+), 48 deletions(-) delete mode 100644 pkgs/stack_trace/lib/src/utils.dart diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8f1931bc2..8d3f042a2 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -8,7 +8,6 @@ library frame; import 'package:pathos/path.dart' as path; import 'trace.dart'; -import 'utils.dart'; final _nativeFrameRegExp = new RegExp( r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); @@ -46,9 +45,8 @@ class Frame { /// This will usually be the string form of [uri], but a relative path will be /// used if possible. String get library { - // TODO(nweiz): handle relative URIs here as well once pathos supports that. if (uri.scheme != 'file') return uri.toString(); - return path.relative(fileUriToPath(uri)); + return path.relative(path.fromUri(uri)); } /// Returns the name of the package this stack frame comes from, or `null` if diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart deleted file mode 100644 index 30a43bcc3..000000000 --- a/pkgs/stack_trace/lib/src/utils.dart +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// 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. - -library utils; - -import 'dart:io'; - -import 'package:pathos/path.dart' as path; - -/// Converts a `file:` [Uri] to a local path string. -String fileUriToPath(Uri uri) { - if (uri.scheme != 'file') { - throw new ArgumentError("Uri $uri must have scheme 'file:'."); - } - if (Platform.operatingSystem != 'windows') return uri.path; - if (uri.path.startsWith("/")) { - // Drive-letter paths look like "file:///C:/path/to/file". The replaceFirst - // removes the extra initial slash. - return uri.path.replaceFirst("/", "").replaceAll("/", "\\"); - } else { - // Network paths look like "file://hostname/path/to/file". - return "\\\\${uri.path.replaceAll("/", "\\")}"; - } -} - -/// Converts a local path string to a `file:` [Uri]. -Uri pathToFileUri(String pathString) { - pathString = path.absolute(pathString); - if (Platform.operatingSystem != 'windows') { - return Uri.parse('file://$pathString'); - } else if (path.rootPrefix(pathString).startsWith('\\\\')) { - // Network paths become "file://hostname/path/to/file". - return Uri.parse('file:${pathString.replaceAll("\\", "/")}'); - } else { - // Drive-letter paths become "file:///C:/path/to/file". - return Uri.parse('file:///${pathString.replaceAll("\\", "/")}'); - } -} diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index d1f53f604..de0715a9d 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -7,7 +7,6 @@ library frame_test; import 'dart:io'; import 'package:pathos/path.dart' as path; -import 'package:stack_trace/src/utils.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -41,7 +40,7 @@ void main() { // TODO(nweiz): use URL-style paths when such a thing exists. var builder = new path.Builder(style: path.Style.posix); expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(16)); + expect(frame.line, equals(15)); expect(frame.column, equals(5)); expect(frame.member, equals('getStackFrame')); }); @@ -115,7 +114,7 @@ void main() { }); test('returns the relative path for file URIs', () { - var uri = pathToFileUri(path.join('foo', 'bar.dart')); + var uri = path.toUri(path.join('foo', 'bar.dart')); expect(new Frame.parse('#0 Foo ($uri:0:0)').library, equals(path.join('foo', 'bar.dart'))); }); @@ -127,7 +126,7 @@ void main() { expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - var uri = pathToFileUri(path.join('foo', 'bar.dart')); + var uri = path.toUri(path.join('foo', 'bar.dart')); expect(new Frame.parse('#0 Foo ($uri:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 902ae80d0..9ecebb5ae 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -7,7 +7,6 @@ library trace_test; import 'dart:io'; import 'package:pathos/path.dart' as path; -import 'package:stack_trace/src/utils.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -91,7 +90,7 @@ void main() { }); test('.toString() nicely formats the stack trace', () { - var uri = pathToFileUri(path.join('foo', 'bar.dart')); + var uri = path.toUri(path.join('foo', 'bar.dart')); var trace = new Trace.parse(''' #0 Foo._bar ($uri:42:21) #1 zip..zap (dart:async/future.dart:0:2) From 6bac11080d17fe17e9d2e4cf3279b4b9f7a626e3 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 19 Jun 2013 22:15:07 +0000 Subject: [PATCH 0020/1215] Fix the pkg/stack_trace tests. On Windows they're now (correctly) using relative URIs as opposed to relative paths. Review URL: https://codereview.chromium.org//17157009 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24205 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 2 +- pkgs/stack_trace/test/frame_test.dart | 10 ++++------ pkgs/stack_trace/test/trace_test.dart | 5 ++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8d3f042a2..d750b9178 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -42,7 +42,7 @@ class Frame { /// Returns a human-friendly description of the library that this stack frame /// comes from. /// - /// This will usually be the string form of [uri], but a relative path will be + /// This will usually be the string form of [uri], but a relative URI will be /// used if possible. String get library { if (uri.scheme != 'file') return uri.toString(); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index de0715a9d..a140670f8 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -114,9 +114,8 @@ void main() { }); test('returns the relative path for file URIs', () { - var uri = path.toUri(path.join('foo', 'bar.dart')); - expect(new Frame.parse('#0 Foo ($uri:0:0)').library, - equals(path.join('foo', 'bar.dart'))); + expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library, + equals('foo/bar.dart')); }); }); @@ -126,9 +125,8 @@ void main() { expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - var uri = path.toUri(path.join('foo', 'bar.dart')); - expect(new Frame.parse('#0 Foo ($uri:1:2)').location, - equals('${path.join('foo', 'bar.dart')} 1:2')); + expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location, + equals('foo/bar.dart 1:2')); }); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 9ecebb5ae..fcf4fe5ce 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -90,15 +90,14 @@ void main() { }); test('.toString() nicely formats the stack trace', () { - var uri = path.toUri(path.join('foo', 'bar.dart')); var trace = new Trace.parse(''' -#0 Foo._bar ($uri:42:21) +#0 Foo._bar (foo/bar.dart:42:21) #1 zip..zap (dart:async/future.dart:0:2) #2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) '''); expect(trace.toString(), equals(''' -${path.join('foo', 'bar.dart')} 42:21 Foo._bar +foo/bar.dart 42:21 Foo._bar dart:async/future.dart 0:2 zip..zap http://pub.dartlang.org/thing.dart 1:100 zip..zap ''')); From 7556a82d8876b6719002b433e64239bee32ed56f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 27 Jun 2013 00:28:28 +0000 Subject: [PATCH 0021/1215] Add support for V8 and Firefox stack traces in pkg/stack_trace. R=rnystrom@google.com Review URL: https://codereview.chromium.org//17765004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24502 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 68 ++++++- pkgs/stack_trace/lib/src/trace.dart | 33 +++- pkgs/stack_trace/test/dartium_test.dart | 109 +++++++++++ pkgs/stack_trace/test/frame_test.dart | 247 ++++++++++++++++-------- pkgs/stack_trace/test/trace_test.dart | 116 ++++++----- pkgs/stack_trace/test/vm_test.dart | 109 +++++++++++ 6 files changed, 536 insertions(+), 146 deletions(-) create mode 100644 pkgs/stack_trace/test/dartium_test.dart create mode 100644 pkgs/stack_trace/test/vm_test.dart diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index d750b9178..3b8036f66 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -9,9 +9,23 @@ import 'package:pathos/path.dart' as path; import 'trace.dart'; -final _nativeFrameRegExp = new RegExp( +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) +final _vmFrame = new RegExp( r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); +// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) +// at http://pub.dartlang.org/stuff.dart.js:560:28 +final _v8Frame = new RegExp( + r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); + +// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 +final _firefoxFrame = new RegExp( + r'^([^@(/]*)(?:\(.*\))?(/[^<]*<)?(?:\(.*\))?@(.*):(\d+)$'); + +final _initialDot = new RegExp(r"^\."); + /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { /// The URI of the file in which the code is located. @@ -76,13 +90,11 @@ class Frame { return new Trace.current(level + 1).frames.first; } - /// Parses a string representation of a stack frame. - /// - /// [frame] should be formatted in the same way as a native stack trace frame. - factory Frame.parse(String frame) { - var match = _nativeFrameRegExp.firstMatch(frame); + /// Parses a string representation of a Dart VM stack frame. + factory Frame.parseVM(String frame) { + var match = _vmFrame.firstMatch(frame); if (match == null) { - throw new FormatException("Couldn't parse stack trace line '$frame'."); + throw new FormatException("Couldn't parse VM stack trace line '$frame'."); } var uri = Uri.parse(match[2]); @@ -90,6 +102,48 @@ class Frame { return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); } + /// Parses a string representation of a Chrome/V8 stack frame. + factory Frame.parseV8(String frame) { + var match = _v8Frame.firstMatch(frame); + if (match == null) { + throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); + } + + // V8 stack frames can be in two forms. + if (match[2] != null) { + // The first form looks like " at FUNCTION (URI:LINE:COL)" + var uri = Uri.parse(match[2]); + var member = match[1].replaceAll("", ""); + return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); + } else { + // The second form looks like " at URI:LINE:COL", and is used for + // anonymous functions. + var uri = Uri.parse(match[5]); + return new Frame(uri, int.parse(match[6]), int.parse(match[7]), ""); + } + } + + /// Parses a string representation of a Firefox stack frame. + factory Frame.parseFirefox(String frame) { + var match = _firefoxFrame.firstMatch(frame); + if (match == null) { + throw new FormatException( + "Couldn't parse Firefox stack trace line '$frame'."); + } + + var uri = Uri.parse(match[3]); + var member = match[1]; + if (member == "") { + member = ""; + } else if (match[2] != null) { + member = "$member."; + } + // Some Firefox members have initial dots. We remove them for consistency + // with other platforms. + member = member.replaceFirst(_initialDot, ''); + return new Frame(uri, int.parse(match[4]), null, member); + } + Frame(this.uri, this.line, this.column, this.member); String toString() => '$location in $member'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index db0e70ba2..986d1645f 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -12,6 +12,13 @@ import 'lazy_trace.dart'; final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); +/// A RegExp to match Firefox's stack traces. +/// +/// Firefox's trace frames start with the name of the function in which the +/// error occurred, possibly including its parameters inside `()`. For example, +/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. +final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@"); + /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { /// The stack frames that comprise this stack trace. @@ -57,9 +64,29 @@ class Trace implements StackTrace { /// Parses a string representation of a stack trace. /// - /// [trace] should be formatted in the same way as native stack traces. - Trace.parse(String trace) - : this(trace.trim().split("\n").map((line) => new Frame.parse(line))); + /// [trace] should be formatted in the same way as a Dart VM or browser stack + /// trace. + factory Trace.parse(String trace) { + if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); + + // Default to parsing the stack trace as a VM trace. This is also hit on IE + // and Safari, where the stack trace is just an empty string (issue 11257). + return new Trace.parseVM(trace); + } + + /// Parses a string representation of a Dart VM stack trace. + Trace.parseVM(String trace) + : this(trace.trim().split("\n").map((line) => new Frame.parseVM(line))); + + /// Parses a string representation of a Chrome/V8 stack trace. + Trace.parseV8(String trace) + : this(trace.split("\n").skip(1).map((line) => new Frame.parseV8(line))); + + /// Parses a string representation of a Firefox stack trace. + Trace.parseFirefox(String trace) + : this(trace.trim().split("\n") + .map((line) => new Frame.parseFirefox(line))); /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) diff --git a/pkgs/stack_trace/test/dartium_test.dart b/pkgs/stack_trace/test/dartium_test.dart new file mode 100644 index 000000000..3756c5911 --- /dev/null +++ b/pkgs/stack_trace/test/dartium_test.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +/// This file tests stack_trace's ability to parse live stack traces. It's a +/// dual of vm_test.dart, since method names can differ somewhat from platform +/// to platform. No similar file exists for dart2js since the specific method +/// names there are implementation details. + +import 'package:pathos/path.dart' as path; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +String getStackTraceString() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString(); + } +} + +StackTrace getStackTraceObject() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace; + } +} + +Frame getCaller([int level]) { + if (level == null) return new Frame.caller(); + return new Frame.caller(level); +} + +Frame nestedGetCaller(int level) => getCaller(level); + +Trace getCurrentTrace([int level]) => new Trace.current(level); + +Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); + +void main() { + group('Trace', () { + test('.parse parses a real stack trace correctly', () { + var string = getStackTraceString(); + var trace = new Trace.parse(string); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('dartium_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceString')); + }); + + test('converts from a native stack trace correctly', () { + var trace = new Trace.from(getStackTraceObject()); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('dartium_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceObject')); + }); + + group('.current()', () { + test('with no argument returns a trace starting at the current frame', + () { + var trace = new Trace.current(); + expect(trace.frames.first.member, equals('main.main...')); + }); + + test('at level 0 returns a trace starting at the current frame', () { + var trace = new Trace.current(0); + expect(trace.frames.first.member, equals('main.main...')); + }); + + test('at level 1 returns a trace starting at the parent frame', () { + var trace = getCurrentTrace(1); + expect(trace.frames.first.member, equals('main.main...')); + }); + + test('at level 2 returns a trace starting at the grandparent frame', () { + var trace = nestedGetCurrentTrace(2); + expect(trace.frames.first.member, equals('main.main...')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Trace.current(-1), throwsArgumentError); + }); + }); + }); + + group('Frame.caller()', () { + test('with no argument returns the parent frame', () { + expect(getCaller().member, equals('main.main..')); + }); + + test('at level 0 returns the current frame', () { + expect(getCaller(0).member, equals('getCaller')); + }); + + test('at level 1 returns the current frame', () { + expect(getCaller(1).member, equals('main.main..')); + }); + + test('at level 2 returns the grandparent frame', () { + expect(nestedGetCaller(2).member, equals('main.main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Frame.caller(-1), throwsArgumentError); + }); + }); +} diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index a140670f8..07bc8dc4f 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -4,73 +4,176 @@ library frame_test; -import 'dart:io'; - import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; -String getStackFrame() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString().split("\n").first; - } -} +void main() { + group('.parseVM', () { + test('parses a stack frame correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart:42:21)"); + expect(frame.uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, equals(42)); + expect(frame.column, equals(21)); + expect(frame.member, equals('Foo._bar')); + }); -Frame getCaller([int level]) { - if (level == null) return new Frame.caller(); - return new Frame.caller(level); -} + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parseVM('#0 $member (foo:0:0)').member; -Frame nestedGetCaller(int level) => getCaller(level); + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); -void main() { - test('parses a stack frame correctly', () { - var frame = new Frame.parse("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart:42:21)"); - expect(frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(frame.line, equals(42)); - expect(frame.column, equals(21)); - expect(frame.member, equals('Foo._bar')); + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseVM(''), throwsFormatException); + expect(() => new Frame.parseVM('#1'), throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'), + throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart:10)'), + throwsFormatException); + expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), + throwsFormatException); + }); }); - test('parses a real stack frame correctly', () { - var frame = new Frame.parse(getStackFrame()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(15)); - expect(frame.column, equals(5)); - expect(frame.member, equals('getStackFrame')); - }); + group('.parseV8', () { + test('parses a stack frame correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + "(http://pub.dartlang.org/stuff.dart.js:560:28)"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses an anonymous stack frame correctly', () { + var frame = new Frame.parseV8( + " at http://pub.dartlang.org/stuff.dart.js:560:28"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('')); + }); - test('converts "" to ""', () { - String parsedMember(String member) => - new Frame.parse('#0 $member (foo:0:0)').member; + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parseV8(' at $member (foo:0:0)').member; + + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); - expect(parsedMember('Foo.'), equals('Foo.')); - expect(parsedMember('..bar'), - equals('..bar')); + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseV8(''), throwsFormatException); + expect(() => new Frame.parseV8(' at'), throwsFormatException); + expect(() => new Frame.parseV8(' at Foo'), throwsFormatException); + expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart:10)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseV8('Foo (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at dart:async/future.dart'), + throwsFormatException); + expect(() => new Frame.parseV8(' at dart:async/future.dart:10'), + throwsFormatException); + expect(() => new Frame.parseV8('dart:async/future.dart:10:15'), + throwsFormatException); + }); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parse(''), throwsFormatException); - expect(() => new Frame.parse('#1'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async/future.dart)'), - throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async/future.dart:10)'), - throwsFormatException); - expect(() => new Frame.parse('#1 (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parse('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); + group('.parseFirefox', () { + test('parses a simple stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a simple anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + "@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("")); + }); + + test('parses a nested anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".foo/<@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('parses a named nested anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('parses a stack frame with parameters correctly', () { + var frame = new Frame.parseFirefox( + '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo")); + }); + + test('parses a nested anonymous stack frame with parameters correctly', () { + var frame = new Frame.parseFirefox( + '.foo(12, "@)()/<")/.fn<@' + 'http://pub.dartlang.org/stuff.dart.js:560'); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseFirefox(''), throwsFormatException); + expect(() => new Frame.parseFirefox('.foo'), throwsFormatException); + expect(() => new Frame.parseFirefox('.foo@dart:async/future.dart'), + throwsFormatException); + expect(() => new Frame.parseFirefox('.foo/@dart:async/future.dart:10'), + throwsFormatException); + expect(() => new Frame.parseFirefox('.foo(@dart:async/future.dart:10'), + throwsFormatException); + expect(() => new Frame.parseFirefox('@dart:async/future.dart'), + throwsFormatException); + }); }); test('only considers dart URIs to be core', () { bool isCore(String library) => - new Frame.parse('#0 Foo ($library:0:0)').isCore; + new Frame.parseVM('#0 Foo ($library:0:0)').isCore; expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); @@ -82,39 +185,17 @@ void main() { expect(isCore('bart:core/uri.dart'), isFalse); }); - group('.caller()', () { - test('with no argument returns the parent frame', () { - expect(getCaller().member, equals('main..')); - }); - - test('at level 0 returns the current frame', () { - expect(getCaller(0).member, equals('getCaller')); - }); - - test('at level 1 returns the current frame', () { - expect(getCaller(1).member, equals('main..')); - }); - - test('at level 2 returns the grandparent frame', () { - expect(nestedGetCaller(2).member, equals('main..')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Frame.caller(-1), throwsArgumentError); - }); - }); - group('.library', () { test('returns the URI string for non-file URIs', () { - expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').library, + expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, equals('dart:async/future.dart')); - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').library, equals('http://dartlang.org/stuff/thing.dart')); }); test('returns the relative path for file URIs', () { - expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library, + expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, equals('foo/bar.dart')); }); }); @@ -122,27 +203,27 @@ void main() { group('.location', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location, + expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, equals('foo/bar.dart 1:2')); }); }); group('.package', () { test('returns null for non-package URIs', () { - expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, isNull); - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').package, isNull); }); test('returns the package name for package: URIs', () { - expect(new Frame.parse('#0 Foo (package:foo/foo.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package, equals('foo')); - expect(new Frame.parse('#0 Foo (package:foo/zap/bar.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package, equals('foo')); }); }); @@ -150,13 +231,13 @@ void main() { group('.toString()', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parse('#0 Foo (http://dartlang.org/thing.dart:5:10)') + expect(new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') .toString(), equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { - expect(new Frame.parse('#0 Foo. ' + expect(new Frame.parseVM('#0 Foo. ' '(dart:core/uri.dart:5:10)').toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index fcf4fe5ce..4a8b37bee 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -4,8 +4,6 @@ library trace_test; -import 'dart:io'; - import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -31,61 +29,73 @@ Trace getCurrentTrace([int level]) => new Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { - test('parses a stack trace correctly', () { - var trace = new Trace.parse(''' -#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) -#1 zip..zap (dart:async/future.dart:0:2) -#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) -'''); - - expect(trace.frames[0].uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); - }); - - test('parses a real stack trace correctly', () { - var trace = new Trace.parse(getStackTraceString()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(trace.frames.first.uri.path), - equals('trace_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceString')); - }); - - test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(trace.frames.first.uri.path), - equals('trace_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceObject')); - }); - - group('.current()', () { - test('with no argument returns a trace starting at the current frame', () { - var trace = new Trace.current(); - expect(trace.frames.first.member, equals('main..')); - }); - - test('at level 0 returns a trace starting at the current frame', () { - var trace = new Trace.current(0); - expect(trace.frames.first.member, equals('main..')); - }); - - test('at level 1 returns a trace starting at the parent frame', () { - var trace = getCurrentTrace(1); - expect(trace.frames.first.member, equals('main..')); + group('.parse', () { + test('.parse parses a VM stack trace correctly', () { + var trace = new Trace.parse( + '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' + '#1 zip..zap (dart:async/future.dart:0:2)\n' + '#2 zip..zap (http://pub.dartlang.org/thing.' + 'dart:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); }); - test('at level 2 returns a trace starting at the grandparent frame', () { - var trace = nestedGetCurrentTrace(2); - expect(trace.frames.first.member, equals('main..')); + test('parses a V8 stack trace correctly', () { + var trace = new Trace.parse( + 'Error\n' + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); - test('throws an ArgumentError for negative levels', () { - expect(() => new Trace.current(-1), throwsArgumentError); + test('parses a Firefox stack trace correctly', () { + var trace = new Trace.parse( + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); }); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart new file mode 100644 index 000000000..38b2b80fd --- /dev/null +++ b/pkgs/stack_trace/test/vm_test.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +/// This file tests stack_trace's ability to parse live stack traces. It's a +/// dual of dartium_test.dart, since method names can differ somewhat from +/// platform to platform. No similar file exists for dart2js since the specific +/// method names there are implementation details. + +import 'package:pathos/path.dart' as path; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +String getStackTraceString() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString(); + } +} + +StackTrace getStackTraceObject() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace; + } +} + +Frame getCaller([int level]) { + if (level == null) return new Frame.caller(); + return new Frame.caller(level); +} + +Frame nestedGetCaller(int level) => getCaller(level); + +Trace getCurrentTrace([int level]) => new Trace.current(level); + +Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); + +void main() { + group('Trace', () { + test('.parse parses a real stack trace correctly', () { + var string = getStackTraceString(); + var trace = new Trace.parse(string); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('vm_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceString')); + }); + + test('converts from a native stack trace correctly', () { + var trace = new Trace.from(getStackTraceObject()); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('vm_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceObject')); + }); + + group('.current()', () { + test('with no argument returns a trace starting at the current frame', + () { + var trace = new Trace.current(); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 0 returns a trace starting at the current frame', () { + var trace = new Trace.current(0); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 1 returns a trace starting at the parent frame', () { + var trace = getCurrentTrace(1); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 2 returns a trace starting at the grandparent frame', () { + var trace = nestedGetCurrentTrace(2); + expect(trace.frames.first.member, equals('main...')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Trace.current(-1), throwsArgumentError); + }); + }); + }); + + group('Frame.caller()', () { + test('with no argument returns the parent frame', () { + expect(getCaller().member, equals('main..')); + }); + + test('at level 0 returns the current frame', () { + expect(getCaller(0).member, equals('getCaller')); + }); + + test('at level 1 returns the current frame', () { + expect(getCaller(1).member, equals('main..')); + }); + + test('at level 2 returns the grandparent frame', () { + expect(nestedGetCaller(2).member, equals('main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Frame.caller(-1), throwsArgumentError); + }); + }); +} From a18f096aafefa49d3fb2f3bbb91993c84544d921 Mon Sep 17 00:00:00 2001 From: "amouravski@google.com" Date: Thu, 27 Jun 2013 02:16:12 +0000 Subject: [PATCH 0022/1215] Revert "Add support for V8 and Firefox stack traces in pkg/stack_trace." This reverts commit r24502. Review URL: https://codereview.chromium.org//17998002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24506 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 68 +------ pkgs/stack_trace/lib/src/trace.dart | 33 +--- pkgs/stack_trace/test/dartium_test.dart | 109 ----------- pkgs/stack_trace/test/frame_test.dart | 247 ++++++++---------------- pkgs/stack_trace/test/trace_test.dart | 116 +++++------ pkgs/stack_trace/test/vm_test.dart | 109 ----------- 6 files changed, 146 insertions(+), 536 deletions(-) delete mode 100644 pkgs/stack_trace/test/dartium_test.dart delete mode 100644 pkgs/stack_trace/test/vm_test.dart diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 3b8036f66..d750b9178 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -9,23 +9,9 @@ import 'package:pathos/path.dart' as path; import 'trace.dart'; -// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) -final _vmFrame = new RegExp( +final _nativeFrameRegExp = new RegExp( r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); -// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) -// at http://pub.dartlang.org/stuff.dart.js:560:28 -final _v8Frame = new RegExp( - r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); - -// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 -// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 -// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 -final _firefoxFrame = new RegExp( - r'^([^@(/]*)(?:\(.*\))?(/[^<]*<)?(?:\(.*\))?@(.*):(\d+)$'); - -final _initialDot = new RegExp(r"^\."); - /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { /// The URI of the file in which the code is located. @@ -90,11 +76,13 @@ class Frame { return new Trace.current(level + 1).frames.first; } - /// Parses a string representation of a Dart VM stack frame. - factory Frame.parseVM(String frame) { - var match = _vmFrame.firstMatch(frame); + /// Parses a string representation of a stack frame. + /// + /// [frame] should be formatted in the same way as a native stack trace frame. + factory Frame.parse(String frame) { + var match = _nativeFrameRegExp.firstMatch(frame); if (match == null) { - throw new FormatException("Couldn't parse VM stack trace line '$frame'."); + throw new FormatException("Couldn't parse stack trace line '$frame'."); } var uri = Uri.parse(match[2]); @@ -102,48 +90,6 @@ class Frame { return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); } - /// Parses a string representation of a Chrome/V8 stack frame. - factory Frame.parseV8(String frame) { - var match = _v8Frame.firstMatch(frame); - if (match == null) { - throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); - } - - // V8 stack frames can be in two forms. - if (match[2] != null) { - // The first form looks like " at FUNCTION (URI:LINE:COL)" - var uri = Uri.parse(match[2]); - var member = match[1].replaceAll("", ""); - return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); - } else { - // The second form looks like " at URI:LINE:COL", and is used for - // anonymous functions. - var uri = Uri.parse(match[5]); - return new Frame(uri, int.parse(match[6]), int.parse(match[7]), ""); - } - } - - /// Parses a string representation of a Firefox stack frame. - factory Frame.parseFirefox(String frame) { - var match = _firefoxFrame.firstMatch(frame); - if (match == null) { - throw new FormatException( - "Couldn't parse Firefox stack trace line '$frame'."); - } - - var uri = Uri.parse(match[3]); - var member = match[1]; - if (member == "") { - member = ""; - } else if (match[2] != null) { - member = "$member."; - } - // Some Firefox members have initial dots. We remove them for consistency - // with other platforms. - member = member.replaceFirst(_initialDot, ''); - return new Frame(uri, int.parse(match[4]), null, member); - } - Frame(this.uri, this.line, this.column, this.member); String toString() => '$location in $member'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 986d1645f..db0e70ba2 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -12,13 +12,6 @@ import 'lazy_trace.dart'; final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); -/// A RegExp to match Firefox's stack traces. -/// -/// Firefox's trace frames start with the name of the function in which the -/// error occurred, possibly including its parameters inside `()`. For example, -/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. -final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@"); - /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { /// The stack frames that comprise this stack trace. @@ -64,29 +57,9 @@ class Trace implements StackTrace { /// Parses a string representation of a stack trace. /// - /// [trace] should be formatted in the same way as a Dart VM or browser stack - /// trace. - factory Trace.parse(String trace) { - if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); - if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); - - // Default to parsing the stack trace as a VM trace. This is also hit on IE - // and Safari, where the stack trace is just an empty string (issue 11257). - return new Trace.parseVM(trace); - } - - /// Parses a string representation of a Dart VM stack trace. - Trace.parseVM(String trace) - : this(trace.trim().split("\n").map((line) => new Frame.parseVM(line))); - - /// Parses a string representation of a Chrome/V8 stack trace. - Trace.parseV8(String trace) - : this(trace.split("\n").skip(1).map((line) => new Frame.parseV8(line))); - - /// Parses a string representation of a Firefox stack trace. - Trace.parseFirefox(String trace) - : this(trace.trim().split("\n") - .map((line) => new Frame.parseFirefox(line))); + /// [trace] should be formatted in the same way as native stack traces. + Trace.parse(String trace) + : this(trace.trim().split("\n").map((line) => new Frame.parse(line))); /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) diff --git a/pkgs/stack_trace/test/dartium_test.dart b/pkgs/stack_trace/test/dartium_test.dart deleted file mode 100644 index 3756c5911..000000000 --- a/pkgs/stack_trace/test/dartium_test.dart +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// 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. - -/// This file tests stack_trace's ability to parse live stack traces. It's a -/// dual of vm_test.dart, since method names can differ somewhat from platform -/// to platform. No similar file exists for dart2js since the specific method -/// names there are implementation details. - -import 'package:pathos/path.dart' as path; -import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; - -String getStackTraceString() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString(); - } -} - -StackTrace getStackTraceObject() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace; - } -} - -Frame getCaller([int level]) { - if (level == null) return new Frame.caller(); - return new Frame.caller(level); -} - -Frame nestedGetCaller(int level) => getCaller(level); - -Trace getCurrentTrace([int level]) => new Trace.current(level); - -Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); - -void main() { - group('Trace', () { - test('.parse parses a real stack trace correctly', () { - var string = getStackTraceString(); - var trace = new Trace.parse(string); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), - equals('dartium_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceString')); - }); - - test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), - equals('dartium_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceObject')); - }); - - group('.current()', () { - test('with no argument returns a trace starting at the current frame', - () { - var trace = new Trace.current(); - expect(trace.frames.first.member, equals('main.main...')); - }); - - test('at level 0 returns a trace starting at the current frame', () { - var trace = new Trace.current(0); - expect(trace.frames.first.member, equals('main.main...')); - }); - - test('at level 1 returns a trace starting at the parent frame', () { - var trace = getCurrentTrace(1); - expect(trace.frames.first.member, equals('main.main...')); - }); - - test('at level 2 returns a trace starting at the grandparent frame', () { - var trace = nestedGetCurrentTrace(2); - expect(trace.frames.first.member, equals('main.main...')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Trace.current(-1), throwsArgumentError); - }); - }); - }); - - group('Frame.caller()', () { - test('with no argument returns the parent frame', () { - expect(getCaller().member, equals('main.main..')); - }); - - test('at level 0 returns the current frame', () { - expect(getCaller(0).member, equals('getCaller')); - }); - - test('at level 1 returns the current frame', () { - expect(getCaller(1).member, equals('main.main..')); - }); - - test('at level 2 returns the grandparent frame', () { - expect(nestedGetCaller(2).member, equals('main.main..')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Frame.caller(-1), throwsArgumentError); - }); - }); -} diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 07bc8dc4f..a140670f8 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -4,176 +4,73 @@ library frame_test; +import 'dart:io'; + import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; -void main() { - group('.parseVM', () { - test('parses a stack frame correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart:42:21)"); - expect(frame.uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(frame.line, equals(42)); - expect(frame.column, equals(21)); - expect(frame.member, equals('Foo._bar')); - }); +String getStackFrame() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString().split("\n").first; + } +} - test('converts "" to ""', () { - String parsedMember(String member) => - new Frame.parseVM('#0 $member (foo:0:0)').member; +Frame getCaller([int level]) { + if (level == null) return new Frame.caller(); + return new Frame.caller(level); +} - expect(parsedMember('Foo.'), equals('Foo.')); - expect(parsedMember('..bar'), - equals('..bar')); - }); +Frame nestedGetCaller(int level) => getCaller(level); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseVM(''), throwsFormatException); - expect(() => new Frame.parseVM('#1'), throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'), - throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart:10)'), - throwsFormatException); - expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); - }); +void main() { + test('parses a stack frame correctly', () { + var frame = new Frame.parse("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart:42:21)"); + expect(frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, equals(42)); + expect(frame.column, equals(21)); + expect(frame.member, equals('Foo._bar')); }); - group('.parseV8', () { - test('parses a stack frame correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " - "(http://pub.dartlang.org/stuff.dart.js:560:28)"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, equals(28)); - expect(frame.member, equals('VW.call\$0')); - }); - - test('parses an anonymous stack frame correctly', () { - var frame = new Frame.parseV8( - " at http://pub.dartlang.org/stuff.dart.js:560:28"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, equals(28)); - expect(frame.member, equals('')); - }); - - test('converts "" to ""', () { - String parsedMember(String member) => - new Frame.parseV8(' at $member (foo:0:0)').member; - - expect(parsedMember('Foo.'), equals('Foo.')); - expect(parsedMember('..bar'), - equals('..bar')); - }); - - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseV8(''), throwsFormatException); - expect(() => new Frame.parseV8(' at'), throwsFormatException); - expect(() => new Frame.parseV8(' at Foo'), throwsFormatException); - expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart:10)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseV8('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at dart:async/future.dart'), - throwsFormatException); - expect(() => new Frame.parseV8(' at dart:async/future.dart:10'), - throwsFormatException); - expect(() => new Frame.parseV8('dart:async/future.dart:10:15'), - throwsFormatException); - }); + test('parses a real stack frame correctly', () { + var frame = new Frame.parse(getStackFrame()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(frame.uri.path), equals('frame_test.dart')); + expect(frame.line, equals(15)); + expect(frame.column, equals(5)); + expect(frame.member, equals('getStackFrame')); }); - group('.parseFirefox', () { - test('parses a simple stack frame correctly', () { - var frame = new Frame.parseFirefox( - ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals('VW.call\$0')); - }); - - test('parses a simple anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( - "@http://pub.dartlang.org/stuff.dart.js:560"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals("")); - }); - - test('parses a nested anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( - ".foo/<@http://pub.dartlang.org/stuff.dart.js:560"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals("foo.")); - }); - - test('parses a named nested anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( - ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560"); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals("foo.")); - }); - - test('parses a stack frame with parameters correctly', () { - var frame = new Frame.parseFirefox( - '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals("foo")); - }); + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parse('#0 $member (foo:0:0)').member; - test('parses a nested anonymous stack frame with parameters correctly', () { - var frame = new Frame.parseFirefox( - '.foo(12, "@)()/<")/.fn<@' - 'http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); - expect(frame.line, equals(560)); - expect(frame.column, isNull); - expect(frame.member, equals("foo.")); - }); + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseFirefox(''), throwsFormatException); - expect(() => new Frame.parseFirefox('.foo'), throwsFormatException); - expect(() => new Frame.parseFirefox('.foo@dart:async/future.dart'), - throwsFormatException); - expect(() => new Frame.parseFirefox('.foo/@dart:async/future.dart:10'), - throwsFormatException); - expect(() => new Frame.parseFirefox('.foo(@dart:async/future.dart:10'), - throwsFormatException); - expect(() => new Frame.parseFirefox('@dart:async/future.dart'), - throwsFormatException); - }); + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parse(''), throwsFormatException); + expect(() => new Frame.parse('#1'), throwsFormatException); + expect(() => new Frame.parse('#1 Foo'), throwsFormatException); + expect(() => new Frame.parse('#1 Foo (dart:async/future.dart)'), + throwsFormatException); + expect(() => new Frame.parse('#1 Foo (dart:async/future.dart:10)'), + throwsFormatException); + expect(() => new Frame.parse('#1 (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parse('Foo (dart:async/future.dart:10:15)'), + throwsFormatException); }); test('only considers dart URIs to be core', () { bool isCore(String library) => - new Frame.parseVM('#0 Foo ($library:0:0)').isCore; + new Frame.parse('#0 Foo ($library:0:0)').isCore; expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); @@ -185,17 +82,39 @@ void main() { expect(isCore('bart:core/uri.dart'), isFalse); }); + group('.caller()', () { + test('with no argument returns the parent frame', () { + expect(getCaller().member, equals('main..')); + }); + + test('at level 0 returns the current frame', () { + expect(getCaller(0).member, equals('getCaller')); + }); + + test('at level 1 returns the current frame', () { + expect(getCaller(1).member, equals('main..')); + }); + + test('at level 2 returns the grandparent frame', () { + expect(nestedGetCaller(2).member, equals('main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Frame.caller(-1), throwsArgumentError); + }); + }); + group('.library', () { test('returns the URI string for non-file URIs', () { - expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, + expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').library, equals('dart:async/future.dart')); - expect(new Frame.parseVM('#0 Foo ' + expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').library, equals('http://dartlang.org/stuff/thing.dart')); }); test('returns the relative path for file URIs', () { - expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, + expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library, equals('foo/bar.dart')); }); }); @@ -203,27 +122,27 @@ void main() { group('.location', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parseVM('#0 Foo ' + expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, + expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location, equals('foo/bar.dart 1:2')); }); }); group('.package', () { test('returns null for non-package URIs', () { - expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, + expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').package, isNull); - expect(new Frame.parseVM('#0 Foo ' + expect(new Frame.parse('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').package, isNull); }); test('returns the package name for package: URIs', () { - expect(new Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package, + expect(new Frame.parse('#0 Foo (package:foo/foo.dart:0:0)').package, equals('foo')); - expect(new Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package, + expect(new Frame.parse('#0 Foo (package:foo/zap/bar.dart:0:0)').package, equals('foo')); }); }); @@ -231,13 +150,13 @@ void main() { group('.toString()', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') + expect(new Frame.parse('#0 Foo (http://dartlang.org/thing.dart:5:10)') .toString(), equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { - expect(new Frame.parseVM('#0 Foo. ' + expect(new Frame.parse('#0 Foo. ' '(dart:core/uri.dart:5:10)').toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 4a8b37bee..fcf4fe5ce 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -4,6 +4,8 @@ library trace_test; +import 'dart:io'; + import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -29,73 +31,61 @@ Trace getCurrentTrace([int level]) => new Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { - group('.parse', () { - test('.parse parses a VM stack trace correctly', () { - var trace = new Trace.parse( - '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' - '#1 zip..zap (dart:async/future.dart:0:2)\n' - '#2 zip..zap (http://pub.dartlang.org/thing.' - 'dart:1:100)'); - - expect(trace.frames[0].uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); + test('parses a stack trace correctly', () { + var trace = new Trace.parse(''' +#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) +#1 zip..zap (dart:async/future.dart:0:2) +#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) +'''); + + expect(trace.frames[0].uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); + }); + + test('parses a real stack trace correctly', () { + var trace = new Trace.parse(getStackTraceString()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(trace.frames.first.uri.path), + equals('trace_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceString')); + }); + + test('converts from a native stack trace correctly', () { + var trace = new Trace.from(getStackTraceObject()); + // TODO(nweiz): use URL-style paths when such a thing exists. + var builder = new path.Builder(style: path.Style.posix); + expect(builder.basename(trace.frames.first.uri.path), + equals('trace_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceObject')); + }); + + group('.current()', () { + test('with no argument returns a trace starting at the current frame', () { + var trace = new Trace.current(); + expect(trace.frames.first.member, equals('main..')); + }); + + test('at level 0 returns a trace starting at the current frame', () { + var trace = new Trace.current(0); + expect(trace.frames.first.member, equals('main..')); + }); + + test('at level 1 returns a trace starting at the parent frame', () { + var trace = getCurrentTrace(1); + expect(trace.frames.first.member, equals('main..')); }); - test('parses a V8 stack trace correctly', () { - var trace = new Trace.parse( - 'Error\n' - ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - ' at http://pub.dartlang.org/stuff.js:0:2\n' - ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); - - expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + test('at level 2 returns a trace starting at the grandparent frame', () { + var trace = nestedGetCurrentTrace(2); + expect(trace.frames.first.member, equals('main..')); }); - test('parses a Firefox stack trace correctly', () { - var trace = new Trace.parse( - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); - - expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - - trace = new Trace.parse( - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); - - expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - - trace = new Trace.parse( - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); - - expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + test('throws an ArgumentError for negative levels', () { + expect(() => new Trace.current(-1), throwsArgumentError); }); }); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart deleted file mode 100644 index 38b2b80fd..000000000 --- a/pkgs/stack_trace/test/vm_test.dart +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// 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. - -/// This file tests stack_trace's ability to parse live stack traces. It's a -/// dual of dartium_test.dart, since method names can differ somewhat from -/// platform to platform. No similar file exists for dart2js since the specific -/// method names there are implementation details. - -import 'package:pathos/path.dart' as path; -import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; - -String getStackTraceString() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString(); - } -} - -StackTrace getStackTraceObject() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace; - } -} - -Frame getCaller([int level]) { - if (level == null) return new Frame.caller(); - return new Frame.caller(level); -} - -Frame nestedGetCaller(int level) => getCaller(level); - -Trace getCurrentTrace([int level]) => new Trace.current(level); - -Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); - -void main() { - group('Trace', () { - test('.parse parses a real stack trace correctly', () { - var string = getStackTraceString(); - var trace = new Trace.parse(string); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), - equals('vm_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceString')); - }); - - test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), - equals('vm_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceObject')); - }); - - group('.current()', () { - test('with no argument returns a trace starting at the current frame', - () { - var trace = new Trace.current(); - expect(trace.frames.first.member, equals('main...')); - }); - - test('at level 0 returns a trace starting at the current frame', () { - var trace = new Trace.current(0); - expect(trace.frames.first.member, equals('main...')); - }); - - test('at level 1 returns a trace starting at the parent frame', () { - var trace = getCurrentTrace(1); - expect(trace.frames.first.member, equals('main...')); - }); - - test('at level 2 returns a trace starting at the grandparent frame', () { - var trace = nestedGetCurrentTrace(2); - expect(trace.frames.first.member, equals('main...')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Trace.current(-1), throwsArgumentError); - }); - }); - }); - - group('Frame.caller()', () { - test('with no argument returns the parent frame', () { - expect(getCaller().member, equals('main..')); - }); - - test('at level 0 returns the current frame', () { - expect(getCaller(0).member, equals('getCaller')); - }); - - test('at level 1 returns the current frame', () { - expect(getCaller(1).member, equals('main..')); - }); - - test('at level 2 returns the grandparent frame', () { - expect(nestedGetCaller(2).member, equals('main..')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Frame.caller(-1), throwsArgumentError); - }); - }); -} From d1bdc79e0bb39abd659a086623fc0cb74f0172a4 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 28 Jun 2013 01:22:36 +0000 Subject: [PATCH 0023/1215] Add support for V8 and Firefox stack traces in pkg/stack_trace. R=jmesserly@google.com Review URL: https://codereview.chromium.org//18167002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24569 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 68 ++++++- pkgs/stack_trace/lib/src/trace.dart | 34 +++- pkgs/stack_trace/test/frame_test.dart | 261 ++++++++++++++++++-------- pkgs/stack_trace/test/trace_test.dart | 119 +++++++----- pkgs/stack_trace/test/vm_test.dart | 109 +++++++++++ 5 files changed, 447 insertions(+), 144 deletions(-) create mode 100644 pkgs/stack_trace/test/vm_test.dart diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index d750b9178..6daca4650 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -9,9 +9,23 @@ import 'package:pathos/path.dart' as path; import 'trace.dart'; -final _nativeFrameRegExp = new RegExp( +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) +final _vmFrame = new RegExp( r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); +// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) +// at http://pub.dartlang.org/stuff.dart.js:560:28 +final _v8Frame = new RegExp( + r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); + +// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 +final _firefoxFrame = new RegExp( + r'^([^@(/]*)(?:\(.*\))?(/[^<]*", ""); + return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); + } else { + // The second form looks like " at URI:LINE:COL", and is used for + // anonymous functions. + var uri = Uri.parse(match[5]); + return new Frame(uri, int.parse(match[6]), int.parse(match[7]), ""); + } + } + + /// Parses a string representation of a Firefox stack frame. + factory Frame.parseFirefox(String frame) { + var match = _firefoxFrame.firstMatch(frame); + if (match == null) { + throw new FormatException( + "Couldn't parse Firefox stack trace line '$frame'."); + } + + var uri = Uri.parse(match[3]); + var member = match[1]; + if (member == "") { + member = ""; + } else if (match[2] != null) { + member = "$member."; + } + // Some Firefox members have initial dots. We remove them for consistency + // with other platforms. + member = member.replaceFirst(_initialDot, ''); + return new Frame(uri, int.parse(match[4]), null, member); + } + Frame(this.uri, this.line, this.column, this.member); String toString() => '$location in $member'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index db0e70ba2..4abf55ade 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -12,6 +12,13 @@ import 'lazy_trace.dart'; final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); +/// A RegExp to match Firefox's stack traces. +/// +/// Firefox's trace frames start with the name of the function in which the +/// error occurred, possibly including its parameters inside `()`. For example, +/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. +final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@"); + /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { /// The stack frames that comprise this stack trace. @@ -57,9 +64,30 @@ class Trace implements StackTrace { /// Parses a string representation of a stack trace. /// - /// [trace] should be formatted in the same way as native stack traces. - Trace.parse(String trace) - : this(trace.trim().split("\n").map((line) => new Frame.parse(line))); + /// [trace] should be formatted in the same way as a Dart VM or browser stack + /// trace. + factory Trace.parse(String trace) { + if (trace.isEmpty) return new Trace([]); + if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); + + // Default to parsing the stack trace as a VM trace. This is also hit on IE + // and Safari, where the stack trace is just an empty string (issue 11257). + return new Trace.parseVM(trace); + } + + /// Parses a string representation of a Dart VM stack trace. + Trace.parseVM(String trace) + : this(trace.trim().split("\n").map((line) => new Frame.parseVM(line))); + + /// Parses a string representation of a Chrome/V8 stack trace. + Trace.parseV8(String trace) + : this(trace.split("\n").skip(1).map((line) => new Frame.parseV8(line))); + + /// Parses a string representation of a Firefox stack trace. + Trace.parseFirefox(String trace) + : this(trace.trim().split("\n") + .map((line) => new Frame.parseFirefox(line))); /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index a140670f8..2ab310c3d 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -4,73 +4,190 @@ library frame_test; -import 'dart:io'; - import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; -String getStackFrame() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString().split("\n").first; - } -} +void main() { + group('.parseVM', () { + test('parses a stack frame correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart:42:21)"); + expect(frame.uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, equals(42)); + expect(frame.column, equals(21)); + expect(frame.member, equals('Foo._bar')); + }); -Frame getCaller([int level]) { - if (level == null) return new Frame.caller(); - return new Frame.caller(level); -} + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parseVM('#0 $member (foo:0:0)').member; -Frame nestedGetCaller(int level) => getCaller(level); + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); -void main() { - test('parses a stack frame correctly', () { - var frame = new Frame.parse("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart:42:21)"); - expect(frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(frame.line, equals(42)); - expect(frame.column, equals(21)); - expect(frame.member, equals('Foo._bar')); + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseVM(''), throwsFormatException); + expect(() => new Frame.parseVM('#1'), throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'), + throwsFormatException); + expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart:10)'), + throwsFormatException); + expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), + throwsFormatException); + }); }); - test('parses a real stack frame correctly', () { - var frame = new Frame.parse(getStackFrame()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(frame.uri.path), equals('frame_test.dart')); - expect(frame.line, equals(15)); - expect(frame.column, equals(5)); - expect(frame.member, equals('getStackFrame')); - }); + group('.parseV8', () { + test('parses a stack frame correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + "(http://pub.dartlang.org/stuff.dart.js:560:28)"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); - test('converts "" to ""', () { - String parsedMember(String member) => - new Frame.parse('#0 $member (foo:0:0)').member; + test('parses an anonymous stack frame correctly', () { + var frame = new Frame.parseV8( + " at http://pub.dartlang.org/stuff.dart.js:560:28"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('')); + }); + + test('converts "" to ""', () { + String parsedMember(String member) => + new Frame.parseV8(' at $member (foo:0:0)').member; - expect(parsedMember('Foo.'), equals('Foo.')); - expect(parsedMember('..bar'), - equals('..bar')); + expect(parsedMember('Foo.'), equals('Foo.')); + expect(parsedMember('..bar'), + equals('..bar')); + }); + + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseV8(''), throwsFormatException); + expect(() => new Frame.parseV8(' at'), throwsFormatException); + expect(() => new Frame.parseV8(' at Foo'), throwsFormatException); + expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart:10)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseV8('Foo (dart:async/future.dart:10:15)'), + throwsFormatException); + expect(() => new Frame.parseV8(' at dart:async/future.dart'), + throwsFormatException); + expect(() => new Frame.parseV8(' at dart:async/future.dart:10'), + throwsFormatException); + expect(() => new Frame.parseV8('dart:async/future.dart:10:15'), + throwsFormatException); + }); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parse(''), throwsFormatException); - expect(() => new Frame.parse('#1'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo'), throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async/future.dart)'), - throwsFormatException); - expect(() => new Frame.parse('#1 Foo (dart:async/future.dart:10)'), - throwsFormatException); - expect(() => new Frame.parse('#1 (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parse('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); + group('.parseFirefox', () { + test('parses a simple stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a simple anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + "@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("")); + }); + + test('parses a nested anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".foo/<@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + + frame = new Frame.parseFirefox( + ".foo/@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('parses a named nested anonymous stack frame correctly', () { + var frame = new Frame.parseFirefox( + ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + + frame = new Frame.parseFirefox( + ".foo/.name@http://pub.dartlang.org/stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('parses a stack frame with parameters correctly', () { + var frame = new Frame.parseFirefox( + '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo")); + }); + + test('parses a nested anonymous stack frame with parameters correctly', () { + var frame = new Frame.parseFirefox( + '.foo(12, "@)()/<")/.fn<@' + 'http://pub.dartlang.org/stuff.dart.js:560'); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals("foo.")); + }); + + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseFirefox(''), throwsFormatException); + expect(() => new Frame.parseFirefox('.foo'), throwsFormatException); + expect(() => new Frame.parseFirefox('.foo@dart:async/future.dart'), + throwsFormatException); + expect(() => new Frame.parseFirefox('.foo(@dart:async/future.dart:10'), + throwsFormatException); + expect(() => new Frame.parseFirefox('@dart:async/future.dart'), + throwsFormatException); + }); }); test('only considers dart URIs to be core', () { bool isCore(String library) => - new Frame.parse('#0 Foo ($library:0:0)').isCore; + new Frame.parseVM('#0 Foo ($library:0:0)').isCore; expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); @@ -82,39 +199,17 @@ void main() { expect(isCore('bart:core/uri.dart'), isFalse); }); - group('.caller()', () { - test('with no argument returns the parent frame', () { - expect(getCaller().member, equals('main..')); - }); - - test('at level 0 returns the current frame', () { - expect(getCaller(0).member, equals('getCaller')); - }); - - test('at level 1 returns the current frame', () { - expect(getCaller(1).member, equals('main..')); - }); - - test('at level 2 returns the grandparent frame', () { - expect(nestedGetCaller(2).member, equals('main..')); - }); - - test('throws an ArgumentError for negative levels', () { - expect(() => new Frame.caller(-1), throwsArgumentError); - }); - }); - group('.library', () { test('returns the URI string for non-file URIs', () { - expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').library, + expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, equals('dart:async/future.dart')); - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').library, equals('http://dartlang.org/stuff/thing.dart')); }); test('returns the relative path for file URIs', () { - expect(new Frame.parse('#0 Foo (foo/bar.dart:0:0)').library, + expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, equals('foo/bar.dart')); }); }); @@ -122,27 +217,27 @@ void main() { group('.location', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); - expect(new Frame.parse('#0 Foo (foo/bar.dart:1:2)').location, + expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, equals('foo/bar.dart 1:2')); }); }); group('.package', () { test('returns null for non-package URIs', () { - expect(new Frame.parse('#0 Foo (dart:async/future.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, isNull); - expect(new Frame.parse('#0 Foo ' + expect(new Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)').package, isNull); }); test('returns the package name for package: URIs', () { - expect(new Frame.parse('#0 Foo (package:foo/foo.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package, equals('foo')); - expect(new Frame.parse('#0 Foo (package:foo/zap/bar.dart:0:0)').package, + expect(new Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package, equals('foo')); }); }); @@ -150,13 +245,13 @@ void main() { group('.toString()', () { test('returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parse('#0 Foo (http://dartlang.org/thing.dart:5:10)') + expect(new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') .toString(), equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { - expect(new Frame.parse('#0 Foo. ' + expect(new Frame.parseVM('#0 Foo. ' '(dart:core/uri.dart:5:10)').toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index fcf4fe5ce..5d34de5b9 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -4,8 +4,6 @@ library trace_test; -import 'dart:io'; - import 'package:pathos/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -31,61 +29,80 @@ Trace getCurrentTrace([int level]) => new Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { - test('parses a stack trace correctly', () { - var trace = new Trace.parse(''' -#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) -#1 zip..zap (dart:async/future.dart:0:2) -#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) -'''); - - expect(trace.frames[0].uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); - expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); - }); - - test('parses a real stack trace correctly', () { - var trace = new Trace.parse(getStackTraceString()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(trace.frames.first.uri.path), - equals('trace_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceString')); - }); - - test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); - // TODO(nweiz): use URL-style paths when such a thing exists. - var builder = new path.Builder(style: path.Style.posix); - expect(builder.basename(trace.frames.first.uri.path), - equals('trace_test.dart')); - expect(trace.frames.first.member, equals('getStackTraceObject')); - }); - - group('.current()', () { - test('with no argument returns a trace starting at the current frame', () { - var trace = new Trace.current(); - expect(trace.frames.first.member, equals('main..')); - }); - - test('at level 0 returns a trace starting at the current frame', () { - var trace = new Trace.current(0); - expect(trace.frames.first.member, equals('main..')); + // This just shouldn't crash. + test('a native stack trace is parseable', () => new Trace.current()); + + group('.parse', () { + test('.parse parses a VM stack trace correctly', () { + var trace = new Trace.parse( + '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' + '#1 zip..zap (dart:async/future.dart:0:2)\n' + '#2 zip..zap (http://pub.dartlang.org/thing.' + 'dart:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); }); - test('at level 1 returns a trace starting at the parent frame', () { - var trace = getCurrentTrace(1); - expect(trace.frames.first.member, equals('main..')); + test('parses a V8 stack trace correctly', () { + var trace = new Trace.parse( + 'Error\n' + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); - test('at level 2 returns a trace starting at the grandparent frame', () { - var trace = nestedGetCurrentTrace(2); - expect(trace.frames.first.member, equals('main..')); + test('parses a Firefox stack trace correctly', () { + var trace = new Trace.parse( + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); - test('throws an ArgumentError for negative levels', () { - expect(() => new Trace.current(-1), throwsArgumentError); + test('parses an empty string correctly', () { + expect(new Trace.parse('').frames, isEmpty); }); }); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart new file mode 100644 index 000000000..38b2b80fd --- /dev/null +++ b/pkgs/stack_trace/test/vm_test.dart @@ -0,0 +1,109 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +/// This file tests stack_trace's ability to parse live stack traces. It's a +/// dual of dartium_test.dart, since method names can differ somewhat from +/// platform to platform. No similar file exists for dart2js since the specific +/// method names there are implementation details. + +import 'package:pathos/path.dart' as path; +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +String getStackTraceString() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace.toString(); + } +} + +StackTrace getStackTraceObject() { + try { + throw ''; + } catch (_, stackTrace) { + return stackTrace; + } +} + +Frame getCaller([int level]) { + if (level == null) return new Frame.caller(); + return new Frame.caller(level); +} + +Frame nestedGetCaller(int level) => getCaller(level); + +Trace getCurrentTrace([int level]) => new Trace.current(level); + +Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); + +void main() { + group('Trace', () { + test('.parse parses a real stack trace correctly', () { + var string = getStackTraceString(); + var trace = new Trace.parse(string); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('vm_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceString')); + }); + + test('converts from a native stack trace correctly', () { + var trace = new Trace.from(getStackTraceObject()); + var builder = new path.Builder(style: path.Style.url); + expect(builder.basename(trace.frames.first.uri.path), + equals('vm_test.dart')); + expect(trace.frames.first.member, equals('getStackTraceObject')); + }); + + group('.current()', () { + test('with no argument returns a trace starting at the current frame', + () { + var trace = new Trace.current(); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 0 returns a trace starting at the current frame', () { + var trace = new Trace.current(0); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 1 returns a trace starting at the parent frame', () { + var trace = getCurrentTrace(1); + expect(trace.frames.first.member, equals('main...')); + }); + + test('at level 2 returns a trace starting at the grandparent frame', () { + var trace = nestedGetCurrentTrace(2); + expect(trace.frames.first.member, equals('main...')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Trace.current(-1), throwsArgumentError); + }); + }); + }); + + group('Frame.caller()', () { + test('with no argument returns the parent frame', () { + expect(getCaller().member, equals('main..')); + }); + + test('at level 0 returns the current frame', () { + expect(getCaller(0).member, equals('getCaller')); + }); + + test('at level 1 returns the current frame', () { + expect(getCaller(1).member, equals('main..')); + }); + + test('at level 2 returns the grandparent frame', () { + expect(nestedGetCaller(2).member, equals('main..')); + }); + + test('throws an ArgumentError for negative levels', () { + expect(() => new Frame.caller(-1), throwsArgumentError); + }); + }); +} From 1a9245cd7a4f7efd6ec67371cf5c16cdb33f6dc4 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 28 Jun 2013 01:50:01 +0000 Subject: [PATCH 0024/1215] Properly handle empty stack traces in package:stack_trace. R=sigmund@google.com Review URL: https://codereview.chromium.org//18170002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24571 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 5 ++--- pkgs/stack_trace/test/trace_test.dart | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 4abf55ade..db7a40454 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -143,10 +143,9 @@ class Trace implements StackTrace { /// Returns a human-readable string representation of [this]. String toString() { - if (frames.length == '') return ''; - // Figure out the longest path so we know how much to pad. - var longest = frames.map((frame) => frame.location.length).reduce(math.max); + var longest = frames.map((frame) => frame.location.length) + .fold(0, math.max); // Print out the stack trace nicely formatted. return frames.map((frame) { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 5d34de5b9..95753a0d2 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -102,7 +102,9 @@ void main() { }); test('parses an empty string correctly', () { - expect(new Trace.parse('').frames, isEmpty); + var trace = new Trace.parse(''); + expect(trace.frames, isEmpty); + expect(trace.toString(), equals('')); }); }); From 074f05aa2f09d2af44d3fccc177ca4905093918d Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 28 Jun 2013 22:24:01 +0000 Subject: [PATCH 0025/1215] Add a couple functions to package:stack_trace. This adds a function to convert a Trace to a VM-style StackTrace object, and to parse a Trace-style string into a Trace. R=jmesserly@google.com Review URL: https://codereview.chromium.org//18029023 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24611 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 25 ++++++++++++++ pkgs/stack_trace/lib/src/lazy_trace.dart | 3 +- pkgs/stack_trace/lib/src/trace.dart | 44 +++++++++--------------- pkgs/stack_trace/lib/src/utils.dart | 20 +++++++++++ pkgs/stack_trace/lib/src/vm_trace.dart | 31 +++++++++++++++++ pkgs/stack_trace/test/frame_test.dart | 37 ++++++++++++++++++++ pkgs/stack_trace/test/trace_test.dart | 36 ++++++++++++++----- 7 files changed, 159 insertions(+), 37 deletions(-) create mode 100644 pkgs/stack_trace/lib/src/utils.dart create mode 100644 pkgs/stack_trace/lib/src/vm_trace.dart diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 6daca4650..6ba30794f 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -24,6 +24,11 @@ final _v8Frame = new RegExp( final _firefoxFrame = new RegExp( r'^([^@(/]*)(?:\(.*\))?(/[^<]* '$location in $member'; diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 8c4482971..ae56b5fc3 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -25,8 +25,7 @@ class LazyTrace implements Trace { } List get frames => _trace.frames; - String get stackTrace => _trace.stackTrace; - String get fullStackTrace => _trace.fullStackTrace; + StackTrace get vmTrace => _trace.vmTrace; Trace get terse => new LazyTrace(() => _trace.terse); Trace foldFrames(bool predicate(frame)) => new LazyTrace(() => _trace.foldFrames(predicate)); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index db7a40454..2b9d22a79 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -9,6 +9,8 @@ import 'dart:math' as math; import 'frame.dart'; import 'lazy_trace.dart'; +import 'utils.dart'; +import 'vm_trace.dart'; final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); @@ -19,6 +21,9 @@ final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); /// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@"); +/// A RegExp to match this package's stack traces. +final _friendlyTrace = new RegExp(r"^[^\s]+( \d+:\d+)?\s+[^\s]+($|\n)"); + /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { /// The stack frames that comprise this stack trace. @@ -70,6 +75,7 @@ class Trace implements StackTrace { if (trace.isEmpty) return new Trace([]); if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); + if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); // Default to parsing the stack trace as a VM trace. This is also hit on IE // and Safari, where the stack trace is just an empty string (issue 11257). @@ -89,23 +95,21 @@ class Trace implements StackTrace { : this(trace.trim().split("\n") .map((line) => new Frame.parseFirefox(line))); + /// Parses this package's a string representation of a stack trace. + Trace.parseFriendly(String trace) + : this(trace.trim().split("\n") + .map((line) => new Frame.parseFriendly(line))); + /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) : frames = new UnmodifiableListView(frames.toList()); - // TODO(nweiz): Keep track of which [Frame]s are part of the partial stack - // trace and only print them. - /// Returns a string representation of this stack trace. - /// - /// This is identical to [toString]. It will not be formatted in the manner of - /// native stack traces. - String get stackTrace => toString(); - - /// Returns a string representation of this stack trace. + /// Returns a VM-style [StackTrace] object. /// - /// This is identical to [toString]. It will not be formatted in the manner of - /// native stack traces. - String get fullStackTrace => toString(); + /// The return value's [toString] method will always return a string + /// representation in the Dart VM's stack trace format, regardless of what + /// platform is being used. + StackTrace get vmTrace => new VMTrace(frames); /// Returns a terser version of [this]. /// @@ -149,21 +153,7 @@ class Trace implements StackTrace { // Print out the stack trace nicely formatted. return frames.map((frame) { - return '${_padRight(frame.location, longest)} ${frame.member}\n'; + return '${padRight(frame.location, longest)} ${frame.member}\n'; }).join(); } } - -/// Returns [string] with enough spaces added to the end to make it [length] -/// characters long. -String _padRight(String string, int length) { - if (string.length >= length) return string; - - var result = new StringBuffer(); - result.write(string); - for (var i = 0; i < length - string.length; i++) { - result.write(' '); - } - - return result.toString(); -} diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart new file mode 100644 index 000000000..08b3b960e --- /dev/null +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.src.utils; + +/// Returns [string] with enough spaces added to the end to make it [length] +/// characters long. +String padRight(String string, int length) { + if (string.length >= length) return string; + + var result = new StringBuffer(); + result.write(string); + for (var i = 0; i < length - string.length; i++) { + result.write(' '); + } + + return result.toString(); +} + diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart new file mode 100644 index 000000000..811601529 --- /dev/null +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library vm_trace; + +import 'frame.dart'; +import 'utils.dart'; + +/// An implementation of [StackTrace] that emulates the behavior of the VM's +/// implementation. +/// +/// In particular, when [toString] is called, this returns a string in the VM's +/// stack trace format. +class VMTrace implements StackTrace { + /// The stack frames that comprise this stack trace. + final List frames; + + VMTrace(this.frames); + + String toString() { + var i = 1; + return frames.map((frame) { + var number = padRight("#${i++}", 8); + var member = frame.member.replaceAll("", ""); + var line = frame.line == null ? 0 : frame.line; + var column = frame.column == null ? 0 : frame.column; + return "$number$member (${frame.uri}:$line:$column)\n"; + }).join(); + } +} diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 2ab310c3d..f38278d64 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -185,6 +185,43 @@ void main() { }); }); + group('.parseFriendly', () { + test('parses a simple stack frame correctly', () { + var frame = new Frame.parseFriendly( + "http://dartlang.org/foo/bar.dart 10:11 Foo..bar"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('Foo..bar')); + }); + + test('parses a stack frame with no line or column correctly', () { + var frame = new Frame.parseFriendly( + "http://dartlang.org/foo/bar.dart Foo..bar"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('Foo..bar')); + }); + + test('parses a stack frame with a relative path correctly', () { + var frame = new Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); + expect(frame.uri, equals( + path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('Foo..bar')); + }); + + test('throws a FormatException for malformed frames', () { + expect(() => new Frame.parseFriendly(''), throwsFormatException); + expect(() => new Frame.parseFriendly('foo/bar.dart'), + throwsFormatException); + expect(() => new Frame.parseFriendly('foo/bar.dart 10:11'), + throwsFormatException); + }); + }); + test('only considers dart URIs to be core', () { bool isCore(String library) => new Frame.parseVM('#0 Foo ($library:0:0)').isCore; diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 95753a0d2..fbe11a330 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -101,6 +101,22 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); + test('parses a package:stack_trace stack trace correctly', () { + var trace = new Trace.parse( + 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/baz.dart Foo..bar'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://dartlang.org/foo/baz.dart"))); + }); + + test('parses a real package:stack_trace stack trace correctly', () { + var traceString = new Trace.current().toString(); + expect(new Trace.parse(traceString).toString(), equals(traceString)); + }); + test('parses an empty string correctly', () { var trace = new Trace.parse(''); expect(trace.frames, isEmpty); @@ -122,14 +138,18 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap ''')); }); - test('.stackTrace forwards to .toString()', () { - var trace = new Trace.current(); - expect(trace.stackTrace, equals(trace.toString())); - }); - - test('.fullStackTrace forwards to .toString()', () { - var trace = new Trace.current(); - expect(trace.fullStackTrace, equals(trace.toString())); + test('.vmTrace returns a native-style trace', () { + var uri = path.toUri(path.absolute('foo')); + var trace = new Trace([ + new Frame(uri, 10, 20, 'Foo.'), + new Frame(Uri.parse('http://dartlang.org/foo.dart'), null, null, 'bar'), + new Frame(Uri.parse('dart:async'), 15, null, 'baz'), + ]); + + expect(trace.vmTrace.toString(), equals( + '#1 Foo. ($uri:10:20)\n' + '#2 bar (http://dartlang.org/foo.dart:0:0)\n' + '#3 baz (dart:async:15:0)\n')); }); test('.terse folds core frames together bottom-up', () { From 1c84d57a6a2ef88063149e30ad7c3bd9749d725a Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 8 Jul 2013 22:25:07 +0000 Subject: [PATCH 0026/1215] Make the Firefox trace RegExp not go exponential on V8. BUG=11645 R=rnystrom@google.com Review URL: https://codereview.chromium.org//18339005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24829 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 2b9d22a79..6b7da758d 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -19,7 +19,7 @@ final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); /// Firefox's trace frames start with the name of the function in which the /// error occurred, possibly including its parameters inside `()`. For example, /// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. -final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]*|\(.*\))*@"); +final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@"); /// A RegExp to match this package's stack traces. final _friendlyTrace = new RegExp(r"^[^\s]+( \d+:\d+)?\s+[^\s]+($|\n)"); From 7c0423b2cc99869217318795073d6af1b58638ff Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 17:54:48 +0000 Subject: [PATCH 0027/1215] Rename "pathos" package to "path". R=ajohnsen@google.com Review URL: https://codereview.chromium.org//18356011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@24964 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 2 +- pkgs/stack_trace/test/trace_test.dart | 2 +- pkgs/stack_trace/test/vm_test.dart | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 6ba30794f..5a0582c95 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -5,7 +5,7 @@ library frame; -import 'package:pathos/path.dart' as path; +import 'package:path/path.dart' as path; import 'trace.dart'; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3a679a826..b672df7ff 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -5,7 +5,7 @@ description: > A package for manipulating stack traces and printing them readably. dependencies: - pathos: any + path: any dev_dependencies: unittest: any diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index f38278d64..75302a7a8 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -4,7 +4,7 @@ library frame_test; -import 'package:pathos/path.dart' as path; +import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index fbe11a330..92b2b2084 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -4,7 +4,7 @@ library trace_test; -import 'package:pathos/path.dart' as path; +import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 38b2b80fd..6570c24c5 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -7,7 +7,7 @@ /// platform to platform. No similar file exists for dart2js since the specific /// method names there are implementation details. -import 'package:pathos/path.dart' as path; +import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; From f147253441b13466847e60bcfd8f592b2366b224 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 21:15:02 +0000 Subject: [PATCH 0028/1215] File watching package. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//18612013 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24971 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/README.md | 2 + pkgs/watcher/example/watch.dart | 24 ++ pkgs/watcher/lib/src/directory_watcher.dart | 226 +++++++++++++++++ pkgs/watcher/lib/src/stat.dart | 33 +++ pkgs/watcher/lib/src/watch_event.dart | 35 +++ pkgs/watcher/lib/watcher.dart | 8 + pkgs/watcher/pubspec.yaml | 13 + pkgs/watcher/test/directory_watcher_test.dart | 239 ++++++++++++++++++ pkgs/watcher/test/utils.dart | 186 ++++++++++++++ 9 files changed, 766 insertions(+) create mode 100644 pkgs/watcher/README.md create mode 100644 pkgs/watcher/example/watch.dart create mode 100644 pkgs/watcher/lib/src/directory_watcher.dart create mode 100644 pkgs/watcher/lib/src/stat.dart create mode 100644 pkgs/watcher/lib/src/watch_event.dart create mode 100644 pkgs/watcher/lib/watcher.dart create mode 100644 pkgs/watcher/pubspec.yaml create mode 100644 pkgs/watcher/test/directory_watcher_test.dart create mode 100644 pkgs/watcher/test/utils.dart diff --git a/pkgs/watcher/README.md b/pkgs/watcher/README.md new file mode 100644 index 000000000..75b0470f0 --- /dev/null +++ b/pkgs/watcher/README.md @@ -0,0 +1,2 @@ +A file watcher. It monitors (currently by polling) for changes to contents of +directories and notifies you when files have been added, removed, or modified. \ No newline at end of file diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart new file mode 100644 index 000000000..247f66a5e --- /dev/null +++ b/pkgs/watcher/example/watch.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +/// Watches the given directory and prints each modification to it. +library watch; + +import 'dart:io'; + +import 'package:pathos/path.dart' as pathos; +import 'package:watcher/watcher.dart'; + +main() { + var args = new Options().arguments; + if (args.length != 1) { + print("Usage: watch "); + return; + } + + var watcher = new DirectoryWatcher(pathos.absolute(args[0])); + watcher.events.listen((event) { + print(event); + }); +} \ No newline at end of file diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart new file mode 100644 index 000000000..0f297ba90 --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -0,0 +1,226 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.directory_watcher; + +import 'dart:async'; +import 'dart:io'; + +import 'package:crypto/crypto.dart'; + +import 'stat.dart'; +import 'watch_event.dart'; + +/// Watches the contents of a directory and emits [WatchEvent]s when something +/// in the directory has changed. +class DirectoryWatcher { + /// The directory whose contents are being monitored. + final String directory; + + /// The broadcast [Stream] of events that have occurred to files in + /// [directory]. + /// + /// Changes will only be monitored while this stream has subscribers. Any + /// file changes that occur during periods when there are no subscribers + /// will not be reported the next time a subscriber is added. + Stream get events => _events.stream; + StreamController _events; + + _WatchState _state = _WatchState.notWatching; + + /// A [Future] that completes when the watcher is initialized and watching + /// for file changes. + /// + /// If the watcher is not currently monitoring the directory (because there + /// are no subscribers to [events]), this returns a future that isn't + /// complete yet. It will complete when a subscriber starts listening and + /// the watcher finishes any initialization work it needs to do. + /// + /// If the watcher is already monitoring, this returns an already complete + /// future. + Future get ready => _ready.future; + Completer _ready = new Completer(); + + /// The previous status of the files in the directory. + /// + /// Used to tell which files have been modified. + final _statuses = new Map(); + + /// Creates a new [DirectoryWatcher] monitoring [directory]. + DirectoryWatcher(this.directory) { + _events = new StreamController.broadcast(onListen: () { + _state = _state.listen(this); + }, onCancel: () { + _state = _state.cancel(this); + }); + } + + /// Starts the asynchronous polling process. + /// + /// Scans the contents of the directory and compares the results to the + /// previous scan. Loops to continue monitoring as long as there are + /// subscribers to the [events] stream. + Future _watch() { + var files = new Set(); + + var stream = new Directory(directory).list(recursive: true); + + return stream.map((entity) { + if (entity is! File) return new Future.value(); + files.add(entity.path); + // TODO(rnystrom): These all run as fast as possible and read the + // contents of the files. That means there's a pretty big IO hit all at + // once. Maybe these should be queued up and rate limited? + return _refreshFile(entity.path); + }).toList().then((futures) { + // Once the listing is done, make sure to wait until each file is also + // done. + return Future.wait(futures); + }).then((_) { + var removedFiles = _statuses.keys.toSet().difference(files); + for (var removed in removedFiles) { + if (_state.shouldNotify) { + _events.add(new WatchEvent(ChangeType.REMOVE, removed)); + } + _statuses.remove(removed); + } + + var previousState = _state; + _state = _state.finish(this); + + // If we were already sending notifications, add a bit of delay before + // restarting just so that we don't whale on the file system. + // TODO(rnystrom): Tune this and/or make it tunable? + if (_state.shouldNotify) { + return new Future.delayed(new Duration(seconds: 1)); + } + }).then((_) { + // Make sure we haven't transitioned to a non-watching state during the + // delay. + if (_state.shouldWatch) _watch(); + }); + } + + /// Compares the current state of the file at [path] to the state it was in + /// the last time it was scanned. + Future _refreshFile(String path) { + return getModificationTime(path).then((modified) { + var lastStatus = _statuses[path]; + + // If it's modification time hasn't changed, assume the file is unchanged. + if (lastStatus != null && lastStatus.modified == modified) return; + + return _hashFile(path).then((hash) { + var status = new _FileStatus(modified, hash); + _statuses[path] = status; + + // Only notify if the file contents changed. + if (_state.shouldNotify && + (lastStatus == null || !_sameHash(lastStatus.hash, hash))) { + var change = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; + _events.add(new WatchEvent(change, path)); + } + }); + }); + } + + /// Calculates the SHA-1 hash of the file at [path]. + Future> _hashFile(String path) { + return new File(path).readAsBytes().then((bytes) { + var sha1 = new SHA1(); + sha1.add(bytes); + return sha1.close(); + }); + } + + /// Returns `true` if [a] and [b] are the same hash value, i.e. the same + /// series of byte values. + bool _sameHash(List a, List b) { + // Hashes should always be the same size. + assert(a.length == b.length); + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) return false; + } + + return true; + } +} + +/// An "event" that is sent to the [_WatchState] FSM to trigger state +/// transitions. +typedef _WatchState _WatchStateEvent(DirectoryWatcher watcher); + +/// The different states that the watcher can be in and the transitions between +/// them. +/// +/// This class defines a finite state machine for keeping track of what the +/// asynchronous file polling is doing. Each instance of this is a state in the +/// machine and its [listen], [cancel], and [finish] fields define the state +/// transitions when those events occur. +class _WatchState { + /// The watcher has no subscribers. + static final notWatching = new _WatchState( + listen: (watcher) { + watcher._watch(); + return _WatchState.scanning; + }); + + /// The watcher has subscribers and is scanning for pre-existing files. + static final scanning = new _WatchState( + cancel: (watcher) { + // No longer watching, so create a new incomplete ready future. + watcher._ready = new Completer(); + return _WatchState.cancelling; + }, finish: (watcher) { + watcher._ready.complete(); + return _WatchState.watching; + }, shouldWatch: true); + + /// The watcher was unsubscribed while polling and we're waiting for the poll + /// to finish. + static final cancelling = new _WatchState( + listen: (_) => _WatchState.scanning, + finish: (_) => _WatchState.notWatching); + + /// The watcher has subscribers, we have scanned for pre-existing files and + /// now we're polling for changes. + static final watching = new _WatchState( + cancel: (watcher) { + // No longer watching, so create a new incomplete ready future. + watcher._ready = new Completer(); + return _WatchState.cancelling; + }, finish: (_) => _WatchState.watching, + shouldWatch: true, shouldNotify: true); + + /// Called when the first subscriber to the watcher has been added. + final _WatchStateEvent listen; + + /// Called when all subscriptions on the watcher have been cancelled. + final _WatchStateEvent cancel; + + /// Called when a poll loop has finished. + final _WatchStateEvent finish; + + /// If the directory watcher should be watching the file system while in + /// this state. + final bool shouldWatch; + + /// If a change event should be sent for a file modification while in this + /// state. + final bool shouldNotify; + + _WatchState({this.listen, this.cancel, this.finish, + this.shouldWatch: false, this.shouldNotify: false}); +} + +class _FileStatus { + /// The last time the file was modified. + DateTime modified; + + /// The SHA-1 hash of the contents of the file. + List hash; + + _FileStatus(this.modified, this.hash); +} \ No newline at end of file diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart new file mode 100644 index 000000000..d36eff3bd --- /dev/null +++ b/pkgs/watcher/lib/src/stat.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.stat; + +import 'dart:async'; +import 'dart:io'; + +/// A function that takes a file path and returns the last modified time for +/// the file at that path. +typedef DateTime MockTimeCallback(String path); + +MockTimeCallback _mockTimeCallback; + +/// Overrides the default behavior for accessing a file's modification time +/// with [callback]. +/// +/// The OS file modification time has pretty rough granularity (like a few +/// seconds) which can make for slow tests that rely on modtime. This lets you +/// replace it with something you control. +void mockGetModificationTime(MockTimeCallback callback) { + _mockTimeCallback = callback; +} + +/// Gets the modification time for the file at [path]. +Future getModificationTime(String path) { + if (_mockTimeCallback != null) { + return new Future.value(_mockTimeCallback(path)); + } + + return FileStat.stat(path).then((stat) => stat.modified); +} diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart new file mode 100644 index 000000000..d998a2532 --- /dev/null +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.watch_event; + +/// An event describing a single change to the file system. +class WatchEvent { + /// The manner in which the file at [path] has changed. + final ChangeType type; + + /// The path of the file that changed. + final String path; + + WatchEvent(this.type, this.path); + + String toString() => "$type $path"; +} + +/// Enum for what kind of change has happened to a file. +class ChangeType { + /// A new file has been added. + static const ADD = const ChangeType("add"); + + /// A file has been removed. + static const REMOVE = const ChangeType("remove"); + + /// The contents of a file have changed. + static const MODIFY = const ChangeType("modify"); + + final String _name; + const ChangeType(this._name); + + String toString() => _name; +} \ No newline at end of file diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart new file mode 100644 index 000000000..c4824b8ec --- /dev/null +++ b/pkgs/watcher/lib/watcher.dart @@ -0,0 +1,8 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher; + +export 'src/watch_event.dart'; +export 'src/directory_watcher.dart'; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml new file mode 100644 index 000000000..263832efb --- /dev/null +++ b/pkgs/watcher/pubspec.yaml @@ -0,0 +1,13 @@ +name: watcher +author: "Dart Team " +homepage: http://www.dartlang.org +description: > + A file watcher. It monitors (currently by polling) for changes to contents + of directories and notifies you when files have been added, removed, or + modified. +dependencies: + crypto: any + path: any +dev_dependencies: + scheduled_test: any + unittest: any diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart new file mode 100644 index 000000000..635f7ee67 --- /dev/null +++ b/pkgs/watcher/test/directory_watcher_test.dart @@ -0,0 +1,239 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'utils.dart'; + +main() { + initConfig(); + + setUp(createSandbox); + + test('does not notify for files that already exist when started', () { + // Make some pre-existing files. + writeFile("a.txt"); + writeFile("b.txt"); + + createWatcher(); + + // Change one after the watcher is running. + writeFile("b.txt", contents: "modified"); + + // We should get a modify event for the changed file, but no add events + // for them before this. + expectModifyEvent("b.txt"); + }); + + test('notifies when a file is added', () { + createWatcher(); + writeFile("file.txt"); + expectAddEvent("file.txt"); + }); + + test('notifies when a file is modified', () { + writeFile("file.txt"); + createWatcher(); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + }); + + test('notifies when a file is removed', () { + writeFile("file.txt"); + createWatcher(); + deleteFile("file.txt"); + expectRemoveEvent("file.txt"); + }); + + test('notifies when a file is moved', () { + writeFile("old.txt"); + createWatcher(); + renameFile("old.txt", "new.txt"); + expectAddEvent("new.txt"); + expectRemoveEvent("old.txt"); + }); + + test('notifies when a file is modified multiple times', () { + writeFile("file.txt"); + createWatcher(); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + writeFile("file.txt", contents: "modified again"); + expectModifyEvent("file.txt"); + }); + + test('does not notify if the file contents are unchanged', () { + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "before"); + createWatcher(); + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "after"); + expectModifyEvent("b.txt"); + }); + + test('does not notify if the modification time did not change', () { + writeFile("a.txt", contents: "before"); + writeFile("b.txt", contents: "before"); + createWatcher(); + writeFile("a.txt", contents: "after", updateModified: false); + writeFile("b.txt", contents: "after"); + expectModifyEvent("b.txt"); + }); + + test('watches files in subdirectories', () { + createWatcher(); + writeFile("a/b/c/d/file.txt"); + expectAddEvent("a/b/c/d/file.txt"); + }); + + test('does not notify for changes when there were no subscribers', () { + // Note that this test doesn't rely as heavily on the test functions in + // utils.dart because it needs to be very explicit about when the event + // stream is and is not subscribed. + var watcher = createWatcher(); + + // Subscribe to the events. + var completer = new Completer(); + var subscription = watcher.events.listen((event) { + expect(event.type, equals(ChangeType.ADD)); + expect(event.path, endsWith("file.txt")); + completer.complete(); + }); + + writeFile("file.txt"); + + // Then wait until we get an event for it. + schedule(() => completer.future); + + // Unsubscribe. + schedule(() { + subscription.cancel(); + }); + + // Now write a file while we aren't listening. + writeFile("unwatched.txt"); + + // Then start listening again. + schedule(() { + completer = new Completer(); + subscription = watcher.events.listen((event) { + // We should get an event for the third file, not the one added while + // we weren't subscribed. + expect(event.type, equals(ChangeType.ADD)); + expect(event.path, endsWith("added.txt")); + completer.complete(); + }); + }); + + // The watcher will have been cancelled and then resumed in the middle of + // its pause between polling loops. That means the second scan to skip + // what changed while we were unsubscribed won't happen until after that + // delay is done. Wait long enough for that to happen. + schedule(() => new Future.delayed(new Duration(seconds: 1))); + + // And add a third file. + writeFile("added.txt"); + + // Wait until we get an event for the third file. + schedule(() => completer.future); + + schedule(() { + subscription.cancel(); + }); + }); + + + test('ready does not complete until after subscription', () { + var watcher = createWatcher(waitForReady: false); + + var ready = false; + watcher.ready.then((_) { + ready = true; + }); + + // Should not be ready yet. + schedule(() { + expect(ready, isFalse); + }); + + // Subscribe to the events. + schedule(() { + var subscription = watcher.events.listen((event) {}); + + currentSchedule.onComplete.schedule(() { + subscription.cancel(); + }); + }); + + // Should eventually be ready. + schedule(() => watcher.ready); + + schedule(() { + expect(ready, isTrue); + }); + }); + + test('ready completes immediately when already ready', () { + var watcher = createWatcher(waitForReady: false); + + // Subscribe to the events. + schedule(() { + var subscription = watcher.events.listen((event) {}); + + currentSchedule.onComplete.schedule(() { + subscription.cancel(); + }); + }); + + // Should eventually be ready. + schedule(() => watcher.ready); + + // Now ready should be a future that immediately completes. + var ready = false; + schedule(() { + watcher.ready.then((_) { + ready = true; + }); + }); + + schedule(() { + expect(ready, isTrue); + }); + }); + + test('ready returns a future that does not complete after unsubscribing', () { + var watcher = createWatcher(waitForReady: false); + + // Subscribe to the events. + var subscription; + schedule(() { + subscription = watcher.events.listen((event) {}); + }); + + var ready = false; + + // Wait until ready. + schedule(() => watcher.ready); + + // Now unsubscribe. + schedule(() { + subscription.cancel(); + + // Track when it's ready again. + ready = false; + watcher.ready.then((_) { + ready = true; + }); + }); + + // Should be back to not ready. + schedule(() { + expect(ready, isFalse); + }); + }); +} diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart new file mode 100644 index 000000000..387b4ad20 --- /dev/null +++ b/pkgs/watcher/test/utils.dart @@ -0,0 +1,186 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.test.utils; + +import 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart'; +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:unittest/compact_vm_config.dart'; +import 'package:watcher/watcher.dart'; +import 'package:watcher/src/stat.dart'; + +/// The path to the temporary sandbox created for each test. All file +/// operations are implicitly relative to this directory. +String _sandboxDir; + +/// The [DirectoryWatcher] being used for the current scheduled test. +DirectoryWatcher _watcher; + +/// The index in [_watcher]'s event stream for the next event. When event +/// expectations are set using [expectEvent] (et. al.), they use this to +/// expect a series of events in order. +var _nextEvent = 0; + +/// The mock modification times (in milliseconds since epoch) for each file. +/// +/// The actual file system has pretty coarse granularity for file modification +/// times. This means using the real file system requires us to put delays in +/// the tests to ensure we wait long enough between operations for the mod time +/// to be different. +/// +/// Instead, we'll just mock that out. Each time a file is written, we manually +/// increment the mod time for that file instantly. +Map _mockFileModificationTimes; + +void initConfig() { + useCompactVMConfiguration(); +} + +/// Creates the sandbox directory the other functions in this library use and +/// ensures it's deleted when the test ends. +/// +/// This should usually be called by [setUp]. +void createSandbox() { + var dir = new Directory("").createTempSync(); + _sandboxDir = dir.path; + + _mockFileModificationTimes = new Map(); + mockGetModificationTime((path) { + path = relative(path, from: _sandboxDir); + + // Make sure we got a path in the sandbox. + assert(isRelative(path) && !path.startsWith("..")); + + return new DateTime.fromMillisecondsSinceEpoch( + _mockFileModificationTimes[path]); + }); + + // Delete the sandbox when done. + currentSchedule.onComplete.schedule(() { + if (_sandboxDir != null) { + new Directory(_sandboxDir).deleteSync(recursive: true); + _sandboxDir = null; + } + + _mockFileModificationTimes = null; + mockGetModificationTime(null); + }, "delete sandbox"); +} + +/// Creates a new [DirectoryWatcher] that watches a temporary directory. +/// +/// Normally, this will pause the schedule until the watcher is done scanning +/// and is polling for changes. If you pass `false` for [waitForReady], it will +/// not schedule this delay. +DirectoryWatcher createWatcher({bool waitForReady}) { + _watcher = new DirectoryWatcher(_sandboxDir); + + // Wait until the scan is finished so that we don't miss changes to files + // that could occur before the scan completes. + if (waitForReady != false) { + schedule(() => _watcher.ready); + } + + currentSchedule.onComplete.schedule(() { + _nextEvent = 0; + _watcher = null; + }, "reset watcher"); + + return _watcher; +} + +void expectEvent(ChangeType type, String path) { + // Immediately create the future. This ensures we don't register too late and + // drop the event before we receive it. + var future = _watcher.events.elementAt(_nextEvent++).then((event) { + expect(event, new _ChangeMatcher(type, path)); + }); + + // Make sure the schedule is watching it in case it fails. + currentSchedule.wrapFuture(future); + + // Schedule it so that later file modifications don't occur until after this + // event is received. + schedule(() => future); +} + +void expectAddEvent(String path) { + expectEvent(ChangeType.ADD, join(_sandboxDir, path)); +} + +void expectModifyEvent(String path) { + expectEvent(ChangeType.MODIFY, join(_sandboxDir, path)); +} + +void expectRemoveEvent(String path) { + expectEvent(ChangeType.REMOVE, join(_sandboxDir, path)); +} + +/// Schedules writing a file in the sandbox at [path] with [contents]. +/// +/// If [contents] is omitted, creates an empty file. If [updatedModified] is +/// `false`, the mock file modification time is not changed. +void writeFile(String path, {String contents, bool updateModified}) { + if (contents == null) contents = ""; + if (updateModified == null) updateModified = true; + + schedule(() { + var fullPath = join(_sandboxDir, path); + + // Create any needed subdirectories. + var dir = new Directory(dirname(fullPath)); + if (!dir.existsSync()) { + dir.createSync(recursive: true); + } + + new File(fullPath).writeAsStringSync(contents); + + // Manually update the mock modification time for the file. + if (updateModified) { + var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0); + _mockFileModificationTimes[path]++; + } + }); +} + +/// Schedules deleting a file in the sandbox at [path]. +void deleteFile(String path) { + schedule(() { + new File(join(_sandboxDir, path)).deleteSync(); + }); +} + +/// Schedules renaming a file in the sandbox from [from] to [to]. +/// +/// If [contents] is omitted, creates an empty file. +void renameFile(String from, String to) { + schedule(() { + new File(join(_sandboxDir, from)).renameSync(join(_sandboxDir, to)); + + // Manually update the mock modification time for the file. + var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); + _mockFileModificationTimes[to]++; + }); +} + +/// A [Matcher] for [WatchEvent]s. +class _ChangeMatcher extends BaseMatcher { + /// The expected change. + final ChangeType type; + + /// The expected path. + final String path; + + _ChangeMatcher(this.type, this.path); + + Description describe(Description description) { + description.add("$type $path"); + } + + bool matches(item, Map matchState) => + item is WatchEvent && item.type == type && item.path == path; +} From a335cac83528fe26f07f810b240da939505137ea Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 21:47:02 +0000 Subject: [PATCH 0029/1215] Fix pathos->path in watcher example. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//18878003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24976 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/example/watch.dart | 4 ++-- pkgs/watcher/test/utils.dart | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index 247f66a5e..235578dd6 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -7,7 +7,7 @@ library watch; import 'dart:io'; -import 'package:pathos/path.dart' as pathos; +import 'package:path/path.dart' as p; import 'package:watcher/watcher.dart'; main() { @@ -17,7 +17,7 @@ main() { return; } - var watcher = new DirectoryWatcher(pathos.absolute(args[0])); + var watcher = new DirectoryWatcher(p.absolute(args[0])); watcher.events.listen((event) { print(event); }); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 387b4ad20..7b3da028a 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -7,7 +7,7 @@ library watcher.test.utils; import 'dart:async'; import 'dart:io'; -import 'package:path/path.dart'; +import 'package:path/path.dart' as p; import 'package:scheduled_test/scheduled_test.dart'; import 'package:unittest/compact_vm_config.dart'; import 'package:watcher/watcher.dart'; @@ -50,10 +50,10 @@ void createSandbox() { _mockFileModificationTimes = new Map(); mockGetModificationTime((path) { - path = relative(path, from: _sandboxDir); + path = p.relative(path, from: _sandboxDir); // Make sure we got a path in the sandbox. - assert(isRelative(path) && !path.startsWith("..")); + assert(p.isRelative(path) && !path.startsWith("..")); return new DateTime.fromMillisecondsSinceEpoch( _mockFileModificationTimes[path]); @@ -109,15 +109,15 @@ void expectEvent(ChangeType type, String path) { } void expectAddEvent(String path) { - expectEvent(ChangeType.ADD, join(_sandboxDir, path)); + expectEvent(ChangeType.ADD, p.join(_sandboxDir, path)); } void expectModifyEvent(String path) { - expectEvent(ChangeType.MODIFY, join(_sandboxDir, path)); + expectEvent(ChangeType.MODIFY, p.join(_sandboxDir, path)); } void expectRemoveEvent(String path) { - expectEvent(ChangeType.REMOVE, join(_sandboxDir, path)); + expectEvent(ChangeType.REMOVE, p.join(_sandboxDir, path)); } /// Schedules writing a file in the sandbox at [path] with [contents]. @@ -129,10 +129,10 @@ void writeFile(String path, {String contents, bool updateModified}) { if (updateModified == null) updateModified = true; schedule(() { - var fullPath = join(_sandboxDir, path); + var fullPath = p.join(_sandboxDir, path); // Create any needed subdirectories. - var dir = new Directory(dirname(fullPath)); + var dir = new Directory(p.dirname(fullPath)); if (!dir.existsSync()) { dir.createSync(recursive: true); } @@ -150,7 +150,7 @@ void writeFile(String path, {String contents, bool updateModified}) { /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { schedule(() { - new File(join(_sandboxDir, path)).deleteSync(); + new File(p.join(_sandboxDir, path)).deleteSync(); }); } @@ -159,7 +159,7 @@ void deleteFile(String path) { /// If [contents] is omitted, creates an empty file. void renameFile(String from, String to) { schedule(() { - new File(join(_sandboxDir, from)).renameSync(join(_sandboxDir, to)); + new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); // Manually update the mock modification time for the file. var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); From 63933a6660a971707356b156e403a559e25f8e33 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 22:45:43 +0000 Subject: [PATCH 0030/1215] Split up tests and add some heartbeats to try to make them not timeout. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//18877005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24978 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 15 +- pkgs/watcher/test/directory_watcher_test.dart | 146 ------------------ pkgs/watcher/test/no_subscription_test.dart | 73 +++++++++ pkgs/watcher/test/ready_test.dart | 106 +++++++++++++ pkgs/watcher/test/utils.dart | 4 +- 5 files changed, 195 insertions(+), 149 deletions(-) create mode 100644 pkgs/watcher/test/no_subscription_test.dart create mode 100644 pkgs/watcher/test/ready_test.dart diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 0f297ba90..61bf6c52a 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -42,13 +42,24 @@ class DirectoryWatcher { Future get ready => _ready.future; Completer _ready = new Completer(); + /// The amount of time the watcher pauses between successive polls of the + /// directory contents. + final Duration pollingDelay; + /// The previous status of the files in the directory. /// /// Used to tell which files have been modified. final _statuses = new Map(); /// Creates a new [DirectoryWatcher] monitoring [directory]. - DirectoryWatcher(this.directory) { + /// + /// If [pollingDelay] is passed, it specifies the amount of time the watcher + /// will pause between successive polls of the directory contents. Making + /// this shorter will give more immediate feedback at the expense of doing + /// more IO and higher CPU usage. Defaults to one second. + DirectoryWatcher(this.directory, {Duration pollingDelay}) + : pollingDelay = pollingDelay != null ? pollingDelay : + new Duration(seconds: 1) { _events = new StreamController.broadcast(onListen: () { _state = _state.listen(this); }, onCancel: () { @@ -93,7 +104,7 @@ class DirectoryWatcher { // restarting just so that we don't whale on the file system. // TODO(rnystrom): Tune this and/or make it tunable? if (_state.shouldNotify) { - return new Future.delayed(new Duration(seconds: 1)); + return new Future.delayed(pollingDelay); } }).then((_) { // Make sure we haven't transitioned to a non-watching state during the diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart index 635f7ee67..800d54d63 100644 --- a/pkgs/watcher/test/directory_watcher_test.dart +++ b/pkgs/watcher/test/directory_watcher_test.dart @@ -90,150 +90,4 @@ main() { writeFile("a/b/c/d/file.txt"); expectAddEvent("a/b/c/d/file.txt"); }); - - test('does not notify for changes when there were no subscribers', () { - // Note that this test doesn't rely as heavily on the test functions in - // utils.dart because it needs to be very explicit about when the event - // stream is and is not subscribed. - var watcher = createWatcher(); - - // Subscribe to the events. - var completer = new Completer(); - var subscription = watcher.events.listen((event) { - expect(event.type, equals(ChangeType.ADD)); - expect(event.path, endsWith("file.txt")); - completer.complete(); - }); - - writeFile("file.txt"); - - // Then wait until we get an event for it. - schedule(() => completer.future); - - // Unsubscribe. - schedule(() { - subscription.cancel(); - }); - - // Now write a file while we aren't listening. - writeFile("unwatched.txt"); - - // Then start listening again. - schedule(() { - completer = new Completer(); - subscription = watcher.events.listen((event) { - // We should get an event for the third file, not the one added while - // we weren't subscribed. - expect(event.type, equals(ChangeType.ADD)); - expect(event.path, endsWith("added.txt")); - completer.complete(); - }); - }); - - // The watcher will have been cancelled and then resumed in the middle of - // its pause between polling loops. That means the second scan to skip - // what changed while we were unsubscribed won't happen until after that - // delay is done. Wait long enough for that to happen. - schedule(() => new Future.delayed(new Duration(seconds: 1))); - - // And add a third file. - writeFile("added.txt"); - - // Wait until we get an event for the third file. - schedule(() => completer.future); - - schedule(() { - subscription.cancel(); - }); - }); - - - test('ready does not complete until after subscription', () { - var watcher = createWatcher(waitForReady: false); - - var ready = false; - watcher.ready.then((_) { - ready = true; - }); - - // Should not be ready yet. - schedule(() { - expect(ready, isFalse); - }); - - // Subscribe to the events. - schedule(() { - var subscription = watcher.events.listen((event) {}); - - currentSchedule.onComplete.schedule(() { - subscription.cancel(); - }); - }); - - // Should eventually be ready. - schedule(() => watcher.ready); - - schedule(() { - expect(ready, isTrue); - }); - }); - - test('ready completes immediately when already ready', () { - var watcher = createWatcher(waitForReady: false); - - // Subscribe to the events. - schedule(() { - var subscription = watcher.events.listen((event) {}); - - currentSchedule.onComplete.schedule(() { - subscription.cancel(); - }); - }); - - // Should eventually be ready. - schedule(() => watcher.ready); - - // Now ready should be a future that immediately completes. - var ready = false; - schedule(() { - watcher.ready.then((_) { - ready = true; - }); - }); - - schedule(() { - expect(ready, isTrue); - }); - }); - - test('ready returns a future that does not complete after unsubscribing', () { - var watcher = createWatcher(waitForReady: false); - - // Subscribe to the events. - var subscription; - schedule(() { - subscription = watcher.events.listen((event) {}); - }); - - var ready = false; - - // Wait until ready. - schedule(() => watcher.ready); - - // Now unsubscribe. - schedule(() { - subscription.cancel(); - - // Track when it's ready again. - ready = false; - watcher.ready.then((_) { - ready = true; - }); - }); - - // Should be back to not ready. - schedule(() { - expect(ready, isFalse); - }); - }); } diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription_test.dart new file mode 100644 index 000000000..e9cb4e363 --- /dev/null +++ b/pkgs/watcher/test/no_subscription_test.dart @@ -0,0 +1,73 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'utils.dart'; + +main() { + initConfig(); + + setUp(createSandbox); + + test('does not notify for changes when there were no subscribers', () { + // Note that this test doesn't rely as heavily on the test functions in + // utils.dart because it needs to be very explicit about when the event + // stream is and is not subscribed. + var watcher = createWatcher(); + + // Subscribe to the events. + var completer = new Completer(); + var subscription = watcher.events.listen((event) { + expect(event.type, equals(ChangeType.ADD)); + expect(event.path, endsWith("file.txt")); + completer.complete(); + }); + + writeFile("file.txt"); + + // Then wait until we get an event for it. + schedule(() => completer.future); + + // Unsubscribe. + schedule(() { + subscription.cancel(); + }); + + // Now write a file while we aren't listening. + writeFile("unwatched.txt"); + + // Then start listening again. + schedule(() { + completer = new Completer(); + subscription = watcher.events.listen((event) { + // We should get an event for the third file, not the one added while + // we weren't subscribed. + expect(event.type, equals(ChangeType.ADD)); + expect(event.path, endsWith("added.txt")); + completer.complete(); + }); + }); + + // The watcher will have been cancelled and then resumed in the middle of + // its pause between polling loops. That means the second scan to skip + // what changed while we were unsubscribed won't happen until after that + // delay is done. Wait long enough for that to happen. + schedule(() => new Future.delayed(new Duration(seconds: 1))); + + // And add a third file. + writeFile("added.txt"); + + // Wait until we get an event for the third file. + schedule(() => completer.future); + + schedule(() { + subscription.cancel(); + }); + }); +} diff --git a/pkgs/watcher/test/ready_test.dart b/pkgs/watcher/test/ready_test.dart new file mode 100644 index 000000000..dd799ce5a --- /dev/null +++ b/pkgs/watcher/test/ready_test.dart @@ -0,0 +1,106 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'utils.dart'; + +main() { + initConfig(); + + setUp(createSandbox); + + test('ready does not complete until after subscription', () { + var watcher = createWatcher(waitForReady: false); + + var ready = false; + watcher.ready.then((_) { + ready = true; + }); + + // Should not be ready yet. + schedule(() { + expect(ready, isFalse); + }); + + // Subscribe to the events. + schedule(() { + var subscription = watcher.events.listen((event) {}); + + currentSchedule.onComplete.schedule(() { + subscription.cancel(); + }); + }); + + // Should eventually be ready. + schedule(() => watcher.ready); + + schedule(() { + expect(ready, isTrue); + }); + }); + + test('ready completes immediately when already ready', () { + var watcher = createWatcher(waitForReady: false); + + // Subscribe to the events. + schedule(() { + var subscription = watcher.events.listen((event) {}); + + currentSchedule.onComplete.schedule(() { + subscription.cancel(); + }); + }); + + // Should eventually be ready. + schedule(() => watcher.ready); + + // Now ready should be a future that immediately completes. + var ready = false; + schedule(() { + watcher.ready.then((_) { + ready = true; + }); + }); + + schedule(() { + expect(ready, isTrue); + }); + }); + + test('ready returns a future that does not complete after unsubscribing', () { + var watcher = createWatcher(waitForReady: false); + + // Subscribe to the events. + var subscription; + schedule(() { + subscription = watcher.events.listen((event) {}); + }); + + var ready = false; + + // Wait until ready. + schedule(() => watcher.ready); + + // Now unsubscribe. + schedule(() { + subscription.cancel(); + + // Track when it's ready again. + ready = false; + watcher.ready.then((_) { + ready = true; + }); + }); + + // Should be back to not ready. + schedule(() { + expect(ready, isFalse); + }); + }); +} diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 7b3da028a..5a22e609b 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -77,7 +77,9 @@ void createSandbox() { /// and is polling for changes. If you pass `false` for [waitForReady], it will /// not schedule this delay. DirectoryWatcher createWatcher({bool waitForReady}) { - _watcher = new DirectoryWatcher(_sandboxDir); + // Use a short delay to make the tests run quickly. + _watcher = new DirectoryWatcher(_sandboxDir, + pollingDelay: new Duration(milliseconds: 100)); // Wait until the scan is finished so that we don't miss changes to files // that could occur before the scan completes. From f07eca145bf2697399131d99b60e1bcbd4ab2cbe Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 23:25:28 +0000 Subject: [PATCH 0031/1215] Add some debug prints to figure out why a test is failing on windows. R=nweiz@google.com Review URL: https://codereview.chromium.org//18513006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24983 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 5a22e609b..d822e1fc2 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -48,6 +48,9 @@ void createSandbox() { var dir = new Directory("").createTempSync(); _sandboxDir = dir.path; + // TODO(rnystrom): Temporary while debugging the Windows bot. + print("create mock modtime map for $_sandboxDir"); + _mockFileModificationTimes = new Map(); mockGetModificationTime((path) { path = p.relative(path, from: _sandboxDir); @@ -55,12 +58,17 @@ void createSandbox() { // Make sure we got a path in the sandbox. assert(p.isRelative(path) && !path.startsWith("..")); + // TODO(rnystrom): Temporary while debugging the Windows bot. + print("get mock modtime for $path = ${_mockFileModificationTimes[path]}"); return new DateTime.fromMillisecondsSinceEpoch( _mockFileModificationTimes[path]); }); // Delete the sandbox when done. currentSchedule.onComplete.schedule(() { + // TODO(rnystrom): Temporary while debugging the Windows bot. + print("delete mock modtime map for $_sandboxDir"); + if (_sandboxDir != null) { new Directory(_sandboxDir).deleteSync(recursive: true); _sandboxDir = null; @@ -139,12 +147,17 @@ void writeFile(String path, {String contents, bool updateModified}) { dir.createSync(recursive: true); } + // TODO(rnystrom): Temporary while debugging the Windows bot. + print("write $path"); + new File(fullPath).writeAsStringSync(contents); // Manually update the mock modification time for the file. if (updateModified) { var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0); _mockFileModificationTimes[path]++; + // TODO(rnystrom): Temporary while debugging the Windows bot. + print(" update modtime to ${_mockFileModificationTimes[path]}"); } }); } @@ -163,9 +176,14 @@ void renameFile(String from, String to) { schedule(() { new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); + // TODO(rnystrom): Temporary while debugging the Windows bot. + print("rename $from -> $to"); + // Manually update the mock modification time for the file. var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); _mockFileModificationTimes[to]++; + // TODO(rnystrom): Temporary while debugging the Windows bot. + print(" update modtime to ${_mockFileModificationTimes[to]}"); }); } From 56a381d77526b03b96f7e1d8dcf673f5c6f135f1 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 12 Jul 2013 23:47:49 +0000 Subject: [PATCH 0032/1215] Normalize paths in mock timestamp map. Makes sure separators are consistent on Windows. Review URL: https://codereview.chromium.org//18430006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24984 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index d822e1fc2..747171657 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -48,27 +48,19 @@ void createSandbox() { var dir = new Directory("").createTempSync(); _sandboxDir = dir.path; - // TODO(rnystrom): Temporary while debugging the Windows bot. - print("create mock modtime map for $_sandboxDir"); - _mockFileModificationTimes = new Map(); mockGetModificationTime((path) { - path = p.relative(path, from: _sandboxDir); + path = p.normalize(p.relative(path, from: _sandboxDir)); // Make sure we got a path in the sandbox. assert(p.isRelative(path) && !path.startsWith("..")); - // TODO(rnystrom): Temporary while debugging the Windows bot. - print("get mock modtime for $path = ${_mockFileModificationTimes[path]}"); return new DateTime.fromMillisecondsSinceEpoch( _mockFileModificationTimes[path]); }); // Delete the sandbox when done. currentSchedule.onComplete.schedule(() { - // TODO(rnystrom): Temporary while debugging the Windows bot. - print("delete mock modtime map for $_sandboxDir"); - if (_sandboxDir != null) { new Directory(_sandboxDir).deleteSync(recursive: true); _sandboxDir = null; @@ -147,17 +139,15 @@ void writeFile(String path, {String contents, bool updateModified}) { dir.createSync(recursive: true); } - // TODO(rnystrom): Temporary while debugging the Windows bot. - print("write $path"); - new File(fullPath).writeAsStringSync(contents); // Manually update the mock modification time for the file. if (updateModified) { + // Make sure we always use the same separator on Windows. + path = p.normalize(path); + var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0); _mockFileModificationTimes[path]++; - // TODO(rnystrom): Temporary while debugging the Windows bot. - print(" update modtime to ${_mockFileModificationTimes[path]}"); } }); } @@ -176,14 +166,12 @@ void renameFile(String from, String to) { schedule(() { new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); - // TODO(rnystrom): Temporary while debugging the Windows bot. - print("rename $from -> $to"); + // Make sure we always use the same separator on Windows. + to = p.normalize(to); // Manually update the mock modification time for the file. var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); _mockFileModificationTimes[to]++; - // TODO(rnystrom): Temporary while debugging the Windows bot. - print(" update modtime to ${_mockFileModificationTimes[to]}"); }); } From 03d30957ff0f1818d1bcb26712282620ad5e7218 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Sat, 13 Jul 2013 00:10:44 +0000 Subject: [PATCH 0033/1215] Normalize paths when matching them. Review URL: https://codereview.chromium.org//18464006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@24986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 747171657..3f5844ba4 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -190,5 +190,7 @@ class _ChangeMatcher extends BaseMatcher { } bool matches(item, Map matchState) => - item is WatchEvent && item.type == type && item.path == path; + item is WatchEvent && + item.type == type && + p.normalize(item.path) == p.normalize(path); } From 2e152fd2b08ba0bbf941d37733c95431f062eea7 Mon Sep 17 00:00:00 2001 From: "gram@google.com" Date: Tue, 23 Jul 2013 19:48:26 +0000 Subject: [PATCH 0034/1215] Add missing newline after Actual value in fail message. Remove the BasMatcher class; it made some sense when we had both 'interface' and 'class' but adds no value now. Fix a comment in the CustomMatcher documentation. Fix tests affected by these changes. R=sigmund@google.com Review URL: https://codereview.chromium.org//18442002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@25356 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 3f5844ba4..5053b76ad 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -176,7 +176,7 @@ void renameFile(String from, String to) { } /// A [Matcher] for [WatchEvent]s. -class _ChangeMatcher extends BaseMatcher { +class _ChangeMatcher extends Matcher { /// The expected change. final ChangeType type; From a8acfcb14db3685ae1490109af871492f29d9b4c Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Fri, 2 Aug 2013 22:01:39 +0000 Subject: [PATCH 0035/1215] Re-implement directory polling. BUG=https://code.google.com/p/dart/issues/detail?id=12107 R=nweiz@google.com Review URL: https://codereview.chromium.org//21628002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@25746 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/async_queue.dart | 74 ++++++ pkgs/watcher/lib/src/directory_watcher.dart | 281 +++++++++++--------- pkgs/watcher/test/no_subscription_test.dart | 10 +- pkgs/watcher/test/utils.dart | 10 +- 4 files changed, 240 insertions(+), 135 deletions(-) create mode 100644 pkgs/watcher/lib/src/async_queue.dart diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart new file mode 100644 index 000000000..9456631af --- /dev/null +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.async_queue; + +import 'dart:async'; +import 'dart:collection'; + +typedef Future ItemProcessor(T item); +typedef void ErrorHandler(error); + +/// A queue of items that are sequentially, asynchronously processed. +/// +/// Unlike [Stream.map] or [Stream.forEach], the callback used to process each +/// item returns a [Future], and it will not advance to the next item until the +/// current item is finished processing. +/// +/// Items can be added at any point in time and processing will be started as +/// needed. When all items are processed, it stops processing until more items +/// are added. +class AsyncQueue { + final _items = new Queue(); + + /// Whether or not the queue is currently waiting on a processing future to + /// complete. + bool _isProcessing = false; + + /// The callback to invoke on each queued item. + /// + /// The next item in the queue will not be processed until the [Future] + /// returned by this completes. + final ItemProcessor _processor; + + /// The handler for errors thrown during processing. + /// + /// Used to avoid top-leveling asynchronous errors. + final ErrorHandler _errorHandler; + + AsyncQueue(this._processor, {ErrorHandler onError}) + : _errorHandler = onError; + + /// Enqueues [item] to be processed and starts asynchronously processing it + /// if a process isn't already running. + void add(T item) { + _items.add(item); + + // Start up the asynchronous processing if not already running. + if (_isProcessing) return; + _isProcessing = true; + + _processNextItem().catchError(_errorHandler); + } + + /// Removes all remaining items to be processed. + void clear() { + _items.clear(); + } + + /// Pulls the next item off [_items] and processes it. + /// + /// When complete, recursively calls itself to continue processing unless + /// the process was cancelled. + Future _processNextItem() { + var item = _items.removeFirst(); + return _processor(item).then((_) { + if (_items.isNotEmpty) return _processNextItem(); + + // We have drained the queue, stop processing and wait until something + // has been enqueued. + _isProcessing = false; + }); + } +} \ No newline at end of file diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 61bf6c52a..913101b60 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -5,10 +5,12 @@ library watcher.directory_watcher; import 'dart:async'; +import 'dart:collection'; import 'dart:io'; import 'package:crypto/crypto.dart'; +import 'async_queue.dart'; import 'stat.dart'; import 'watch_event.dart'; @@ -27,7 +29,7 @@ class DirectoryWatcher { Stream get events => _events.stream; StreamController _events; - _WatchState _state = _WatchState.notWatching; + _WatchState _state = _WatchState.UNSUBSCRIBED; /// A [Future] that completes when the watcher is initialized and watching /// for file changes. @@ -51,6 +53,26 @@ class DirectoryWatcher { /// Used to tell which files have been modified. final _statuses = new Map(); + /// The subscription used while [directory] is being listed. + /// + /// Will be `null` if a list is not currently happening. + StreamSubscription _listSubscription; + + /// The queue of files waiting to be processed to see if they have been + /// modified. + /// + /// Processing a file is asynchronous, as is listing the directory, so the + /// queue exists to let each of those proceed at their own rate. The lister + /// will enqueue files as quickly as it can. Meanwhile, files are dequeued + /// and processed sequentially. + AsyncQueue _filesToProcess; + + /// The set of files that have been seen in the current directory listing. + /// + /// Used to tell which files have been removed: files that are in [_statuses] + /// but not in here when a poll completes have been removed. + final _polledFiles = new Set(); + /// Creates a new [DirectoryWatcher] monitoring [directory]. /// /// If [pollingDelay] is passed, it specifies the amount of time the watcher @@ -60,82 +82,133 @@ class DirectoryWatcher { DirectoryWatcher(this.directory, {Duration pollingDelay}) : pollingDelay = pollingDelay != null ? pollingDelay : new Duration(seconds: 1) { - _events = new StreamController.broadcast(onListen: () { - _state = _state.listen(this); - }, onCancel: () { - _state = _state.cancel(this); - }); + _events = new StreamController.broadcast( + onListen: _watch, onCancel: _cancel); + + _filesToProcess = new AsyncQueue(_processFile, + onError: _events.addError); } - /// Starts the asynchronous polling process. - /// - /// Scans the contents of the directory and compares the results to the - /// previous scan. Loops to continue monitoring as long as there are - /// subscribers to the [events] stream. - Future _watch() { - var files = new Set(); + /// Scans to see which files were already present before the watcher was + /// subscribed to, and then starts watching the directory for changes. + void _watch() { + assert(_state == _WatchState.UNSUBSCRIBED); + _state = _WatchState.SCANNING; + _poll(); + } - var stream = new Directory(directory).list(recursive: true); + /// Stops watching the directory when there are no more subscribers. + void _cancel() { + assert(_state != _WatchState.UNSUBSCRIBED); + _state = _WatchState.UNSUBSCRIBED; - return stream.map((entity) { - if (entity is! File) return new Future.value(); - files.add(entity.path); - // TODO(rnystrom): These all run as fast as possible and read the - // contents of the files. That means there's a pretty big IO hit all at - // once. Maybe these should be queued up and rate limited? - return _refreshFile(entity.path); - }).toList().then((futures) { - // Once the listing is done, make sure to wait until each file is also - // done. - return Future.wait(futures); - }).then((_) { - var removedFiles = _statuses.keys.toSet().difference(files); - for (var removed in removedFiles) { - if (_state.shouldNotify) { - _events.add(new WatchEvent(ChangeType.REMOVE, removed)); - } - _statuses.remove(removed); - } + // If we're in the middle of listing the directory, stop. + if (_listSubscription != null) _listSubscription.cancel(); - var previousState = _state; - _state = _state.finish(this); + // Don't process any remaining files. + _filesToProcess.clear(); + _polledFiles.clear(); + _statuses.clear(); - // If we were already sending notifications, add a bit of delay before - // restarting just so that we don't whale on the file system. - // TODO(rnystrom): Tune this and/or make it tunable? - if (_state.shouldNotify) { - return new Future.delayed(pollingDelay); - } - }).then((_) { - // Make sure we haven't transitioned to a non-watching state during the - // delay. - if (_state.shouldWatch) _watch(); + _ready = new Completer(); + } + + /// Scans the contents of the directory once to see which files have been + /// added, removed, and modified. + void _poll() { + _filesToProcess.clear(); + _polledFiles.clear(); + + var stream = new Directory(directory).list(recursive: true); + _listSubscription = stream.listen((entity) { + assert(_state != _WatchState.UNSUBSCRIBED); + + if (entity is! File) return; + _filesToProcess.add(entity.path); + }, onDone: () { + assert(_state != _WatchState.UNSUBSCRIBED); + _listSubscription = null; + + // Null tells the queue consumer that we're done listing. + _filesToProcess.add(null); }); } - /// Compares the current state of the file at [path] to the state it was in - /// the last time it was scanned. - Future _refreshFile(String path) { - return getModificationTime(path).then((modified) { - var lastStatus = _statuses[path]; + /// Processes [file] to determine if it has been modified since the last + /// time it was scanned. + Future _processFile(String file) { + assert(_state != _WatchState.UNSUBSCRIBED); + + // `null` is the sentinel which means the directory listing is complete. + if (file == null) return _completePoll(); + + return getModificationTime(file).then((modified) { + if (_checkForCancel()) return; + + var lastStatus = _statuses[file]; - // If it's modification time hasn't changed, assume the file is unchanged. - if (lastStatus != null && lastStatus.modified == modified) return; + // If its modification time hasn't changed, assume the file is unchanged. + if (lastStatus != null && lastStatus.modified == modified) { + // The file is still here. + _polledFiles.add(file); + return; + } + + return _hashFile(file).then((hash) { + if (_checkForCancel()) return; - return _hashFile(path).then((hash) { var status = new _FileStatus(modified, hash); - _statuses[path] = status; - - // Only notify if the file contents changed. - if (_state.shouldNotify && - (lastStatus == null || !_sameHash(lastStatus.hash, hash))) { - var change = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; - _events.add(new WatchEvent(change, path)); - } + _statuses[file] = status; + _polledFiles.add(file); + + // Only notify while in the watching state. + if (_state != _WatchState.WATCHING) return; + + // And the file is different. + var changed = lastStatus == null || !_sameHash(lastStatus.hash, hash); + if (!changed) return; + + var type = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; + _events.add(new WatchEvent(type, file)); }); }); } + /// After the directory listing is complete, this determines which files were + /// removed and then restarts the next poll. + Future _completePoll() { + // Any files that were not seen in the last poll but that we have a + // status for must have been removed. + var removedFiles = _statuses.keys.toSet().difference(_polledFiles); + for (var removed in removedFiles) { + if (_state == _WatchState.WATCHING) { + _events.add(new WatchEvent(ChangeType.REMOVE, removed)); + } + _statuses.remove(removed); + } + + if (_state == _WatchState.SCANNING) { + _state = _WatchState.WATCHING; + _ready.complete(); + } + + // Wait and then poll again. + return new Future.delayed(pollingDelay).then((_) { + if (_checkForCancel()) return; + _poll(); + }); + } + + /// Returns `true` and clears the processing queue if the watcher has been + /// unsubscribed. + bool _checkForCancel() { + if (_state != _WatchState.UNSUBSCRIBED) return false; + + // Don't process any more files. + _filesToProcess.clear(); + return true; + } + /// Calculates the SHA-1 hash of the file at [path]. Future> _hashFile(String path) { return new File(path).readAsBytes().then((bytes) { @@ -159,71 +232,29 @@ class DirectoryWatcher { } } -/// An "event" that is sent to the [_WatchState] FSM to trigger state -/// transitions. -typedef _WatchState _WatchStateEvent(DirectoryWatcher watcher); - -/// The different states that the watcher can be in and the transitions between -/// them. -/// -/// This class defines a finite state machine for keeping track of what the -/// asynchronous file polling is doing. Each instance of this is a state in the -/// machine and its [listen], [cancel], and [finish] fields define the state -/// transitions when those events occur. +/// Enum class for the states that the [DirectoryWatcher] can be in. class _WatchState { - /// The watcher has no subscribers. - static final notWatching = new _WatchState( - listen: (watcher) { - watcher._watch(); - return _WatchState.scanning; - }); - - /// The watcher has subscribers and is scanning for pre-existing files. - static final scanning = new _WatchState( - cancel: (watcher) { - // No longer watching, so create a new incomplete ready future. - watcher._ready = new Completer(); - return _WatchState.cancelling; - }, finish: (watcher) { - watcher._ready.complete(); - return _WatchState.watching; - }, shouldWatch: true); - - /// The watcher was unsubscribed while polling and we're waiting for the poll - /// to finish. - static final cancelling = new _WatchState( - listen: (_) => _WatchState.scanning, - finish: (_) => _WatchState.notWatching); - - /// The watcher has subscribers, we have scanned for pre-existing files and - /// now we're polling for changes. - static final watching = new _WatchState( - cancel: (watcher) { - // No longer watching, so create a new incomplete ready future. - watcher._ready = new Completer(); - return _WatchState.cancelling; - }, finish: (_) => _WatchState.watching, - shouldWatch: true, shouldNotify: true); - - /// Called when the first subscriber to the watcher has been added. - final _WatchStateEvent listen; - - /// Called when all subscriptions on the watcher have been cancelled. - final _WatchStateEvent cancel; - - /// Called when a poll loop has finished. - final _WatchStateEvent finish; - - /// If the directory watcher should be watching the file system while in - /// this state. - final bool shouldWatch; - - /// If a change event should be sent for a file modification while in this - /// state. - final bool shouldNotify; - - _WatchState({this.listen, this.cancel, this.finish, - this.shouldWatch: false, this.shouldNotify: false}); + /// There are no subscribers to the watcher's event stream and no watching + /// is going on. + static const UNSUBSCRIBED = const _WatchState("unsubscribed"); + + /// There are subscribers and the watcher is doing an initial scan of the + /// directory to see which files were already present before watching started. + /// + /// The watcher does not send notifications for changes that occurred while + /// there were no subscribers, or for files already present before watching. + /// The initial scan is used to determine what "before watching" state of + /// the file system was. + static const SCANNING = const _WatchState("scanning"); + + /// There are subscribers and the watcher is polling the directory to look + /// for changes. + static const WATCHING = const _WatchState("watching"); + + /// The name of the state. + final String name; + + const _WatchState(this.name); } class _FileStatus { diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription_test.dart index e9cb4e363..8a3b03159 100644 --- a/pkgs/watcher/test/no_subscription_test.dart +++ b/pkgs/watcher/test/no_subscription_test.dart @@ -23,11 +23,11 @@ main() { // Subscribe to the events. var completer = new Completer(); - var subscription = watcher.events.listen((event) { + var subscription = watcher.events.listen(wrapAsync((event) { expect(event.type, equals(ChangeType.ADD)); expect(event.path, endsWith("file.txt")); completer.complete(); - }); + })); writeFile("file.txt"); @@ -45,20 +45,20 @@ main() { // Then start listening again. schedule(() { completer = new Completer(); - subscription = watcher.events.listen((event) { + subscription = watcher.events.listen(wrapAsync((event) { // We should get an event for the third file, not the one added while // we weren't subscribed. expect(event.type, equals(ChangeType.ADD)); expect(event.path, endsWith("added.txt")); completer.complete(); - }); + })); }); // The watcher will have been cancelled and then resumed in the middle of // its pause between polling loops. That means the second scan to skip // what changed while we were unsubscribed won't happen until after that // delay is done. Wait long enough for that to happen. - schedule(() => new Future.delayed(new Duration(seconds: 1))); + schedule(() => new Future.delayed(watcher.pollingDelay * 2)); // And add a third file. writeFile("added.txt"); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 5053b76ad..65d47197d 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -84,7 +84,7 @@ DirectoryWatcher createWatcher({bool waitForReady}) { // Wait until the scan is finished so that we don't miss changes to files // that could occur before the scan completes. if (waitForReady != false) { - schedule(() => _watcher.ready); + schedule(() => _watcher.ready, "wait for watcher to be ready"); } currentSchedule.onComplete.schedule(() { @@ -107,7 +107,7 @@ void expectEvent(ChangeType type, String path) { // Schedule it so that later file modifications don't occur until after this // event is received. - schedule(() => future); + schedule(() => future, "wait for $type event"); } void expectAddEvent(String path) { @@ -149,14 +149,14 @@ void writeFile(String path, {String contents, bool updateModified}) { var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0); _mockFileModificationTimes[path]++; } - }); + }, "write file $path"); } /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { schedule(() { new File(p.join(_sandboxDir, path)).deleteSync(); - }); + }, "delete file $path"); } /// Schedules renaming a file in the sandbox from [from] to [to]. @@ -172,7 +172,7 @@ void renameFile(String from, String to) { // Manually update the mock modification time for the file. var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); _mockFileModificationTimes[to]++; - }); + }, "rename file $from to $to"); } /// A [Matcher] for [WatchEvent]s. From 954d17fa3bf65e0f57a476663c84f634fc82713c Mon Sep 17 00:00:00 2001 From: "kevmoo@j832.com" Date: Tue, 6 Aug 2013 20:42:04 +0000 Subject: [PATCH 0036/1215] pkg: analysis aided cleanup Removed a lot of warnings and hints when opening many pkg projects in the editor R=gram@google.com Review URL: https://codereview.chromium.org//22284003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@25831 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 1 - pkgs/watcher/test/directory_watcher_test.dart | 4 ---- pkgs/watcher/test/no_subscription_test.dart | 1 - pkgs/watcher/test/ready_test.dart | 2 -- 4 files changed, 8 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 913101b60..c5dd9db60 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -5,7 +5,6 @@ library watcher.directory_watcher; import 'dart:async'; -import 'dart:collection'; import 'dart:io'; import 'package:crypto/crypto.dart'; diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart index 800d54d63..9070179a9 100644 --- a/pkgs/watcher/test/directory_watcher_test.dart +++ b/pkgs/watcher/test/directory_watcher_test.dart @@ -2,11 +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. -import 'dart:async'; -import 'dart:io'; - import 'package:scheduled_test/scheduled_test.dart'; -import 'package:watcher/watcher.dart'; import 'utils.dart'; diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription_test.dart index 8a3b03159..d0a396ac4 100644 --- a/pkgs/watcher/test/no_subscription_test.dart +++ b/pkgs/watcher/test/no_subscription_test.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:io'; import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/test/ready_test.dart b/pkgs/watcher/test/ready_test.dart index dd799ce5a..11b77e02c 100644 --- a/pkgs/watcher/test/ready_test.dart +++ b/pkgs/watcher/test/ready_test.dart @@ -3,10 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:io'; import 'package:scheduled_test/scheduled_test.dart'; -import 'package:watcher/watcher.dart'; import 'utils.dart'; From 976aafa6ea57c6afd982582656b65aa2bffff279 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 14 Aug 2013 18:10:23 +0000 Subject: [PATCH 0037/1215] Support "..." VM frames in pkg/stack_trace. Also include the original stack trace when a parse error occurs. R=rnystrom@google.com Review URL: https://codereview.chromium.org//23133004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@26132 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 6 ++++++ pkgs/stack_trace/lib/src/trace.dart | 21 +++++++++++++-------- pkgs/stack_trace/test/frame_test.dart | 9 +++++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 5a0582c95..3db4ab59e 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -97,6 +97,12 @@ class Frame { /// Parses a string representation of a Dart VM stack frame. factory Frame.parseVM(String frame) { + // The VM sometimes folds multiple stack frames together and replaces them + // with "...". + if (frame == '...') { + return new Frame(new Uri(), null, null, '...'); + } + var match = _vmFrame.firstMatch(frame); if (match == null) { throw new FormatException("Couldn't parse VM stack trace line '$frame'."); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 6b7da758d..863d64ef7 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -72,14 +72,19 @@ class Trace implements StackTrace { /// [trace] should be formatted in the same way as a Dart VM or browser stack /// trace. factory Trace.parse(String trace) { - if (trace.isEmpty) return new Trace([]); - if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); - if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); - if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); - - // Default to parsing the stack trace as a VM trace. This is also hit on IE - // and Safari, where the stack trace is just an empty string (issue 11257). - return new Trace.parseVM(trace); + try { + if (trace.isEmpty) return new Trace([]); + if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); + if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); + + // Default to parsing the stack trace as a VM trace. This is also hit on + // IE and Safari, where the stack trace is just an empty string (issue + // 11257). + return new Trace.parseVM(trace); + } on FormatException catch (error) { + throw new FormatException('${error.message}\nStack trace:\n$trace'); + } } /// Parses a string representation of a Dart VM stack trace. diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 75302a7a8..0be717da0 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -29,6 +29,15 @@ void main() { equals('..bar')); }); + test('parses a folded frame correctly', () { + var frame = new Frame.parseVM('...'); + + expect(frame.member, equals('...')); + expect(frame.uri, equals(new Uri())); + expect(frame.line, isNull); + expect(frame.column, isNull); + }); + test('throws a FormatException for malformed frames', () { expect(() => new Frame.parseVM(''), throwsFormatException); expect(() => new Frame.parseVM('#1'), throwsFormatException); From 35f471795db05676d02ef6c0cde10a1740d05524 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Wed, 14 Aug 2013 21:02:02 +0000 Subject: [PATCH 0038/1215] Handle watching a non-existent directory. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//22999008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@26153 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 27 ++++++-- pkgs/watcher/lib/src/utils.dart | 16 +++++ pkgs/watcher/test/directory_watcher_test.dart | 19 +++++ pkgs/watcher/test/utils.dart | 69 +++++++++++++------ 4 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 pkgs/watcher/lib/src/utils.dart diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index c5dd9db60..eb948f57c 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -11,6 +11,7 @@ import 'package:crypto/crypto.dart'; import 'async_queue.dart'; import 'stat.dart'; +import 'utils.dart'; import 'watch_event.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something @@ -118,19 +119,33 @@ class DirectoryWatcher { _filesToProcess.clear(); _polledFiles.clear(); + endListing() { + assert(_state != _WatchState.UNSUBSCRIBED); + _listSubscription = null; + + // Null tells the queue consumer that we're done listing. + _filesToProcess.add(null); + } + var stream = new Directory(directory).list(recursive: true); _listSubscription = stream.listen((entity) { assert(_state != _WatchState.UNSUBSCRIBED); if (entity is! File) return; _filesToProcess.add(entity.path); - }, onDone: () { - assert(_state != _WatchState.UNSUBSCRIBED); - _listSubscription = null; + }, onError: (error) { + if (isDirectoryNotFoundException(error)) { + // If the directory doesn't exist, we end the listing normally, which + // has the desired effect of marking all files that were in the + // directory as being removed. + endListing(); + return; + } - // Null tells the queue consumer that we're done listing. - _filesToProcess.add(null); - }); + // It's some unknown error. Pipe it over to the event stream so we don't + // take down the whole isolate. + _events.addError(error); + }, onDone: endListing); } /// Processes [file] to determine if it has been modified since the last diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart new file mode 100644 index 000000000..319835ec9 --- /dev/null +++ b/pkgs/watcher/lib/src/utils.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.utils; + +import 'dart:io'; + +/// Returns `true` if [error] is a [DirectoryException] for a missing directory. +bool isDirectoryNotFoundException(error) { + if (error is! DirectoryException) return false; + + // See dartbug.com/12461 and tests/standalone/io/directory_error_test.dart. + var notFoundCode = Platform.operatingSystem == "windows" ? 3 : 2; + return error.osError.errorCode == notFoundCode; +} diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart index 9070179a9..841dd0808 100644 --- a/pkgs/watcher/test/directory_watcher_test.dart +++ b/pkgs/watcher/test/directory_watcher_test.dart @@ -86,4 +86,23 @@ main() { writeFile("a/b/c/d/file.txt"); expectAddEvent("a/b/c/d/file.txt"); }); + + test('watches a directory created after the watcher', () { + // Watch a subdirectory that doesn't exist yet. + createWatcher(dir: "a"); + + // This implicity creates it. + writeFile("a/b/c/d/file.txt"); + expectAddEvent("a/b/c/d/file.txt"); + }); + + test('when the watched directory is deleted, removes all files', () { + writeFile("dir/a.txt"); + writeFile("dir/b.txt"); + + createWatcher(dir: "dir"); + + deleteDir("dir"); + expectRemoveEvents(["dir/a.txt", "dir/b.txt"]); + }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 65d47197d..18bec9728 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -76,9 +76,17 @@ void createSandbox() { /// Normally, this will pause the schedule until the watcher is done scanning /// and is polling for changes. If you pass `false` for [waitForReady], it will /// not schedule this delay. -DirectoryWatcher createWatcher({bool waitForReady}) { +/// +/// If [dir] is provided, watches a subdirectory in the sandbox with that name. +DirectoryWatcher createWatcher({String dir, bool waitForReady}) { + if (dir == null) { + dir = _sandboxDir; + } else { + dir = p.join(_sandboxDir, dir); + } + // Use a short delay to make the tests run quickly. - _watcher = new DirectoryWatcher(_sandboxDir, + _watcher = new DirectoryWatcher(dir, pollingDelay: new Duration(milliseconds: 100)); // Wait until the scan is finished so that we don't miss changes to files @@ -95,31 +103,45 @@ DirectoryWatcher createWatcher({bool waitForReady}) { return _watcher; } -void expectEvent(ChangeType type, String path) { - // Immediately create the future. This ensures we don't register too late and - // drop the event before we receive it. - var future = _watcher.events.elementAt(_nextEvent++).then((event) { - expect(event, new _ChangeMatcher(type, path)); - }); +/// Expects that the next set of events will all be changes of [type] on +/// [paths]. +/// +/// Validates that events are delivered for all paths in [paths], but allows +/// them in any order. +void expectEvents(ChangeType type, Iterable paths) { + var pathSet = paths.map((path) => p.join(_sandboxDir, path)).toSet(); + + // Create an expectation for as many paths as we have. + var futures = []; + + for (var i = 0; i < paths.length; i++) { + // Immediately create the futures. This ensures we don't register too + // late and drop the event before we receive it. + var future = _watcher.events.elementAt(_nextEvent++).then((event) { + expect(event.type, equals(type)); + expect(pathSet, contains(event.path)); + + pathSet.remove(event.path); + }); - // Make sure the schedule is watching it in case it fails. - currentSchedule.wrapFuture(future); + // Make sure the schedule is watching it in case it fails. + currentSchedule.wrapFuture(future); + + futures.add(future); + } // Schedule it so that later file modifications don't occur until after this // event is received. - schedule(() => future, "wait for $type event"); -} - -void expectAddEvent(String path) { - expectEvent(ChangeType.ADD, p.join(_sandboxDir, path)); + schedule(() => Future.wait(futures), + "wait for $type events on ${paths.join(', ')}"); } -void expectModifyEvent(String path) { - expectEvent(ChangeType.MODIFY, p.join(_sandboxDir, path)); -} +void expectAddEvent(String path) => expectEvents(ChangeType.ADD, [path]); +void expectModifyEvent(String path) => expectEvents(ChangeType.MODIFY, [path]); +void expectRemoveEvent(String path) => expectEvents(ChangeType.REMOVE, [path]); -void expectRemoveEvent(String path) { - expectEvent(ChangeType.REMOVE, p.join(_sandboxDir, path)); +void expectRemoveEvents(Iterable paths) { + expectEvents(ChangeType.REMOVE, paths); } /// Schedules writing a file in the sandbox at [path] with [contents]. @@ -175,6 +197,13 @@ void renameFile(String from, String to) { }, "rename file $from to $to"); } +/// Schedules deleting a directory in the sandbox at [path]. +void deleteDir(String path) { + schedule(() { + new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true); + }, "delete directory $path"); +} + /// A [Matcher] for [WatchEvent]s. class _ChangeMatcher extends Matcher { /// The expected change. From 897f32c771badac59bb350566e62338f4fdca53c Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Wed, 14 Aug 2013 21:28:31 +0000 Subject: [PATCH 0039/1215] Fix error handling in watcher. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//23085006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@26156 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index eb948f57c..16a5cf1c5 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -134,18 +134,17 @@ class DirectoryWatcher { if (entity is! File) return; _filesToProcess.add(entity.path); }, onError: (error) { - if (isDirectoryNotFoundException(error)) { - // If the directory doesn't exist, we end the listing normally, which - // has the desired effect of marking all files that were in the - // directory as being removed. - endListing(); - return; + if (!isDirectoryNotFoundException(error)) { + // It's some unknown error. Pipe it over to the event stream so the + // user can see it. + _events.addError(error); } - // It's some unknown error. Pipe it over to the event stream so we don't - // take down the whole isolate. - _events.addError(error); - }, onDone: endListing); + // When an error occurs, we end the listing normally, which has the + // desired effect of marking all files that were in the directory as + // being removed. + endListing(); + }, onDone: endListing, cancelOnError: true); } /// Processes [file] to determine if it has been modified since the last From 1da9e39ae97edcd8cf210668dc26569aca31c9f5 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Wed, 14 Aug 2013 21:46:41 +0000 Subject: [PATCH 0040/1215] Normalize test paths. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//23183006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@26160 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 18bec9728..3bbe0e1a6 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -109,7 +109,10 @@ DirectoryWatcher createWatcher({String dir, bool waitForReady}) { /// Validates that events are delivered for all paths in [paths], but allows /// them in any order. void expectEvents(ChangeType type, Iterable paths) { - var pathSet = paths.map((path) => p.join(_sandboxDir, path)).toSet(); + var pathSet = paths + .map((path) => p.join(_sandboxDir, path)) + .map(p.normalize) + .toSet(); // Create an expectation for as many paths as we have. var futures = []; From bebd98d30738b274d367c5492d23b9a7e85761aa Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 20 Aug 2013 21:41:33 +0000 Subject: [PATCH 0041/1215] Properly parse V8 stack traces that contain the exception description. R=rnystrom@google.com BUG=12151 Review URL: https://codereview.chromium.org//23159007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@26395 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 17 ++++++++++++++-- pkgs/stack_trace/test/trace_test.dart | 29 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 863d64ef7..4aea96023 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -14,6 +14,14 @@ import 'vm_trace.dart'; final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); +/// A RegExp to match V8's stack traces. +/// +/// V8's traces start with a line that's either just "Error" or else is a +/// description of the exception that occurred. That description can be multiple +/// lines, so we just look for any line other than the first that begins with +/// four spaces and "at". +final _v8Trace = new RegExp(r"\n at "); + /// A RegExp to match Firefox's stack traces. /// /// Firefox's trace frames start with the name of the function in which the @@ -74,7 +82,7 @@ class Trace implements StackTrace { factory Trace.parse(String trace) { try { if (trace.isEmpty) return new Trace([]); - if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); @@ -93,7 +101,12 @@ class Trace implements StackTrace { /// Parses a string representation of a Chrome/V8 stack trace. Trace.parseV8(String trace) - : this(trace.split("\n").skip(1).map((line) => new Frame.parseV8(line))); + : this(trace.split("\n").skip(1) + // It's possible that an Exception's description contains a line that + // looks like a V8 trace line, which will screw this up. + // Unfortunately, that's impossible to detect. + .skipWhile((line) => !line.startsWith(" at ")) + .map((line) => new Frame.parseV8(line))); /// Parses a string representation of a Firefox stack trace. Trace.parseFirefox(String trace) diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 92b2b2084..f185d7971 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -61,6 +61,35 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + "Exception: foo\n" + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'Exception: foo\n' + ' bar\n' + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); test('parses a Firefox stack trace correctly', () { From 1ea23b15deda8c6fd72520f40d830b822f195880 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 21 Aug 2013 19:58:07 +0000 Subject: [PATCH 0042/1215] Support IE and Safari stack traces. R=rnystrom@google.com BUG=12380 Review URL: https://codereview.chromium.org//23068019 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@26464 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 12 ++++++++++++ pkgs/stack_trace/lib/src/trace.dart | 21 ++++++++++++++++++++- pkgs/stack_trace/test/trace_test.dart | 16 ++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 3db4ab59e..b2227370e 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -134,6 +134,12 @@ class Frame { } } + /// Parses a string representation of an IE stack frame. + /// + /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't + /// be retrieved. + factory Frame.parseIE(String frame) => new Frame.parseV8(frame); + /// Parses a string representation of a Firefox stack frame. factory Frame.parseFirefox(String frame) { var match = _firefoxFrame.firstMatch(frame); @@ -155,6 +161,12 @@ class Frame { return new Frame(uri, int.parse(match[4]), null, member); } + /// Parses a string representation of a Safari stack frame. + /// + /// Safari 6+ frames look just like Firefox frames. Prior to Safari 6, stack + /// traces can't be retrieved. + factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); + /// Parses this package's string representation of a stack frame. factory Frame.parseFriendly(String frame) { var match = _friendlyFrame.firstMatch(frame); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 4aea96023..46baadaa5 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -82,7 +82,8 @@ class Trace implements StackTrace { factory Trace.parse(String trace) { try { if (trace.isEmpty) return new Trace([]); - if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); + if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + // Valid Safari traces are a superset of valid Firefox traces. if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); @@ -108,11 +109,29 @@ class Trace implements StackTrace { .skipWhile((line) => !line.startsWith(" at ")) .map((line) => new Frame.parseV8(line))); + /// Parses a string representation of an Internet Explorer stack trace. + /// + /// IE10+ traces look just like V8 traces. Prior to IE10, stack traces can't + /// be retrieved. + Trace.parseIE(String trace) + : this.parseV8(trace); + /// Parses a string representation of a Firefox stack trace. Trace.parseFirefox(String trace) : this(trace.trim().split("\n") .map((line) => new Frame.parseFirefox(line))); + /// Parses a string representation of a Safari stack trace. + /// + /// Safari 6+ stack traces look just like Firefox traces, except that they + /// sometimes (e.g. in isolates) have a "[native code]" frame. We just ignore + /// this frame to make the stack format more consistent between browsers. + /// Prior to Safari 6, stack traces can't be retrieved. + Trace.parseSafari(String trace) + : this(trace.trim().split("\n") + .where((line) => line != '[native code]') + .map((line) => new Frame.parseFirefox(line))); + /// Parses this package's a string representation of a stack trace. Trace.parseFriendly(String trace) : this(trace.trim().split("\n") diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index f185d7971..c3ce03906 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -130,6 +130,22 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); + test('.parseSafari', () { + var trace = new Trace.parse( + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + '[native code]'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + expect(trace.frames.length, equals(3)); + }); + test('parses a package:stack_trace stack trace correctly', () { var trace = new Trace.parse( 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' From f33985029af6ac11e339eb53f3a5a8e5dd39c203 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 21 Aug 2013 20:15:01 +0000 Subject: [PATCH 0043/1215] Fix a bad merge in pkg/stack_trace. TBR R=rnystrom@google.com Review URL: https://codereview.chromium.org//22880030 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@26467 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 46baadaa5..19f0a12c5 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -82,9 +82,9 @@ class Trace implements StackTrace { factory Trace.parse(String trace) { try { if (trace.isEmpty) return new Trace([]); - if (trace.startsWith("Error\n")) return new Trace.parseV8(trace); + if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); // Valid Safari traces are a superset of valid Firefox traces. - if (trace.contains(_firefoxTrace)) return new Trace.parseFirefox(trace); + if (trace.contains(_firefoxTrace)) return new Trace.parseSafari(trace); if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); // Default to parsing the stack trace as a VM trace. This is also hit on From 16484efa44f9f9472afd89fcd29f914e56f89563 Mon Sep 17 00:00:00 2001 From: "blois@google.com" Date: Tue, 27 Aug 2013 18:35:08 +0000 Subject: [PATCH 0044/1215] Fixing stack traces on IE10. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//23445005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@26735 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 19f0a12c5..bf14ee2fb 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -19,8 +19,14 @@ final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); /// V8's traces start with a line that's either just "Error" or else is a /// description of the exception that occurred. That description can be multiple /// lines, so we just look for any line other than the first that begins with -/// four spaces and "at". -final _v8Trace = new RegExp(r"\n at "); +/// three or four spaces and "at". +final _v8Trace = new RegExp(r"\n ?at "); + +/// A RegExp to match indidual lines of V8's stack traces. +/// +/// This is intended to filter out the leading exception details of the trace +/// though it is possible for the message to match this as well. +final _v8TraceLine = new RegExp(r" ?at "); /// A RegExp to match Firefox's stack traces. /// @@ -106,7 +112,7 @@ class Trace implements StackTrace { // It's possible that an Exception's description contains a line that // looks like a V8 trace line, which will screw this up. // Unfortunately, that's impossible to detect. - .skipWhile((line) => !line.startsWith(" at ")) + .skipWhile((line) => !line.startsWith(_v8TraceLine)) .map((line) => new Frame.parseV8(line))); /// Parses a string representation of an Internet Explorer stack trace. From b027f42cf926c97aac7b49a49c586f6af5953c72 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 27 Aug 2013 23:13:30 +0000 Subject: [PATCH 0045/1215] Use filtered stacks in pub, barback, and watcher tests. This also exposes more unittest stuff to users of scheduled_test. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//23582003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@26751 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 3bbe0e1a6..656ddf8ed 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -38,6 +38,7 @@ Map _mockFileModificationTimes; void initConfig() { useCompactVMConfiguration(); + filterStacks = true; } /// Creates the sandbox directory the other functions in this library use and From 5998dcf6b8152da2678b12e1590f079e5ce5c699 Mon Sep 17 00:00:00 2001 From: "kathyw@google.com" Date: Wed, 11 Sep 2013 19:28:17 +0000 Subject: [PATCH 0046/1215] One-liners for unittest and matcher. Also had to give a one-liner to stack_trace, to work around a doc generation issue (dartbug.com/13246). R=gram@google.com Review URL: https://codereview.chromium.org//23828006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@27398 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/stack_trace.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index f031f956b..dba95e947 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. /** + * Stack trace generation and parsing. + * * ## Installing ## * * Use [pub][] to install this package. Add the following to your `pubspec.yaml` From 7128a6cf651df438771d25438f8d24c79e795a94 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 20 Sep 2013 19:38:58 +0000 Subject: [PATCH 0047/1215] Support "[as ...]" in V8 stack traces in pkg/stack_trace. BUG=13431 R=jmesserly@google.com Review URL: https://codereview.chromium.org//23533074 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@27720 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 3 ++- pkgs/stack_trace/test/frame_test.dart | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index b2227370e..e82f078b6 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -16,7 +16,8 @@ final _vmFrame = new RegExp( // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 final _v8Frame = new RegExp( - r'^\s*at (?:([^\s].*) \((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); + r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? ' + r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 0be717da0..26a0f21cd 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -74,6 +74,18 @@ void main() { expect(frame.member, equals('')); }); + test('parses a stack frame with [as ...] correctly', () { + // Ignore "[as ...]", since other stack trace formats don't support a + // similar construct. + var frame = new Frame.parseV8(" at VW.call\$0 [as call\$4] " + "(http://pub.dartlang.org/stuff.dart.js:560:28)"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseV8(' at $member (foo:0:0)').member; From d4088af0d771e6265acc41f0dbf5b6ff2b0cfb25 Mon Sep 17 00:00:00 2001 From: "iposva@google.com" Date: Tue, 24 Sep 2013 17:32:40 +0000 Subject: [PATCH 0048/1215] - Use simplified token location call where appropriate. R=asiva@google.com, hausner@google.com, mlippautz@google.com Review URL: https://codereview.chromium.org//23850014 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@27833 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 14 +++++++++++--- pkgs/stack_trace/test/frame_test.dart | 2 -- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index e82f078b6..b7937f799 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -11,7 +11,7 @@ import 'trace.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) final _vmFrame = new RegExp( - r'^#\d+\s+([^\s].*) \((.+):(\d+):(\d+)\)$'); + r'^#\d+\s+([^\s].*) \((.+?):(\d+)(?::(\d+))?\)$'); // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 @@ -109,9 +109,17 @@ class Frame { throw new FormatException("Couldn't parse VM stack trace line '$frame'."); } - var uri = Uri.parse(match[2]); + // Get the pieces out of the regexp match. Function, URI and line should + // always be found. The column is optional. var member = match[1].replaceAll("", ""); - return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); + var uri = Uri.parse(match[2]); + var line = int.parse(match[3]); + var col = null; + var col_match = match[4]; + if (col_match != null) { + col = int.parse(col_match); + } + return new Frame(uri, line, col, member); } /// Parses a string representation of a Chrome/V8 stack frame. diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 26a0f21cd..9cbff1460 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -44,8 +44,6 @@ void main() { expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'), throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart:10)'), - throwsFormatException); expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), throwsFormatException); expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), From e663f144c7f1e99fa08f7352954195e82370cc02 Mon Sep 17 00:00:00 2001 From: "iposva@google.com" Date: Tue, 24 Sep 2013 20:54:26 +0000 Subject: [PATCH 0049/1215] Address codereview comments: - Update variable names. - Add test case for column-free stack frame. Review URL: https://codereview.chromium.org//24395014 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@27852 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 8 ++++---- pkgs/stack_trace/test/frame_test.dart | 12 +++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index b7937f799..6325f374c 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -114,10 +114,10 @@ class Frame { var member = match[1].replaceAll("", ""); var uri = Uri.parse(match[2]); var line = int.parse(match[3]); - var col = null; - var col_match = match[4]; - if (col_match != null) { - col = int.parse(col_match); + var column = null; + var columnMatch = match[4]; + if (columnMatch != null) { + col = int.parse(columnMatch); } return new Frame(uri, line, col, member); } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 9cbff1460..62cfd2ee0 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -10,7 +10,7 @@ import 'package:unittest/unittest.dart'; void main() { group('.parseVM', () { - test('parses a stack frame correctly', () { + test('parses a stack frame with column correctly', () { var frame = new Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:42:21)"); expect(frame.uri, @@ -20,6 +20,16 @@ void main() { expect(frame.member, equals('Foo._bar')); }); + test('parses a stack frame without column correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart:24)"); + expect(frame.uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, equals(24)); + expect(frame.column, null); + expect(frame.member, equals('Foo._bar')); + }); + test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseVM('#0 $member (foo:0:0)').member; From 3ddba308401e7094306f1fc2eac6a81397954343 Mon Sep 17 00:00:00 2001 From: "iposva@google.com" Date: Tue, 24 Sep 2013 21:15:04 +0000 Subject: [PATCH 0050/1215] - Fix build. Review URL: https://codereview.chromium.org//24249010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@27854 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 6325f374c..797bef173 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -117,9 +117,9 @@ class Frame { var column = null; var columnMatch = match[4]; if (columnMatch != null) { - col = int.parse(columnMatch); + column = int.parse(columnMatch); } - return new Frame(uri, line, col, member); + return new Frame(uri, line, column, member); } /// Parses a string representation of a Chrome/V8 stack frame. From 18200151eab235cc5b4a27e672164f09ca2b4981 Mon Sep 17 00:00:00 2001 From: "whesse@google.com" Date: Thu, 3 Oct 2013 13:12:10 +0000 Subject: [PATCH 0051/1215] Use Directory.systemTemp getter in pkg subdirectory of repository. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//25731003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@28218 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 656ddf8ed..28d57b05c 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -46,7 +46,7 @@ void initConfig() { /// /// This should usually be called by [setUp]. void createSandbox() { - var dir = new Directory("").createTempSync(); + var dir = Directory.systemTemp.createTempSync('watcher_test_'); _sandboxDir = dir.path; _mockFileModificationTimes = new Map(); From 41732d43baefcd4509306770375540316c53b74d Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Tue, 8 Oct 2013 00:14:44 +0000 Subject: [PATCH 0052/1215] Bump wait time for watcher test. This is to see if it makes the test less flaky on the bots, in particular the ARM ones. BUG=https://code.google.com/p/dart/issues/detail?id=13705 R=nweiz@google.com Review URL: https://codereview.chromium.org//26398002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@28341 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/no_subscription_test.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription_test.dart index d0a396ac4..2e7b6d3ff 100644 --- a/pkgs/watcher/test/no_subscription_test.dart +++ b/pkgs/watcher/test/no_subscription_test.dart @@ -57,7 +57,10 @@ main() { // its pause between polling loops. That means the second scan to skip // what changed while we were unsubscribed won't happen until after that // delay is done. Wait long enough for that to happen. - schedule(() => new Future.delayed(watcher.pollingDelay * 2)); + // + // We're doing * 4 here because that seems to give the slower bots enough + // time for this to complete. + schedule(() => new Future.delayed(watcher.pollingDelay * 4)); // And add a third file. writeFile("added.txt"); From 7fd14c90f3b58462612b60b2ebed3c39b5fcf2b1 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" Date: Fri, 11 Oct 2013 12:02:20 +0000 Subject: [PATCH 0053/1215] Adapt streams for additional stackTrace argument. R=lrn@google.com Review URL: https://codereview.chromium.org//25094002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@28511 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 16a5cf1c5..3b39f5a3e 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -133,11 +133,11 @@ class DirectoryWatcher { if (entity is! File) return; _filesToProcess.add(entity.path); - }, onError: (error) { + }, onError: (error, StackTrace stackTrace) { if (!isDirectoryNotFoundException(error)) { // It's some unknown error. Pipe it over to the event stream so the // user can see it. - _events.addError(error); + _events.addError(error, stackTrace); } // When an error occurs, we end the listing normally, which has the From 9dd08971d6f0a970fd9ae098082e2dac5d1832d8 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 17 Oct 2013 18:09:58 +0000 Subject: [PATCH 0054/1215] Work around issue 14125 in stack_trace by adding a dummy setter. R=rnystrom@google.com BUG=13945 Review URL: https://codereview.chromium.org//27416002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@28811 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/lazy_trace.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index ae56b5fc3..874123ef4 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -30,4 +30,7 @@ class LazyTrace implements Trace { Trace foldFrames(bool predicate(frame)) => new LazyTrace(() => _trace.foldFrames(predicate)); String toString() => _trace.toString(); + + // Work around issue 14075. + set frames(_) => throw new UnimplementedError(); } From 3903706c6c80247258496e04d8cc0f58b86fcb3f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 18 Oct 2013 21:55:41 +0000 Subject: [PATCH 0055/1215] Make stack frames without columns print correctly. This works around issue 14233. R=alanknight@google.com Review URL: https://codereview.chromium.org//29323004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@28884 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 5 +++-- pkgs/stack_trace/test/frame_test.dart | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 797bef173..b6b596232 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -28,7 +28,7 @@ final _firefoxFrame = new RegExp( // foo/bar.dart 10:11 in Foo._bar // http://dartlang.org/foo/bar.dart in Foo._bar final _friendlyFrame = new RegExp( - r'^([^\s]+)(?: (\d+):(\d+))?\s+([^\d][^\s]*)$'); + r'^([^\s]+)(?: (\d+)(?::(\d+))?)?\s+([^\d][^\s]*)$'); final _initialDot = new RegExp(r"^\."); @@ -78,7 +78,8 @@ class Frame { /// A human-friendly description of the code location. String get location { - if (line == null || column == null) return library; + if (line == null) return library; + if (column == null) return '$library $line'; return '$library $line:$column'; } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 62cfd2ee0..75b92a473 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -233,6 +233,15 @@ void main() { expect(frame.member, equals('Foo..bar')); }); + test('parses a stack frame with no line correctly', () { + var frame = new Frame.parseFriendly( + "http://dartlang.org/foo/bar.dart 10 Foo..bar"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, isNull); + expect(frame.member, equals('Foo..bar')); + }); + test('parses a stack frame with a relative path correctly', () { var frame = new Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); expect(frame.uri, equals( @@ -321,5 +330,10 @@ void main() { '(dart:core/uri.dart:5:10)').toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); + + test('prints a frame without a column correctly', () { + expect(new Frame.parseVM('#0 Foo (dart:core/uri.dart:5)').toString(), + equals('dart:core/uri.dart 5 in Foo')); + }); }); } From 05bcd20f81074d014c972785303fe2aa3774fa61 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 18 Oct 2013 22:57:06 +0000 Subject: [PATCH 0056/1215] Properly parse friendly stack traces without columns. Review URL: https://codereview.chromium.org//28783006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@28892 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 10 ++++------ pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/test/frame_test.dart | 12 ++++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index b6b596232..0b4f5771b 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -23,7 +23,7 @@ final _v8Frame = new RegExp( // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 final _firefoxFrame = new RegExp( - r'^([^@(/]*)(?:\(.*\))?(/[^<]*"; - } else if (match[2] != null) { - member = "$member."; - } + member += new List.filled('/'.allMatches(match[2]).length, ".").join(); + if (member == '') member = ''; + // Some Firefox members have initial dots. We remove them for consistency // with other platforms. member = member.replaceFirst(_initialDot, ''); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index bf14ee2fb..95d41ad47 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -36,7 +36,7 @@ final _v8TraceLine = new RegExp(r" ?at "); final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@"); /// A RegExp to match this package's stack traces. -final _friendlyTrace = new RegExp(r"^[^\s]+( \d+:\d+)?\s+[^\s]+($|\n)"); +final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?\s+[^\s]+($|\n)"); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 75b92a473..ab7c40122 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -202,6 +202,18 @@ void main() { expect(frame.member, equals("foo.")); }); + test('parses a deeply-nested anonymous stack frame with parameters ' + 'correctly', () { + var frame = new Frame.parseFirefox( + '.convertDartClosureToJS/\$function.")); + }); + test('throws a FormatException for malformed frames', () { expect(() => new Frame.parseFirefox(''), throwsFormatException); expect(() => new Frame.parseFirefox('.foo'), throwsFormatException); From f2807baf801592d5a8baec9e5e653d117ed987c2 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Thu, 24 Oct 2013 12:17:20 +0000 Subject: [PATCH 0057/1215] Remove FileException, DirectoryException and LinkException from dart:io and use FileSystemException instaed. BUG=https://code.google.com/p/dart/issues/detail?id=12461 R=nweiz@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//26968003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29168 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/utils.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 319835ec9..3d00c0843 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -6,9 +6,10 @@ library watcher.utils; import 'dart:io'; -/// Returns `true` if [error] is a [DirectoryException] for a missing directory. +/// Returns `true` if [error] is a [FileSystemException] for a missing +/// directory. bool isDirectoryNotFoundException(error) { - if (error is! DirectoryException) return false; + if (error is! FileSystemException) return false; // See dartbug.com/12461 and tests/standalone/io/directory_error_test.dart. var notFoundCode = Platform.operatingSystem == "windows" ? 3 : 2; From 2ff292e83b1fa9e6174ed921b87ab3e06819d3e6 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 28 Oct 2013 21:50:23 +0000 Subject: [PATCH 0058/1215] Support Safari 6.1's new stack trace format in pkg/stack_trace. R=rnystrom@google.com BUG=14534 Review URL: https://codereview.chromium.org//48273005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@29399 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 28 +++++++++++++--- pkgs/stack_trace/lib/src/trace.dart | 48 +++++++++++++++++++++++---- pkgs/stack_trace/test/frame_test.dart | 47 ++++++++++++++++++++++++++ pkgs/stack_trace/test/trace_test.dart | 16 ++++++++- 4 files changed, 127 insertions(+), 12 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 0b4f5771b..b15f65140 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -19,6 +19,10 @@ final _v8Frame = new RegExp( r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? ' r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); +/// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 +/// http://pub.dartlang.org/stuff.dart.js:560:28 +final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$"); + // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 @@ -169,11 +173,27 @@ class Frame { return new Frame(uri, int.parse(match[4]), null, member); } - /// Parses a string representation of a Safari stack frame. + /// Parses a string representation of a Safari 6.0 stack frame. /// - /// Safari 6+ frames look just like Firefox frames. Prior to Safari 6, stack - /// traces can't be retrieved. - factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); + /// Safari 6.0 frames look just like Firefox frames. Prior to Safari 6.0, + /// stack traces can't be retrieved. + factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame); + + /// Parses a string representation of a Safari 6.1+ stack frame. + factory Frame.parseSafari6_1(String frame) { + var match = _safariFrame.firstMatch(frame); + if (match == null) { + throw new FormatException( + "Couldn't parse Safari stack trace line '$frame'."); + } + + var uri = Uri.parse(match[2]); + var member = match[1]; + if (member == null) member = ''; + var line = match[3] == '' ? null : int.parse(match[3]); + var column = match[4] == '' ? null : int.parse(match[4]); + return new Frame(uri, line, column, member); + } /// Parses this package's string representation of a stack frame. factory Frame.parseFriendly(String frame) { diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 95d41ad47..c3db43ecd 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -28,6 +28,19 @@ final _v8Trace = new RegExp(r"\n ?at "); /// though it is possible for the message to match this as well. final _v8TraceLine = new RegExp(r" ?at "); +/// A RegExp to match Safari's stack traces. +/// +/// Prior to version 6, Safari's stack traces were uncapturable. In v6 they were +/// almost identical to Firefox traces, and so are handled by the Firefox code. +/// In v6.1+, they have their own format that's similar to Firefox but distinct +/// enough to warrant handling separately. +/// +/// Most notably, Safari traces occasionally don't include the initial method +/// name followed by "@", and they always have both the line and column number +/// (or just a trailing colon if no column number is available). +final _safariTrace = new RegExp(r"^([0-9A-Za-z_$]*@)?.*:\d*:\d*$", + multiLine: true); + /// A RegExp to match Firefox's stack traces. /// /// Firefox's trace frames start with the name of the function in which the @@ -36,7 +49,8 @@ final _v8TraceLine = new RegExp(r" ?at "); final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@"); /// A RegExp to match this package's stack traces. -final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?\s+[^\s]+($|\n)"); +final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?[ \t]+[^\s]+$", + multiLine: true); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { @@ -89,9 +103,15 @@ class Trace implements StackTrace { try { if (trace.isEmpty) return new Trace([]); if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); - // Valid Safari traces are a superset of valid Firefox traces. - if (trace.contains(_firefoxTrace)) return new Trace.parseSafari(trace); - if (trace.contains(_friendlyTrace)) return new Trace.parseFriendly(trace); + // Safari 6.1+ traces could be misinterpreted as Firefox traces, so we + // check for them first. + if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace); + // Safari 6.0 traces are a superset of Firefox traces, so we parse those + // two together. + if (trace.contains(_firefoxTrace)) return new Trace.parseSafari6_0(trace); + if (trace.contains(_friendlyTrace)) { + return new Trace.parseFriendly(trace); + } // Default to parsing the stack trace as a VM trace. This is also hit on // IE and Safari, where the stack trace is just an empty string (issue @@ -129,11 +149,25 @@ class Trace implements StackTrace { /// Parses a string representation of a Safari stack trace. /// - /// Safari 6+ stack traces look just like Firefox traces, except that they + /// This will automatically decide between [parseSafari6_0] and + /// [parseSafari6_1] based on the contents of [trace]. + factory Trace.parseSafari(String trace) { + if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace); + return new Trace.parseSafari6_0(trace); + } + + /// Parses a string representation of a Safari 6.1+ stack trace. + Trace.parseSafari6_1(String trace) + : this(trace.trim().split("\n") + .map((line) => new Frame.parseSafari6_1(line))); + + /// Parses a string representation of a Safari 6.0 stack trace. + /// + /// Safari 6.0 stack traces look just like Firefox traces, except that they /// sometimes (e.g. in isolates) have a "[native code]" frame. We just ignore /// this frame to make the stack format more consistent between browsers. - /// Prior to Safari 6, stack traces can't be retrieved. - Trace.parseSafari(String trace) + /// Prior to Safari 6.0, stack traces can't be retrieved. + Trace.parseSafari6_0(String trace) : this(trace.trim().split("\n") .where((line) => line != '[native code]') .map((line) => new Frame.parseFirefox(line))); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index ab7c40122..97cf48a22 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -226,6 +226,53 @@ void main() { }); }); + group('.parseSafari6_1', () { + test('parses a simple stack frame correctly', () { + var frame = new Frame.parseSafari6_1( + "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('foo\$bar')); + }); + + test('parses an anonymous stack frame correctly', () { + var frame = new Frame.parseSafari6_1( + "http://dartlang.org/foo/bar.dart:10:11"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('')); + }); + + test('parses a stack frame with no line correctly', () { + var frame = new Frame.parseSafari6_1( + "foo\$bar@http://dartlang.org/foo/bar.dart::11"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, isNull); + expect(frame.column, equals(11)); + expect(frame.member, equals('foo\$bar')); + }); + + test('parses a stack frame with no column correctly', () { + var frame = new Frame.parseSafari6_1( + "foo\$bar@http://dartlang.org/foo/bar.dart:10:"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, isNull); + expect(frame.member, equals('foo\$bar')); + }); + + test('parses a stack frame with no line or column correctly', () { + var frame = new Frame.parseSafari6_1( + "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('foo\$bar')); + }); + }); + group('.parseFriendly', () { test('parses a simple stack frame correctly', () { var frame = new Frame.parseFriendly( diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index c3ce03906..ad916f156 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -130,7 +130,7 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); - test('.parseSafari', () { + test('parses a Safari 6.0 stack trace correctly', () { var trace = new Trace.parse( 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' @@ -146,6 +146,20 @@ void main() { expect(trace.frames.length, equals(3)); }); + test('parses a Safari 6.1 stack trace correctly', () { + var trace = new Trace.parse( + 'http://pub.dartlang.org/stuff.js:42:43\n' + 'zip@http://pub.dartlang.org/stuff.js:0:1\n' + 'zip\$zap@http://pub.dartlang.org/thing.js:1:2'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + }); + test('parses a package:stack_trace stack trace correctly', () { var trace = new Trace.parse( 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' From 5bd235d02ede233fdb74d488529a5dd825fd3a51 Mon Sep 17 00:00:00 2001 From: "whesse@google.com" Date: Wed, 30 Oct 2013 15:17:01 +0000 Subject: [PATCH 0059/1215] Remove uses of Options from pkg, samples, tests, and third_party directories. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//52573002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29552 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/example/watch.dart | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index 235578dd6..aba127d6d 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -10,15 +10,14 @@ import 'dart:io'; import 'package:path/path.dart' as p; import 'package:watcher/watcher.dart'; -main() { - var args = new Options().arguments; - if (args.length != 1) { +main(List arguments) { + if (arguments.length != 1) { print("Usage: watch "); return; } - var watcher = new DirectoryWatcher(p.absolute(args[0])); + var watcher = new DirectoryWatcher(p.absolute(arguments[0])); watcher.events.listen((event) { print(event); }); -} \ No newline at end of file +} From 1efdfcbf104c87a3f92ef4e8c8bdd5c8a9b56afa Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Thu, 31 Oct 2013 02:43:00 +0000 Subject: [PATCH 0060/1215] fix csslib and watcher warnings R=rnystrom@google.com, terry@google.com Review URL: https://codereview.chromium.org//50703011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29632 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 3b39f5a3e..679e227e8 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -156,7 +156,7 @@ class DirectoryWatcher { if (file == null) return _completePoll(); return getModificationTime(file).then((modified) { - if (_checkForCancel()) return; + if (_checkForCancel()) return null; var lastStatus = _statuses[file]; @@ -164,7 +164,7 @@ class DirectoryWatcher { if (lastStatus != null && lastStatus.modified == modified) { // The file is still here. _polledFiles.add(file); - return; + return null; } return _hashFile(file).then((hash) { From a867a3471d2f380d50eca97e2f2ec06ac69651db Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 6 Nov 2013 03:27:58 +0000 Subject: [PATCH 0061/1215] add versions and constraints for packages and samples - all packages at 0.9.0, except "analyzer" which had a version already - dependencies at ">=0.9.0 <0.10.0" except analyzer is ">=0.10.0 <0.11.0" - sdk constraint ">=1.0.0 <2.0.0" R=sigmund@google.com Review URL: https://codereview.chromium.org//59763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@29957 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/pubspec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index b672df7ff..33af86741 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,14 @@ name: stack_trace +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > A package for manipulating stack traces and printing them readably. dependencies: - path: any + path: ">=0.9.0 <0.10.0" dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=1.0.0 <2.0.0" From 0abea1bfb5a8b5ce0f4877879b7c4633ddc68431 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 6 Nov 2013 03:27:58 +0000 Subject: [PATCH 0062/1215] add versions and constraints for packages and samples - all packages at 0.9.0, except "analyzer" which had a version already - dependencies at ">=0.9.0 <0.10.0" except analyzer is ">=0.10.0 <0.11.0" - sdk constraint ">=1.0.0 <2.0.0" R=sigmund@google.com Review URL: https://codereview.chromium.org//59763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29957 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 263832efb..6b8faca8e 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,4 +1,5 @@ name: watcher +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -6,8 +7,10 @@ description: > of directories and notifies you when files have been added, removed, or modified. dependencies: - crypto: any - path: any + crypto: ">=0.9.0 <0.10.0" + path: ">=0.9.0 <0.10.0" dev_dependencies: - scheduled_test: any - unittest: any + scheduled_test: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=1.0.0 <2.0.0" From 2e46c8d7067487a8b2bc2b8c2e917f2464d84eb0 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 6 Nov 2013 09:09:18 +0000 Subject: [PATCH 0063/1215] Revert "add versions and constraints for packages and samples" This is currently blocking us from testing samples. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//59513007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@29960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/pubspec.yaml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 33af86741..b672df7ff 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,14 +1,11 @@ name: stack_trace -version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > A package for manipulating stack traces and printing them readably. dependencies: - path: ">=0.9.0 <0.10.0" + path: any dev_dependencies: - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + unittest: any From db84ec8e7b68f8e1311deb7e4b81b1c8c0b5bf57 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 6 Nov 2013 09:09:18 +0000 Subject: [PATCH 0064/1215] Revert "add versions and constraints for packages and samples" This is currently blocking us from testing samples. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//59513007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 6b8faca8e..263832efb 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,4 @@ name: watcher -version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -7,10 +6,8 @@ description: > of directories and notifies you when files have been added, removed, or modified. dependencies: - crypto: ">=0.9.0 <0.10.0" - path: ">=0.9.0 <0.10.0" + crypto: any + path: any dev_dependencies: - scheduled_test: ">=0.9.0 <0.10.0" - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + scheduled_test: any + unittest: any From c3ab9489d6a7ec85147c59bf03a86dd9a23cae71 Mon Sep 17 00:00:00 2001 From: "dgrove@google.com" Date: Wed, 6 Nov 2013 18:28:22 +0000 Subject: [PATCH 0065/1215] Re-land r29957 (add versions and constraints for packages and samples), with SDK constraints bumped from 1.0.0 to 0.8.10+6 . R=ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//62473002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@29986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/pubspec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index b672df7ff..63a1bf9c1 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,14 @@ name: stack_trace +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > A package for manipulating stack traces and printing them readably. dependencies: - path: any + path: ">=0.9.0 <0.10.0" dev_dependencies: - unittest: any + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=0.8.10+6 <2.0.0" From c8c3d49c28f603bae92edcc63307d43184645003 Mon Sep 17 00:00:00 2001 From: "dgrove@google.com" Date: Wed, 6 Nov 2013 18:28:22 +0000 Subject: [PATCH 0066/1215] Re-land r29957 (add versions and constraints for packages and samples), with SDK constraints bumped from 1.0.0 to 0.8.10+6 . R=ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//62473002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@29986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 263832efb..b95c7efdf 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,4 +1,5 @@ name: watcher +version: 0.9.0 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -6,8 +7,10 @@ description: > of directories and notifies you when files have been added, removed, or modified. dependencies: - crypto: any - path: any + crypto: ">=0.9.0 <0.10.0" + path: ">=0.9.0 <0.10.0" dev_dependencies: - scheduled_test: any - unittest: any + scheduled_test: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=0.8.10+6 <2.0.0" From 55901f418d1525632c44c8d8f115337de1335667 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 7 Nov 2013 22:41:42 +0000 Subject: [PATCH 0067/1215] Properly parse jsshell and d8 stack frames. It turns out jsshell and d8 can use native paths where Firefox and Chrome usually use URLs. This CL accommodates that. R=rnystrom@google.com BUG=14897 Review URL: https://codereview.chromium.org//63603005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30079 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 40 ++++++++++-- pkgs/stack_trace/test/frame_test.dart | 92 +++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index b15f65140..3bead03ba 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -136,14 +136,17 @@ class Frame { // V8 stack frames can be in two forms. if (match[2] != null) { - // The first form looks like " at FUNCTION (URI:LINE:COL)" - var uri = Uri.parse(match[2]); + // The first form looks like " at FUNCTION (PATH:LINE:COL)". PATH is + // usually an absolute URL, but it can be a path if the stack frame came + // from d8. + var uri = _uriOrPathToUri(match[2]); var member = match[1].replaceAll("", ""); return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); } else { - // The second form looks like " at URI:LINE:COL", and is used for - // anonymous functions. - var uri = Uri.parse(match[5]); + // The second form looks like " at PATH:LINE:COL", and is used for + // anonymous functions. PATH is usually an absolute URL, but it can be a + // path if the stack frame came from d8. + var uri = _uriOrPathToUri(match[5]); return new Frame(uri, int.parse(match[6]), int.parse(match[7]), ""); } } @@ -162,7 +165,8 @@ class Frame { "Couldn't parse Firefox stack trace line '$frame'."); } - var uri = Uri.parse(match[3]); + // Normally this is a URI, but in a jsshell trace it can be a path. + var uri = _uriOrPathToUri(match[3]); var member = match[1]; member += new List.filled('/'.allMatches(match[2]).length, ".").join(); if (member == '') member = ''; @@ -215,6 +219,30 @@ class Frame { return new Frame(uri, line, column, match[4]); } + /// A regular expression matching an absolute URI. + static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); + + /// A regular expression matching a Windows path. + static final _windowsRegExp = new RegExp(r'^([a-zA-Z]:[\\/]|\\\\)'); + + /// Converts [uriOrPath], which can be a URI, a Windows path, or a Posix path, + /// to a URI (absolute if possible). + static Uri _uriOrPathToUri(String uriOrPath) { + if (uriOrPath.contains(_uriRegExp)) { + return Uri.parse(uriOrPath); + } else if (uriOrPath.contains(_windowsRegExp)) { + return new Uri.file(uriOrPath, windows: true); + } else if (uriOrPath.startsWith('/')) { + return new Uri.file(uriOrPath, windows: false); + } + + // As far as I've seen, Firefox and V8 both always report absolute paths in + // their stack frames. However, if we do get a relative path, we should + // handle it gracefully. + if (uriOrPath.contains('\\')) return path.windows.toUri(uriOrPath); + return Uri.parse(uriOrPath); + } + Frame(this.uri, this.line, this.column, this.member); String toString() => '$location in $member'; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 97cf48a22..87a8c4dc7 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -72,6 +72,52 @@ void main() { expect(frame.member, equals('VW.call\$0')); }); + test('parses a stack frame with an absolute POSIX path correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + "(/path/to/stuff.dart.js:560:28)"); + expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with an absolute Windows path correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + r"(C:\path\to\stuff.dart.js:560:28)"); + expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a Windows UNC path correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + r"(\\mount\path\to\stuff.dart.js:560:28)"); + expect(frame.uri, + equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a relative POSIX path correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + "(path/to/stuff.dart.js:560:28)"); + expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a relative Windows path correctly', () { + var frame = new Frame.parseV8(" at VW.call\$0 " + r"(path\to\stuff.dart.js:560:28)"); + expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + test('parses an anonymous stack frame correctly', () { var frame = new Frame.parseV8( " at http://pub.dartlang.org/stuff.dart.js:560:28"); @@ -135,6 +181,52 @@ void main() { expect(frame.member, equals('VW.call\$0')); }); + test('parses a stack frame with an absolute POSIX path correctly', () { + var frame = new Frame.parseFirefox( + ".VW.call\$0@/path/to/stuff.dart.js:560"); + expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with an absolute Windows path correctly', () { + var frame = new Frame.parseFirefox( + r".VW.call$0@C:\path\to\stuff.dart.js:560"); + expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a Windows UNC path correctly', () { + var frame = new Frame.parseFirefox( + r".VW.call$0@\\mount\path\to\stuff.dart.js:560"); + expect(frame.uri, + equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a relative POSIX path correctly', () { + var frame = new Frame.parseFirefox( + ".VW.call\$0@path/to/stuff.dart.js:560"); + expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + + test('parses a stack frame with a relative Windows path correctly', () { + var frame = new Frame.parseFirefox( + r".VW.call$0@path\to\stuff.dart.js:560"); + expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, isNull); + expect(frame.member, equals('VW.call\$0')); + }); + test('parses a simple anonymous stack frame correctly', () { var frame = new Frame.parseFirefox( "@http://pub.dartlang.org/stuff.dart.js:560"); From 90e0361e775586d496ea5bfc83f9a25c09766820 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 7 Nov 2013 22:49:18 +0000 Subject: [PATCH 0068/1215] Wrap Directory.watch on linux for the watcher package. R=rnystrom@google.com BUG=14428 Review URL: https://codereview.chromium.org//46843003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30081 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 264 ++-------------- .../lib/src/directory_watcher/linux.dart | 298 ++++++++++++++++++ .../lib/src/directory_watcher/polling.dart | 217 +++++++++++++ .../src/directory_watcher/resubscribable.dart | 79 +++++ pkgs/watcher/lib/src/utils.dart | 56 ++++ pkgs/watcher/lib/watcher.dart | 1 + .../test/directory_watcher/linux_test.dart | 62 ++++ .../test/directory_watcher/polling_test.dart | 39 +++ .../test/directory_watcher/shared.dart | 222 +++++++++++++ pkgs/watcher/test/directory_watcher_test.dart | 108 ------- .../test/no_subscription/linux_test.dart | 20 ++ .../test/no_subscription/polling_test.dart | 19 ++ .../shared.dart} | 22 +- pkgs/watcher/test/ready/linux_test.dart | 20 ++ pkgs/watcher/test/ready/polling_test.dart | 19 ++ .../{ready_test.dart => ready/shared.dart} | 10 +- pkgs/watcher/test/utils.dart | 199 ++++++++---- 17 files changed, 1213 insertions(+), 442 deletions(-) create mode 100644 pkgs/watcher/lib/src/directory_watcher/linux.dart create mode 100644 pkgs/watcher/lib/src/directory_watcher/polling.dart create mode 100644 pkgs/watcher/lib/src/directory_watcher/resubscribable.dart create mode 100644 pkgs/watcher/test/directory_watcher/linux_test.dart create mode 100644 pkgs/watcher/test/directory_watcher/polling_test.dart create mode 100644 pkgs/watcher/test/directory_watcher/shared.dart delete mode 100644 pkgs/watcher/test/directory_watcher_test.dart create mode 100644 pkgs/watcher/test/no_subscription/linux_test.dart create mode 100644 pkgs/watcher/test/no_subscription/polling_test.dart rename pkgs/watcher/test/{no_subscription_test.dart => no_subscription/shared.dart} (73%) create mode 100644 pkgs/watcher/test/ready/linux_test.dart create mode 100644 pkgs/watcher/test/ready/polling_test.dart rename pkgs/watcher/test/{ready_test.dart => ready/shared.dart} (95%) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 679e227e8..4484c2b77 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -7,18 +7,15 @@ library watcher.directory_watcher; import 'dart:async'; import 'dart:io'; -import 'package:crypto/crypto.dart'; - -import 'async_queue.dart'; -import 'stat.dart'; -import 'utils.dart'; import 'watch_event.dart'; +import 'directory_watcher/linux.dart'; +import 'directory_watcher/polling.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something /// in the directory has changed. -class DirectoryWatcher { +abstract class DirectoryWatcher { /// The directory whose contents are being monitored. - final String directory; + String get directory; /// The broadcast [Stream] of events that have occurred to files in /// [directory]. @@ -26,10 +23,12 @@ class DirectoryWatcher { /// Changes will only be monitored while this stream has subscribers. Any /// file changes that occur during periods when there are no subscribers /// will not be reported the next time a subscriber is added. - Stream get events => _events.stream; - StreamController _events; + Stream get events; - _WatchState _state = _WatchState.UNSUBSCRIBED; + /// Whether the watcher is initialized and watching for file changes. + /// + /// This is true if and only if [ready] is complete. + bool get isReady; /// A [Future] that completes when the watcher is initialized and watching /// for file changes. @@ -41,241 +40,20 @@ class DirectoryWatcher { /// /// If the watcher is already monitoring, this returns an already complete /// future. - Future get ready => _ready.future; - Completer _ready = new Completer(); - - /// The amount of time the watcher pauses between successive polls of the - /// directory contents. - final Duration pollingDelay; - - /// The previous status of the files in the directory. - /// - /// Used to tell which files have been modified. - final _statuses = new Map(); - - /// The subscription used while [directory] is being listed. - /// - /// Will be `null` if a list is not currently happening. - StreamSubscription _listSubscription; - - /// The queue of files waiting to be processed to see if they have been - /// modified. - /// - /// Processing a file is asynchronous, as is listing the directory, so the - /// queue exists to let each of those proceed at their own rate. The lister - /// will enqueue files as quickly as it can. Meanwhile, files are dequeued - /// and processed sequentially. - AsyncQueue _filesToProcess; - - /// The set of files that have been seen in the current directory listing. - /// - /// Used to tell which files have been removed: files that are in [_statuses] - /// but not in here when a poll completes have been removed. - final _polledFiles = new Set(); + Future get ready; /// Creates a new [DirectoryWatcher] monitoring [directory]. /// - /// If [pollingDelay] is passed, it specifies the amount of time the watcher - /// will pause between successive polls of the directory contents. Making - /// this shorter will give more immediate feedback at the expense of doing - /// more IO and higher CPU usage. Defaults to one second. - DirectoryWatcher(this.directory, {Duration pollingDelay}) - : pollingDelay = pollingDelay != null ? pollingDelay : - new Duration(seconds: 1) { - _events = new StreamController.broadcast( - onListen: _watch, onCancel: _cancel); - - _filesToProcess = new AsyncQueue(_processFile, - onError: _events.addError); - } - - /// Scans to see which files were already present before the watcher was - /// subscribed to, and then starts watching the directory for changes. - void _watch() { - assert(_state == _WatchState.UNSUBSCRIBED); - _state = _WatchState.SCANNING; - _poll(); - } - - /// Stops watching the directory when there are no more subscribers. - void _cancel() { - assert(_state != _WatchState.UNSUBSCRIBED); - _state = _WatchState.UNSUBSCRIBED; - - // If we're in the middle of listing the directory, stop. - if (_listSubscription != null) _listSubscription.cancel(); - - // Don't process any remaining files. - _filesToProcess.clear(); - _polledFiles.clear(); - _statuses.clear(); - - _ready = new Completer(); - } - - /// Scans the contents of the directory once to see which files have been - /// added, removed, and modified. - void _poll() { - _filesToProcess.clear(); - _polledFiles.clear(); - - endListing() { - assert(_state != _WatchState.UNSUBSCRIBED); - _listSubscription = null; - - // Null tells the queue consumer that we're done listing. - _filesToProcess.add(null); - } - - var stream = new Directory(directory).list(recursive: true); - _listSubscription = stream.listen((entity) { - assert(_state != _WatchState.UNSUBSCRIBED); - - if (entity is! File) return; - _filesToProcess.add(entity.path); - }, onError: (error, StackTrace stackTrace) { - if (!isDirectoryNotFoundException(error)) { - // It's some unknown error. Pipe it over to the event stream so the - // user can see it. - _events.addError(error, stackTrace); - } - - // When an error occurs, we end the listing normally, which has the - // desired effect of marking all files that were in the directory as - // being removed. - endListing(); - }, onDone: endListing, cancelOnError: true); - } - - /// Processes [file] to determine if it has been modified since the last - /// time it was scanned. - Future _processFile(String file) { - assert(_state != _WatchState.UNSUBSCRIBED); - - // `null` is the sentinel which means the directory listing is complete. - if (file == null) return _completePoll(); - - return getModificationTime(file).then((modified) { - if (_checkForCancel()) return null; - - var lastStatus = _statuses[file]; - - // If its modification time hasn't changed, assume the file is unchanged. - if (lastStatus != null && lastStatus.modified == modified) { - // The file is still here. - _polledFiles.add(file); - return null; - } - - return _hashFile(file).then((hash) { - if (_checkForCancel()) return; - - var status = new _FileStatus(modified, hash); - _statuses[file] = status; - _polledFiles.add(file); - - // Only notify while in the watching state. - if (_state != _WatchState.WATCHING) return; - - // And the file is different. - var changed = lastStatus == null || !_sameHash(lastStatus.hash, hash); - if (!changed) return; - - var type = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; - _events.add(new WatchEvent(type, file)); - }); - }); - } - - /// After the directory listing is complete, this determines which files were - /// removed and then restarts the next poll. - Future _completePoll() { - // Any files that were not seen in the last poll but that we have a - // status for must have been removed. - var removedFiles = _statuses.keys.toSet().difference(_polledFiles); - for (var removed in removedFiles) { - if (_state == _WatchState.WATCHING) { - _events.add(new WatchEvent(ChangeType.REMOVE, removed)); - } - _statuses.remove(removed); - } - - if (_state == _WatchState.SCANNING) { - _state = _WatchState.WATCHING; - _ready.complete(); - } - - // Wait and then poll again. - return new Future.delayed(pollingDelay).then((_) { - if (_checkForCancel()) return; - _poll(); - }); - } - - /// Returns `true` and clears the processing queue if the watcher has been - /// unsubscribed. - bool _checkForCancel() { - if (_state != _WatchState.UNSUBSCRIBED) return false; - - // Don't process any more files. - _filesToProcess.clear(); - return true; - } - - /// Calculates the SHA-1 hash of the file at [path]. - Future> _hashFile(String path) { - return new File(path).readAsBytes().then((bytes) { - var sha1 = new SHA1(); - sha1.add(bytes); - return sha1.close(); - }); - } - - /// Returns `true` if [a] and [b] are the same hash value, i.e. the same - /// series of byte values. - bool _sameHash(List a, List b) { - // Hashes should always be the same size. - assert(a.length == b.length); - - for (var i = 0; i < a.length; i++) { - if (a[i] != b[i]) return false; - } - - return true; - } -} - -/// Enum class for the states that the [DirectoryWatcher] can be in. -class _WatchState { - /// There are no subscribers to the watcher's event stream and no watching - /// is going on. - static const UNSUBSCRIBED = const _WatchState("unsubscribed"); - - /// There are subscribers and the watcher is doing an initial scan of the - /// directory to see which files were already present before watching started. + /// If a native directory watcher is available for this platform, this will + /// use it. Otherwise, it will fall back to a [PollingDirectoryWatcher]. /// - /// The watcher does not send notifications for changes that occurred while - /// there were no subscribers, or for files already present before watching. - /// The initial scan is used to determine what "before watching" state of - /// the file system was. - static const SCANNING = const _WatchState("scanning"); - - /// There are subscribers and the watcher is polling the directory to look - /// for changes. - static const WATCHING = const _WatchState("watching"); - - /// The name of the state. - final String name; - - const _WatchState(this.name); + /// If [_pollingDelay] is passed, it specifies the amount of time the watcher + /// will pause between successive polls of the directory contents. Making this + /// shorter will give more immediate feedback at the expense of doing more IO + /// and higher CPU usage. Defaults to one second. Ignored for non-polling + /// watchers. + factory DirectoryWatcher(String directory, {Duration pollingDelay}) { + if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); + return new PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); + } } - -class _FileStatus { - /// The last time the file was modified. - DateTime modified; - - /// The SHA-1 hash of the contents of the file. - List hash; - - _FileStatus(this.modified, this.hash); -} \ No newline at end of file diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart new file mode 100644 index 000000000..9acecf17b --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -0,0 +1,298 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.directory_watcher.linux; + +import 'dart:async'; +import 'dart:io'; + +import '../directory_watcher.dart'; +import '../utils.dart'; +import '../watch_event.dart'; +import 'resubscribable.dart'; + +import 'package:stack_trace/stack_trace.dart'; + +/// Uses the inotify subsystem to watch for filesystem events. +/// +/// Inotify doesn't suport recursively watching subdirectories, nor does +/// [Directory.watch] polyfill that functionality. This class polyfills it +/// instead. +/// +/// This class also compensates for the non-inotify-specific issues of +/// [Directory.watch] producing multiple events for a single logical action +/// (issue 14372) and providing insufficient information about move events +/// (issue 14424). +class LinuxDirectoryWatcher extends ResubscribableDirectoryWatcher { + LinuxDirectoryWatcher(String directory) + : super(directory, () => new _LinuxDirectoryWatcher(directory)); +} + +class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + final String directory; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + /// The last known state for each entry in this directory. + /// + /// The keys in this map are the paths to the directory entries; the values + /// are [_EntryState]s indicating whether the entries are files or + /// directories. + final _entries = new Map(); + + /// The watchers for subdirectories of [directory]. + final _subWatchers = new Map(); + + /// A set of all subscriptions that this watcher subscribes to. + /// + /// These are gathered together so that they may all be canceled when the + /// watcher is closed. + final _subscriptions = new Set(); + + _LinuxDirectoryWatcher(String directory) + : directory = directory { + // Batch the inotify changes together so that we can dedup events. + var innerStream = new Directory(directory).watch().transform( + new BatchedStreamTransformer()); + _listen(innerStream, _onBatch, + onError: _eventsController.addError, + onDone: _onDone); + + _listen(new Directory(directory).list(), (entity) { + _entries[entity.path] = new _EntryState(entity is Directory); + if (entity is! Directory) return; + _watchSubdir(entity.path); + }, onError: (error, stackTrace) { + _eventsController.addError(error, stackTrace); + close(); + }, onDone: () { + _waitUntilReady().then((_) => _readyCompleter.complete()); + }, cancelOnError: true); + } + + /// Returns a [Future] that completes once all the subdirectory watchers are + /// fully initialized. + Future _waitUntilReady() { + return Future.wait(_subWatchers.values.map((watcher) => watcher.ready)) + .then((_) { + if (_subWatchers.values.every((watcher) => watcher.isReady)) return; + return _waitUntilReady(); + }); + } + + void close() { + for (var subscription in _subscriptions) { + subscription.cancel(); + } + for (var watcher in _subWatchers.values) { + watcher.close(); + } + + _subWatchers.clear(); + _subscriptions.clear(); + _eventsController.close(); + } + + /// Returns all files (not directories) that this watcher knows of are + /// recursively in the watched directory. + Set get _allFiles { + var files = new Set(); + _getAllFiles(files); + return files; + } + + /// Helper function for [_allFiles]. + /// + /// Adds all files that this watcher knows of to [files]. + void _getAllFiles(Set files) { + files.addAll(_entries.keys + .where((path) => _entries[path] == _EntryState.FILE).toSet()); + for (var watcher in _subWatchers.values) { + watcher._getAllFiles(files); + } + } + + /// Watch a subdirectory of [directory] for changes. + /// + /// If the subdirectory was added after [this] began emitting events, its + /// contents will be emitted as ADD events. + void _watchSubdir(String path) { + if (_subWatchers.containsKey(path)) return; + var watcher = new _LinuxDirectoryWatcher(path); + _subWatchers[path] = watcher; + + // TODO(nweiz): Catch any errors here that indicate that the directory in + // question doesn't exist and silently stop watching it instead of + // propagating the errors. + _listen(watcher.events, (event) { + if (isReady) _eventsController.add(event); + }, onError: (error, stackTrace) { + _eventsController.addError(error, stackTrace); + _eventsController.close(); + }, onDone: () { + if (_subWatchers[path] == watcher) _subWatchers.remove(path); + + // It's possible that a directory was removed and recreated very quickly. + // If so, make sure we're still watching it. + if (new Directory(path).existsSync()) _watchSubdir(path); + }); + + // TODO(nweiz): Right now it's possible for the watcher to emit an event for + // a file before the directory list is complete. This could lead to the user + // seeing a MODIFY or REMOVE event for a file before they see an ADD event, + // which is bad. We should handle that. + // + // One possibility is to provide a general means (e.g. + // `DirectoryWatcher.eventsAndExistingFiles`) to tell a watcher to emit + // events for all the files that already exist. This would be useful for + // top-level clients such as barback as well, and could be implemented with + // a wrapper similar to how listening/canceling works now. + + // If a directory is added after we're finished with the initial scan, emit + // an event for each entry in it. This gives the user consistently gets an + // event for every new file. + watcher.ready.then((_) { + if (!isReady || _eventsController.isClosed) return; + _listen(new Directory(path).list(recursive: true), (entry) { + if (entry is Directory) return; + _eventsController.add(new WatchEvent(ChangeType.ADD, entry.path)); + }, onError: (error, stackTrace) { + // Ignore an exception caused by the dir not existing. It's fine if it + // was added and then quickly removed. + if (error is FileSystemException) return; + + _eventsController.addError(error, stackTrace); + _eventsController.close(); + }, cancelOnError: true); + }); + } + + /// The callback that's run when a batch of changes comes in. + void _onBatch(List batch) { + var changedEntries = new Set(); + var oldEntries = new Map.from(_entries); + + // inotify event batches are ordered by occurrence, so we treat them as a + // log of what happened to a file. + for (var event in batch) { + // If the watched directory is deleted or moved, we'll get a deletion + // event for it. Ignore it; we handle closing [this] when the underlying + // stream is closed. + if (event.path == directory) continue; + + changedEntries.add(event.path); + + if (event is FileSystemMoveEvent) { + changedEntries.add(event.destination); + _changeEntryState(event.path, ChangeType.REMOVE, event.isDirectory); + _changeEntryState(event.destination, ChangeType.ADD, event.isDirectory); + } else { + _changeEntryState(event.path, _changeTypeFor(event), event.isDirectory); + } + } + + for (var path in changedEntries) { + emitEvent(ChangeType type) { + if (isReady) _eventsController.add(new WatchEvent(type, path)); + } + + var oldState = oldEntries[path]; + var newState = _entries[path]; + + if (oldState != _EntryState.FILE && newState == _EntryState.FILE) { + emitEvent(ChangeType.ADD); + } else if (oldState == _EntryState.FILE && newState == _EntryState.FILE) { + emitEvent(ChangeType.MODIFY); + } else if (oldState == _EntryState.FILE && newState != _EntryState.FILE) { + emitEvent(ChangeType.REMOVE); + } + + if (oldState == _EntryState.DIRECTORY) { + var watcher = _subWatchers.remove(path); + if (watcher == null) return; + for (var path in watcher._allFiles) { + _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + } + watcher.close(); + } + + if (newState == _EntryState.DIRECTORY) _watchSubdir(path); + } + } + + /// Changes the known state of the entry at [path] based on [change] and + /// [isDir]. + void _changeEntryState(String path, ChangeType change, bool isDir) { + if (change == ChangeType.ADD || change == ChangeType.MODIFY) { + _entries[path] = new _EntryState(isDir); + } else { + assert(change == ChangeType.REMOVE); + _entries.remove(path); + } + } + + /// Determines the [ChangeType] associated with [event]. + ChangeType _changeTypeFor(FileSystemEvent event) { + if (event is FileSystemDeleteEvent) return ChangeType.REMOVE; + if (event is FileSystemCreateEvent) return ChangeType.ADD; + + assert(event is FileSystemModifyEvent); + return ChangeType.MODIFY; + } + + /// Handles the underlying event stream closing, indicating that the directory + /// being watched was removed. + void _onDone() { + // The parent directory often gets a close event before the subdirectories + // are done emitting events. We wait for them to finish before we close + // [events] so that we can be sure to emit a remove event for every file + // that used to exist. + Future.wait(_subWatchers.values.map((watcher) { + try { + return watcher.events.toList(); + } on StateError catch (_) { + // It's possible that [watcher.events] is closed but the onDone event + // hasn't reached us yet. It's fine if so. + return new Future.value(); + } + })).then((_) => close()); + } + + /// Like [Stream.listen], but automatically adds the subscription to + /// [_subscriptions] so that it can be canceled when [close] is called. + void _listen(Stream stream, void onData(event), {Function onError, + void onDone(), bool cancelOnError}) { + var subscription; + subscription = stream.listen(onData, onError: onError, onDone: () { + _subscriptions.remove(subscription); + if (onDone != null) onDone(); + }, cancelOnError: cancelOnError); + _subscriptions.add(subscription); + } +} + +/// An enum for the possible states of entries in a watched directory. +class _EntryState { + final String _name; + + /// The entry is a file. + static const FILE = const _EntryState._("file"); + + /// The entry is a directory. + static const DIRECTORY = const _EntryState._("directory"); + + const _EntryState._(this._name); + + /// Returns [DIRECTORY] if [isDir] is true, and [FILE] otherwise. + factory _EntryState(bool isDir) => + isDir ? _EntryState.DIRECTORY : _EntryState.FILE; + + String toString() => _name; +} diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart new file mode 100644 index 000000000..91ca005f3 --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -0,0 +1,217 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.directory_watcher.polling; + +import 'dart:async'; +import 'dart:io'; + +import 'package:crypto/crypto.dart'; + +import '../async_queue.dart'; +import '../directory_watcher.dart'; +import '../stat.dart'; +import '../utils.dart'; +import '../watch_event.dart'; +import 'resubscribable.dart'; + +/// Periodically polls a directory for changes. +class PollingDirectoryWatcher extends ResubscribableDirectoryWatcher { + /// Creates a new polling watcher monitoring [directory]. + /// + /// If [_pollingDelay] is passed, it specifies the amount of time the watcher + /// will pause between successive polls of the directory contents. Making this + /// shorter will give more immediate feedback at the expense of doing more IO + /// and higher CPU usage. Defaults to one second. + PollingDirectoryWatcher(String directory, {Duration pollingDelay}) + : super(directory, () { + return new _PollingDirectoryWatcher(directory, + pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + }); +} + +class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + final String directory; + + Stream get events => _events.stream; + final _events = new StreamController.broadcast(); + + bool get isReady => _ready.isCompleted; + + Future get ready => _ready.future; + final _ready = new Completer(); + + /// The amount of time the watcher pauses between successive polls of the + /// directory contents. + final Duration _pollingDelay; + + /// The previous status of the files in the directory. + /// + /// Used to tell which files have been modified. + final _statuses = new Map(); + + /// The subscription used while [directory] is being listed. + /// + /// Will be `null` if a list is not currently happening. + StreamSubscription _listSubscription; + + /// The queue of files waiting to be processed to see if they have been + /// modified. + /// + /// Processing a file is asynchronous, as is listing the directory, so the + /// queue exists to let each of those proceed at their own rate. The lister + /// will enqueue files as quickly as it can. Meanwhile, files are dequeued + /// and processed sequentially. + AsyncQueue _filesToProcess; + + /// The set of files that have been seen in the current directory listing. + /// + /// Used to tell which files have been removed: files that are in [_statuses] + /// but not in here when a poll completes have been removed. + final _polledFiles = new Set(); + + _PollingDirectoryWatcher(this.directory, this._pollingDelay) { + _filesToProcess = new AsyncQueue(_processFile, + onError: _events.addError); + + _poll(); + } + + void close() { + _events.close(); + + // If we're in the middle of listing the directory, stop. + if (_listSubscription != null) _listSubscription.cancel(); + + // Don't process any remaining files. + _filesToProcess.clear(); + _polledFiles.clear(); + _statuses.clear(); + } + + /// Scans the contents of the directory once to see which files have been + /// added, removed, and modified. + void _poll() { + _filesToProcess.clear(); + _polledFiles.clear(); + + endListing() { + assert(!_events.isClosed); + _listSubscription = null; + + // Null tells the queue consumer that we're done listing. + _filesToProcess.add(null); + } + + var stream = new Directory(directory).list(recursive: true); + _listSubscription = stream.listen((entity) { + assert(!_events.isClosed); + + if (entity is! File) return; + _filesToProcess.add(entity.path); + }, onError: (error, stackTrace) { + if (!isDirectoryNotFoundException(error)) { + // It's some unknown error. Pipe it over to the event stream so the + // user can see it. + _events.addError(error, stackTrace); + } + + // When an error occurs, we end the listing normally, which has the + // desired effect of marking all files that were in the directory as + // being removed. + endListing(); + }, onDone: endListing, cancelOnError: true); + } + + /// Processes [file] to determine if it has been modified since the last + /// time it was scanned. + Future _processFile(String file) { + // `null` is the sentinel which means the directory listing is complete. + if (file == null) return _completePoll(); + + return getModificationTime(file).then((modified) { + if (_events.isClosed) return null; + + var lastStatus = _statuses[file]; + + // If its modification time hasn't changed, assume the file is unchanged. + if (lastStatus != null && lastStatus.modified == modified) { + // The file is still here. + _polledFiles.add(file); + return null; + } + + return _hashFile(file).then((hash) { + if (_events.isClosed) return; + + var status = new _FileStatus(modified, hash); + _statuses[file] = status; + _polledFiles.add(file); + + // Only notify if we're ready to emit events. + if (!isReady) return; + + // And the file is different. + var changed = lastStatus == null || !_sameHash(lastStatus.hash, hash); + if (!changed) return; + + var type = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; + _events.add(new WatchEvent(type, file)); + }); + }); + } + + /// After the directory listing is complete, this determines which files were + /// removed and then restarts the next poll. + Future _completePoll() { + // Any files that were not seen in the last poll but that we have a + // status for must have been removed. + var removedFiles = _statuses.keys.toSet().difference(_polledFiles); + for (var removed in removedFiles) { + if (isReady) _events.add(new WatchEvent(ChangeType.REMOVE, removed)); + _statuses.remove(removed); + } + + if (!isReady) _ready.complete(); + + // Wait and then poll again. + return new Future.delayed(_pollingDelay).then((_) { + if (_events.isClosed) return; + _poll(); + }); + } + + /// Calculates the SHA-1 hash of the file at [path]. + Future> _hashFile(String path) { + return new File(path).readAsBytes().then((bytes) { + var sha1 = new SHA1(); + sha1.add(bytes); + return sha1.close(); + }); + } + + /// Returns `true` if [a] and [b] are the same hash value, i.e. the same + /// series of byte values. + bool _sameHash(List a, List b) { + // Hashes should always be the same size. + assert(a.length == b.length); + + for (var i = 0; i < a.length; i++) { + if (a[i] != b[i]) return false; + } + + return true; + } +} + +class _FileStatus { + /// The last time the file was modified. + DateTime modified; + + /// The SHA-1 hash of the contents of the file. + List hash; + + _FileStatus(this.modified, this.hash); +} + diff --git a/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart b/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart new file mode 100644 index 000000000..daa813a3e --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart @@ -0,0 +1,79 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.directory_watcher.resubscribable; + +import 'dart:async'; +import 'dart:io'; + +import '../directory_watcher.dart'; +import '../utils.dart'; +import '../watch_event.dart'; + +typedef ManuallyClosedDirectoryWatcher WatcherFactory(); + +/// A wrapper for [ManuallyClosedDirectoryWatcher] that encapsulates support for +/// closing the watcher when it has no subscribers and re-opening it when it's +/// re-subscribed. +/// +/// It's simpler to implement watchers without worrying about this behavior. +/// This class wraps a watcher class which can be written with the simplifying +/// assumption that it can continue emitting events until an explicit `close` +/// method is called, at which point it will cease emitting events entirely. The +/// [ManuallyClosedDirectoryWatcher] interface is used for these watchers. +/// +/// This would be more cleanly implemented as a function that takes a class and +/// emits a new class, but Dart doesn't support that sort of thing. Instead it +/// takes a factory function that produces instances of the inner class. +abstract class ResubscribableDirectoryWatcher implements DirectoryWatcher { + /// The factory function that produces instances of the inner class. + final WatcherFactory _factory; + + final String directory; + + Stream get events => _eventsController.stream; + StreamController _eventsController; + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + var _readyCompleter = new Completer(); + + /// Creates a new [ResubscribableDirectoryWatcher] wrapping the watchers + /// emitted by [_factory]. + ResubscribableDirectoryWatcher(this.directory, this._factory) { + var watcher; + var subscription; + + _eventsController = new StreamController.broadcast( + onListen: () { + watcher = _factory(); + subscription = watcher.events.listen(_eventsController.add, + onError: _eventsController.addError, + onDone: _eventsController.close); + + // It's important that we complete the value of [_readyCompleter] at the + // time [onListen] is called, as opposed to the value when [watcher.ready] + // fires. A new completer may be created by that time. + watcher.ready.then(_readyCompleter.complete); + }, onCancel: () { + // Cancel the subscription before closing the watcher so that the + // watcher's `onDone` event doesn't close [events]. + subscription.cancel(); + watcher.close(); + _readyCompleter = new Completer(); + }, sync: true); + } +} + +/// An interface for watchers with an explicit, manual [close] method. +/// +/// See [ResubscribableDirectoryWatcher]. +abstract class ManuallyClosedDirectoryWatcher implements DirectoryWatcher { + /// Closes the watcher. + /// + /// Subclasses should close their [events] stream and release any internal + /// resources. + void close(); +} diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 3d00c0843..e4e445794 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -4,7 +4,9 @@ library watcher.utils; +import 'dart:async'; import 'dart:io'; +import 'dart:collection'; /// Returns `true` if [error] is a [FileSystemException] for a missing /// directory. @@ -15,3 +17,57 @@ bool isDirectoryNotFoundException(error) { var notFoundCode = Platform.operatingSystem == "windows" ? 3 : 2; return error.osError.errorCode == notFoundCode; } + +/// Returns a buffered stream that will emit the same values as the stream +/// returned by [future] once [future] completes. +/// +/// If [future] completes to an error, the return value will emit that error and +/// then close. +Stream futureStream(Future future) { + var controller = new StreamController(sync: true); + future.then((stream) { + stream.listen( + controller.add, + onError: controller.addError, + onDone: controller.close); + }).catchError((e, stackTrace) { + controller.addError(e, stackTrace); + controller.close(); + }); + return controller.stream; +} + +/// Like [new Future], but avoids around issue 11911 by using [new Future.value] +/// under the covers. +Future newFuture(callback()) => new Future.value().then((_) => callback()); + +/// A stream transformer that batches all events that are sent at the same time. +/// +/// When multiple events are synchronously added to a stream controller, the +/// [StreamController] implementation uses [scheduleMicrotask] to schedule the +/// asynchronous firing of each event. In order to recreate the synchronous +/// batches, this collates all the events that are received in "nearby" +/// microtasks. +class BatchedStreamTransformer implements StreamTransformer> { + Stream> bind(Stream input) { + var batch = new Queue(); + return new StreamTransformer>.fromHandlers( + handleData: (event, sink) { + batch.add(event); + + // [Timer.run] schedules an event that runs after any microtasks that have + // been scheduled. + Timer.run(() { + if (batch.isEmpty) return; + sink.add(batch.toList()); + batch.clear(); + }); + }, handleDone: (sink) { + if (batch.isNotEmpty) { + sink.add(batch.toList()); + batch.clear(); + } + sink.close(); + }).bind(input); + } +} diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index c4824b8ec..88531f203 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -6,3 +6,4 @@ library watcher; export 'src/watch_event.dart'; export 'src/directory_watcher.dart'; +export 'src/directory_watcher/polling.dart'; diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart new file mode 100644 index 000000000..ba695698b --- /dev/null +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -0,0 +1,62 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/linux.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + + setUp(() { + // Increase the timeout because closing a [Directory.watch] stream blocks + // the main isolate for a very long time on Goobuntu, as of kernel + // 3.2.5-gg1336 (see issue 14606). + currentSchedule.timeout *= 3; + + createSandbox(); + }); + + sharedTests(); + + test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { + expect(new DirectoryWatcher('.'), + new isInstanceOf()); + }); + + test('notifies even if the file contents are unchanged', () { + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "before"); + startWatcher(); + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "after"); + expectModifyEvent("a.txt"); + expectModifyEvent("b.txt"); + }); + + test('emits events for many nested files moved out then immediately back in', + () { + withPermutations((i, j, k) => + writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + startWatcher(dir: "dir"); + + renameDir("dir/sub", "sub"); + renameDir("sub", "dir/sub"); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + }); +} diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart new file mode 100644 index 000000000..02ed5d215 --- /dev/null +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -0,0 +1,39 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + // Use a short delay to make the tests run quickly. + watcherFactory = (dir) => new PollingDirectoryWatcher(dir, + pollingDelay: new Duration(milliseconds: 100)); + + setUp(createSandbox); + + sharedTests(); + + test('does not notify if the file contents are unchanged', () { + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "before"); + startWatcher(); + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "after"); + expectModifyEvent("b.txt"); + }); + + test('does not notify if the modification time did not change', () { + writeFile("a.txt", contents: "before"); + writeFile("b.txt", contents: "before"); + startWatcher(); + writeFile("a.txt", contents: "after", updateModified: false); + writeFile("b.txt", contents: "after"); + expectModifyEvent("b.txt"); + }); +} diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart new file mode 100644 index 000000000..eed606931 --- /dev/null +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -0,0 +1,222 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; + +import '../utils.dart'; + +sharedTests() { + test('does not notify for files that already exist when started', () { + // Make some pre-existing files. + writeFile("a.txt"); + writeFile("b.txt"); + + startWatcher(); + + // Change one after the watcher is running. + writeFile("b.txt", contents: "modified"); + + // We should get a modify event for the changed file, but no add events + // for them before this. + expectModifyEvent("b.txt"); + }); + + test('notifies when a file is added', () { + startWatcher(); + writeFile("file.txt"); + expectAddEvent("file.txt"); + }); + + test('notifies when a file is modified', () { + writeFile("file.txt"); + startWatcher(); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + }); + + test('notifies when a file is removed', () { + writeFile("file.txt"); + startWatcher(); + deleteFile("file.txt"); + expectRemoveEvent("file.txt"); + }); + + test('notifies when a file is modified multiple times', () { + writeFile("file.txt"); + startWatcher(); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + writeFile("file.txt", contents: "modified again"); + expectModifyEvent("file.txt"); + }); + + test('when the watched directory is deleted, removes all files', () { + writeFile("dir/a.txt"); + writeFile("dir/b.txt"); + + startWatcher(dir: "dir"); + + deleteDir("dir"); + inAnyOrder(() { + expectRemoveEvent("dir/a.txt"); + expectRemoveEvent("dir/b.txt"); + }); + }); + + group("moves", () { + test('notifies when a file is moved within the watched directory', () { + writeFile("old.txt"); + startWatcher(); + renameFile("old.txt", "new.txt"); + + inAnyOrder(() { + expectAddEvent("new.txt"); + expectRemoveEvent("old.txt"); + }); + }); + + test('notifies when a file is moved from outside the watched directory', + () { + writeFile("old.txt"); + createDir("dir"); + startWatcher(dir: "dir"); + + renameFile("old.txt", "dir/new.txt"); + expectAddEvent("dir/new.txt"); + }); + + test('notifies when a file is moved outside the watched directory', () { + writeFile("dir/old.txt"); + startWatcher(dir: "dir"); + + renameFile("dir/old.txt", "new.txt"); + expectRemoveEvent("dir/old.txt"); + }); + }); + + group("clustered changes", () { + test("doesn't notify when a file is created and then immediately removed", + () { + startWatcher(); + writeFile("file.txt"); + deleteFile("file.txt"); + + // [startWatcher] will assert that no events were fired. + }); + + test("reports a modification when a file is deleted and then immediately " + "recreated", () { + writeFile("file.txt"); + startWatcher(); + + deleteFile("file.txt"); + writeFile("file.txt", contents: "re-created"); + expectModifyEvent("file.txt"); + }); + + test("reports a modification when a file is moved and then immediately " + "recreated", () { + writeFile("old.txt"); + startWatcher(); + + renameFile("old.txt", "new.txt"); + writeFile("old.txt", contents: "re-created"); + inAnyOrder(() { + expectModifyEvent("old.txt"); + expectAddEvent("new.txt"); + }); + }); + + test("reports a removal when a file is modified and then immediately " + "removed", () { + writeFile("file.txt"); + startWatcher(); + + writeFile("file.txt", contents: "modified"); + deleteFile("file.txt"); + expectRemoveEvent("file.txt"); + }); + + test("reports an add when a file is added and then immediately modified", + () { + startWatcher(); + + writeFile("file.txt"); + writeFile("file.txt", contents: "modified"); + expectAddEvent("file.txt"); + }); + }); + + group("subdirectories", () { + test('watches files in subdirectories', () { + startWatcher(); + writeFile("a/b/c/d/file.txt"); + expectAddEvent("a/b/c/d/file.txt"); + }); + + test('notifies when a subdirectory is moved within the watched directory ' + 'and then its contents are modified', () { + writeFile("old/file.txt"); + startWatcher(); + + renameDir("old", "new"); + inAnyOrder(() { + expectRemoveEvent("old/file.txt"); + expectAddEvent("new/file.txt"); + }); + + writeFile("new/file.txt", contents: "modified"); + expectModifyEvent("new/file.txt"); + }); + + test('emits events for many nested files added at once', () { + withPermutations((i, j, k) => + writeFile("sub/sub-$i/sub-$j/file-$k.txt")); + + createDir("dir"); + startWatcher(dir: "dir"); + renameDir("sub", "dir/sub"); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + }); + + test('emits events for many nested files removed at once', () { + withPermutations((i, j, k) => + writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + + createDir("dir"); + startWatcher(dir: "dir"); + + // Rename the directory rather than deleting it because native watchers + // report a rename as a single DELETE event for the directory, whereas + // they report recursive deletion with DELETE events for every file in the + // directory. + renameDir("dir/sub", "sub"); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + }); + + test('emits events for many nested files moved at once', () { + withPermutations((i, j, k) => + writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); + + createDir("dir"); + startWatcher(dir: "dir"); + renameDir("dir/old", "dir/new"); + + inAnyOrder(() { + withPermutations((i, j, k) { + expectRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"); + expectAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt"); + }); + }); + }); + }); +} diff --git a/pkgs/watcher/test/directory_watcher_test.dart b/pkgs/watcher/test/directory_watcher_test.dart deleted file mode 100644 index 841dd0808..000000000 --- a/pkgs/watcher/test/directory_watcher_test.dart +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'package:scheduled_test/scheduled_test.dart'; - -import 'utils.dart'; - -main() { - initConfig(); - - setUp(createSandbox); - - test('does not notify for files that already exist when started', () { - // Make some pre-existing files. - writeFile("a.txt"); - writeFile("b.txt"); - - createWatcher(); - - // Change one after the watcher is running. - writeFile("b.txt", contents: "modified"); - - // We should get a modify event for the changed file, but no add events - // for them before this. - expectModifyEvent("b.txt"); - }); - - test('notifies when a file is added', () { - createWatcher(); - writeFile("file.txt"); - expectAddEvent("file.txt"); - }); - - test('notifies when a file is modified', () { - writeFile("file.txt"); - createWatcher(); - writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); - }); - - test('notifies when a file is removed', () { - writeFile("file.txt"); - createWatcher(); - deleteFile("file.txt"); - expectRemoveEvent("file.txt"); - }); - - test('notifies when a file is moved', () { - writeFile("old.txt"); - createWatcher(); - renameFile("old.txt", "new.txt"); - expectAddEvent("new.txt"); - expectRemoveEvent("old.txt"); - }); - - test('notifies when a file is modified multiple times', () { - writeFile("file.txt"); - createWatcher(); - writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); - writeFile("file.txt", contents: "modified again"); - expectModifyEvent("file.txt"); - }); - - test('does not notify if the file contents are unchanged', () { - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "before"); - createWatcher(); - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "after"); - expectModifyEvent("b.txt"); - }); - - test('does not notify if the modification time did not change', () { - writeFile("a.txt", contents: "before"); - writeFile("b.txt", contents: "before"); - createWatcher(); - writeFile("a.txt", contents: "after", updateModified: false); - writeFile("b.txt", contents: "after"); - expectModifyEvent("b.txt"); - }); - - test('watches files in subdirectories', () { - createWatcher(); - writeFile("a/b/c/d/file.txt"); - expectAddEvent("a/b/c/d/file.txt"); - }); - - test('watches a directory created after the watcher', () { - // Watch a subdirectory that doesn't exist yet. - createWatcher(dir: "a"); - - // This implicity creates it. - writeFile("a/b/c/d/file.txt"); - expectAddEvent("a/b/c/d/file.txt"); - }); - - test('when the watched directory is deleted, removes all files', () { - writeFile("dir/a.txt"); - writeFile("dir/b.txt"); - - createWatcher(dir: "dir"); - - deleteDir("dir"); - expectRemoveEvents(["dir/a.txt", "dir/b.txt"]); - }); -} diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart new file mode 100644 index 000000000..7978830bc --- /dev/null +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/linux.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart new file mode 100644 index 000000000..fa4f0cbe2 --- /dev/null +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new PollingDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/no_subscription_test.dart b/pkgs/watcher/test/no_subscription/shared.dart similarity index 73% rename from pkgs/watcher/test/no_subscription_test.dart rename to pkgs/watcher/test/no_subscription/shared.dart index 2e7b6d3ff..cd279e1ca 100644 --- a/pkgs/watcher/test/no_subscription_test.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -7,14 +7,10 @@ import 'dart:async'; import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; -import 'utils.dart'; +import '../utils.dart'; -main() { - initConfig(); - - setUp(createSandbox); - - test('does not notify for changes when there were no subscribers', () { +sharedTests() { + test('does not notify for changes when there are no subscribers', () { // Note that this test doesn't rely as heavily on the test functions in // utils.dart because it needs to be very explicit about when the event // stream is and is not subscribed. @@ -51,16 +47,10 @@ main() { expect(event.path, endsWith("added.txt")); completer.complete(); })); - }); - // The watcher will have been cancelled and then resumed in the middle of - // its pause between polling loops. That means the second scan to skip - // what changed while we were unsubscribed won't happen until after that - // delay is done. Wait long enough for that to happen. - // - // We're doing * 4 here because that seems to give the slower bots enough - // time for this to complete. - schedule(() => new Future.delayed(watcher.pollingDelay * 4)); + // Wait until the watcher is ready to dispatch events again. + return watcher.ready; + }); // And add a third file. writeFile("added.txt"); diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart new file mode 100644 index 000000000..7978830bc --- /dev/null +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/linux.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart new file mode 100644 index 000000000..fa4f0cbe2 --- /dev/null +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -0,0 +1,19 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new PollingDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/ready_test.dart b/pkgs/watcher/test/ready/shared.dart similarity index 95% rename from pkgs/watcher/test/ready_test.dart rename to pkgs/watcher/test/ready/shared.dart index 11b77e02c..af1b58f99 100644 --- a/pkgs/watcher/test/ready_test.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -2,17 +2,11 @@ // 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. -import 'dart:async'; - import 'package:scheduled_test/scheduled_test.dart'; -import 'utils.dart'; - -main() { - initConfig(); - - setUp(createSandbox); +import '../utils.dart'; +sharedTests() { test('ready does not complete until after subscription', () { var watcher = createWatcher(waitForReady: false); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 28d57b05c..d1b9f94b8 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -5,6 +5,7 @@ library watcher.test.utils; import 'dart:async'; +import 'dart:collection'; import 'dart:io'; import 'package:path/path.dart' as p; @@ -12,6 +13,7 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:unittest/compact_vm_config.dart'; import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; +import 'package:watcher/src/utils.dart'; /// The path to the temporary sandbox created for each test. All file /// operations are implicitly relative to this directory. @@ -36,6 +38,14 @@ var _nextEvent = 0; /// increment the mod time for that file instantly. Map _mockFileModificationTimes; +typedef DirectoryWatcher WatcherFactory(String directory); + +/// Sets the function used to create the directory watcher. +set watcherFactory(WatcherFactory factory) { + _watcherFactory = factory; +} +WatcherFactory _watcherFactory; + void initConfig() { useCompactVMConfiguration(); filterStacks = true; @@ -54,10 +64,10 @@ void createSandbox() { path = p.normalize(p.relative(path, from: _sandboxDir)); // Make sure we got a path in the sandbox. - assert(p.isRelative(path) && !path.startsWith("..")); + assert(p.isRelative(path) && !path.startsWith("..")); - return new DateTime.fromMillisecondsSinceEpoch( - _mockFileModificationTimes[path]); + var mtime = _mockFileModificationTimes[path]; + return new DateTime.fromMillisecondsSinceEpoch(mtime == null ? 0 : mtime); }); // Delete the sandbox when done. @@ -86,68 +96,113 @@ DirectoryWatcher createWatcher({String dir, bool waitForReady}) { dir = p.join(_sandboxDir, dir); } - // Use a short delay to make the tests run quickly. - _watcher = new DirectoryWatcher(dir, - pollingDelay: new Duration(milliseconds: 100)); + var watcher = _watcherFactory(dir); // Wait until the scan is finished so that we don't miss changes to files // that could occur before the scan completes. if (waitForReady != false) { - schedule(() => _watcher.ready, "wait for watcher to be ready"); + schedule(() => watcher.ready, "wait for watcher to be ready"); } - currentSchedule.onComplete.schedule(() { - _nextEvent = 0; - _watcher = null; - }, "reset watcher"); - - return _watcher; + return watcher; } -/// Expects that the next set of events will all be changes of [type] on -/// [paths]. +/// The stream of events from the watcher started with [startWatcher]. +Stream _watcherEvents; + +/// Creates a new [DirectoryWatcher] that watches a temporary directory and +/// starts monitoring it for events. /// -/// Validates that events are delivered for all paths in [paths], but allows -/// them in any order. -void expectEvents(ChangeType type, Iterable paths) { - var pathSet = paths - .map((path) => p.join(_sandboxDir, path)) - .map(p.normalize) - .toSet(); - - // Create an expectation for as many paths as we have. - var futures = []; - - for (var i = 0; i < paths.length; i++) { - // Immediately create the futures. This ensures we don't register too - // late and drop the event before we receive it. - var future = _watcher.events.elementAt(_nextEvent++).then((event) { - expect(event.type, equals(type)); - expect(pathSet, contains(event.path)); - - pathSet.remove(event.path); - }); - - // Make sure the schedule is watching it in case it fails. - currentSchedule.wrapFuture(future); - - futures.add(future); - } +/// If [dir] is provided, watches a subdirectory in the sandbox with that name. +void startWatcher({String dir}) { + // We want to wait until we're ready *after* we subscribe to the watcher's + // events. + _watcher = createWatcher(dir: dir, waitForReady: false); + + // Schedule [_watcher.events.listen] so that the watcher doesn't start + // watching [dir] before it exists. Expose [_watcherEvents] immediately so + // that it can be accessed synchronously after this. + _watcherEvents = futureStream(schedule(() { + var allEvents = new Queue(); + var subscription = _watcher.events.listen(allEvents.add, + onError: currentSchedule.signalError); + + currentSchedule.onComplete.schedule(() { + var numEvents = _nextEvent; + subscription.cancel(); + _nextEvent = 0; + _watcher = null; + + // If there are already errors, don't add this to the output and make + // people think it might be the root cause. + if (currentSchedule.errors.isEmpty) { + expect(allEvents, hasLength(numEvents)); + } + }, "reset watcher"); + + return _watcher.events; + }, "create watcher")).asBroadcastStream(); + + schedule(() => _watcher.ready, "wait for watcher to be ready"); +} - // Schedule it so that later file modifications don't occur until after this - // event is received. - schedule(() => Future.wait(futures), - "wait for $type events on ${paths.join(', ')}"); +/// A future set by [inAnyOrder] that will complete to the set of events that +/// occur in the [inAnyOrder] block. +Future> _unorderedEventFuture; + +/// Runs [block] and allows multiple [expectEvent] calls in that block to match +/// events in any order. +void inAnyOrder(block()) { + var oldFuture = _unorderedEventFuture; + try { + var firstEvent = _nextEvent; + var completer = new Completer(); + _unorderedEventFuture = completer.future; + block(); + + _watcherEvents.skip(firstEvent).take(_nextEvent - firstEvent).toSet() + .then(completer.complete, onError: completer.completeError); + currentSchedule.wrapFuture(_unorderedEventFuture, + "waiting for ${_nextEvent - firstEvent} events"); + } finally { + _unorderedEventFuture = oldFuture; + } } -void expectAddEvent(String path) => expectEvents(ChangeType.ADD, [path]); -void expectModifyEvent(String path) => expectEvents(ChangeType.MODIFY, [path]); -void expectRemoveEvent(String path) => expectEvents(ChangeType.REMOVE, [path]); +/// Expects that the next set of event will be a change of [type] on [path]. +/// +/// Multiple calls to [expectEvent] require that the events are received in that +/// order unless they're called in an [inAnyOrder] block. +void expectEvent(ChangeType type, String path) { + var matcher = predicate((e) { + return e is WatchEvent && e.type == type && + e.path == p.join(_sandboxDir, path); + }, "is $type $path"); + + if (_unorderedEventFuture != null) { + // Assign this to a local variable since it will be un-assigned by the time + // the scheduled callback runs. + var future = _unorderedEventFuture; + + expect( + schedule(() => future, "should fire $type event on $path"), + completion(contains(matcher))); + } else { + var future = currentSchedule.wrapFuture( + _watcherEvents.elementAt(_nextEvent), + "waiting for $type event on $path"); -void expectRemoveEvents(Iterable paths) { - expectEvents(ChangeType.REMOVE, paths); + expect( + schedule(() => future, "should fire $type event on $path"), + completion(matcher)); + } + _nextEvent++; } +void expectAddEvent(String path) => expectEvent(ChangeType.ADD, path); +void expectModifyEvent(String path) => expectEvent(ChangeType.MODIFY, path); +void expectRemoveEvent(String path) => expectEvent(ChangeType.REMOVE, path); + /// Schedules writing a file in the sandbox at [path] with [contents]. /// /// If [contents] is omitted, creates an empty file. If [updatedModified] is @@ -201,6 +256,21 @@ void renameFile(String from, String to) { }, "rename file $from to $to"); } +/// Schedules creating a directory in the sandbox at [path]. +void createDir(String path) { + schedule(() { + new Directory(p.join(_sandboxDir, path)).createSync(); + }, "create directory $path"); +} + +/// Schedules renaming a directory in the sandbox from [from] to [to]. +void renameDir(String from, String to) { + schedule(() { + new Directory(p.join(_sandboxDir, from)) + .renameSync(p.join(_sandboxDir, to)); + }, "rename directory $from to $to"); +} + /// Schedules deleting a directory in the sandbox at [path]. void deleteDir(String path) { schedule(() { @@ -208,22 +278,17 @@ void deleteDir(String path) { }, "delete directory $path"); } -/// A [Matcher] for [WatchEvent]s. -class _ChangeMatcher extends Matcher { - /// The expected change. - final ChangeType type; - - /// The expected path. - final String path; - - _ChangeMatcher(this.type, this.path); - - Description describe(Description description) { - description.add("$type $path"); +/// Runs [callback] with every permutation of non-negative [i], [j], and [k] +/// less than [limit]. +/// +/// [limit] defaults to 3. +void withPermutations(callback(int i, int j, int k), {int limit}) { + if (limit == null) limit = 3; + for (var i = 0; i < limit; i++) { + for (var j = 0; j < limit; j++) { + for (var k = 0; k < limit; k++) { + callback(i, j, k); + } + } } - - bool matches(item, Map matchState) => - item is WatchEvent && - item.type == type && - p.normalize(item.path) == p.normalize(path); } From 3d4e068bf707fe4a87c3152ef1f02ffd48f75361 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 8 Nov 2013 01:44:53 +0000 Subject: [PATCH 0069/1215] Fix the watcher tests on Windows. The tests were assuming POSIX paths. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//66073002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30091 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index d1b9f94b8..3070d7906 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -176,7 +176,7 @@ void inAnyOrder(block()) { void expectEvent(ChangeType type, String path) { var matcher = predicate((e) { return e is WatchEvent && e.type == type && - e.path == p.join(_sandboxDir, path); + e.path == p.join(_sandboxDir, p.normalize(path)); }, "is $type $path"); if (_unorderedEventFuture != null) { From 1b8eb689d0b2a46abb0f0944d38f1320077f6ac3 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 8 Nov 2013 01:46:11 +0000 Subject: [PATCH 0070/1215] Fix an analyzer error in the linux directory watcher. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//65533005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30093 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 9acecf17b..7ac6e6e08 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -82,7 +82,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { Future _waitUntilReady() { return Future.wait(_subWatchers.values.map((watcher) => watcher.ready)) .then((_) { - if (_subWatchers.values.every((watcher) => watcher.isReady)) return; + if (_subWatchers.values.every((watcher) => watcher.isReady)) return null; return _waitUntilReady(); }); } From 9d1f993889574a9957bc3427254ec019121d0be9 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 11 Nov 2013 19:47:18 +0000 Subject: [PATCH 0071/1215] Wrap Directory.watch on Mac OS for the watcher package. R=rnystrom@google.com BUG=14428 Review URL: https://codereview.chromium.org//66163002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30168 260f80e4-7a28-3924-810f-c04153c831b5 --- .../src/constructable_file_system_event.dart | 60 +++ pkgs/watcher/lib/src/directory_watcher.dart | 2 + .../lib/src/directory_watcher/linux.dart | 2 - .../lib/src/directory_watcher/mac_os.dart | 355 ++++++++++++++++++ pkgs/watcher/lib/src/path_set.dart | 168 +++++++++ pkgs/watcher/lib/src/utils.dart | 4 + .../test/directory_watcher/mac_os_test.dart | 67 ++++ .../test/directory_watcher/shared.dart | 18 + .../test/no_subscription/mac_os_test.dart | 46 +++ pkgs/watcher/test/path_set_test.dart | 235 ++++++++++++ pkgs/watcher/test/ready/mac_os_test.dart | 20 + pkgs/watcher/test/utils.dart | 2 + 12 files changed, 977 insertions(+), 2 deletions(-) create mode 100644 pkgs/watcher/lib/src/constructable_file_system_event.dart create mode 100644 pkgs/watcher/lib/src/directory_watcher/mac_os.dart create mode 100644 pkgs/watcher/lib/src/path_set.dart create mode 100644 pkgs/watcher/test/directory_watcher/mac_os_test.dart create mode 100644 pkgs/watcher/test/no_subscription/mac_os_test.dart create mode 100644 pkgs/watcher/test/path_set_test.dart create mode 100644 pkgs/watcher/test/ready/mac_os_test.dart diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart new file mode 100644 index 000000000..e65e25827 --- /dev/null +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.constructable_file_system_event; + +import 'dart:io'; + +abstract class _ConstructableFileSystemEvent implements FileSystemEvent { + final bool isDirectory; + final String path; + final int type; + + _ConstructableFileSystemEvent(this.path, this.isDirectory); +} + +class ConstructableFileSystemCreateEvent extends _ConstructableFileSystemEvent + implements FileSystemCreateEvent { + final type = FileSystemEvent.CREATE; + + ConstructableFileSystemCreateEvent(String path, bool isDirectory) + : super(path, isDirectory); + + String toString() => "FileSystemCreateEvent('$path')"; +} + +class ConstructableFileSystemDeleteEvent extends _ConstructableFileSystemEvent + implements FileSystemDeleteEvent { + final type = FileSystemEvent.DELETE; + + ConstructableFileSystemDeleteEvent(String path, bool isDirectory) + : super(path, isDirectory); + + String toString() => "FileSystemDeleteEvent('$path')"; +} + +class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent + implements FileSystemModifyEvent { + final bool contentChanged; + final type = FileSystemEvent.MODIFY; + + ConstructableFileSystemModifyEvent(String path, bool isDirectory, + this.contentChanged) + : super(path, isDirectory); + + String toString() => + "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; +} + +class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent + implements FileSystemMoveEvent { + final String destination; + final type = FileSystemEvent.MOVE; + + ConstructableFileSystemMoveEvent(String path, bool isDirectory, + this.destination) + : super(path, isDirectory); + + String toString() => "FileSystemMoveEvent('$path', '$destination')"; +} diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 4484c2b77..78b1174e1 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -9,6 +9,7 @@ import 'dart:io'; import 'watch_event.dart'; import 'directory_watcher/linux.dart'; +import 'directory_watcher/mac_os.dart'; import 'directory_watcher/polling.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something @@ -54,6 +55,7 @@ abstract class DirectoryWatcher { /// watchers. factory DirectoryWatcher(String directory, {Duration pollingDelay}) { if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); + if (Platform.isMacOS) return new MacOSDirectoryWatcher(directory); return new PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); } } diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 7ac6e6e08..f0622f646 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -12,8 +12,6 @@ import '../utils.dart'; import '../watch_event.dart'; import 'resubscribable.dart'; -import 'package:stack_trace/stack_trace.dart'; - /// Uses the inotify subsystem to watch for filesystem events. /// /// Inotify doesn't suport recursively watching subdirectories, nor does diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart new file mode 100644 index 000000000..9d3660df7 --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -0,0 +1,355 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.directory_watcher.mac_os; + +import 'dart:async'; +import 'dart:io'; + +import '../constructable_file_system_event.dart'; +import '../path_set.dart'; +import '../utils.dart'; +import '../watch_event.dart'; +import 'resubscribable.dart'; + +import 'package:path/path.dart' as p; + +/// Uses the FSEvents subsystem to watch for filesystem events. +/// +/// FSEvents has two main idiosyncrasies that this class works around. First, it +/// will occasionally report events that occurred before the filesystem watch +/// was initiated. Second, if multiple events happen to the same file in close +/// succession, it won't report them in the order they occurred. See issue +/// 14373. +/// +/// This also works around issues 14793, 14806, and 14849 in the implementation +/// of [Directory.watch]. +class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { + MacOSDirectoryWatcher(String directory) + : super(directory, () => new _MacOSDirectoryWatcher(directory)); +} + +class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + final String directory; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + /// The number of event batches that have been received from + /// [Directory.watch]. + /// + /// This is used to determine if the [Directory.watch] stream was falsely + /// closed due to issue 14849. A close caused by events in the past will only + /// happen before or immediately after the first batch of events. + int batches = 0; + + /// The set of files that are known to exist recursively within the watched + /// directory. + /// + /// The state of files on the filesystem is compared against this to determine + /// the real change that occurred when working around issue 14373. This is + /// also used to emit REMOVE events when subdirectories are moved out of the + /// watched directory. + final PathSet _files; + + /// The subscription to the stream returned by [Directory.watch]. + /// + /// This is separate from [_subscriptions] because this stream occasionally + /// needs to be resubscribed in order to work around issue 14849. + StreamSubscription _watchSubscription; + + /// A set of subscriptions that this watcher subscribes to. + /// + /// These are gathered together so that they may all be canceled when the + /// watcher is closed. This does not include [_watchSubscription]. + final _subscriptions = new Set(); + + _MacOSDirectoryWatcher(String directory) + : directory = directory, + _files = new PathSet(directory) { + _startWatch(); + + _listen(new Directory(directory).list(recursive: true), + (entity) { + if (entity is! Directory) _files.add(entity.path); + }, + onError: _emitError, + onDone: _readyCompleter.complete, + cancelOnError: true); + } + + void close() { + for (var subscription in _subscriptions) { + subscription.cancel(); + } + _subscriptions.clear(); + if (_watchSubscription != null) _watchSubscription.cancel(); + _watchSubscription = null; + _eventsController.close(); + } + + /// The callback that's run when [Directory.watch] emits a batch of events. + void _onBatch(List batch) { + batches++; + + _sortEvents(batch).forEach((path, events) { + var canonicalEvent = _canonicalEvent(events); + events = canonicalEvent == null ? + _eventsBasedOnFileSystem(path) : [canonicalEvent]; + + for (var event in events) { + if (event is FileSystemCreateEvent) { + if (!event.isDirectory) { + _emitEvent(ChangeType.ADD, path); + _files.add(path); + continue; + } + + _listen(new Directory(path).list(recursive: true), (entity) { + if (entity is Directory) return; + _emitEvent(ChangeType.ADD, entity.path); + _files.add(entity.path); + }, onError: _emitError, cancelOnError: true); + } else if (event is FileSystemModifyEvent) { + assert(!event.isDirectory); + _emitEvent(ChangeType.MODIFY, path); + } else { + assert(event is FileSystemDeleteEvent); + for (var removedPath in _files.remove(path)) { + _emitEvent(ChangeType.REMOVE, removedPath); + } + } + } + }); + } + + /// Sort all the events in a batch into sets based on their path. + /// + /// A single input event may result in multiple events in the returned map; + /// for example, a MOVE event becomes a DELETE event for the source and a + /// CREATE event for the destination. + /// + /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it + /// contain any events relating to [directory]. + Map> _sortEvents(List batch) { + var eventsForPaths = {}; + + // FSEvents can report past events, including events on the root directory + // such as it being created. We want to ignore these. If the directory is + // really deleted, that's handled by [_onDone]. + batch = batch.where((event) => event.path != directory).toList(); + + // Events within directories that already have events are superfluous; the + // directory's full contents will be examined anyway, so we ignore such + // events. Emitting them could cause useless or out-of-order events. + var directories = unionAll(batch.map((event) { + if (!event.isDirectory) return new Set(); + if (event is! FileSystemMoveEvent) return new Set.from([event.path]); + return new Set.from([event.path, event.destination]); + })); + + isInModifiedDirectory(path) => + directories.any((dir) => path != dir && path.startsWith(dir)); + + addEvent(path, event) { + if (isInModifiedDirectory(path)) return; + var set = eventsForPaths.putIfAbsent(path, () => new Set()); + set.add(event); + } + + for (var event in batch.where((event) => event is! FileSystemMoveEvent)) { + addEvent(event.path, event); + } + + // Issue 14806 means that move events can be misleading if they're in the + // same batch as another modification of a related file. If they are, we + // make the event set empty to ensure we check the state of the filesystem. + // Otherwise, treat them as a DELETE followed by an ADD. + for (var event in batch.where((event) => event is FileSystemMoveEvent)) { + if (eventsForPaths.containsKey(event.path) || + eventsForPaths.containsKey(event.destination)) { + + if (!isInModifiedDirectory(event.path)) { + eventsForPaths[event.path] = new Set(); + } + if (!isInModifiedDirectory(event.destination)) { + eventsForPaths[event.destination] = new Set(); + } + + continue; + } + + addEvent(event.path, new ConstructableFileSystemDeleteEvent( + event.path, event.isDirectory)); + addEvent(event.destination, new ConstructableFileSystemCreateEvent( + event.path, event.isDirectory)); + } + + return eventsForPaths; + } + + /// Returns the canonical event from a batch of events on the same path, if + /// one exists. + /// + /// If [batch] doesn't contain any contradictory events (e.g. DELETE and + /// CREATE, or events with different values for [isDirectory]), this returns a + /// single event that describes what happened to the path in question. + /// + /// If [batch] does contain contradictory events, this returns `null` to + /// indicate that the state of the path on the filesystem should be checked to + /// determine what occurred. + FileSystemEvent _canonicalEvent(Set batch) { + // An empty batch indicates that we've learned earlier that the batch is + // contradictory (e.g. because of a move). + if (batch.isEmpty) return null; + + var type = batch.first.type; + var isDir = batch.first.isDirectory; + + for (var event in batch.skip(1)) { + // If one event reports that the file is a directory and another event + // doesn't, that's a contradiction. + if (isDir != event.isDirectory) return null; + + // Modify events don't contradict either CREATE or REMOVE events. We can + // safely assume the file was modified after a CREATE or before the + // REMOVE; otherwise there will also be a REMOVE or CREATE event + // (respectively) that will be contradictory. + if (event is FileSystemModifyEvent) continue; + assert(event is FileSystemCreateEvent || event is FileSystemDeleteEvent); + + // If we previously thought this was a MODIFY, we now consider it to be a + // CREATE or REMOVE event. This is safe for the same reason as above. + if (type == FileSystemEvent.MODIFY) { + type = event.type; + continue; + } + + // A CREATE event contradicts a REMOVE event and vice versa. + assert(type == FileSystemEvent.CREATE || type == FileSystemEvent.DELETE); + if (type != event.type) return null; + } + + switch (type) { + case FileSystemEvent.CREATE: + // Issue 14793 means that CREATE events can actually mean DELETE, so we + // should always check the filesystem for them. + return null; + case FileSystemEvent.DELETE: + return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + case FileSystemEvent.MODIFY: + return new ConstructableFileSystemModifyEvent( + batch.first.path, isDir, false); + default: assert(false); + } + } + + /// Returns one or more events that describe the change between the last known + /// state of [path] and its current state on the filesystem. + /// + /// This returns a list whose order should be reflected in the events emitted + /// to the user, unlike the batched events from [Directory.watch]. The + /// returned list may be empty, indicating that no changes occurred to [path] + /// (probably indicating that it was created and then immediately deleted). + List _eventsBasedOnFileSystem(String path) { + var fileExisted = _files.contains(path); + var dirExisted = _files.containsDir(path); + var fileExists = new File(path).existsSync(); + var dirExists = new Directory(path).existsSync(); + + var events = []; + if (fileExisted) { + if (fileExists) { + events.add(new ConstructableFileSystemModifyEvent(path, false, false)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, false)); + } + } else if (dirExisted) { + if (dirExists) { + // If we got contradictory events for a directory that used to exist and + // still exists, we need to rescan the whole thing in case it was + // replaced with a different directory. + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + } + } + + if (!fileExisted && fileExists) { + events.add(new ConstructableFileSystemCreateEvent(path, false)); + } else if (!dirExisted && dirExists) { + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } + + return events; + } + + /// The callback that's run when the [Directory.watch] stream is closed. + void _onDone() { + _watchSubscription = null; + + // If the directory still exists and we haven't seen more than one batch, + // this is probably issue 14849 rather than a real close event. We should + // just restart the watcher. + if (batches < 2 && new Directory(directory).existsSync()) { + _startWatch(); + return; + } + + // FSEvents can fail to report the contents of the directory being removed + // when the directory itself is removed, so we need to manually mark the as + // removed. + for (var file in _files.toSet()) { + _emitEvent(ChangeType.REMOVE, file); + } + _files.clear(); + close(); + } + + /// Start or restart the underlying [Directory.watch] stream. + void _startWatch() { + // Batch the FSEvent changes together so that we can dedup events. + var innerStream = new Directory(directory).watch(recursive: true).transform( + new BatchedStreamTransformer()); + _watchSubscription = innerStream.listen(_onBatch, + onError: _eventsController.addError, + onDone: _onDone); + } + + /// Emit an event with the given [type] and [path]. + void _emitEvent(ChangeType type, String path) { + if (!isReady) return; + + // Don't emit ADD events for files that we already know about. Such an event + // probably comes from FSEvents reporting an add that happened prior to the + // watch beginning. + if (type == ChangeType.ADD && _files.contains(path)) return; + + _eventsController.add(new WatchEvent(type, path)); + } + + /// Emit an error, then close the watcher. + void _emitError(error, StackTrace stackTrace) { + _eventsController.add(error, stackTrace); + close(); + } + + /// Like [Stream.listen], but automatically adds the subscription to + /// [_subscriptions] so that it can be canceled when [close] is called. + void _listen(Stream stream, void onData(event), {Function onError, + void onDone(), bool cancelOnError}) { + var subscription; + subscription = stream.listen(onData, onError: onError, onDone: () { + _subscriptions.remove(subscription); + if (onDone != null) onDone(); + }, cancelOnError: cancelOnError); + _subscriptions.add(subscription); + } +} diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart new file mode 100644 index 000000000..01d4208f4 --- /dev/null +++ b/pkgs/watcher/lib/src/path_set.dart @@ -0,0 +1,168 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.path_dart; + +import 'dart:collection'; + +import 'package:path/path.dart' as p; + +/// A set of paths, organized into a directory hierarchy. +/// +/// When a path is [add]ed, it creates an implicit directory structure above +/// that path. Directories can be inspected using [containsDir] and removed +/// using [remove]. If they're removed, their contents are removed as well. +/// +/// The paths in the set are normalized so that they all begin with [root]. +class PathSet { + /// The root path, which all paths in the set must be under. + final String root; + + /// The path set's directory hierarchy. + /// + /// Each level of this hierarchy has the same structure: a map from strings to + /// other maps, which are further levels of the hierarchy. A map with no + /// elements indicates a path that was added to the set that has no paths + /// beneath it. Such a path should not be treated as a directory by + /// [containsDir]. + final _entries = new Map(); + + /// The set of paths that were explicitly added to this set. + /// + /// This is needed to disambiguate a directory that was explicitly added to + /// the set from a directory that was implicitly added by adding a path + /// beneath it. + final _paths = new Set(); + + PathSet(this.root); + + /// Adds [path] to the set. + void add(String path) { + path = _normalize(path); + _paths.add(path); + + var parts = _split(path); + var dir = _entries; + for (var part in parts) { + dir = dir.putIfAbsent(part, () => {}); + } + } + + /// Removes [path] and any paths beneath it from the set and returns the + /// removed paths. + /// + /// Even if [path] itself isn't in the set, if it's a directory containing + /// paths that are in the set those paths will be removed and returned. + /// + /// If neither [path] nor any paths beneath it are in the set, returns an + /// empty set. + Set remove(String path) { + path = _normalize(path); + var parts = new Queue.from(_split(path)); + + // Remove the children of [dir], as well as [dir] itself if necessary. + // + // [partialPath] is the path to [dir], and a prefix of [path]; the remaining + // components of [path] are in [parts]. + recurse(dir, partialPath) { + if (parts.length > 1) { + // If there's more than one component left in [path], recurse down to + // the next level. + var part = parts.removeFirst(); + var entry = dir[part]; + if (entry.isEmpty) return new Set(); + + partialPath = p.join(partialPath, part); + var paths = recurse(entry, partialPath); + // After removing this entry's children, if it has no more children and + // it's not in the set in its own right, remove it as well. + if (entry.isEmpty && !_paths.contains(partialPath)) dir.remove(part); + return paths; + } + + // If there's only one component left in [path], we should remove it. + var entry = dir.remove(parts.first); + if (entry == null) return new Set(); + + if (entry.isEmpty) { + _paths.remove(path); + return new Set.from([path]); + } + + var set = _removePathsIn(entry, path); + if (_paths.contains(path)) { + _paths.remove(path); + set.add(path); + } + return set; + } + + return recurse(_entries, root); + } + + /// Recursively removes and returns all paths in [dir]. + /// + /// [root] should be the path to [dir]. + Set _removePathsIn(Map dir, String root) { + var removedPaths = new Set(); + recurse(dir, path) { + dir.forEach((name, entry) { + var entryPath = p.join(path, name); + if (_paths.remove(entryPath)) removedPaths.add(entryPath); + recurse(entry, entryPath); + }); + } + + recurse(dir, root); + return removedPaths; + } + + /// Returns whether [this] contains [path]. + /// + /// This only returns true for paths explicitly added to [this]. + /// Implicitly-added directories can be inspected using [containsDir]. + bool contains(String path) => _paths.contains(_normalize(path)); + + /// Returns whether [this] contains paths beneath [path]. + bool containsDir(String path) { + path = _normalize(path); + var dir = _entries; + + for (var part in _split(path)) { + dir = dir[part]; + if (dir == null) return false; + } + + return !dir.isEmpty; + } + + /// Returns a [Set] of all paths in [this]. + Set toSet() => _paths.toSet(); + + /// Removes all paths from [this]. + void clear() { + _paths.clear(); + _entries.clear(); + } + + String toString() => _paths.toString(); + + /// Returns a normalized version of [path]. + /// + /// This removes any extra ".." or "."s and ensure that the returned path + /// begins with [root]. It's an error if [path] isn't within [root]. + String _normalize(String path) { + var relative = p.relative(p.normalize(path), from: root); + var parts = p.split(relative); + // TODO(nweiz): replace this with [p.isWithin] when that exists (issue + // 14980). + if (!p.isRelative(relative) || parts.first == '..' || parts.first == '.') { + throw new ArgumentError('Path "$path" is not inside "$root".'); + } + return p.join(root, relative); + } + + /// Returns the segments of [path] beneath [root]. + List _split(String path) => p.split(p.relative(path, from: root)); +} diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index e4e445794..66c0f09cf 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -18,6 +18,10 @@ bool isDirectoryNotFoundException(error) { return error.osError.errorCode == notFoundCode; } +/// Returns the union of all elements in each set in [sets]. +Set unionAll(Iterable sets) => + sets.fold(new Set(), (union, set) => union.union(set)); + /// Returns a buffered stream that will emit the same values as the stream /// returned by [future] once [future] completes. /// diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart new file mode 100644 index 000000000..f7f8176ae --- /dev/null +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/mac_os.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); + + test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { + expect(new DirectoryWatcher('.'), + new isInstanceOf()); + }); + + test('does not notify about the watched directory being deleted and ' + 'recreated immediately before watching', () { + createDir("dir"); + writeFile("dir/old.txt"); + deleteDir("dir"); + createDir("dir"); + + startWatcher(dir: "dir"); + writeFile("dir/newer.txt"); + expectAddEvent("dir/newer.txt"); + }); + + test('notifies even if the file contents are unchanged', () { + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "before"); + startWatcher(); + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "after"); + expectModifyEvent("a.txt"); + expectModifyEvent("b.txt"); + }); + + test('emits events for many nested files moved out then immediately back in', + () { + withPermutations((i, j, k) => + writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + startWatcher(dir: "dir"); + + renameDir("dir/sub", "sub"); + renameDir("sub", "dir/sub"); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + + inAnyOrder(() { + withPermutations((i, j, k) => + expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + }); +} diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index eed606931..34b5e6284 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -6,6 +6,8 @@ import 'package:scheduled_test/scheduled_test.dart'; import '../utils.dart'; +import 'dart:async'; + sharedTests() { test('does not notify for files that already exist when started', () { // Make some pre-existing files. @@ -218,5 +220,21 @@ sharedTests() { }); }); }); + + test("emits events for many files added at once in a subdirectory with the " + "same name as a removed file", () { + writeFile("dir/sub"); + withPermutations((i, j, k) => + writeFile("old/sub-$i/sub-$j/file-$k.txt")); + startWatcher(dir: "dir"); + + deleteFile("dir/sub"); + renameDir("old", "dir/sub"); + inAnyOrder(() { + expectRemoveEvent("dir/sub"); + withPermutations((i, j, k) => + expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + }); + }); }); } diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart new file mode 100644 index 000000000..3862134d6 --- /dev/null +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -0,0 +1,46 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/mac_os.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +// This is currently failing due to issue 14793. The reason is fairly complex: +// +// 1. As part of the test, an "unwatched.txt" file is created while there are no +// active watchers on the containing directory. +// +// 2. A watcher is then added. +// +// 3. The watcher lists the contents of the directory and notices that +// "unwatched.txt" already exists. +// +// 4. Since FSEvents reports past changes (issue 14373), the IO event stream +// emits a CREATED event for "unwatched.txt". +// +// 5. Due to issue 14793, the watcher cannot trust that this is really a CREATED +// event and checks the status of "unwatched.txt" on the filesystem against +// its internal state. +// +// 6. "unwatched.txt" exists on the filesystem and the watcher knows about it +// internally as well. It assumes this means that the file was modified. +// +// 7. The watcher emits an unexpected MODIFIED event for "unwatched.txt", +// causing the test to fail. +// +// Once issue 14793 is fixed, this will no longer be the case and the test will +// work again. + +main() { + initConfig(); + + watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart new file mode 100644 index 000000000..cc8932d78 --- /dev/null +++ b/pkgs/watcher/test/path_set_test.dart @@ -0,0 +1,235 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:path/path.dart' as p; +import 'package:unittest/unittest.dart'; +import 'package:watcher/src/path_set.dart'; + +import 'utils.dart'; + +Matcher containsPath(String path) => predicate((set) => + set is PathSet && set.contains(path), + 'set contains "$path"'); + +Matcher containsDir(String path) => predicate((set) => + set is PathSet && set.containsDir(path), + 'set contains directory "$path"'); + +void main() { + initConfig(); + + var set; + setUp(() => set = new PathSet("root")); + + group("adding a path", () { + test("stores the path in the set", () { + set.add("root/path/to/file"); + expect(set, containsPath("root/path/to/file")); + }); + + test("that's a subdir of another path keeps both in the set", () { + set.add("root/path"); + set.add("root/path/to/file"); + expect(set, containsPath("root/path")); + expect(set, containsPath("root/path/to/file")); + }); + + test("that's not normalized normalizes the path before storing it", () { + set.add("root/../root/path/to/../to/././file"); + expect(set, containsPath("root/path/to/file")); + }); + + test("that's absolute normalizes the path before storing it", () { + set.add(p.absolute("root/path/to/file")); + expect(set, containsPath("root/path/to/file")); + }); + + test("that's not beneath the root throws an error", () { + expect(() => set.add("path/to/file"), throwsArgumentError); + }); + }); + + group("removing a path", () { + test("that's in the set removes and returns that path", () { + set.add("root/path/to/file"); + expect(set.remove("root/path/to/file"), + unorderedEquals(["root/path/to/file"])); + expect(set, isNot(containsPath("root/path/to/file"))); + }); + + test("that's not in the set returns an empty set", () { + set.add("root/path/to/file"); + expect(set.remove("root/path/to/nothing"), isEmpty); + }); + + test("that's a directory removes and returns all files beneath it", () { + set.add("root/outside"); + set.add("root/path/to/one"); + set.add("root/path/to/two"); + set.add("root/path/to/sub/three"); + + expect(set.remove("root/path"), unorderedEquals([ + "root/path/to/one", + "root/path/to/two", + "root/path/to/sub/three" + ])); + + expect(set, containsPath("root/outside")); + expect(set, isNot(containsPath("root/path/to/one"))); + expect(set, isNot(containsPath("root/path/to/two"))); + expect(set, isNot(containsPath("root/path/to/sub/three"))); + }); + + test("that's a directory in the set removes and returns it and all files " + "beneath it", () { + set.add("root/path"); + set.add("root/path/to/one"); + set.add("root/path/to/two"); + set.add("root/path/to/sub/three"); + + expect(set.remove("root/path"), unorderedEquals([ + "root/path", + "root/path/to/one", + "root/path/to/two", + "root/path/to/sub/three" + ])); + + expect(set, isNot(containsPath("root/path"))); + expect(set, isNot(containsPath("root/path/to/one"))); + expect(set, isNot(containsPath("root/path/to/two"))); + expect(set, isNot(containsPath("root/path/to/sub/three"))); + }); + + test("that's not normalized removes and returns the normalized path", () { + set.add("root/path/to/file"); + expect(set.remove("root/../root/path/to/../to/./file"), + unorderedEquals(["root/path/to/file"])); + }); + + test("that's absolute removes and returns the normalized path", () { + set.add("root/path/to/file"); + expect(set.remove(p.absolute("root/path/to/file")), + unorderedEquals(["root/path/to/file"])); + }); + + test("that's not beneath the root throws an error", () { + expect(() => set.remove("path/to/file"), throwsArgumentError); + }); + }); + + group("containsPath()", () { + test("returns false for a non-existent path", () { + set.add("root/path/to/file"); + expect(set, isNot(containsPath("root/path/to/nothing"))); + }); + + test("returns false for a directory that wasn't added explicitly", () { + set.add("root/path/to/file"); + expect(set, isNot(containsPath("root/path"))); + }); + + test("returns true for a directory that was added explicitly", () { + set.add("root/path"); + set.add("root/path/to/file"); + expect(set, containsPath("root/path")); + }); + + test("with a non-normalized path normalizes the path before looking it up", + () { + set.add("root/path/to/file"); + expect(set, containsPath("root/../root/path/to/../to/././file")); + }); + + test("with an absolute path normalizes the path before looking it up", () { + set.add("root/path/to/file"); + expect(set, containsPath(p.absolute("root/path/to/file"))); + }); + + test("with a path that's not beneath the root throws an error", () { + expect(() => set.contains("path/to/file"), throwsArgumentError); + }); + }); + + group("containsDir()", () { + test("returns true for a directory that was added implicitly", () { + set.add("root/path/to/file"); + expect(set, containsDir("root/path")); + expect(set, containsDir("root/path/to")); + }); + + test("returns true for a directory that was added explicitly", () { + set.add("root/path"); + set.add("root/path/to/file"); + expect(set, containsDir("root/path")); + }); + + test("returns false for a directory that wasn't added", () { + expect(set, isNot(containsDir("root/nothing"))); + }); + + test("returns false for a non-directory path that was added", () { + set.add("root/path/to/file"); + expect(set, isNot(containsDir("root/path/to/file"))); + }); + + test("returns false for a directory that was added implicitly and then " + "removed implicitly", () { + set.add("root/path/to/file"); + set.remove("root/path/to/file"); + expect(set, isNot(containsDir("root/path"))); + }); + + test("returns false for a directory that was added explicitly whose " + "children were then removed", () { + set.add("root/path"); + set.add("root/path/to/file"); + set.remove("root/path/to/file"); + expect(set, isNot(containsDir("root/path"))); + }); + + test("with a non-normalized path normalizes the path before looking it up", + () { + set.add("root/path/to/file"); + expect(set, containsDir("root/../root/path/to/../to/.")); + }); + + test("with an absolute path normalizes the path before looking it up", () { + set.add("root/path/to/file"); + expect(set, containsDir(p.absolute("root/path"))); + }); + }); + + group("toSet", () { + test("returns paths added to the set", () { + set.add("root/path"); + set.add("root/path/to/one"); + set.add("root/path/to/two"); + + expect(set.toSet(), unorderedEquals([ + "root/path", + "root/path/to/one", + "root/path/to/two", + ])); + }); + + test("doesn't return paths removed from the set", () { + set.add("root/path/to/one"); + set.add("root/path/to/two"); + set.remove("root/path/to/two"); + + expect(set.toSet(), unorderedEquals(["root/path/to/one"])); + }); + }); + + group("clear", () { + test("removes all paths from the set", () { + set.add("root/path"); + set.add("root/path/to/one"); + set.add("root/path/to/two"); + + set.clear(); + expect(set.toSet(), isEmpty); + }); + }); +} diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart new file mode 100644 index 000000000..e0275c4ee --- /dev/null +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/mac_os.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); +} \ No newline at end of file diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 3070d7906..e18c7e813 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -137,6 +137,8 @@ void startWatcher({String dir}) { // people think it might be the root cause. if (currentSchedule.errors.isEmpty) { expect(allEvents, hasLength(numEvents)); + } else { + currentSchedule.addDebugInfo("Events fired:\n${allEvents.join('\n')}"); } }, "reset watcher"); From 1918a1ad6618809b68f349346d6cfac9d2849778 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 11 Nov 2013 21:01:41 +0000 Subject: [PATCH 0072/1215] Make path_set_test use Windows-friendly paths where necessary. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//68683004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30171 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/path_set_test.dart | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index cc8932d78..dc1f72977 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -54,7 +54,7 @@ void main() { test("that's in the set removes and returns that path", () { set.add("root/path/to/file"); expect(set.remove("root/path/to/file"), - unorderedEquals(["root/path/to/file"])); + unorderedEquals([p.normalize("root/path/to/file")])); expect(set, isNot(containsPath("root/path/to/file"))); }); @@ -73,7 +73,7 @@ void main() { "root/path/to/one", "root/path/to/two", "root/path/to/sub/three" - ])); + ].map(p.normalize))); expect(set, containsPath("root/outside")); expect(set, isNot(containsPath("root/path/to/one"))); @@ -93,7 +93,7 @@ void main() { "root/path/to/one", "root/path/to/two", "root/path/to/sub/three" - ])); + ].map(p.normalize))); expect(set, isNot(containsPath("root/path"))); expect(set, isNot(containsPath("root/path/to/one"))); @@ -104,13 +104,13 @@ void main() { test("that's not normalized removes and returns the normalized path", () { set.add("root/path/to/file"); expect(set.remove("root/../root/path/to/../to/./file"), - unorderedEquals(["root/path/to/file"])); + unorderedEquals([p.normalize("root/path/to/file")])); }); test("that's absolute removes and returns the normalized path", () { set.add("root/path/to/file"); expect(set.remove(p.absolute("root/path/to/file")), - unorderedEquals(["root/path/to/file"])); + unorderedEquals([p.normalize("root/path/to/file")])); }); test("that's not beneath the root throws an error", () { @@ -210,7 +210,7 @@ void main() { "root/path", "root/path/to/one", "root/path/to/two", - ])); + ].map(p.normalize))); }); test("doesn't return paths removed from the set", () { @@ -218,7 +218,7 @@ void main() { set.add("root/path/to/two"); set.remove("root/path/to/two"); - expect(set.toSet(), unorderedEquals(["root/path/to/one"])); + expect(set.toSet(), unorderedEquals([p.normalizze("root/path/to/one")])); }); }); From 00908271600de1d70cc5aa1062546d1ea6b47d51 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 11 Nov 2013 21:02:06 +0000 Subject: [PATCH 0073/1215] Fix some analyzer warnings and hints in pkg/watcher. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//69013003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30172 260f80e4-7a28-3924-810f-c04153c831b5 --- .../src/constructable_file_system_event.dart | 2 +- .../lib/src/directory_watcher/linux.dart | 1 - .../lib/src/directory_watcher/mac_os.dart | 4 +--- .../lib/src/directory_watcher/polling.dart | 1 - .../src/directory_watcher/resubscribable.dart | 2 -- .../watcher/test/directory_watcher/shared.dart | 2 -- pkgs/watcher/test/no_subscription/shared.dart | 16 ++++++++++++---- pkgs/watcher/test/utils.dart | 18 +++++++++++------- 8 files changed, 25 insertions(+), 21 deletions(-) diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index e65e25827..010d2979d 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -9,7 +9,7 @@ import 'dart:io'; abstract class _ConstructableFileSystemEvent implements FileSystemEvent { final bool isDirectory; final String path; - final int type; + int get type; _ConstructableFileSystemEvent(this.path, this.isDirectory); } diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index f0622f646..519607839 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -7,7 +7,6 @@ library watcher.directory_watcher.linux; import 'dart:async'; import 'dart:io'; -import '../directory_watcher.dart'; import '../utils.dart'; import '../watch_event.dart'; import 'resubscribable.dart'; diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 9d3660df7..5b1feb342 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -13,8 +13,6 @@ import '../utils.dart'; import '../watch_event.dart'; import 'resubscribable.dart'; -import 'package:path/path.dart' as p; - /// Uses the FSEvents subsystem to watch for filesystem events. /// /// FSEvents has two main idiosyncrasies that this class works around. First, it @@ -337,7 +335,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Emit an error, then close the watcher. void _emitError(error, StackTrace stackTrace) { - _eventsController.add(error, stackTrace); + _eventsController.addError(error, stackTrace); close(); } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 91ca005f3..0e190b02b 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -10,7 +10,6 @@ import 'dart:io'; import 'package:crypto/crypto.dart'; import '../async_queue.dart'; -import '../directory_watcher.dart'; import '../stat.dart'; import '../utils.dart'; import '../watch_event.dart'; diff --git a/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart b/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart index daa813a3e..7d99fc05b 100644 --- a/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart +++ b/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart @@ -5,10 +5,8 @@ library watcher.directory_watcher.resubscribable; import 'dart:async'; -import 'dart:io'; import '../directory_watcher.dart'; -import '../utils.dart'; import '../watch_event.dart'; typedef ManuallyClosedDirectoryWatcher WatcherFactory(); diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 34b5e6284..fe76a03d3 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -6,8 +6,6 @@ import 'package:scheduled_test/scheduled_test.dart'; import '../utils.dart'; -import 'dart:async'; - sharedTests() { test('does not notify for files that already exist when started', () { // Make some pre-existing files. diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index cd279e1ca..6623ba363 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -19,8 +19,7 @@ sharedTests() { // Subscribe to the events. var completer = new Completer(); var subscription = watcher.events.listen(wrapAsync((event) { - expect(event.type, equals(ChangeType.ADD)); - expect(event.path, endsWith("file.txt")); + expect(event, isWatchEvent(ChangeType.ADD, "file.txt")); completer.complete(); })); @@ -41,10 +40,19 @@ sharedTests() { schedule(() { completer = new Completer(); subscription = watcher.events.listen(wrapAsync((event) { + // TODO(nweiz): Remove this when either issue 14373 or 14793 is fixed. + // Issue 14373 means that the new [Directory.watch] will emit an event + // for "unwatched.txt" being created, and issue 14793 means we have to + // check the filesystem, which leads us to assume that the file has been + // modified. + if (Platform.isMacOS && event.path.endsWith("unwatched.txt")) { + expect(event, isWatchEvent(ChangeType.MODIFY, "unwatched.txt")); + return; + } + // We should get an event for the third file, not the one added while // we weren't subscribed. - expect(event.type, equals(ChangeType.ADD)); - expect(event.path, endsWith("added.txt")); + expect(event, isWatchEvent(ChangeType.ADD, "added.txt")); completer.complete(); })); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index e18c7e813..651fd6de4 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -176,11 +176,6 @@ void inAnyOrder(block()) { /// Multiple calls to [expectEvent] require that the events are received in that /// order unless they're called in an [inAnyOrder] block. void expectEvent(ChangeType type, String path) { - var matcher = predicate((e) { - return e is WatchEvent && e.type == type && - e.path == p.join(_sandboxDir, p.normalize(path)); - }, "is $type $path"); - if (_unorderedEventFuture != null) { // Assign this to a local variable since it will be un-assigned by the time // the scheduled callback runs. @@ -188,7 +183,7 @@ void expectEvent(ChangeType type, String path) { expect( schedule(() => future, "should fire $type event on $path"), - completion(contains(matcher))); + completion(contains(isWatchEvent(type, path)))); } else { var future = currentSchedule.wrapFuture( _watcherEvents.elementAt(_nextEvent), @@ -196,11 +191,20 @@ void expectEvent(ChangeType type, String path) { expect( schedule(() => future, "should fire $type event on $path"), - completion(matcher)); + completion(isWatchEvent(type, path))); } _nextEvent++; } +/// Returns a matcher that matches a [WatchEvent] with the given [type] and +/// [path]. +Match isWatchEvent(ChangeType type, String path) { + return predicate((e) { + return e is WatchEvent && e.type == type && + e.path == p.join(_sandboxDir, p.normalize(path)); + }, "is $type $path"); +} + void expectAddEvent(String path) => expectEvent(ChangeType.ADD, path); void expectModifyEvent(String path) => expectEvent(ChangeType.MODIFY, path); void expectRemoveEvent(String path) => expectEvent(ChangeType.REMOVE, path); From a05fcc1851ea931461fb49b7d76c73245a89265c Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 11 Nov 2013 21:20:51 +0000 Subject: [PATCH 0074/1215] Fix a typo in path_set_test. I'd have sworn I fixed this in the orignal CL. R=rnystrom@google.com TBR Review URL: https://codereview.chromium.org//67973003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30173 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/path_set_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index dc1f72977..f433ad3c3 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -218,7 +218,7 @@ void main() { set.add("root/path/to/two"); set.remove("root/path/to/two"); - expect(set.toSet(), unorderedEquals([p.normalizze("root/path/to/one")])); + expect(set.toSet(), unorderedEquals([p.normalize("root/path/to/one")])); }); }); From 85894abd806ad30ca2991c8ef51d0cb976a4f554 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 11 Nov 2013 21:26:11 +0000 Subject: [PATCH 0075/1215] Work around a flake in the Mac OS watcher test on the bots. Issues 14373 and 14793 were tag-teaming to cause no_subscription_test to fail for the Mac OS watcher occasionally. This also marks directory_watcher/mac_os_test as timing out, apparently due to issue 14943. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//59143006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30174 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/no_subscription/shared.dart | 1 + pkgs/watcher/test/utils.dart | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 6623ba363..de625d51d 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:io'; import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 651fd6de4..136c8b014 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -198,7 +198,7 @@ void expectEvent(ChangeType type, String path) { /// Returns a matcher that matches a [WatchEvent] with the given [type] and /// [path]. -Match isWatchEvent(ChangeType type, String path) { +Matcher isWatchEvent(ChangeType type, String path) { return predicate((e) { return e is WatchEvent && e.type == type && e.path == p.join(_sandboxDir, p.normalize(path)); From f76c642db49a72e64a1a7cf7661009c638d00658 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 01:42:00 +0000 Subject: [PATCH 0076/1215] Properly close watcher streams during tests. This also makes [futureStream] pass cancellations through to the underlying stream, and adds the ability for it to return broadcast streams. R=rnystrom@google.com BUG=14943 Review URL: https://codereview.chromium.org//66293008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30180 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/utils.dart | 43 +++++++++++++++++++++++++++------ pkgs/watcher/test/utils.dart | 2 +- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 66c0f09cf..a64575b9f 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -27,17 +27,44 @@ Set unionAll(Iterable sets) => /// /// If [future] completes to an error, the return value will emit that error and /// then close. -Stream futureStream(Future future) { - var controller = new StreamController(sync: true); - future.then((stream) { - stream.listen( - controller.add, - onError: controller.addError, - onDone: controller.close); - }).catchError((e, stackTrace) { +/// +/// If [broadcast] is true, a broadcast stream is returned. This assumes that +/// the stream returned by [future] will be a broadcast stream as well. +/// [broadcast] defaults to false. +Stream futureStream(Future future, {bool broadcast: false}) { + var subscription; + var controller; + + future = future.catchError((e, stackTrace) { + if (controller == null) return; controller.addError(e, stackTrace); controller.close(); + controller = null; }); + + onListen() { + future.then((stream) { + if (controller == null) return; + subscription = stream.listen( + controller.add, + onError: controller.addError, + onDone: controller.close); + }); + } + + onCancel() { + if (subscription != null) subscription.cancel(); + subscription = null; + controller = null; + } + + if (broadcast) { + controller = new StreamController.broadcast( + sync: true, onListen: onListen, onCancel: onCancel); + } else { + controller = new StreamController( + sync: true, onListen: onListen, onCancel: onCancel); + } return controller.stream; } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 136c8b014..567bdb221 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -143,7 +143,7 @@ void startWatcher({String dir}) { }, "reset watcher"); return _watcher.events; - }, "create watcher")).asBroadcastStream(); + }, "create watcher"), broadcast: true); schedule(() => _watcher.ready, "wait for watcher to be ready"); } From 713dcc22febf47ad64dc3b3024dcce5ba61eabc2 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 01:43:38 +0000 Subject: [PATCH 0077/1215] Add a bunch of debugging prints to the Mac OS watcher. This should help debug the intermittent, difficult-to-reproduce issues on the vm-mac-release bot. R=rnystrom@google.com Review URL: https://codereview.chromium.org//68293005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30181 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 5b1feb342..3063e0915 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,6 +7,8 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import 'package:path/path.dart' as p; + import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -78,7 +80,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: _readyCompleter.complete, + onDone: () { + if (_runningOnBuildbot) { + print("watcher is ready"); + } + _readyCompleter.complete(); + }, cancelOnError: true); } @@ -94,12 +101,38 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { + if (_runningOnBuildbot) { + print("======== batch:"); + for (var event in batch) { + print(" ${_formatEvent(event)}"); + } + + print("known files:"); + for (var foo in _files.toSet()) { + print(" ${p.relative(foo, from: directory)}"); + } + } + batches++; _sortEvents(batch).forEach((path, events) { + var relativePath = p.relative(path, from: directory); + if (_runningOnBuildbot) { + print("events for $relativePath:\n"); + for (var event in events) { + print(" ${_formatEvent(event)}"); + } + } + var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; + if (_runningOnBuildbot) { + print("canonical event for $relativePath: " + "${_formatEvent(canonicalEvent)}"); + print("actionable events for $relativePath: " + "${events.map(_formatEvent)}"); + } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -113,7 +146,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: _emitError, cancelOnError: true); + }, onError: (e, stackTrace) { + if (_runningOnBuildbot) { + print("got error listing $relativePath: $e"); + } + _emitError(e, stackTrace); + }, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -125,6 +163,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); + + if (_runningOnBuildbot) { + print("========"); + } } /// Sort all the events in a batch into sets based on their path. @@ -261,6 +303,13 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); + if (_runningOnBuildbot) { + print("file existed: $fileExisted"); + print("dir existed: $dirExisted"); + print("file exists: $fileExists"); + print("dir exists: $dirExists"); + } + var events = []; if (fileExisted) { if (fileExists) { @@ -330,6 +379,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; + if (_runningOnBuildbot) { + print("emitting $type ${p.relative(path, from: directory)}"); + } + _eventsController.add(new WatchEvent(type, path)); } @@ -350,4 +403,27 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } + + /// Return a human-friendly string representation of [event]. + String _formatEvent(FileSystemEvent event) { + if (event == null) return 'null'; + + var path = p.relative(event.path, from: directory); + var type = event.isDirectory ? 'directory' : 'file'; + if (event is FileSystemCreateEvent) { + return "create $type $path"; + } else if (event is FileSystemDeleteEvent) { + return "delete $type $path"; + } else if (event is FileSystemModifyEvent) { + return "modify $type $path"; + } else if (event is FileSystemMoveEvent) { + return "move $type $path to " + "${p.relative(event.destination, from: directory)}"; + } + } + + // TODO(nweiz): remove this when the buildbots calm down. + /// Whether this code is running on a buildbot. + bool get _runningOnBuildbot => + Platform.environment.containsKey('BUILDBOT_BUILDERNAME'); } From 51905f5a941f724af4c9ffa230997e61d7045c54 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 01:56:18 +0000 Subject: [PATCH 0078/1215] Fix a synchronous event bug in futureStream. R=rnystrom@google.com TBR Review URL: https://codereview.chromium.org//68713004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30182 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/utils.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index a64575b9f..a235f7da5 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -36,9 +36,10 @@ Stream futureStream(Future future, {bool broadcast: false}) { var controller; future = future.catchError((e, stackTrace) { - if (controller == null) return; - controller.addError(e, stackTrace); - controller.close(); + // Since [controller] is synchronous, it's likely that emitting an error + // will cause it to be cancelled before we call close. + if (controller != null) controller.addError(e, stackTrace); + if (controller != null) controller.close(); controller = null; }); From 782237371f6aaaf02eb69d58643bda969e5d011d Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 02:23:05 +0000 Subject: [PATCH 0079/1215] Revert "Add a bunch of debugging prints to the Mac OS watcher." This reverts r30181. This CL causes the pub tests to fail due to excess output, so I didn't want to leave it in the build overnight. In addition, it didn't seem to be working; no additional output was being printed in the tests. It's possible BUILDBOT_BUILDERNAME isn't being set on vm-mac-release. This also marks the directory_watcher/mac_os_test as flaky. R=rnystrom@google.com TBR Review URL: https://codereview.chromium.org//68203008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30184 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 80 +------------------ 1 file changed, 2 insertions(+), 78 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 3063e0915..5b1feb342 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; -import 'package:path/path.dart' as p; - import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -80,12 +78,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: () { - if (_runningOnBuildbot) { - print("watcher is ready"); - } - _readyCompleter.complete(); - }, + onDone: _readyCompleter.complete, cancelOnError: true); } @@ -101,38 +94,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { - if (_runningOnBuildbot) { - print("======== batch:"); - for (var event in batch) { - print(" ${_formatEvent(event)}"); - } - - print("known files:"); - for (var foo in _files.toSet()) { - print(" ${p.relative(foo, from: directory)}"); - } - } - batches++; _sortEvents(batch).forEach((path, events) { - var relativePath = p.relative(path, from: directory); - if (_runningOnBuildbot) { - print("events for $relativePath:\n"); - for (var event in events) { - print(" ${_formatEvent(event)}"); - } - } - var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; - if (_runningOnBuildbot) { - print("canonical event for $relativePath: " - "${_formatEvent(canonicalEvent)}"); - print("actionable events for $relativePath: " - "${events.map(_formatEvent)}"); - } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -146,12 +113,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (e, stackTrace) { - if (_runningOnBuildbot) { - print("got error listing $relativePath: $e"); - } - _emitError(e, stackTrace); - }, cancelOnError: true); + }, onError: _emitError, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -163,10 +125,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); - - if (_runningOnBuildbot) { - print("========"); - } } /// Sort all the events in a batch into sets based on their path. @@ -303,13 +261,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - if (_runningOnBuildbot) { - print("file existed: $fileExisted"); - print("dir existed: $dirExisted"); - print("file exists: $fileExists"); - print("dir exists: $dirExists"); - } - var events = []; if (fileExisted) { if (fileExists) { @@ -379,10 +330,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; - if (_runningOnBuildbot) { - print("emitting $type ${p.relative(path, from: directory)}"); - } - _eventsController.add(new WatchEvent(type, path)); } @@ -403,27 +350,4 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } - - /// Return a human-friendly string representation of [event]. - String _formatEvent(FileSystemEvent event) { - if (event == null) return 'null'; - - var path = p.relative(event.path, from: directory); - var type = event.isDirectory ? 'directory' : 'file'; - if (event is FileSystemCreateEvent) { - return "create $type $path"; - } else if (event is FileSystemDeleteEvent) { - return "delete $type $path"; - } else if (event is FileSystemModifyEvent) { - return "modify $type $path"; - } else if (event is FileSystemMoveEvent) { - return "move $type $path to " - "${p.relative(event.destination, from: directory)}"; - } - } - - // TODO(nweiz): remove this when the buildbots calm down. - /// Whether this code is running on a buildbot. - bool get _runningOnBuildbot => - Platform.environment.containsKey('BUILDBOT_BUILDERNAME'); } From a3d8591f22613cd27c7cd6b5997845214d4ad01a Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 20:08:41 +0000 Subject: [PATCH 0080/1215] Add a bunch of debugging prints to the Mac OS watcher. This reverts r30184, which in turn reverted r30181. It correctly detects whether it's running on a buildbot in a way that will work for the vm-mac-release bot. This is a temporary CL intended to help provide information about a test failure that's only reproducing on the build bot. It will be rolled back as soon as sufficient information is gathered. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//69933007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30205 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 5b1feb342..cd3a4832e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,6 +7,8 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import 'package:path/path.dart' as p; + import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -78,7 +80,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: _readyCompleter.complete, + onDone: () { + if (_runningOnBuildbot) { + print("watcher is ready"); + } + _readyCompleter.complete(); + }, cancelOnError: true); } @@ -94,12 +101,38 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { + if (_runningOnBuildbot) { + print("======== batch:"); + for (var event in batch) { + print(" ${_formatEvent(event)}"); + } + + print("known files:"); + for (var foo in _files.toSet()) { + print(" ${p.relative(foo, from: directory)}"); + } + } + batches++; _sortEvents(batch).forEach((path, events) { + var relativePath = p.relative(path, from: directory); + if (_runningOnBuildbot) { + print("events for $relativePath:\n"); + for (var event in events) { + print(" ${_formatEvent(event)}"); + } + } + var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; + if (_runningOnBuildbot) { + print("canonical event for $relativePath: " + "${_formatEvent(canonicalEvent)}"); + print("actionable events for $relativePath: " + "${events.map(_formatEvent)}"); + } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -113,7 +146,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: _emitError, cancelOnError: true); + }, onError: (e, stackTrace) { + if (_runningOnBuildbot) { + print("got error listing $relativePath: $e"); + } + _emitError(e, stackTrace); + }, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -125,6 +163,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); + + if (_runningOnBuildbot) { + print("========"); + } } /// Sort all the events in a batch into sets based on their path. @@ -261,6 +303,13 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); + if (_runningOnBuildbot) { + print("file existed: $fileExisted"); + print("dir existed: $dirExisted"); + print("file exists: $fileExists"); + print("dir exists: $dirExists"); + } + var events = []; if (fileExisted) { if (fileExists) { @@ -330,6 +379,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; + if (_runningOnBuildbot) { + print("emitting $type ${p.relative(path, from: directory)}"); + } + _eventsController.add(new WatchEvent(type, path)); } @@ -350,4 +403,27 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } + + /// Return a human-friendly string representation of [event]. + String _formatEvent(FileSystemEvent event) { + if (event == null) return 'null'; + + var path = p.relative(event.path, from: directory); + var type = event.isDirectory ? 'directory' : 'file'; + if (event is FileSystemCreateEvent) { + return "create $type $path"; + } else if (event is FileSystemDeleteEvent) { + return "delete $type $path"; + } else if (event is FileSystemModifyEvent) { + return "modify $type $path"; + } else if (event is FileSystemMoveEvent) { + return "move $type $path to " + "${p.relative(event.destination, from: directory)}"; + } + } + + // TODO(nweiz): remove this when the buildbots calm down. + /// Whether this code is running on a buildbot. + bool get _runningOnBuildbot => + Platform.environment['LOGNAME'] == 'chrome-bot'; } From 1815318f12f5c2df534e2b90e6c594f4c09b1147 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 12 Nov 2013 22:17:01 +0000 Subject: [PATCH 0081/1215] Be sure we don't forward an error to a closed event stream. R=rnystrom@google.com BUG=15034 Review URL: https://codereview.chromium.org//68253010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30210 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/async_queue.dart | 5 ++--- pkgs/watcher/lib/src/directory_watcher/polling.dart | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 9456631af..8ac0cdfe1 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -8,7 +8,6 @@ import 'dart:async'; import 'dart:collection'; typedef Future ItemProcessor(T item); -typedef void ErrorHandler(error); /// A queue of items that are sequentially, asynchronously processed. /// @@ -35,9 +34,9 @@ class AsyncQueue { /// The handler for errors thrown during processing. /// /// Used to avoid top-leveling asynchronous errors. - final ErrorHandler _errorHandler; + final Function _errorHandler; - AsyncQueue(this._processor, {ErrorHandler onError}) + AsyncQueue(this._processor, {Function onError}) : _errorHandler = onError; /// Enqueues [item] to be processed and starts asynchronously processing it diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 0e190b02b..e50a0c05c 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -72,7 +72,9 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _PollingDirectoryWatcher(this.directory, this._pollingDelay) { _filesToProcess = new AsyncQueue(_processFile, - onError: _events.addError); + onError: (e, stackTrace) { + if (!_events.isClosed) _events.addError(e, stackTrace); + }); _poll(); } From dfb26e9baa64b0ff4b87cad6009adddb12e4bd18 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 13 Nov 2013 03:03:33 +0000 Subject: [PATCH 0082/1215] "Reverting 30205" Review URL: https://codereview.chromium.org//69863003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30217 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 80 +------------------ 1 file changed, 2 insertions(+), 78 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index cd3a4832e..5b1feb342 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; -import 'package:path/path.dart' as p; - import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -80,12 +78,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: () { - if (_runningOnBuildbot) { - print("watcher is ready"); - } - _readyCompleter.complete(); - }, + onDone: _readyCompleter.complete, cancelOnError: true); } @@ -101,38 +94,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { - if (_runningOnBuildbot) { - print("======== batch:"); - for (var event in batch) { - print(" ${_formatEvent(event)}"); - } - - print("known files:"); - for (var foo in _files.toSet()) { - print(" ${p.relative(foo, from: directory)}"); - } - } - batches++; _sortEvents(batch).forEach((path, events) { - var relativePath = p.relative(path, from: directory); - if (_runningOnBuildbot) { - print("events for $relativePath:\n"); - for (var event in events) { - print(" ${_formatEvent(event)}"); - } - } - var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; - if (_runningOnBuildbot) { - print("canonical event for $relativePath: " - "${_formatEvent(canonicalEvent)}"); - print("actionable events for $relativePath: " - "${events.map(_formatEvent)}"); - } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -146,12 +113,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (e, stackTrace) { - if (_runningOnBuildbot) { - print("got error listing $relativePath: $e"); - } - _emitError(e, stackTrace); - }, cancelOnError: true); + }, onError: _emitError, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -163,10 +125,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); - - if (_runningOnBuildbot) { - print("========"); - } } /// Sort all the events in a batch into sets based on their path. @@ -303,13 +261,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - if (_runningOnBuildbot) { - print("file existed: $fileExisted"); - print("dir existed: $dirExisted"); - print("file exists: $fileExists"); - print("dir exists: $dirExists"); - } - var events = []; if (fileExisted) { if (fileExists) { @@ -379,10 +330,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; - if (_runningOnBuildbot) { - print("emitting $type ${p.relative(path, from: directory)}"); - } - _eventsController.add(new WatchEvent(type, path)); } @@ -403,27 +350,4 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } - - /// Return a human-friendly string representation of [event]. - String _formatEvent(FileSystemEvent event) { - if (event == null) return 'null'; - - var path = p.relative(event.path, from: directory); - var type = event.isDirectory ? 'directory' : 'file'; - if (event is FileSystemCreateEvent) { - return "create $type $path"; - } else if (event is FileSystemDeleteEvent) { - return "delete $type $path"; - } else if (event is FileSystemModifyEvent) { - return "modify $type $path"; - } else if (event is FileSystemMoveEvent) { - return "move $type $path to " - "${p.relative(event.destination, from: directory)}"; - } - } - - // TODO(nweiz): remove this when the buildbots calm down. - /// Whether this code is running on a buildbot. - bool get _runningOnBuildbot => - Platform.environment['LOGNAME'] == 'chrome-bot'; } From e3b44e1a36092b5e1796111abd34b5629513b4d2 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 13 Nov 2013 21:56:52 +0000 Subject: [PATCH 0083/1215] Roll forward r30205. Unlike previous versions of this CL, the debug info will only be printed when running directory_watcher/mac_os_test, so it won't break the pub bots. R=rnystrom@google.com BUG=15042 Review URL: https://codereview.chromium.org//71353011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30254 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 79 ++++++++++++++++++- .../test/directory_watcher/mac_os_test.dart | 1 + 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 5b1feb342..09fdd66d9 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,6 +7,8 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import 'package:path/path.dart' as p; + import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -24,6 +26,9 @@ import 'resubscribable.dart'; /// This also works around issues 14793, 14806, and 14849 in the implementation /// of [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { + // TODO(nweiz): remove this when issue 15042 is fixed. + static bool logDebugInfo = false; + MacOSDirectoryWatcher(String directory) : super(directory, () => new _MacOSDirectoryWatcher(directory)); } @@ -78,7 +83,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: _readyCompleter.complete, + onDone: () { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("watcher is ready"); + } + _readyCompleter.complete(); + }, cancelOnError: true); } @@ -94,12 +104,38 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("======== batch:"); + for (var event in batch) { + print(" ${_formatEvent(event)}"); + } + + print("known files:"); + for (var foo in _files.toSet()) { + print(" ${p.relative(foo, from: directory)}"); + } + } + batches++; _sortEvents(batch).forEach((path, events) { + var relativePath = p.relative(path, from: directory); + if (MacOSDirectoryWatcher.logDebugInfo) { + print("events for $relativePath:\n"); + for (var event in events) { + print(" ${_formatEvent(event)}"); + } + } + var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("canonical event for $relativePath: " + "${_formatEvent(canonicalEvent)}"); + print("actionable events for $relativePath: " + "${events.map(_formatEvent)}"); + } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -113,7 +149,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: _emitError, cancelOnError: true); + }, onError: (e, stackTrace) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("got error listing $relativePath: $e"); + } + _emitError(e, stackTrace); + }, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -125,6 +166,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); + + if (MacOSDirectoryWatcher.logDebugInfo) { + print("========"); + } } /// Sort all the events in a batch into sets based on their path. @@ -261,6 +306,13 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); + if (MacOSDirectoryWatcher.logDebugInfo) { + print("file existed: $fileExisted"); + print("dir existed: $dirExisted"); + print("file exists: $fileExists"); + print("dir exists: $dirExists"); + } + var events = []; if (fileExisted) { if (fileExists) { @@ -330,6 +382,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("emitting $type ${p.relative(path, from: directory)}"); + } + _eventsController.add(new WatchEvent(type, path)); } @@ -350,4 +406,23 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } + + // TODO(nweiz): remove this when issue 15042 is fixed. + /// Return a human-friendly string representation of [event]. + String _formatEvent(FileSystemEvent event) { + if (event == null) return 'null'; + + var path = p.relative(event.path, from: directory); + var type = event.isDirectory ? 'directory' : 'file'; + if (event is FileSystemCreateEvent) { + return "create $type $path"; + } else if (event is FileSystemDeleteEvent) { + return "delete $type $path"; + } else if (event is FileSystemModifyEvent) { + return "modify $type $path"; + } else if (event is FileSystemMoveEvent) { + return "move $type $path to " + "${p.relative(event.destination, from: directory)}"; + } + } } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index f7f8176ae..78ff88985 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -11,6 +11,7 @@ import '../utils.dart'; main() { initConfig(); + MacOSDirectoryWatcher.logDebugInfo = true; watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); From f7f7051739f032b8a0385fcce0805aaf9ba54fea Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 15 Nov 2013 21:43:50 +0000 Subject: [PATCH 0084/1215] Re-mark directory_watcher/mac_os_test as passing. As before, this test is expected to fail. It's only failing on the bots so we need to get the debug information from the bots to figure out how to fix it. This also adds some additional debug information to help clarify some confusing output from the most recent failing log. R=rnystrom@google.com BUG=15024 Review URL: https://codereview.chromium.org//64383004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30315 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 58 ++++++++++++------- pkgs/watcher/test/utils.dart | 12 ++++ 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 09fdd66d9..e7b97e46c 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -26,14 +26,21 @@ import 'resubscribable.dart'; /// This also works around issues 14793, 14806, and 14849 in the implementation /// of [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { - // TODO(nweiz): remove this when issue 15042 is fixed. - static bool logDebugInfo = false; + // TODO(nweiz): remove these when issue 15042 is fixed. + static var logDebugInfo = false; + static var _count = 0; + final int _id; MacOSDirectoryWatcher(String directory) - : super(directory, () => new _MacOSDirectoryWatcher(directory)); + : _id = _count++, + super(directory, () => new _MacOSDirectoryWatcher(directory, _count)); } class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + // TODO(nweiz): remove these when issue 15042 is fixed. + static var _count = 0; + final String _id; + final String directory; Stream get events => _eventsController.stream; @@ -73,9 +80,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// watcher is closed. This does not include [_watchSubscription]. final _subscriptions = new Set(); - _MacOSDirectoryWatcher(String directory) + _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, - _files = new PathSet(directory) { + _files = new PathSet(directory), + _id = "$parentId/${_count++}" { _startWatch(); _listen(new Directory(directory).list(recursive: true), @@ -85,7 +93,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { onError: _emitError, onDone: () { if (MacOSDirectoryWatcher.logDebugInfo) { - print("watcher is ready"); + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } } _readyCompleter.complete(); }, @@ -93,6 +104,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } void close() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is closed"); + } for (var subscription in _subscriptions) { subscription.cancel(); } @@ -105,14 +119,14 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { if (MacOSDirectoryWatcher.logDebugInfo) { - print("======== batch:"); + print("[$_id] ======== batch:"); for (var event in batch) { - print(" ${_formatEvent(event)}"); + print("[$_id] ${_formatEvent(event)}"); } - print("known files:"); - for (var foo in _files.toSet()) { - print(" ${p.relative(foo, from: directory)}"); + print("[$_id] known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); } } @@ -121,9 +135,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { - print("events for $relativePath:\n"); + print("[$_id] events for $relativePath:\n"); for (var event in events) { - print(" ${_formatEvent(event)}"); + print("[$_id] ${_formatEvent(event)}"); } } @@ -131,9 +145,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; if (MacOSDirectoryWatcher.logDebugInfo) { - print("canonical event for $relativePath: " + print("[$_id] canonical event for $relativePath: " "${_formatEvent(canonicalEvent)}"); - print("actionable events for $relativePath: " + print("[$_id] actionable events for $relativePath: " "${events.map(_formatEvent)}"); } @@ -151,7 +165,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files.add(entity.path); }, onError: (e, stackTrace) { if (MacOSDirectoryWatcher.logDebugInfo) { - print("got error listing $relativePath: $e"); + print("[$_id] got error listing $relativePath: $e"); } _emitError(e, stackTrace); }, cancelOnError: true); @@ -168,7 +182,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }); if (MacOSDirectoryWatcher.logDebugInfo) { - print("========"); + print("[$_id] ======== batch complete"); } } @@ -307,10 +321,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var dirExists = new Directory(path).existsSync(); if (MacOSDirectoryWatcher.logDebugInfo) { - print("file existed: $fileExisted"); - print("dir existed: $dirExisted"); - print("file exists: $fileExists"); - print("dir exists: $dirExists"); + print("[$_id] file existed: $fileExisted"); + print("[$_id] dir existed: $dirExisted"); + print("[$_id] file exists: $fileExists"); + print("[$_id] dir exists: $dirExists"); } var events = []; @@ -383,7 +397,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (type == ChangeType.ADD && _files.contains(path)) return; if (MacOSDirectoryWatcher.logDebugInfo) { - print("emitting $type ${p.relative(path, from: directory)}"); + print("[$_id] emitting $type ${p.relative(path, from: directory)}"); } _eventsController.add(new WatchEvent(type, path)); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 567bdb221..a7bd9b636 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -15,6 +15,9 @@ import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; import 'package:watcher/src/utils.dart'; +// TODO(nweiz): remove this when issue 15042 is fixed. +import 'package:watcher/src/directory_watcher/mac_os.dart'; + /// The path to the temporary sandbox created for each test. All file /// operations are implicitly relative to this directory. String _sandboxDir; @@ -115,6 +118,11 @@ Stream _watcherEvents; /// /// If [dir] is provided, watches a subdirectory in the sandbox with that name. void startWatcher({String dir}) { + var testCase = currentTestCase.description; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("starting watcher for $testCase"); + } + // We want to wait until we're ready *after* we subscribe to the watcher's // events. _watcher = createWatcher(dir: dir, waitForReady: false); @@ -128,6 +136,10 @@ void startWatcher({String dir}) { onError: currentSchedule.signalError); currentSchedule.onComplete.schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("stopping watcher for $testCase"); + } + var numEvents = _nextEvent; subscription.cancel(); _nextEvent = 0; From 07276f710a3a33fb5dd67fbfd08a8d3721553084 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 15 Nov 2013 22:16:10 +0000 Subject: [PATCH 0085/1215] Work around issue 11901 in stack_trace. For some reason, timer_impl.dart in dart:async has the incorrect URL in VM stack traces. This adds manual handling for that in the stack_trace package. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//63393004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30318 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 4 ++++ pkgs/stack_trace/test/frame_test.dart | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 3bead03ba..6a88a268c 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -118,6 +118,10 @@ class Frame { // always be found. The column is optional. var member = match[1].replaceAll("", ""); var uri = Uri.parse(match[2]); + // Work around issue 11901. + if (uri == new Uri(path: 'timer_impl.dart')) { + uri = Uri.parse('dart:async/timer_impl.dart'); + } var line = int.parse(match[3]); var column = null; var columnMatch = match[4]; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 87a8c4dc7..bd09ed882 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -30,6 +30,15 @@ void main() { expect(frame.member, equals('Foo._bar')); }); + test('parses a stack frame with timer_impl correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(timer_impl.dart:24)"); + expect(frame.uri, equals(Uri.parse("dart:async/timer_impl.dart"))); + expect(frame.line, equals(24)); + expect(frame.column, null); + expect(frame.member, equals('Foo._bar')); + }); + test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseVM('#0 $member (foo:0:0)').member; From 31241bc2e72dc2396552cf993581e9d905f940e1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 16 Nov 2013 00:54:50 +0000 Subject: [PATCH 0086/1215] Fix the Mac OS directory watcher tests on the bots. R=rnystrom@google.com BUG=15024 Review URL: https://codereview.chromium.org//58903015 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30328 260f80e4-7a28-3924-810f-c04153c831b5 --- .../test/directory_watcher/mac_os_test.dart | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 78ff88985..b6a65e6e2 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -50,6 +50,29 @@ main() { () { withPermutations((i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + + // We sleep here because a narrow edge case caused by two interacting bugs + // can produce events that aren't expected if we start the watcher too + // soon after creating the files above. Here's what happens: + // + // * We create "dir/sub" and its contents above. + // + // * We initialize the watcher watching "dir". + // + // * Due to issue 14373, the watcher can receive native events describing + // the creation of "dir/sub" and its contents despite the fact that they + // occurred before the watcher was started. + // + // * Usually the above events will occur while the watcher is doing its + // initial scan of "dir/sub" and be ignored, but occasionally they will + // occur afterwards. + // + // * When processing the bogus CREATE events, the watcher has to assume that + // they could mean something other than CREATE (issue 14793). Thus it + // assumes that the files or directories in question could have changed + // and emits CHANGE events or additional REMOVE/CREATE pairs for them. + schedule(() => new Future.delayed(new Duration(seconds: 2))); + startWatcher(dir: "dir"); renameDir("dir/sub", "sub"); From 84caa2ac2782d30ab2818415f7662bd8492ad3e0 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 16 Nov 2013 01:05:45 +0000 Subject: [PATCH 0087/1215] Remove debugging prints from the Mac OS directory watcher. R=rnystrom@google.com BUG=15024 Review URL: https://codereview.chromium.org//63643008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30329 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 99 +------------------ .../test/directory_watcher/mac_os_test.dart | 1 - pkgs/watcher/test/utils.dart | 12 --- 3 files changed, 5 insertions(+), 107 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index e7b97e46c..5b1feb342 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; -import 'package:path/path.dart' as p; - import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -26,21 +24,11 @@ import 'resubscribable.dart'; /// This also works around issues 14793, 14806, and 14849 in the implementation /// of [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { - // TODO(nweiz): remove these when issue 15042 is fixed. - static var logDebugInfo = false; - static var _count = 0; - final int _id; - MacOSDirectoryWatcher(String directory) - : _id = _count++, - super(directory, () => new _MacOSDirectoryWatcher(directory, _count)); + : super(directory, () => new _MacOSDirectoryWatcher(directory)); } class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - // TODO(nweiz): remove these when issue 15042 is fixed. - static var _count = 0; - final String _id; - final String directory; Stream get events => _eventsController.stream; @@ -80,10 +68,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// watcher is closed. This does not include [_watchSubscription]. final _subscriptions = new Set(); - _MacOSDirectoryWatcher(String directory, int parentId) + _MacOSDirectoryWatcher(String directory) : directory = directory, - _files = new PathSet(directory), - _id = "$parentId/${_count++}" { + _files = new PathSet(directory) { _startWatch(); _listen(new Directory(directory).list(recursive: true), @@ -91,22 +78,11 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: () { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is ready, known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - _readyCompleter.complete(); - }, + onDone: _readyCompleter.complete, cancelOnError: true); } void close() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is closed"); - } for (var subscription in _subscriptions) { subscription.cancel(); } @@ -118,38 +94,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] ======== batch:"); - for (var event in batch) { - print("[$_id] ${_formatEvent(event)}"); - } - - print("[$_id] known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - batches++; _sortEvents(batch).forEach((path, events) { - var relativePath = p.relative(path, from: directory); - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] events for $relativePath:\n"); - for (var event in events) { - print("[$_id] ${_formatEvent(event)}"); - } - } - var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] canonical event for $relativePath: " - "${_formatEvent(canonicalEvent)}"); - print("[$_id] actionable events for $relativePath: " - "${events.map(_formatEvent)}"); - } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -163,12 +113,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (e, stackTrace) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] got error listing $relativePath: $e"); - } - _emitError(e, stackTrace); - }, cancelOnError: true); + }, onError: _emitError, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -180,10 +125,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); - - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] ======== batch complete"); - } } /// Sort all the events in a batch into sets based on their path. @@ -320,13 +261,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] file existed: $fileExisted"); - print("[$_id] dir existed: $dirExisted"); - print("[$_id] file exists: $fileExists"); - print("[$_id] dir exists: $dirExists"); - } - var events = []; if (fileExisted) { if (fileExists) { @@ -396,10 +330,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // watch beginning. if (type == ChangeType.ADD && _files.contains(path)) return; - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] emitting $type ${p.relative(path, from: directory)}"); - } - _eventsController.add(new WatchEvent(type, path)); } @@ -420,23 +350,4 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } - - // TODO(nweiz): remove this when issue 15042 is fixed. - /// Return a human-friendly string representation of [event]. - String _formatEvent(FileSystemEvent event) { - if (event == null) return 'null'; - - var path = p.relative(event.path, from: directory); - var type = event.isDirectory ? 'directory' : 'file'; - if (event is FileSystemCreateEvent) { - return "create $type $path"; - } else if (event is FileSystemDeleteEvent) { - return "delete $type $path"; - } else if (event is FileSystemModifyEvent) { - return "modify $type $path"; - } else if (event is FileSystemMoveEvent) { - return "move $type $path to " - "${p.relative(event.destination, from: directory)}"; - } - } } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index b6a65e6e2..8a30e27e6 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -11,7 +11,6 @@ import '../utils.dart'; main() { initConfig(); - MacOSDirectoryWatcher.logDebugInfo = true; watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index a7bd9b636..567bdb221 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -15,9 +15,6 @@ import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; import 'package:watcher/src/utils.dart'; -// TODO(nweiz): remove this when issue 15042 is fixed. -import 'package:watcher/src/directory_watcher/mac_os.dart'; - /// The path to the temporary sandbox created for each test. All file /// operations are implicitly relative to this directory. String _sandboxDir; @@ -118,11 +115,6 @@ Stream _watcherEvents; /// /// If [dir] is provided, watches a subdirectory in the sandbox with that name. void startWatcher({String dir}) { - var testCase = currentTestCase.description; - if (MacOSDirectoryWatcher.logDebugInfo) { - print("starting watcher for $testCase"); - } - // We want to wait until we're ready *after* we subscribe to the watcher's // events. _watcher = createWatcher(dir: dir, waitForReady: false); @@ -136,10 +128,6 @@ void startWatcher({String dir}) { onError: currentSchedule.signalError); currentSchedule.onComplete.schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("stopping watcher for $testCase"); - } - var numEvents = _nextEvent; subscription.cancel(); _nextEvent = 0; From 3451b4bd7e61bb7df64dca91eb09bb34743198f5 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 16 Nov 2013 01:10:23 +0000 Subject: [PATCH 0088/1215] Add a missing import to mac_os_watcher. TBR Review URL: https://codereview.chromium.org//68523020 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30330 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/directory_watcher/mac_os_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 8a30e27e6..7d31221de 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -2,6 +2,8 @@ // 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. +import 'dart:async'; + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'package:watcher/watcher.dart'; From a54a4d113b257a0f61cac5890013c9501ab109af Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 19 Nov 2013 20:48:45 +0000 Subject: [PATCH 0089/1215] Refactor pkg/path. This CL does several things: * Splits lib/path.dart into multiple libraries. * Renames "Builder" to "Context". * Makes the Context API match the top-level functions ("root" was renamed to "current" and "resolve" was renamed to "absolute"). * The top-level "absolute" function now takes multiple parts, to match [Context.absolute]. R=rnystrom@google.com BUG=14981 Review URL: https://codereview.chromium.org//62753005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30423 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/vm_test.dart | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 6570c24c5..7e00b7a61 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -43,16 +43,14 @@ void main() { test('.parse parses a real stack trace correctly', () { var string = getStackTraceString(); var trace = new Trace.parse(string); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), + expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceString')); }); test('converts from a native stack trace correctly', () { var trace = new Trace.from(getStackTraceObject()); - var builder = new path.Builder(style: path.Style.url); - expect(builder.basename(trace.frames.first.uri.path), + expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceObject')); }); From 01f82b5f2c7f9f86235e7c221f6e23d12a2a719f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 20 Nov 2013 21:02:03 +0000 Subject: [PATCH 0090/1215] Make the stack_trace package print relative URLs for browser paths. Prior to this, only console paths were printed as relative. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//75543013 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30484 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 3 ++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 6 ++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 6a88a268c..74aafcda3 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -69,7 +69,8 @@ class Frame { /// This will usually be the string form of [uri], but a relative URI will be /// used if possible. String get library { - if (uri.scheme != 'file') return uri.toString(); + if (uri.scheme != Uri.base.scheme) return uri.toString(); + if (path.style == path.Style.url) return path.relative(uri.toString()); return path.relative(path.fromUri(uri)); } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 63a1bf9c1..c71a7819e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -6,7 +6,7 @@ description: > A package for manipulating stack traces and printing them readably. dependencies: - path: ">=0.9.0 <0.10.0" + path: ">=1.0.0-rc.1 <2.0.0" dev_dependencies: unittest: ">=0.9.0 <0.10.0" diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index bd09ed882..9722d38df 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -495,5 +495,11 @@ void main() { expect(new Frame.parseVM('#0 Foo (dart:core/uri.dart:5)').toString(), equals('dart:core/uri.dart 5 in Foo')); }); + + test('prints relative paths as relative', () { + var relative = path.normalize('relative/path/to/foo.dart'); + expect(new Frame.parseFriendly('$relative 5:10 Foo').toString(), + equals('$relative 5:10 in Foo')); + }); }); } From 778821e1faac76d67b9df7e00c6e79652a7f5ad7 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Nov 2013 01:16:56 +0000 Subject: [PATCH 0091/1215] Properly close the Linux directory watcher when listing a subdirectory fails. R=rnystrom@google.com BUG=15279 Review URL: https://codereview.chromium.org//89503002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30690 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 519607839..d62c6ef10 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -166,7 +166,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (error is FileSystemException) return; _eventsController.addError(error, stackTrace); - _eventsController.close(); + close(); }, cancelOnError: true); }); } From fe2b8a0954a340e677fb1b1578d32d0baa13bcf4 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Nov 2013 23:03:49 +0000 Subject: [PATCH 0092/1215] Add a stack chain class to the stack trace package. This class uses zones to track stack traces across asynchronous boundaries. It will aid considerably in debugging errors in heavily-asynchronous programs. R=floitsch@google.com, rnystrom@google.com BUG=7040 Review URL: https://codereview.chromium.org//75863004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30738 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/chain.dart | 173 +++++ .../lib/src/stack_zone_specification.dart | 205 ++++++ pkgs/stack_trace/lib/src/trace.dart | 18 +- pkgs/stack_trace/lib/src/utils.dart | 16 + pkgs/stack_trace/lib/stack_trace.dart | 1 + pkgs/stack_trace/test/chain_test.dart | 618 ++++++++++++++++++ pkgs/stack_trace/test/trace_test.dart | 18 + pkgs/stack_trace/test/utils.dart | 37 ++ 8 files changed, 1082 insertions(+), 4 deletions(-) create mode 100644 pkgs/stack_trace/lib/src/chain.dart create mode 100644 pkgs/stack_trace/lib/src/stack_zone_specification.dart create mode 100644 pkgs/stack_trace/test/chain_test.dart create mode 100644 pkgs/stack_trace/test/utils.dart diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart new file mode 100644 index 000000000..f6e2f3fb3 --- /dev/null +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -0,0 +1,173 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.chain; + +import 'dart:async'; +import 'dart:collection'; + +import 'stack_zone_specification.dart'; +import 'trace.dart'; +import 'utils.dart'; + +/// A function that handles errors in the zone wrapped by [Chain.capture]. +typedef void ChainHandler(error, Chain chain); + +/// A chain of stack traces. +/// +/// A stack chain is a collection of one or more stack traces that collectively +/// represent the path from [main] through nested function calls to a particular +/// code location, usually where an error was thrown. Multiple stack traces are +/// necessary when using asynchronous functions, since the program's stack is +/// reset before each asynchronous callback is run. +/// +/// Stack chains can be automatically tracked using [Chain.capture]. This sets +/// up a new [Zone] in which the current stack chain is tracked and can be +/// accessed using [new Chain.current]. Any errors that would be top-leveled in +/// the zone can be handled, along with their associated chains, with the +/// `onError` callback. +/// +/// For the most part [Chain.capture] will notice when an error is thrown and +/// associate the correct stack chain with it; the chain can be accessed using +/// [new Chain.forTrace]. However, there are some cases where exceptions won't +/// be automatically detected: any [Future] constructor, +/// [Completer.completeError], [Stream.addError], and libraries that use these. +/// For these, all you need to do is wrap the Future or Stream in a call to +/// [Chain.track] and the errors will be tracked correctly. +class Chain implements StackTrace { + /// The line used in the string representation of stack chains to represent + /// the gap between traces. + static const _GAP = '===== asynchronous gap ===========================\n'; + + /// The stack traces that make up this chain. + /// + /// Like the frames in a stack trace, the traces are ordered from most local + /// to least local. The first one is the trace where the actual exception was + /// raised, the second one is where that callback was scheduled, and so on. + final List traces; + + /// The [StackZoneSpecification] for the current zone. + static StackZoneSpecification get _currentSpec => + Zone.current[#stack_trace.stack_zone.spec]; + + /// Runs [callback] in a [Zone] in which the current stack chain is tracked + /// and automatically associated with (most) errors. + /// + /// If [onError] is passed, any error in the zone that would otherwise go + /// unhandled is passed to it, along with the [Chain] associated with that + /// error. Note that if [callback] produces multiple unhandled errors, + /// [onError] may be called more than once. If [onError] isn't passed, the + /// parent Zone's `unhandledErrorHandler` will be called with the error and + /// its chain. + /// + /// For the most part an error thrown in the zone will have the correct stack + /// chain associated with it. However, there are some cases where exceptions + /// won't be automatically detected: any [Future] constructor, + /// [Completer.completeError], [Stream.addError], and libraries that use + /// these. For these, all you need to do is wrap the Future or Stream in a + /// call to [Chain.track] and the errors will be tracked correctly. + /// + /// Note that even if [onError] isn't passed, this zone will still be an error + /// zone. This means that any errors that would cross the zone boundary are + /// considered unhandled. + /// + /// If [callback] returns a value, it will be returned by [capture] as well. + /// + /// Currently, capturing stack chains doesn't work when using dart2js due to + /// issues [15171] and [15105]. Stack chains reported on dart2js will contain + /// only one trace. + /// + /// [15171]: https://code.google.com/p/dart/issues/detail?id=15171 + /// [15105]: https://code.google.com/p/dart/issues/detail?id=15105 + static capture(callback(), {ChainHandler onError}) { + var spec = new StackZoneSpecification(onError); + return runZoned(callback, zoneSpecification: spec.toSpec(), zoneValues: { + #stack_trace.stack_zone.spec: spec + }); + } + + /// Ensures that any errors emitted by [futureOrStream] have the correct stack + /// chain information associated with them. + /// + /// For the most part an error thrown within a [capture] zone will have the + /// correct stack chain automatically associated with it. However, there are + /// some cases where exceptions won't be automatically detected: any [Future] + /// constructor, [Completer.completeError], [Stream.addError], and libraries + /// that use these. + /// + /// This returns a [Future] or [Stream] that will emit the same values and + /// errors as [futureOrStream]. The only exception is that if [futureOrStream] + /// emits an error without a stack trace, one will be added in the return + /// value. + /// + /// If this is called outside of a [capture] zone, it just returns + /// [futureOrStream] as-is. + /// + /// As the name suggests, [futureOrStream] may be either a [Future] or a + /// [Stream]. + static track(futureOrStream) { + if (_currentSpec == null) return futureOrStream; + if (futureOrStream is Future) { + return _currentSpec.trackFuture(futureOrStream, 1); + } else { + return _currentSpec.trackStream(futureOrStream, 1); + } + } + + /// Returns the current stack chain. + /// + /// By default, the first frame of the first trace will be the line where + /// [Chain.current] is called. If [level] is passed, the first trace will + /// start that many frames up instead. + /// + /// If this is called outside of a [capture] zone, it just returns a + /// single-trace chain. + factory Chain.current([int level=0]) { + if (_currentSpec != null) return _currentSpec.currentChain(level + 1); + return new Chain([new Trace.current(level + 1)]); + } + + /// Returns the stack chain associated with [trace]. + /// + /// The first stack trace in the returned chain will always be [trace] + /// (converted to a [Trace] if necessary). If there is no chain associated + /// with [trace] or if this is called outside of a [capture] zone, this just + /// returns a single-trace chain containing [trace]. + /// + /// If [trace] is already a [Chain], it will be returned as-is. + factory Chain.forTrace(StackTrace trace) { + if (trace is Chain) return trace; + if (_currentSpec == null) return new Chain([new Trace.from(trace)]); + return _currentSpec.chainFor(trace); + } + + /// Parses a string representation of a stack chain. + /// + /// Specifically, this parses the output of [Chain.toString]. + factory Chain.parse(String chain) => + new Chain(chain.split(_GAP).map((trace) => new Trace.parseFriendly(trace))); + + /// Returns a new [Chain] comprised of [traces]. + Chain(Iterable traces) + : traces = new UnmodifiableListView(traces.toList()); + + /// Returns a terser version of [this]. + /// + /// This calls [Trace.terse] on every trace in [traces], and discards any + /// trace that contain only internal frames. + Chain get terse { + return new Chain(traces.map((trace) => trace.terse).where((trace) { + // Ignore traces that contain only internal processing. + return trace.frames.length > 1; + })); + } + + /// Converts [this] to a [Trace]. + /// + /// The trace version of a chain is just the concatenation of all the traces + /// in the chain. + Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames))); + + String toString() => traces.join(_GAP); +} diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart new file mode 100644 index 000000000..36e0717d2 --- /dev/null +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -0,0 +1,205 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.stack_zone_specification; + +import 'dart:async'; + +import 'trace.dart'; +import 'chain.dart'; + +/// A class encapsulating the zone specification for a [Chain.capture] zone. +/// +/// Until they're materialized and exposed to the user, stack chains are tracked +/// as linked lists of [Trace]s using the [_Node] class. These nodes are stored +/// in three distinct ways: +/// +/// * When a callback is registered, a node is created and stored as a captured +/// local variable until the callback is run. +/// +/// * When a callback is run, its captured node is set as the [_currentNode] so +/// it can be available to [Chain.current] and to be linked into additional +/// chains when more callbacks are scheduled. +/// +/// * When a callback throws an error or a [Chain.track]ed Future or Stream +/// emits an error, the current node is associated with that error's stack +/// trace using the [_chains] expando. +/// +/// Since [ZoneSpecification] can't be extended or even implemented, in order to +/// get a real [ZoneSpecification] instance it's necessary to call [toSpec]. +class StackZoneSpecification { + /// The expando that associates stack chains with [StackTrace]s. + /// + /// The chains are associated with stack traces rather than errors themselves + /// because it's a common practice to throw strings as errors, which can't be + /// used with expandos. + /// + /// The chain associated with a given stack trace doesn't contain a node for + /// that stack trace. + final _chains = new Expando<_Node>("stack chains"); + + /// The error handler for the zone. + /// + /// If this is null, that indicates that any unhandled errors should be passed + /// to the parent zone. + final ChainHandler _onError; + + /// The most recent node of the current stack chain. + _Node _currentNode; + + StackZoneSpecification([this._onError]); + + /// Converts [this] to a real [ZoneSpecification]. + ZoneSpecification toSpec() { + return new ZoneSpecification( + handleUncaughtError: handleUncaughtError, + registerCallback: registerCallback, + registerUnaryCallback: registerUnaryCallback, + registerBinaryCallback: registerBinaryCallback); + } + + /// Returns the current stack chain. + /// + /// By default, the first frame of the first trace will be the line where + /// [currentChain] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + Chain currentChain([int level=0]) => _createNode(level + 1).toChain(); + + /// Returns the stack chain associated with [trace], if one exists. + /// + /// The first stack trace in the returned chain will always be [trace] + /// (converted to a [Trace] if necessary). If there is no chain associated + /// with [trace], this just returns a single-trace chain containing [trace]. + Chain chainFor(StackTrace trace) { + if (trace is Chain) return trace; + var previous = trace == null ? null : _chains[trace]; + return new _Node(trace, previous).toChain(); + } + + /// Ensures that an error emitted by [future] has the correct stack + /// information associated with it. + /// + /// By default, the first frame of the first trace will be the line where + /// [trackFuture] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + Future trackFuture(Future future, [int level=0]) { + var completer = new Completer.sync(); + var node = _createNode(level + 1); + future.then(completer.complete).catchError((e, stackTrace) { + if (stackTrace == null) stackTrace = new Trace.current(); + if (_chains[stackTrace] == null) _chains[stackTrace] = node; + completer.completeError(e, stackTrace); + }); + return completer.future; + } + + /// Ensures that any errors emitted by [stream] have the correct stack + /// information associated with them. + /// + /// By default, the first frame of the first trace will be the line where + /// [trackStream] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + Stream trackStream(Stream stream, [int level=0]) { + var node = _createNode(level + 1); + return stream.transform(new StreamTransformer.fromHandlers( + handleError: (error, stackTrace, sink) { + if (stackTrace == null) stackTrace = new Trace.current(); + if (_chains[stackTrace] == null) _chains[stackTrace] = node; + sink.addError(error, stackTrace); + })); + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneCallback registerCallback(Zone self, ZoneDelegate parent, Zone zone, + Function f) { + if (f == null) return parent.registerCallback(zone, null); + var node = _createNode(1); + return parent.registerCallback(zone, () => _run(f, node)); + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneUnaryCallback registerUnaryCallback(Zone self, ZoneDelegate parent, + Zone zone, Function f) { + if (f == null) return parent.registerUnaryCallback(zone, null); + var node = _createNode(1); + return parent.registerUnaryCallback(zone, (arg) { + return _run(() => f(arg), node); + }); + } + + /// Tracks the current stack chain so it can be set to [_currentChain] when + /// [f] is run. + ZoneBinaryCallback registerBinaryCallback(Zone self, ZoneDelegate parent, + Zone zone, Function f) { + if (f == null) return parent.registerBinaryCallback(zone, null); + var node = _createNode(1); + return parent.registerBinaryCallback(zone, (arg1, arg2) { + return _run(() => f(arg1, arg2), node); + }); + } + + /// Looks up the chain associated with [stackTrace] and passes it either to + /// [_onError] or [parent]'s error handler. + handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error, + StackTrace stackTrace) { + if (_onError == null) { + return parent.handleUncaughtError(zone, error, chainFor(stackTrace)); + } else { + _onError(error, chainFor(stackTrace)); + } + } + + /// Creates a [_Node] with the current stack trace and linked to + /// [_currentNode]. + /// + /// By default, the first frame of the first trace will be the line where + /// [_createNode] is called. If [level] is passed, the first trace will start + /// that many frames up instead. + _Node _createNode([int level=0]) => + new _Node(new Trace.current(level + 1), _currentNode); + + // TODO(nweiz): use a more robust way of detecting and tracking errors when + // issue 15105 is fixed. + /// Runs [f] with [_currentNode] set to [node]. + /// + /// If [f] throws an error, this associates [node] with that error's stack + /// trace. + _run(Function f, _Node node) { + var previousNode = _currentNode; + _currentNode = node; + try { + return f(); + } catch (e, stackTrace) { + _chains[stackTrace] = node; + rethrow; + } finally { + _currentNode = previousNode; + } + } +} + +/// A linked list node representing a single entry in a stack chain. +class _Node { + /// The stack trace for this link of the chain. + final Trace trace; + + /// The previous node in the chain. + final _Node previous; + + _Node(StackTrace trace, [this.previous]) + : trace = trace == null ? new Trace.current() : new Trace.from(trace); + + /// Converts this to a [Chain]. + Chain toChain() { + var nodes = []; + var node = this; + while (node != null) { + nodes.add(node.trace); + node = node.previous; + } + return new Chain(nodes); + } +} diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index c3db43ecd..88b927518 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -7,6 +7,7 @@ library trace; import 'dart:collection'; import 'dart:math' as math; +import 'chain.dart'; import 'frame.dart'; import 'lazy_trace.dart'; import 'utils.dart'; @@ -92,6 +93,7 @@ class Trace implements StackTrace { /// a [Trace], it will be returned as-is. factory Trace.from(StackTrace trace) { if (trace is Trace) return trace; + if (trace is Chain) return trace.toTrace(); return new LazyTrace(() => new Trace.parse(trace.toString())); } @@ -172,9 +174,14 @@ class Trace implements StackTrace { .where((line) => line != '[native code]') .map((line) => new Frame.parseFirefox(line))); - /// Parses this package's a string representation of a stack trace. + /// Parses this package's string representation of a stack trace. + /// + /// This also parses string representations of [Chain]s. They parse to the + /// same trace that [Chain.toTrace] would return. Trace.parseFriendly(String trace) : this(trace.trim().split("\n") + // Filter out asynchronous gaps from [Chain]s. + .where((line) => !line.startsWith('=====')) .map((line) => new Frame.parseFriendly(line))); /// Returns a new [Trace] comprised of [frames]. @@ -191,10 +198,13 @@ class Trace implements StackTrace { /// Returns a terser version of [this]. /// /// This is accomplished by folding together multiple stack frames from the - /// core library, as in [foldFrames]. Remaining core library frames have their - /// libraries, "-patch" suffixes, and line numbers removed. + /// core library or from this package, as in [foldFrames]. Remaining core + /// library frames have their libraries, "-patch" suffixes, and line numbers + /// removed. Trace get terse { - return new Trace(foldFrames((frame) => frame.isCore).frames.map((frame) { + return new Trace(foldFrames((frame) { + return frame.isCore || frame.package == 'stack_trace'; + }).frames.map((frame) { if (!frame.isCore) return frame; var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 08b3b960e..62a282085 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -18,3 +18,19 @@ String padRight(String string, int length) { return result.toString(); } +/// Flattens nested lists inside an iterable into a single list containing only +/// non-list elements. +List flatten(Iterable nested) { + var result = []; + helper(list) { + for (var element in list) { + if (element is List) { + helper(element); + } else { + result.add(element); + } + } + } + helper(nested); + return result; +} diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index dba95e947..ac875a910 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -25,3 +25,4 @@ library stack_trace; export 'src/trace.dart'; export 'src/frame.dart'; +export 'src/chain.dart'; diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart new file mode 100644 index 000000000..4a58a64d9 --- /dev/null +++ b/pkgs/stack_trace/test/chain_test.dart @@ -0,0 +1,618 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library chain_test; + +import 'dart:async'; + +import 'package:stack_trace/stack_trace.dart'; +import 'package:unittest/unittest.dart'; + +import 'utils.dart'; + +void main() { + group('capture() with onError catches exceptions', () { + test('thrown in a microtask', () { + return captureFuture(() => inMicrotask(() => throw 'error')) + .then((chain) { + // Since there was only one asynchronous operation, there should be only + // two traces in the chain. + expect(chain.traces, hasLength(2)); + + // The first frame of the first trace should be the line on which the + // actual error was thrown. + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + + // The second trace should describe the stack when the error callback + // was scheduled. + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('thrown in a one-shot timer', () { + return captureFuture(() => inOneShotTimer(() => throw 'error')) + .then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + }); + }); + + test('thrown in a periodic timer', () { + return captureFuture(() => inPeriodicTimer(() => throw 'error')) + .then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('thrown in a nested series of asynchronous operations', () { + return captureFuture(() { + inPeriodicTimer(() { + inOneShotTimer(() => inMicrotask(() => throw 'error')); + }); + }).then((chain) { + expect(chain.traces, hasLength(4)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + expect(chain.traces[3].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('thrown in a long future chain', () { + return captureFuture(() => inFutureChain(() => throw 'error')) + .then((chain) { + // Despite many asynchronous operations, there's only one level of + // nested calls, so there should be only two traces in the chain. This + // is important; programmers expect stack trace memory consumption to be + // O(depth of program), not O(length of program). + expect(chain.traces, hasLength(2)); + + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inFutureChain')))); + }); + }); + + test('multiple times', () { + var completer = new Completer(); + var first = true; + + Chain.capture(() { + inMicrotask(() => throw 'first error'); + inPeriodicTimer(() => throw 'second error'); + }, onError: (error, chain) { + if (first) { + expect(error, equals('first error')); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + first = false; + } else { + expect(error, equals('second error')); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + completer.complete(); + } + }); + + return completer.future; + }); + }); + + test('capture() without onError passes exceptions to parent zone', () { + var completer = new Completer(); + + runZoned(() { + Chain.capture(() => inMicrotask(() => throw 'error')); + }, onError: (error, chain) { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + completer.complete(); + }); + + return completer.future; + }); + + group('current() within capture()', () { + test('called in a microtask', () { + var completer = new Completer(); + Chain.capture(() { + inMicrotask(() => completer.complete(new Chain.current())); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('called in a one-shot timer', () { + var completer = new Completer(); + Chain.capture(() { + inOneShotTimer(() => completer.complete(new Chain.current())); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + }); + }); + + test('called in a periodic timer', () { + var completer = new Completer(); + Chain.capture(() { + inPeriodicTimer(() => completer.complete(new Chain.current())); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('called in a nested series of asynchronous operations', () { + var completer = new Completer(); + Chain.capture(() { + inPeriodicTimer(() { + inOneShotTimer(() { + inMicrotask(() => completer.complete(new Chain.current())); + }); + }); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(4)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + expect(chain.traces[3].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('called in a long future chain', () { + var completer = new Completer(); + Chain.capture(() { + inFutureChain(() => completer.complete(new Chain.current())); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inFutureChain')))); + }); + }); + }); + + test('current() outside of capture() returns a chain wrapping the current ' + 'trace', () { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); + + return completer.future.then((chain) { + // Since the chain wasn't loaded within [Chain.capture], the full stack + // chain isn't available and it just returns the current stack when + // called. + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.frames.first, frameMember(startsWith('main'))); + }); + }); + + group('forTrace() within capture()', () { + test('called for a stack trace from a microtask', () { + return Chain.capture(() { + return chainForTrace(inMicrotask, () => throw 'error'); + }).then((chain) { + // Because [chainForTrace] has to set up a future chain to capture the + // stack trace while still showing it to the zone specification, it adds + // an additional level of async nesting and so an additional trace. + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('chainForTrace')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('called for a stack trace from a one-shot timer', () { + return Chain.capture(() { + return chainForTrace(inOneShotTimer, () => throw 'error'); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('chainForTrace')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + }); + }); + + test('called for a stack trace from a periodic timer', () { + return Chain.capture(() { + return chainForTrace(inPeriodicTimer, () => throw 'error'); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('chainForTrace')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('called for a stack trace from a nested series of asynchronous ' + 'operations', () { + return Chain.capture(() { + return chainForTrace((callback) { + inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); + }, () => throw 'error'); + }).then((chain) { + expect(chain.traces, hasLength(5)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('chainForTrace')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + expect(chain.traces[3].frames, + contains(frameMember(startsWith('inOneShotTimer')))); + expect(chain.traces[4].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + }); + }); + + test('called for a stack trace from a long future chain', () { + return Chain.capture(() { + return chainForTrace(inFutureChain, () => throw 'error'); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('chainForTrace')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inFutureChain')))); + }); + }); + + test('called for an unregistered stack trace returns a chain wrapping that ' + 'trace', () { + var trace; + var chain = Chain.capture(() { + try { + throw 'error'; + } catch (_, stackTrace) { + trace = stackTrace; + return new Chain.forTrace(stackTrace); + } + }); + + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.toString(), + equals(new Trace.from(trace).toString())); + }); + }); + + test('forTrace() outside of capture() returns a chain wrapping the given ' + 'trace', () { + var trace; + var chain = Chain.capture(() { + try { + throw 'error'; + } catch (_, stackTrace) { + trace = stackTrace; + return new Chain.forTrace(stackTrace); + } + }); + + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.toString(), + equals(new Trace.from(trace).toString())); + }); + + test('Chain.parse() parses a real Chain', () { + return captureFuture(() => inMicrotask(() => throw 'error')).then((chain) { + expect(new Chain.parse(chain.toString()).toString(), + equals(chain.toString())); + }); + }); + + group('Chain.terse', () { + test('makes each trace terse', () { + var chain = new Chain([ + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n' + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Zip.zap\n' + 'dart:core 10:11 Zop.zoop'), + new Trace.parse( + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap\n' + 'user/code.dart 10:11 Zop.zoop') + ]); + + expect(chain.terse.toString(), equals( + 'dart:core Bar.baz\n' + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core Zip.zap\n' + 'user/code.dart 10:11 Zop.zoop\n')); + }); + + test('eliminates internal-only traces', () { + var chain = new Chain([ + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz'), + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap'), + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz') + ]); + + expect(chain.terse.toString(), equals( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core Bar.baz\n' + '===== asynchronous gap ===========================\n' + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core Bar.baz\n')); + }); + }); + + test('Chain.toTrace eliminates asynchronous gaps', () { + var trace = new Chain([ + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz'), + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz') + ]).toTrace(); + + expect(trace.toString(), equals( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n' + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n')); + }); + + group('Chain.track(Future)', () { + test('associates the current chain with a manually-reported exception with ' + 'a stack trace', () { + var trace = new Trace.current(); + return captureFuture(() { + inMicrotask(() => trackedErrorFuture(trace)); + }).then((chain) { + expect(chain.traces, hasLength(3)); + + // The first trace is the trace that was manually reported for the + // error. + expect(chain.traces.first.toString(), equals(trace.toString())); + + // The second trace is the trace that was captured when [Chain.track] + // was called. + expect(chain.traces[1].frames.first, + frameMember(startsWith('trackedErrorFuture'))); + + // The third trace is the automatically-captured trace from when the + // microtask was scheduled. + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('associates the current chain with a manually-reported exception with ' + 'no stack trace', () { + return captureFuture(() { + inMicrotask(() => trackedErrorFuture()); + }).then((chain) { + expect(chain.traces, hasLength(3)); + + // The first trace is the one captured by + // [StackZoneSpecification.trackFuture], which should contain only + // stack_trace and dart: frames. + expect(chain.traces.first.frames, + everyElement(frameLibrary(isNot(contains('chain_test'))))); + + expect(chain.traces[1].frames.first, + frameMember(startsWith('trackedErrorFuture'))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('forwards the future value within Chain.capture()', () { + Chain.capture(() { + expect(Chain.track(new Future.value('value')), + completion(equals('value'))); + + var trace = new Trace.current(); + expect(Chain.track(new Future.error('error', trace)) + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + test('forwards the future value outside of Chain.capture()', () { + expect(Chain.track(new Future.value('value')), + completion(equals('value'))); + + var trace = new Trace.current(); + expect(Chain.track(new Future.error('error', trace)) + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + group('Chain.track(Stream)', () { + test('associates the current chain with a manually-reported exception with ' + 'a stack trace', () { + var trace = new Trace.current(); + return captureFuture(() { + inMicrotask(() => trackedErrorStream(trace).listen(null)); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces.first.toString(), equals(trace.toString())); + expect(chain.traces[1].frames.first, + frameMember(startsWith('trackedErrorStream'))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('associates the current chain with a manually-reported exception with ' + 'no stack trace', () { + return captureFuture(() { + inMicrotask(() => trackedErrorStream().listen(null)); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces.first.frames, + everyElement(frameLibrary(isNot(contains('chain_test'))))); + expect(chain.traces[1].frames.first, + frameMember(startsWith('trackedErrorStream'))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('forwards stream values within Chain.capture()', () { + Chain.capture(() { + var controller = new StreamController() + ..add(1)..add(2)..add(3)..close(); + expect(Chain.track(controller.stream).toList(), + completion(equals([1, 2, 3]))); + + var trace = new Trace.current(); + controller = new StreamController()..addError('error', trace); + expect(Chain.track(controller.stream).toList() + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + test('forwards stream values outside of Chain.capture()', () { + Chain.capture(() { + var controller = new StreamController() + ..add(1)..add(2)..add(3)..close(); + expect(Chain.track(controller.stream).toList(), + completion(equals([1, 2, 3]))); + + var trace = new Trace.current(); + controller = new StreamController()..addError('error', trace); + expect(Chain.track(controller.stream).toList() + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + }); +} + +/// Runs [callback] in a microtask callback. +void inMicrotask(callback()) => scheduleMicrotask(callback); + +/// Runs [callback] in a one-shot timer callback. +void inOneShotTimer(callback()) => Timer.run(callback); + +/// Runs [callback] once in a periodic timer callback. +void inPeriodicTimer(callback()) { + var count = 0; + new Timer.periodic(new Duration(milliseconds: 1), (timer) { + count++; + if (count != 5) return; + timer.cancel(); + callback(); + }); +} + +/// Runs [callback] within a long asynchronous Future chain. +void inFutureChain(callback()) { + new Future(() {}) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => callback()) + .then((_) => new Future(() {})); +} + +/// Returns a Future that completes to an error and is wrapped in [Chain.track]. +/// +/// If [trace] is passed, it's used as the stack trace for the error. +Future trackedErrorFuture([StackTrace trace]) { + var completer = new Completer(); + completer.completeError('error', trace); + return Chain.track(completer.future); +} + +/// Returns a Stream that emits an error and is wrapped in [Chain.track]. +/// +/// If [trace] is passed, it's used as the stack trace for the error. +Stream trackedErrorStream([StackTrace trace]) { + var controller = new StreamController(); + controller.addError('error', trace); + return Chain.track(controller.stream); +} + +/// Runs [callback] within [asyncFn], then converts any errors raised into a +/// [Chain] with [Chain.forTrace]. +Future chainForTrace(asyncFn(callback()), callback()) { + var completer = new Completer(); + asyncFn(() { + // We use `new Future.value().then(...)` here as opposed to [new Future] or + // [new Future.sync] because those methods don't pass the exception through + // the zone specification before propagating it, so there's no chance to + // attach a chain to its stack trace. See issue 15105. + new Future.value().then((_) => callback()) + .catchError(completer.completeError); + }); + return completer.future + .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); +} + +/// Runs [callback] in a [Chain.capture] zone and returns a Future that +/// completes to the stack chain for an error thrown by [callback]. +/// +/// [callback] is expected to throw the string `"error"`. +Future captureFuture(callback()) { + var completer = new Completer(); + Chain.capture(callback, onError: (error, chain) { + expect(error, equals('error')); + completer.complete(chain); + }); + return completer.future; +} diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index ad916f156..4c3278f37 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -171,6 +171,24 @@ void main() { equals(Uri.parse("http://dartlang.org/foo/baz.dart"))); }); + test('parses a package:stack_trace stack chain correctly', () { + var trace = new Trace.parse( + 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/baz.dart Foo..bar\n' + '===== asynchronous gap ===========================\n' + 'http://dartlang.org/foo/bang.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/quux.dart Foo..bar'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://dartlang.org/foo/baz.dart"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://dartlang.org/foo/bang.dart"))); + expect(trace.frames[3].uri, + equals(Uri.parse("http://dartlang.org/foo/quux.dart"))); + }); + test('parses a real package:stack_trace stack trace correctly', () { var traceString = new Trace.current().toString(); expect(new Trace.parse(traceString).toString(), equals(traceString)); diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart new file mode 100644 index 000000000..ed756313c --- /dev/null +++ b/pkgs/stack_trace/test/utils.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.test.utils; + +import 'package:unittest/unittest.dart'; + +/// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. +Matcher frameMember(matcher) => + transform((frame) => frame.member, matcher, 'member'); + +/// Returns a matcher that runs [matcher] against a [Frame]'s `library` field. +Matcher frameLibrary(matcher) => + transform((frame) => frame.library, matcher, 'library'); + +/// Returns a matcher that runs [transformation] on its input, then matches +/// the output against [matcher]. +/// +/// [description] should be a noun phrase that describes the relation of the +/// output of [transformation] to its input. +Matcher transform(transformation(value), matcher, String description) => + new _TransformMatcher(transformation, wrapMatcher(matcher), description); + +class _TransformMatcher extends Matcher { + final Function _transformation; + final Matcher _matcher; + final String _description; + + _TransformMatcher(this._transformation, this._matcher, this._description); + + bool matches(item, Map matchState) => + _matcher.matches(_transformation(item), matchState); + + Description describe(Description description) => + description.add(_description).add(' ').addDescriptionOf(_matcher); +} From c13855faf20be1911056fe0ba067fb98becf75e7 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 27 Nov 2013 23:58:40 +0000 Subject: [PATCH 0093/1215] Fix stack trace chain tests on Windows. R=rnystrom@google.com TBR Review URL: https://codereview.chromium.org//92863003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30739 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/chain_test.dart | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 4a58a64d9..4d31acbb4 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -6,6 +6,7 @@ library chain_test; import 'dart:async'; +import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import 'package:unittest/unittest.dart'; @@ -336,6 +337,7 @@ void main() { }); }); + var userSlashCode = p.join('user', 'code.dart'); group('Chain.terse', () { test('makes each trace terse', () { var chain = new Chain([ @@ -355,12 +357,12 @@ void main() { expect(chain.terse.toString(), equals( 'dart:core Bar.baz\n' - 'user/code.dart 10:11 Bang.qux\n' + '$userSlashCode 10:11 Bang.qux\n' 'dart:core Zop.zoop\n' '===== asynchronous gap ===========================\n' - 'user/code.dart 10:11 Bang.qux\n' + '$userSlashCode 10:11 Bang.qux\n' 'dart:core Zip.zap\n' - 'user/code.dart 10:11 Zop.zoop\n')); + '$userSlashCode 10:11 Zop.zoop\n')); }); test('eliminates internal-only traces', () { @@ -378,10 +380,10 @@ void main() { ]); expect(chain.terse.toString(), equals( - 'user/code.dart 10:11 Foo.bar\n' + '$userSlashCode 10:11 Foo.bar\n' 'dart:core Bar.baz\n' '===== asynchronous gap ===========================\n' - 'user/code.dart 10:11 Foo.bar\n' + '$userSlashCode 10:11 Foo.bar\n' 'dart:core Bar.baz\n')); }); }); @@ -397,9 +399,9 @@ void main() { ]).toTrace(); expect(trace.toString(), equals( - 'user/code.dart 10:11 Foo.bar\n' + '$userSlashCode 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n' - 'user/code.dart 10:11 Foo.bar\n' + '$userSlashCode 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n')); }); From cb64c9e76d8e2d1219471c0091c6f19adf01182b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 4 Dec 2013 22:31:18 +0000 Subject: [PATCH 0094/1215] Update the Linux watcher to accommodate changes in [Directory.watch]. This also removes the extra time allotted for the test since issue 14606 is now mitigated. R=rnystrom@google.com BUG=15446 Review URL: https://codereview.chromium.org//99483006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30874 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 13 ++++++++++++- pkgs/watcher/test/directory_watcher/linux_test.dart | 9 +-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index d62c6ef10..5e86a4344 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -213,7 +213,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (oldState == _EntryState.DIRECTORY) { var watcher = _subWatchers.remove(path); - if (watcher == null) return; + if (watcher == null) continue; for (var path in watcher._allFiles) { _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); } @@ -247,6 +247,17 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Handles the underlying event stream closing, indicating that the directory /// being watched was removed. void _onDone() { + // Most of the time when a directory is removed, its contents will get + // individual REMOVE events before the watch stream is closed -- in that + // case, [_entries] will be empty here. However, if the directory's removal + // is caused by a MOVE, we need to manually emit events. + if (isReady) { + _entries.forEach((path, state) { + if (state == _EntryState.DIRECTORY) return; + _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + }); + } + // The parent directory often gets a close event before the subdirectories // are done emitting events. We wait for them to finish before we close // [events] so that we can be sure to emit a remove event for every file diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index ba695698b..f53b272b4 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -14,14 +14,7 @@ main() { watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); - setUp(() { - // Increase the timeout because closing a [Directory.watch] stream blocks - // the main isolate for a very long time on Goobuntu, as of kernel - // 3.2.5-gg1336 (see issue 14606). - currentSchedule.timeout *= 3; - - createSandbox(); - }); + setUp(createSandbox); sharedTests(); From 91f82aa4facf3a2b02f6185a02d32505163d0c62 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 5 Dec 2013 19:31:19 +0000 Subject: [PATCH 0095/1215] Add stack chain support to pkg/watcher and pkg/http. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//94093007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30912 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 10 ++++++---- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 10 ++++++---- pkgs/watcher/lib/src/directory_watcher/polling.dart | 5 +++-- pkgs/watcher/lib/src/stat.dart | 4 +++- pkgs/watcher/pubspec.yaml | 1 + 5 files changed, 19 insertions(+), 11 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 5e86a4344..76558dd27 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -7,6 +7,8 @@ library watcher.directory_watcher.linux; import 'dart:async'; import 'dart:io'; +import 'package:stack_trace/stack_trace.dart'; + import '../utils.dart'; import '../watch_event.dart'; import 'resubscribable.dart'; @@ -56,13 +58,13 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _LinuxDirectoryWatcher(String directory) : directory = directory { // Batch the inotify changes together so that we can dedup events. - var innerStream = new Directory(directory).watch().transform( - new BatchedStreamTransformer()); + var innerStream = Chain.track(new Directory(directory).watch()) + .transform(new BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError, onDone: _onDone); - _listen(new Directory(directory).list(), (entity) { + _listen(Chain.track(new Directory(directory).list()), (entity) { _entries[entity.path] = new _EntryState(entity is Directory); if (entity is! Directory) return; _watchSubdir(entity.path); @@ -157,7 +159,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // event for every new file. watcher.ready.then((_) { if (!isReady || _eventsController.isClosed) return; - _listen(new Directory(path).list(recursive: true), (entry) { + _listen(Chain.track(new Directory(path).list(recursive: true)), (entry) { if (entry is Directory) return; _eventsController.add(new WatchEvent(ChangeType.ADD, entry.path)); }, onError: (error, stackTrace) { diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 5b1feb342..16de1d93f 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -73,7 +73,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files = new PathSet(directory) { _startWatch(); - _listen(new Directory(directory).list(recursive: true), + _listen(Chain.track(new Directory(directory).list(recursive: true)), (entity) { if (entity is! Directory) _files.add(entity.path); }, @@ -109,7 +109,8 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { continue; } - _listen(new Directory(path).list(recursive: true), (entity) { + _listen(Chain.track(new Directory(path).list(recursive: true)), + (entity) { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); @@ -314,8 +315,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = new Directory(directory).watch(recursive: true).transform( - new BatchedStreamTransformer()); + var innerStream = + Chain.track(new Directory(directory).watch(recursive: true)) + .transform(new BatchedStreamTransformer()); _watchSubscription = innerStream.listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index e50a0c05c..684f7aad8 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -8,6 +8,7 @@ import 'dart:async'; import 'dart:io'; import 'package:crypto/crypto.dart'; +import 'package:stack_trace/stack_trace.dart'; import '../async_queue.dart'; import '../stat.dart'; @@ -105,7 +106,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _filesToProcess.add(null); } - var stream = new Directory(directory).list(recursive: true); + var stream = Chain.track(new Directory(directory).list(recursive: true)); _listSubscription = stream.listen((entity) { assert(!_events.isClosed); @@ -185,7 +186,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Calculates the SHA-1 hash of the file at [path]. Future> _hashFile(String path) { - return new File(path).readAsBytes().then((bytes) { + return Chain.track(new File(path).readAsBytes()).then((bytes) { var sha1 = new SHA1(); sha1.add(bytes); return sha1.close(); diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index d36eff3bd..166d78988 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -7,6 +7,8 @@ library watcher.stat; import 'dart:async'; import 'dart:io'; +import 'package:stack_trace/stack_trace.dart'; + /// A function that takes a file path and returns the last modified time for /// the file at that path. typedef DateTime MockTimeCallback(String path); @@ -29,5 +31,5 @@ Future getModificationTime(String path) { return new Future.value(_mockTimeCallback(path)); } - return FileStat.stat(path).then((stat) => stat.modified); + return Chain.track(FileStat.stat(path)).then((stat) => stat.modified); } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index b95c7efdf..93d8eb48c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -9,6 +9,7 @@ description: > dependencies: crypto: ">=0.9.0 <0.10.0" path: ">=0.9.0 <0.10.0" + stack_trace: ">=0.9.0 <0.10.0" dev_dependencies: scheduled_test: ">=0.9.0 <0.10.0" unittest: ">=0.9.0 <0.10.0" From d222b70ac1c0294f3171304a1e4b2a43977df565 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 5 Dec 2013 20:24:10 +0000 Subject: [PATCH 0096/1215] Add a missing import to pkg/watcher. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//104033003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30914 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 16de1d93f..c3e03b852 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,6 +7,8 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import 'package:stack_trace/stack_trace.dart'; + import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; From dc5efb8cce969e118008b31d372b1ac414d35aeb Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 5 Dec 2013 20:26:18 +0000 Subject: [PATCH 0097/1215] Update the Mac OS watcher in pkg/watcher. The behavior of Directory.watch has changed, and this updates the watcher to match the new behavior. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//100823005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30915 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 68 +++++++++---------- .../test/directory_watcher/mac_os_test.dart | 24 ------- .../test/no_subscription/mac_os_test.dart | 26 ------- pkgs/watcher/test/no_subscription/shared.dart | 10 --- 4 files changed, 31 insertions(+), 97 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index c3e03b852..3e68cd936 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -23,8 +23,8 @@ import 'resubscribable.dart'; /// succession, it won't report them in the order they occurred. See issue /// 14373. /// -/// This also works around issues 14793, 14806, and 14849 in the implementation -/// of [Directory.watch]. +/// This also works around issues 15458 and 14849 in the implementation of +/// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { MacOSDirectoryWatcher(String directory) : super(directory, () => new _MacOSDirectoryWatcher(directory)); @@ -106,11 +106,18 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { for (var event in events) { if (event is FileSystemCreateEvent) { if (!event.isDirectory) { + // Don't emit ADD events for files or directories that we already + // know about. Such an event comes from FSEvents reporting an add + // that happened prior to the watch beginning. + if (_files.contains(path)) continue; + _emitEvent(ChangeType.ADD, path); _files.add(path); continue; } + if (_files.containsDir(path)) continue; + _listen(Chain.track(new Directory(path).list(recursive: true)), (entity) { if (entity is Directory) return; @@ -164,34 +171,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { set.add(event); } - for (var event in batch.where((event) => event is! FileSystemMoveEvent)) { + for (var event in batch) { + // The Mac OS watcher doesn't emit move events. See issue 14806. + assert(event is! FileSystemMoveEvent); addEvent(event.path, event); } - // Issue 14806 means that move events can be misleading if they're in the - // same batch as another modification of a related file. If they are, we - // make the event set empty to ensure we check the state of the filesystem. - // Otherwise, treat them as a DELETE followed by an ADD. - for (var event in batch.where((event) => event is FileSystemMoveEvent)) { - if (eventsForPaths.containsKey(event.path) || - eventsForPaths.containsKey(event.destination)) { - - if (!isInModifiedDirectory(event.path)) { - eventsForPaths[event.path] = new Set(); - } - if (!isInModifiedDirectory(event.destination)) { - eventsForPaths[event.destination] = new Set(); - } - - continue; - } - - addEvent(event.path, new ConstructableFileSystemDeleteEvent( - event.path, event.isDirectory)); - addEvent(event.destination, new ConstructableFileSystemCreateEvent( - event.path, event.isDirectory)); - } - return eventsForPaths; } @@ -212,6 +197,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var type = batch.first.type; var isDir = batch.first.isDirectory; + var hadModifyEvent = false; for (var event in batch.skip(1)) { // If one event reports that the file is a directory and another event @@ -222,7 +208,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // safely assume the file was modified after a CREATE or before the // REMOVE; otherwise there will also be a REMOVE or CREATE event // (respectively) that will be contradictory. - if (event is FileSystemModifyEvent) continue; + if (event is FileSystemModifyEvent) { + hadModifyEvent = true; + continue; + } assert(event is FileSystemCreateEvent || event is FileSystemDeleteEvent); // If we previously thought this was a MODIFY, we now consider it to be a @@ -237,13 +226,23 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (type != event.type) return null; } + // If we got a CREATE event for a file we already knew about, that comes + // from FSEvents reporting an add that happened prior to the watch + // beginning. If we also received a MODIFY event, we want to report that, + // but not the CREATE. + if (type == FileSystemEvent.CREATE && hadModifyEvent && + _files.contains(batch.first.path)) { + type = FileSystemEvent.MODIFY; + } + switch (type) { case FileSystemEvent.CREATE: - // Issue 14793 means that CREATE events can actually mean DELETE, so we - // should always check the filesystem for them. - return null; + return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); case FileSystemEvent.DELETE: - return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + // Issue 15458 means that DELETE events for directories can actually + // mean CREATE, so we always check the filesystem for them. + if (isDir) return null; + return new ConstructableFileSystemCreateEvent(batch.first.path, false); case FileSystemEvent.MODIFY: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); @@ -329,11 +328,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { void _emitEvent(ChangeType type, String path) { if (!isReady) return; - // Don't emit ADD events for files that we already know about. Such an event - // probably comes from FSEvents reporting an add that happened prior to the - // watch beginning. - if (type == ChangeType.ADD && _files.contains(path)) return; - _eventsController.add(new WatchEvent(type, path)); } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 7d31221de..b71e1458b 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -2,8 +2,6 @@ // 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. -import 'dart:async'; - import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'package:watcher/watcher.dart'; @@ -52,28 +50,6 @@ main() { withPermutations((i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - // We sleep here because a narrow edge case caused by two interacting bugs - // can produce events that aren't expected if we start the watcher too - // soon after creating the files above. Here's what happens: - // - // * We create "dir/sub" and its contents above. - // - // * We initialize the watcher watching "dir". - // - // * Due to issue 14373, the watcher can receive native events describing - // the creation of "dir/sub" and its contents despite the fact that they - // occurred before the watcher was started. - // - // * Usually the above events will occur while the watcher is doing its - // initial scan of "dir/sub" and be ignored, but occasionally they will - // occur afterwards. - // - // * When processing the bogus CREATE events, the watcher has to assume that - // they could mean something other than CREATE (issue 14793). Thus it - // assumes that the files or directories in question could have changed - // and emits CHANGE events or additional REMOVE/CREATE pairs for them. - schedule(() => new Future.delayed(new Duration(seconds: 2))); - startWatcher(dir: "dir"); renameDir("dir/sub", "sub"); diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index 3862134d6..e0275c4ee 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -9,32 +9,6 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -// This is currently failing due to issue 14793. The reason is fairly complex: -// -// 1. As part of the test, an "unwatched.txt" file is created while there are no -// active watchers on the containing directory. -// -// 2. A watcher is then added. -// -// 3. The watcher lists the contents of the directory and notices that -// "unwatched.txt" already exists. -// -// 4. Since FSEvents reports past changes (issue 14373), the IO event stream -// emits a CREATED event for "unwatched.txt". -// -// 5. Due to issue 14793, the watcher cannot trust that this is really a CREATED -// event and checks the status of "unwatched.txt" on the filesystem against -// its internal state. -// -// 6. "unwatched.txt" exists on the filesystem and the watcher knows about it -// internally as well. It assumes this means that the file was modified. -// -// 7. The watcher emits an unexpected MODIFIED event for "unwatched.txt", -// causing the test to fail. -// -// Once issue 14793 is fixed, this will no longer be the case and the test will -// work again. - main() { initConfig(); diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index de625d51d..99172a2e8 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -41,16 +41,6 @@ sharedTests() { schedule(() { completer = new Completer(); subscription = watcher.events.listen(wrapAsync((event) { - // TODO(nweiz): Remove this when either issue 14373 or 14793 is fixed. - // Issue 14373 means that the new [Directory.watch] will emit an event - // for "unwatched.txt" being created, and issue 14793 means we have to - // check the filesystem, which leads us to assume that the file has been - // modified. - if (Platform.isMacOS && event.path.endsWith("unwatched.txt")) { - expect(event, isWatchEvent(ChangeType.MODIFY, "unwatched.txt")); - return; - } - // We should get an event for the third file, not the one added while // we weren't subscribed. expect(event, isWatchEvent(ChangeType.ADD, "added.txt")); From c47d6266a2f9eec62fd66ac9dee39f2d29191418 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 5 Dec 2013 22:49:03 +0000 Subject: [PATCH 0098/1215] Add debugging prints to the Mac OS directory watcher. This is a temporary CL that will make it easier to track down and fix the errors in the mac watcher. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//107403002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30919 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 96 ++++++++++++++++++- .../test/directory_watcher/mac_os_test.dart | 1 + pkgs/watcher/test/utils.dart | 12 +++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 3e68cd936..90036ccc4 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,6 +7,7 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import '../constructable_file_system_event.dart'; @@ -26,11 +27,19 @@ import 'resubscribable.dart'; /// This also works around issues 15458 and 14849 in the implementation of /// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { + // TODO(nweiz): remove these when issue 15042 is fixed. + static var logDebugInfo = false; + static var _count = 0; + MacOSDirectoryWatcher(String directory) - : super(directory, () => new _MacOSDirectoryWatcher(directory)); + : super(directory, () => new _MacOSDirectoryWatcher(directory, _count++)); } class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + // TODO(nweiz): remove these when issue 15042 is fixed. + static var _count = 0; + final String _id; + final String directory; Stream get events => _eventsController.stream; @@ -70,9 +79,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// watcher is closed. This does not include [_watchSubscription]. final _subscriptions = new Set(); - _MacOSDirectoryWatcher(String directory) + _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, - _files = new PathSet(directory) { + _files = new PathSet(directory), + _id = "$parentId/${_count++}" { _startWatch(); _listen(Chain.track(new Directory(directory).list(recursive: true)), @@ -80,11 +90,22 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, - onDone: _readyCompleter.complete, + onDone: () { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + _readyCompleter.complete(); + }, cancelOnError: true); } void close() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is closed"); + } for (var subscription in _subscriptions) { subscription.cancel(); } @@ -96,12 +117,38 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] ======== batch:"); + for (var event in batch) { + print("[$_id] ${_formatEvent(event)}"); + } + + print("[$_id] known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + batches++; _sortEvents(batch).forEach((path, events) { + var relativePath = p.relative(path, from: directory); + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] events for $relativePath:\n"); + for (var event in events) { + print("[$_id] ${_formatEvent(event)}"); + } + } + var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] canonical event for $relativePath: " + "${_formatEvent(canonicalEvent)}"); + print("[$_id] actionable events for $relativePath: " + "${events.map(_formatEvent)}"); + } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -123,7 +170,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (entity is Directory) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: _emitError, cancelOnError: true); + }, onError: (e, stackTrace) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] got error listing $relativePath: $e"); + } + _emitError(e, stackTrace); + }, cancelOnError: true); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); @@ -135,6 +187,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); + + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] ======== batch complete"); + } } /// Sort all the events in a batch into sets based on their path. @@ -263,6 +319,13 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] file existed: $fileExisted"); + print("[$_id] dir existed: $dirExisted"); + print("[$_id] file exists: $fileExists"); + print("[$_id] dir exists: $dirExists"); + } + var events = []; if (fileExisted) { if (fileExists) { @@ -328,6 +391,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { void _emitEvent(ChangeType type, String path) { if (!isReady) return; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] emitting $type ${p.relative(path, from: directory)}"); + } + _eventsController.add(new WatchEvent(type, path)); } @@ -348,4 +415,23 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } + + // TODO(nweiz): remove this when issue 15042 is fixed. + /// Return a human-friendly string representation of [event]. + String _formatEvent(FileSystemEvent event) { + if (event == null) return 'null'; + + var path = p.relative(event.path, from: directory); + var type = event.isDirectory ? 'directory' : 'file'; + if (event is FileSystemCreateEvent) { + return "create $type $path"; + } else if (event is FileSystemDeleteEvent) { + return "delete $type $path"; + } else if (event is FileSystemModifyEvent) { + return "modify $type $path"; + } else if (event is FileSystemMoveEvent) { + return "move $type $path to " + "${p.relative(event.destination, from: directory)}"; + } + } } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index b71e1458b..8fc2d3e54 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -11,6 +11,7 @@ import '../utils.dart'; main() { initConfig(); + MacOSDirectoryWatcher.logDebugInfo = true; watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 567bdb221..a7bd9b636 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -15,6 +15,9 @@ import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; import 'package:watcher/src/utils.dart'; +// TODO(nweiz): remove this when issue 15042 is fixed. +import 'package:watcher/src/directory_watcher/mac_os.dart'; + /// The path to the temporary sandbox created for each test. All file /// operations are implicitly relative to this directory. String _sandboxDir; @@ -115,6 +118,11 @@ Stream _watcherEvents; /// /// If [dir] is provided, watches a subdirectory in the sandbox with that name. void startWatcher({String dir}) { + var testCase = currentTestCase.description; + if (MacOSDirectoryWatcher.logDebugInfo) { + print("starting watcher for $testCase"); + } + // We want to wait until we're ready *after* we subscribe to the watcher's // events. _watcher = createWatcher(dir: dir, waitForReady: false); @@ -128,6 +136,10 @@ void startWatcher({String dir}) { onError: currentSchedule.signalError); currentSchedule.onComplete.schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("stopping watcher for $testCase"); + } + var numEvents = _nextEvent; subscription.cancel(); _nextEvent = 0; From 4214ba98b8a962370847ca988f35c43ee3e47854 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 9 Dec 2013 20:44:05 +0000 Subject: [PATCH 0099/1215] Increment package versions for stack trace changes. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//110613003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@30997 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 93d8eb48c..90b93e551 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.0 +version: 0.9.1 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -9,7 +9,7 @@ description: > dependencies: crypto: ">=0.9.0 <0.10.0" path: ">=0.9.0 <0.10.0" - stack_trace: ">=0.9.0 <0.10.0" + stack_trace: ">=0.9.1 <0.10.0" dev_dependencies: scheduled_test: ">=0.9.0 <0.10.0" unittest: ">=0.9.0 <0.10.0" From 71eddd366c2ff94e46abf1a3e3adba70202ed78a Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 9 Dec 2013 20:44:05 +0000 Subject: [PATCH 0100/1215] Increment package versions for stack trace changes. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//110613003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@30997 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index c71a7819e..ac41d931b 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.0 +version: 0.9.1 author: "Dart Team " homepage: http://www.dartlang.org description: > From ce9c760bd4ce9f56b26c5628706ac075a6d48dfb Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 10 Dec 2013 00:24:01 +0000 Subject: [PATCH 0101/1215] Make pkg/path 1.0.0 and upgrade dependencies appropriately. All existing packages that use pkg/path (other than pkg/stack_trace, which has already been updated) are compatible with both the pre-1.0 and post-1.0 path API, so I've marked their version constraints as ">=0.9.0 <2.0.0". I've also incremented their patch versions and I intend to release new versions as soon as this CL lands. R=alanknight@google.com, efortuna@google.com, jmesserly@google.com, rnystrom@google.com, scheglov@google.com Review URL: https://codereview.chromium.org//110873002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31005 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 90b93e551..a9672946d 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.1 +version: 0.9.2 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -8,7 +8,7 @@ description: > modified. dependencies: crypto: ">=0.9.0 <0.10.0" - path: ">=0.9.0 <0.10.0" + path: ">=0.9.0 <2.0.0" stack_trace: ">=0.9.1 <0.10.0" dev_dependencies: scheduled_test: ">=0.9.0 <0.10.0" From a325f8588b05c5c4989f4d0c1fe287b704cd1f8a Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 17 Dec 2013 01:09:29 +0000 Subject: [PATCH 0102/1215] Chain.terse shouldn't return an empty chain. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//116913003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31177 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/chain.dart | 13 +++++++++++-- pkgs/stack_trace/test/chain_test.dart | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index f6e2f3fb3..4055bc847 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -157,10 +157,19 @@ class Chain implements StackTrace { /// This calls [Trace.terse] on every trace in [traces], and discards any /// trace that contain only internal frames. Chain get terse { - return new Chain(traces.map((trace) => trace.terse).where((trace) { + var terseTraces = traces.map((trace) => trace.terse); + var nonEmptyTraces = terseTraces.where((trace) { // Ignore traces that contain only internal processing. return trace.frames.length > 1; - })); + }); + + // If all the traces contain only internal processing, preserve the last + // (top-most) one so that the chain isn't empty. + if (nonEmptyTraces.isEmpty && terseTraces.isNotEmpty) { + return new Chain([terseTraces.last]); + } + + return new Chain(nonEmptyTraces); } /// Converts [this] to a [Trace]. diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 4d31acbb4..9c166909e 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -386,6 +386,21 @@ void main() { '$userSlashCode 10:11 Foo.bar\n' 'dart:core Bar.baz\n')); }); + + test("doesn't return in an empty chain", () { + var chain = new Chain([ + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap'), + new Trace.parse( + 'dart:core 10:11 A.b\n' + 'package:stack_trace/stack_trace.dart 10:11 C.d\n' + 'dart:core 10:11 E.f') + ]); + + expect(chain.terse.toString(), equals('dart:core E.f\n')); + }); }); test('Chain.toTrace eliminates asynchronous gaps', () { From bce1ecb4b4c12d0f3d5f63087de1ec7556a9f21b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 7 Jan 2014 00:39:31 +0000 Subject: [PATCH 0103/1215] Work around issue 15920 in pkg/stack_trace. R=rnystrom@google.com Review URL: https://codereview.chromium.org//112953004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31526 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 5 ++++- pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 88b927518..45cb42c75 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -126,7 +126,10 @@ class Trace implements StackTrace { /// Parses a string representation of a Dart VM stack trace. Trace.parseVM(String trace) - : this(trace.trim().split("\n").map((line) => new Frame.parseVM(line))); + : this(trace.trim().split("\n"). + // TODO(nweiz): remove this when issue 15920 is fixed. + where((line) => line.isNotEmpty). + map((line) => new Frame.parseVM(line))); /// Parses a string representation of a Chrome/V8 stack trace. Trace.parseV8(String trace) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ac41d931b..5a023c046 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.1 +version: 0.9.1-dev+1 author: "Dart Team " homepage: http://www.dartlang.org description: > From f16db649803d130ce25e33f6dd8be1ae3292d9de Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Tue, 7 Jan 2014 21:09:58 +0000 Subject: [PATCH 0104/1215] Don't test for file differences in the polling watcher. The non-polling forms don't do this, so this makes the polling style behave the same. It also has two important benefits: 1. On Windows, this avoids opening the files being watched. Since opening a file prevents it from being deleted on Windows, this causes the watcher to interfere with the files and leads to some flaky tests and buggy user behavior. 2. It saves some time and memory since we don't need to store the SHA1 for every file being watched. BUG=http://dartbug.com/13026, http://dartbug.com/15431 R=nweiz@google.com Review URL: https://codereview.chromium.org//122573003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31574 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/polling.dart | 69 ++++--------------- pkgs/watcher/pubspec.yaml | 8 +-- .../test/directory_watcher/linux_test.dart | 10 --- .../test/directory_watcher/mac_os_test.dart | 10 --- .../test/directory_watcher/polling_test.dart | 9 --- .../test/directory_watcher/shared.dart | 10 +++ 6 files changed, 27 insertions(+), 89 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 684f7aad8..12a32458e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -7,7 +7,6 @@ library watcher.directory_watcher.polling; import 'dart:async'; import 'dart:io'; -import 'package:crypto/crypto.dart'; import 'package:stack_trace/stack_trace.dart'; import '../async_queue.dart'; @@ -46,10 +45,10 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// directory contents. final Duration _pollingDelay; - /// The previous status of the files in the directory. + /// The previous modification times of the files in the directory. /// /// Used to tell which files have been modified. - final _statuses = new Map(); + final _lastModifieds = new Map(); /// The subscription used while [directory] is being listed. /// @@ -89,7 +88,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // Don't process any remaining files. _filesToProcess.clear(); _polledFiles.clear(); - _statuses.clear(); + _lastModifieds.clear(); } /// Scans the contents of the directory once to see which files have been @@ -135,32 +134,25 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { return getModificationTime(file).then((modified) { if (_events.isClosed) return null; - var lastStatus = _statuses[file]; + var lastModified = _lastModifieds[file]; // If its modification time hasn't changed, assume the file is unchanged. - if (lastStatus != null && lastStatus.modified == modified) { + if (lastModified != null && lastModified == modified) { // The file is still here. _polledFiles.add(file); return null; } - return _hashFile(file).then((hash) { - if (_events.isClosed) return; - - var status = new _FileStatus(modified, hash); - _statuses[file] = status; - _polledFiles.add(file); + if (_events.isClosed) return null; - // Only notify if we're ready to emit events. - if (!isReady) return; + _lastModifieds[file] = modified; + _polledFiles.add(file); - // And the file is different. - var changed = lastStatus == null || !_sameHash(lastStatus.hash, hash); - if (!changed) return; + // Only notify if we're ready to emit events. + if (!isReady) return null; - var type = lastStatus == null ? ChangeType.ADD : ChangeType.MODIFY; - _events.add(new WatchEvent(type, file)); - }); + var type = lastModified == null ? ChangeType.ADD : ChangeType.MODIFY; + _events.add(new WatchEvent(type, file)); }); } @@ -169,10 +161,10 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { Future _completePoll() { // Any files that were not seen in the last poll but that we have a // status for must have been removed. - var removedFiles = _statuses.keys.toSet().difference(_polledFiles); + var removedFiles = _lastModifieds.keys.toSet().difference(_polledFiles); for (var removed in removedFiles) { if (isReady) _events.add(new WatchEvent(ChangeType.REMOVE, removed)); - _statuses.remove(removed); + _lastModifieds.remove(removed); } if (!isReady) _ready.complete(); @@ -183,37 +175,4 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _poll(); }); } - - /// Calculates the SHA-1 hash of the file at [path]. - Future> _hashFile(String path) { - return Chain.track(new File(path).readAsBytes()).then((bytes) { - var sha1 = new SHA1(); - sha1.add(bytes); - return sha1.close(); - }); - } - - /// Returns `true` if [a] and [b] are the same hash value, i.e. the same - /// series of byte values. - bool _sameHash(List a, List b) { - // Hashes should always be the same size. - assert(a.length == b.length); - - for (var i = 0; i < a.length; i++) { - if (a[i] != b[i]) return false; - } - - return true; - } -} - -class _FileStatus { - /// The last time the file was modified. - DateTime modified; - - /// The SHA-1 hash of the contents of the file. - List hash; - - _FileStatus(this.modified, this.hash); } - diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index a9672946d..c77dddfd2 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,13 +1,11 @@ name: watcher -version: 0.9.2 +version: 0.9.3-dev author: "Dart Team " homepage: http://www.dartlang.org description: > - A file watcher. It monitors (currently by polling) for changes to contents - of directories and notifies you when files have been added, removed, or - modified. + A file watcher. It monitors for changes to contents of directories and + notifies you when files have been added, removed, or modified. dependencies: - crypto: ">=0.9.0 <0.10.0" path: ">=0.9.0 <2.0.0" stack_trace: ">=0.9.1 <0.10.0" dev_dependencies: diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index f53b272b4..c2d017677 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -23,16 +23,6 @@ main() { new isInstanceOf()); }); - test('notifies even if the file contents are unchanged', () { - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "before"); - startWatcher(); - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "after"); - expectModifyEvent("a.txt"); - expectModifyEvent("b.txt"); - }); - test('emits events for many nested files moved out then immediately back in', () { withPermutations((i, j, k) => diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 8fc2d3e54..077787a29 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -36,16 +36,6 @@ main() { expectAddEvent("dir/newer.txt"); }); - test('notifies even if the file contents are unchanged', () { - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "before"); - startWatcher(); - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "after"); - expectModifyEvent("a.txt"); - expectModifyEvent("b.txt"); - }); - test('emits events for many nested files moved out then immediately back in', () { withPermutations((i, j, k) => diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 02ed5d215..da292073c 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -19,15 +19,6 @@ main() { sharedTests(); - test('does not notify if the file contents are unchanged', () { - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "before"); - startWatcher(); - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "after"); - expectModifyEvent("b.txt"); - }); - test('does not notify if the modification time did not change', () { writeFile("a.txt", contents: "before"); writeFile("b.txt", contents: "before"); diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index fe76a03d3..f831196a8 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -51,6 +51,16 @@ sharedTests() { expectModifyEvent("file.txt"); }); + test('notifies even if the file contents are unchanged', () { + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "before"); + startWatcher(); + writeFile("a.txt", contents: "same"); + writeFile("b.txt", contents: "after"); + expectModifyEvent("a.txt"); + expectModifyEvent("b.txt"); + }); + test('when the watched directory is deleted, removes all files', () { writeFile("dir/a.txt"); writeFile("dir/b.txt"); From 5be127ba595f23601bbe85ee3d9f8fa3fc91f525 Mon Sep 17 00:00:00 2001 From: "rnystrom@google.com" Date: Tue, 7 Jan 2014 23:39:17 +0000 Subject: [PATCH 0105/1215] I guess Linux doesn't iterate over folders alphabetically. R=nweiz@google.com Review URL: https://codereview.chromium.org//127033002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31591 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/test/directory_watcher/shared.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index f831196a8..2e0186f52 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -55,10 +55,13 @@ sharedTests() { writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "before"); startWatcher(); + writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "after"); - expectModifyEvent("a.txt"); - expectModifyEvent("b.txt"); + inAnyOrder(() { + expectModifyEvent("a.txt"); + expectModifyEvent("b.txt"); + }); }); test('when the watched directory is deleted, removes all files', () { From c8588e759e67e6c70009b17f931abcc3f61d5713 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 9 Jan 2014 01:52:31 +0000 Subject: [PATCH 0106/1215] Properly parse V8 lines involving eval in pkg/stack_trace. R=sigmund@google.com Review URL: https://codereview.chromium.org//130443002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31644 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 56 ++++++++++++++++++++------- pkgs/stack_trace/test/frame_test.dart | 30 ++++++++++++++ 2 files changed, 71 insertions(+), 15 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 74aafcda3..8544c786f 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -14,13 +14,24 @@ final _vmFrame = new RegExp( r'^#\d+\s+([^\s].*) \((.+?):(\d+)(?::(\d+))?\)$'); // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) +// at VW.call$0 (eval as fn +// (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 final _v8Frame = new RegExp( - r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? ' - r'\((.+):(\d+):(\d+)\)|(.+):(\d+):(\d+))$'); + r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); -/// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 -/// http://pub.dartlang.org/stuff.dart.js:560:28 +// http://pub.dartlang.org/stuff.dart.js:560:28 +final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$'); + +// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28 +// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) +// eval as function (eval as otherFunction +// (http://pub.dartlang.org/stuff.dart.js:560:28)) +final _v8EvalLocation = new RegExp( + r'^eval at (?:[^\s].*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); + +// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 +// http://pub.dartlang.org/stuff.dart.js:560:28 final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$"); // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 @@ -139,20 +150,35 @@ class Frame { throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); } + // v8 location strings can be arbitrarily-nested, since it adds a layer of + // nesting for each eval performed on that line. + parseLocation(location, member) { + var evalMatch = _v8EvalLocation.firstMatch(location); + if (evalMatch != null) return parseLocation(evalMatch[1], member); + + + var urlMatch = _v8UrlLocation.firstMatch(location); + if (urlMatch == null) { + throw new FormatException( + "Couldn't parse V8 stack trace line '$frame'."); + } + + return new Frame( + _uriOrPathToUri(urlMatch[1]), + int.parse(urlMatch[2]), + int.parse(urlMatch[3]), + member); + } + // V8 stack frames can be in two forms. if (match[2] != null) { - // The first form looks like " at FUNCTION (PATH:LINE:COL)". PATH is - // usually an absolute URL, but it can be a path if the stack frame came - // from d8. - var uri = _uriOrPathToUri(match[2]); - var member = match[1].replaceAll("", ""); - return new Frame(uri, int.parse(match[3]), int.parse(match[4]), member); + // The first form looks like " at FUNCTION (LOCATION)". + return parseLocation( + match[2], match[1].replaceAll("", "")); } else { - // The second form looks like " at PATH:LINE:COL", and is used for - // anonymous functions. PATH is usually an absolute URL, but it can be a - // path if the stack frame came from d8. - var uri = _uriOrPathToUri(match[5]); - return new Frame(uri, int.parse(match[6]), int.parse(match[7]), ""); + // The second form looks like " at LOCATION", and is used for anonymous + // functions. + return parseLocation(match[3], ""); } } diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 9722d38df..482794c31 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -149,6 +149,36 @@ void main() { expect(frame.member, equals('VW.call\$0')); }); + test('parses a basic eval stack frame correctly', () { + var frame = new Frame.parseV8(" at eval (eval at " + "(http://pub.dartlang.org/stuff.dart.js:560:28))"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('eval')); + }); + + test('parses an eval stack frame with inner position info correctly', () { + var frame = new Frame.parseV8(" at eval (eval at " + "(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('eval')); + }); + + test('parses a nested eval stack frame correctly', () { + var frame = new Frame.parseV8(" at eval (eval at " + "(eval at sub (http://pub.dartlang.org/stuff.dart.js:560:28)))"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('eval')); + }); + test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseV8(' at $member (foo:0:0)').member; From 117f97272492d65be8c15a7ce4cd944fd444e28f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 9 Jan 2014 22:02:27 +0000 Subject: [PATCH 0107/1215] Code review changes for r31644. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//132223003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31679 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8544c786f..7b9c7b1a9 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -11,14 +11,14 @@ import 'trace.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) final _vmFrame = new RegExp( - r'^#\d+\s+([^\s].*) \((.+?):(\d+)(?::(\d+))?\)$'); + r'^#\d+\s+(\S.*) \((.+?):(\d+)(?::(\d+))?\)$'); // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) // at VW.call$0 (eval as fn // (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 final _v8Frame = new RegExp( - r'^\s*at (?:([^\s].*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); + r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // http://pub.dartlang.org/stuff.dart.js:560:28 final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$'); @@ -28,7 +28,7 @@ final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$'); // eval as function (eval as otherFunction // (http://pub.dartlang.org/stuff.dart.js:560:28)) final _v8EvalLocation = new RegExp( - r'^eval at (?:[^\s].*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); + r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); // foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 // http://pub.dartlang.org/stuff.dart.js:560:28 @@ -43,7 +43,7 @@ final _firefoxFrame = new RegExp( // foo/bar.dart 10:11 in Foo._bar // http://dartlang.org/foo/bar.dart in Foo._bar final _friendlyFrame = new RegExp( - r'^([^\s]+)(?: (\d+)(?::(\d+))?)?\s+([^\d][^\s]*)$'); + r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$'); final _initialDot = new RegExp(r"^\."); @@ -154,8 +154,10 @@ class Frame { // nesting for each eval performed on that line. parseLocation(location, member) { var evalMatch = _v8EvalLocation.firstMatch(location); - if (evalMatch != null) return parseLocation(evalMatch[1], member); - + while (evalMatch != null) { + location = evalMatch[1]; + evalMatch = _v8EvalLocation.firstMatch(location); + } var urlMatch = _v8UrlLocation.firstMatch(location); if (urlMatch == null) { From 51191b81bb183f77196fdcdac61f32b0d9909216 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 10 Jan 2014 20:36:33 +0000 Subject: [PATCH 0108/1215] Use stream matchers to unflake the mac OS watcher tests. R=rnystrom@google.com BUG=15024 Review URL: https://codereview.chromium.org//129473003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31705 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/utils.dart | 12 ++ pkgs/watcher/pubspec.yaml | 4 +- .../test/directory_watcher/linux_test.dart | 17 +- .../test/directory_watcher/mac_os_test.dart | 42 ++-- .../test/directory_watcher/shared.dart | 111 +++++++---- pkgs/watcher/test/utils.dart | 182 ++++++++++++------ 6 files changed, 240 insertions(+), 128 deletions(-) diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index a235f7da5..163e9f445 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -73,6 +73,18 @@ Stream futureStream(Future future, {bool broadcast: false}) { /// under the covers. Future newFuture(callback()) => new Future.value().then((_) => callback()); +/// Returns a [Future] that completes after pumping the event queue [times] +/// times. By default, this should pump the event queue enough times to allow +/// any code to run, as long as it's not waiting on some external event. +Future pumpEventQueue([int times=20]) { + if (times == 0) return new Future.value(); + // We use a delayed future to allow microtask events to finish. The + // Future.value or Future() constructors use scheduleMicrotask themselves and + // would therefore not wait for microtask callbacks that are scheduled after + // invoking this method. + return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); +} + /// A stream transformer that batches all events that are sent at the same time. /// /// When multiple events are synchronously added to a stream controller, the diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index c77dddfd2..bf00d9e31 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -9,7 +9,7 @@ dependencies: path: ">=0.9.0 <2.0.0" stack_trace: ">=0.9.1 <0.10.0" dev_dependencies: - scheduled_test: ">=0.9.0 <0.10.0" - unittest: ">=0.9.0 <0.10.0" + scheduled_test: ">=0.9.3-dev <0.10.0" + unittest: ">=0.9.2 <0.10.0" environment: sdk: ">=0.8.10+6 <2.0.0" diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index c2d017677..cae38adf8 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -32,14 +32,15 @@ main() { renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); - inAnyOrder(() { - withPermutations((i, j, k) => - expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); - - inAnyOrder(() { - withPermutations((i, j, k) => - expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + allowEither(() { + inAnyOrder(withPermutations((i, j, k) => + isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + + inAnyOrder(withPermutations((i, j, k) => + isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + }, () { + inAnyOrder(withPermutations((i, j, k) => + isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 077787a29..43567f0e7 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -36,24 +36,26 @@ main() { expectAddEvent("dir/newer.txt"); }); - test('emits events for many nested files moved out then immediately back in', - () { - withPermutations((i, j, k) => - writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - - startWatcher(dir: "dir"); - - renameDir("dir/sub", "sub"); - renameDir("sub", "dir/sub"); - - inAnyOrder(() { - withPermutations((i, j, k) => - expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); - - inAnyOrder(() { - withPermutations((i, j, k) => - expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); - }); + // TODO(nweiz): re-enable this when issue 16003 is fixed. + // test('emits events for many nested files moved out then immediately back in', + // () { + // withPermutations((i, j, k) => + // writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + + // startWatcher(dir: "dir"); + + // renameDir("dir/sub", "sub"); + // renameDir("sub", "dir/sub"); + + // allowEither(() { + // inAnyOrder(withPermutations((i, j, k) => + // isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + + // inAnyOrder(withPermutations((i, j, k) => + // isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + // }, () { + // inAnyOrder(withPermutations((i, j, k) => + // isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + // }); + // }); } diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 2e0186f52..849cea00d 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/utils.dart'; import '../utils.dart'; @@ -58,10 +59,10 @@ sharedTests() { writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "after"); - inAnyOrder(() { - expectModifyEvent("a.txt"); - expectModifyEvent("b.txt"); - }); + inAnyOrder([ + isModifyEvent("a.txt"), + isModifyEvent("b.txt") + ]); }); test('when the watched directory is deleted, removes all files', () { @@ -71,10 +72,10 @@ sharedTests() { startWatcher(dir: "dir"); deleteDir("dir"); - inAnyOrder(() { - expectRemoveEvent("dir/a.txt"); - expectRemoveEvent("dir/b.txt"); - }); + inAnyOrder([ + isRemoveEvent("dir/a.txt"), + isRemoveEvent("dir/b.txt") + ]); }); group("moves", () { @@ -83,10 +84,10 @@ sharedTests() { startWatcher(); renameFile("old.txt", "new.txt"); - inAnyOrder(() { - expectAddEvent("new.txt"); - expectRemoveEvent("old.txt"); - }); + inAnyOrder([ + isAddEvent("new.txt"), + isRemoveEvent("old.txt") + ]); }); test('notifies when a file is moved from outside the watched directory', @@ -108,6 +109,13 @@ sharedTests() { }); }); + // Most of the time, when multiple filesystem actions happen in sequence, + // they'll be batched together and the watcher will see them all at once. + // These tests verify that the watcher normalizes and combine these events + // properly. However, very occasionally the events will be reported in + // separate batches, and the watcher will report them as though they occurred + // far apart in time, so each of these tests has a "backup case" to allow for + // that as well. group("clustered changes", () { test("doesn't notify when a file is created and then immediately removed", () { @@ -115,7 +123,12 @@ sharedTests() { writeFile("file.txt"); deleteFile("file.txt"); - // [startWatcher] will assert that no events were fired. + // Backup case. + startClosingEventStream(); + allowEvents(() { + expectAddEvent("file.txt"); + expectRemoveEvent("file.txt"); + }); }); test("reports a modification when a file is deleted and then immediately " @@ -125,7 +138,14 @@ sharedTests() { deleteFile("file.txt"); writeFile("file.txt", contents: "re-created"); - expectModifyEvent("file.txt"); + + allowEither(() { + expectModifyEvent("file.txt"); + }, () { + // Backup case. + expectRemoveEvent("file.txt"); + expectAddEvent("file.txt"); + }); }); test("reports a modification when a file is moved and then immediately " @@ -135,9 +155,17 @@ sharedTests() { renameFile("old.txt", "new.txt"); writeFile("old.txt", contents: "re-created"); - inAnyOrder(() { - expectModifyEvent("old.txt"); + + allowEither(() { + inAnyOrder([ + isModifyEvent("old.txt"), + isAddEvent("new.txt") + ]); + }, () { + // Backup case. + expectRemoveEvent("old.txt"); expectAddEvent("new.txt"); + expectAddEvent("old.txt"); }); }); @@ -148,6 +176,10 @@ sharedTests() { writeFile("file.txt", contents: "modified"); deleteFile("file.txt"); + + // Backup case. + allowModifyEvent("file.txt"); + expectRemoveEvent("file.txt"); }); @@ -157,7 +189,12 @@ sharedTests() { writeFile("file.txt"); writeFile("file.txt", contents: "modified"); + expectAddEvent("file.txt"); + + // Backup case. + startClosingEventStream(); + allowModifyEvent("file.txt"); }); }); @@ -174,10 +211,10 @@ sharedTests() { startWatcher(); renameDir("old", "new"); - inAnyOrder(() { - expectRemoveEvent("old/file.txt"); - expectAddEvent("new/file.txt"); - }); + inAnyOrder([ + isRemoveEvent("old/file.txt"), + isAddEvent("new/file.txt") + ]); writeFile("new/file.txt", contents: "modified"); expectModifyEvent("new/file.txt"); @@ -191,10 +228,8 @@ sharedTests() { startWatcher(dir: "dir"); renameDir("sub", "dir/sub"); - inAnyOrder(() { - withPermutations((i, j, k) => - expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); + inAnyOrder(withPermutations((i, j, k) => + isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); test('emits events for many nested files removed at once', () { @@ -210,10 +245,8 @@ sharedTests() { // directory. renameDir("dir/sub", "sub"); - inAnyOrder(() { - withPermutations((i, j, k) => - expectRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); + inAnyOrder(withPermutations((i, j, k) => + isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); test('emits events for many nested files moved at once', () { @@ -224,12 +257,12 @@ sharedTests() { startWatcher(dir: "dir"); renameDir("dir/old", "dir/new"); - inAnyOrder(() { - withPermutations((i, j, k) { - expectRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"); - expectAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt"); - }); - }); + inAnyOrder(unionAll(withPermutations((i, j, k) { + return new Set.from([ + isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"), + isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt") + ]); + }))); }); test("emits events for many files added at once in a subdirectory with the " @@ -241,11 +274,11 @@ sharedTests() { deleteFile("dir/sub"); renameDir("old", "dir/sub"); - inAnyOrder(() { - expectRemoveEvent("dir/sub"); - withPermutations((i, j, k) => - expectAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - }); + + var events = withPermutations((i, j, k) => + isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + events.add(isRemoveEvent("dir/sub")); + inAnyOrder(events); }); }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index a7bd9b636..f7e35f18a 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -9,6 +9,7 @@ import 'dart:collection'; import 'dart:io'; import 'package:path/path.dart' as p; +import 'package:scheduled_test/scheduled_stream.dart'; import 'package:scheduled_test/scheduled_test.dart'; import 'package:unittest/compact_vm_config.dart'; import 'package:watcher/watcher.dart'; @@ -25,11 +26,6 @@ String _sandboxDir; /// The [DirectoryWatcher] being used for the current scheduled test. DirectoryWatcher _watcher; -/// The index in [_watcher]'s event stream for the next event. When event -/// expectations are set using [expectEvent] (et. al.), they use this to -/// expect a series of events in order. -var _nextEvent = 0; - /// The mock modification times (in milliseconds since epoch) for each file. /// /// The actual file system has pretty coarse granularity for file modification @@ -111,7 +107,7 @@ DirectoryWatcher createWatcher({String dir, bool waitForReady}) { } /// The stream of events from the watcher started with [startWatcher]. -Stream _watcherEvents; +ScheduledStream _watcherEvents; /// Creates a new [DirectoryWatcher] that watches a temporary directory and /// starts monitoring it for events. @@ -130,82 +126,102 @@ void startWatcher({String dir}) { // Schedule [_watcher.events.listen] so that the watcher doesn't start // watching [dir] before it exists. Expose [_watcherEvents] immediately so // that it can be accessed synchronously after this. - _watcherEvents = futureStream(schedule(() { - var allEvents = new Queue(); - var subscription = _watcher.events.listen(allEvents.add, - onError: currentSchedule.signalError); - + _watcherEvents = new ScheduledStream(futureStream(schedule(() { currentSchedule.onComplete.schedule(() { if (MacOSDirectoryWatcher.logDebugInfo) { print("stopping watcher for $testCase"); } - var numEvents = _nextEvent; - subscription.cancel(); - _nextEvent = 0; _watcher = null; + if (!_closePending) _watcherEvents.close(); // If there are already errors, don't add this to the output and make // people think it might be the root cause. if (currentSchedule.errors.isEmpty) { - expect(allEvents, hasLength(numEvents)); - } else { - currentSchedule.addDebugInfo("Events fired:\n${allEvents.join('\n')}"); + _watcherEvents.expect(isDone); } }, "reset watcher"); return _watcher.events; - }, "create watcher"), broadcast: true); + }, "create watcher"), broadcast: true)); schedule(() => _watcher.ready, "wait for watcher to be ready"); } -/// A future set by [inAnyOrder] that will complete to the set of events that -/// occur in the [inAnyOrder] block. -Future> _unorderedEventFuture; +/// Whether an event to close [_watcherEvents] has been scheduled. +bool _closePending = false; -/// Runs [block] and allows multiple [expectEvent] calls in that block to match -/// events in any order. -void inAnyOrder(block()) { - var oldFuture = _unorderedEventFuture; +/// Schedule closing the directory watcher stream after the event queue has been +/// pumped. +/// +/// This is necessary when events are allowed to occur, but don't have to occur, +/// at the end of a test. Otherwise, if they don't occur, the test will wait +/// indefinitely because they might in the future and because the watcher is +/// normally only closed after the test completes. +void startClosingEventStream() { + schedule(() { + _closePending = true; + pumpEventQueue().then((_) => _watcherEvents.close()).whenComplete(() { + _closePending = false; + }); + }, 'start closing event stream'); +} + +/// A list of [StreamMatcher]s that have been collected using +/// [_collectStreamMatcher]. +List _collectedStreamMatchers; + +/// Collects all stream matchers that are registered within [block] into a +/// single stream matcher. +/// +/// The returned matcher will match each of the collected matchers in order. +StreamMatcher _collectStreamMatcher(block()) { + var oldStreamMatchers = _collectedStreamMatchers; + _collectedStreamMatchers = new List(); try { - var firstEvent = _nextEvent; - var completer = new Completer(); - _unorderedEventFuture = completer.future; block(); - - _watcherEvents.skip(firstEvent).take(_nextEvent - firstEvent).toSet() - .then(completer.complete, onError: completer.completeError); - currentSchedule.wrapFuture(_unorderedEventFuture, - "waiting for ${_nextEvent - firstEvent} events"); + return inOrder(_collectedStreamMatchers); } finally { - _unorderedEventFuture = oldFuture; + _collectedStreamMatchers = oldStreamMatchers; } } -/// Expects that the next set of event will be a change of [type] on [path]. +/// Either add [streamMatcher] as an expectation to [_watcherEvents], or collect +/// it with [_collectStreamMatcher]. /// -/// Multiple calls to [expectEvent] require that the events are received in that -/// order unless they're called in an [inAnyOrder] block. -void expectEvent(ChangeType type, String path) { - if (_unorderedEventFuture != null) { - // Assign this to a local variable since it will be un-assigned by the time - // the scheduled callback runs. - var future = _unorderedEventFuture; - - expect( - schedule(() => future, "should fire $type event on $path"), - completion(contains(isWatchEvent(type, path)))); +/// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value. +void _expectOrCollect(streamMatcher) { + if (_collectedStreamMatchers != null) { + _collectedStreamMatchers.add(new StreamMatcher.wrap(streamMatcher)); } else { - var future = currentSchedule.wrapFuture( - _watcherEvents.elementAt(_nextEvent), - "waiting for $type event on $path"); - - expect( - schedule(() => future, "should fire $type event on $path"), - completion(isWatchEvent(type, path))); + _watcherEvents.expect(streamMatcher); } - _nextEvent++; +} + +/// Expects that [matchers] will match emitted events in any order. +/// +/// [matchers] may be [Matcher]s or values, but not [StreamMatcher]s. +void inAnyOrder(Iterable matchers) { + matchers = matchers.toSet(); + _expectOrCollect(nextValues(matchers.length, unorderedMatches(matchers))); +} + +/// Expects that the expectations established in either [block1] or [block2] +/// will match the emitted events. +/// +/// If both blocks match, the one that consumed more events will be used. +void allowEither(block1(), block2()) { + _expectOrCollect(either( + _collectStreamMatcher(block1), _collectStreamMatcher(block2))); +} + +/// Allows the expectations established in [block] to match the emitted events. +/// +/// If the expectations in [block] don't match, no error will be raised and no +/// events will be consumed. If this is used at the end of a test, +/// [startClosingEventStream] should be called before it. +void allowEvents(block()) { + _expectOrCollect(allow(_collectStreamMatcher(block))); } /// Returns a matcher that matches a [WatchEvent] with the given [type] and @@ -217,9 +233,53 @@ Matcher isWatchEvent(ChangeType type, String path) { }, "is $type $path"); } -void expectAddEvent(String path) => expectEvent(ChangeType.ADD, path); -void expectModifyEvent(String path) => expectEvent(ChangeType.MODIFY, path); -void expectRemoveEvent(String path) => expectEvent(ChangeType.REMOVE, path); +/// Returns a [Matcher] that matches a [WatchEvent] for an add event for [path]. +Matcher isAddEvent(String path) => isWatchEvent(ChangeType.ADD, path); + +/// Returns a [Matcher] that matches a [WatchEvent] for a modification event for +/// [path]. +Matcher isModifyEvent(String path) => isWatchEvent(ChangeType.MODIFY, path); + +/// Returns a [Matcher] that matches a [WatchEvent] for a removal event for +/// [path]. +Matcher isRemoveEvent(String path) => isWatchEvent(ChangeType.REMOVE, path); + +/// Expects that the next event emitted will be for an add event for [path]. +void expectAddEvent(String path) => + _expectOrCollect(isWatchEvent(ChangeType.ADD, path)); + +/// Expects that the next event emitted will be for a modification event for +/// [path]. +void expectModifyEvent(String path) => + _expectOrCollect(isWatchEvent(ChangeType.MODIFY, path)); + +/// Expects that the next event emitted will be for a removal event for [path]. +void expectRemoveEvent(String path) => + _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path)); + +/// Consumes an add event for [path] if one is emitted at this point in the +/// schedule, but doesn't throw an error if it isn't. +/// +/// If this is used at the end of a test, [startClosingEventStream] should be +/// called before it. +void allowAddEvent(String path) => + _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path))); + +/// Consumes a modification event for [path] if one is emitted at this point in +/// the schedule, but doesn't throw an error if it isn't. +/// +/// If this is used at the end of a test, [startClosingEventStream] should be +/// called before it. +void allowModifyEvent(String path) => + _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path))); + +/// Consumes a removal event for [path] if one is emitted at this point in the +/// schedule, but doesn't throw an error if it isn't. +/// +/// If this is used at the end of a test, [startClosingEventStream] should be +/// called before it. +void allowRemoveEvent(String path) => + _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path))); /// Schedules writing a file in the sandbox at [path] with [contents]. /// @@ -299,14 +359,18 @@ void deleteDir(String path) { /// Runs [callback] with every permutation of non-negative [i], [j], and [k] /// less than [limit]. /// +/// Returns a set of all values returns by [callback]. +/// /// [limit] defaults to 3. -void withPermutations(callback(int i, int j, int k), {int limit}) { +Set withPermutations(callback(int i, int j, int k), {int limit}) { if (limit == null) limit = 3; + var results = new Set(); for (var i = 0; i < limit; i++) { for (var j = 0; j < limit; j++) { for (var k = 0; k < limit; k++) { - callback(i, j, k); + results.add(callback(i, j, k)); } } } + return results; } From 1fe426cd684bdd6efaca6236d161b6637dda6c86 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 10 Jan 2014 21:27:08 +0000 Subject: [PATCH 0109/1215] Stop working around issue 15458 in pkg/watcher. R=rnystrom@google.com Review URL: https://codereview.chromium.org//134773002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31709 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 90036ccc4..17c25adbc 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -24,7 +24,7 @@ import 'resubscribable.dart'; /// succession, it won't report them in the order they occurred. See issue /// 14373. /// -/// This also works around issues 15458 and 14849 in the implementation of +/// This also works around issue 14849 in the implementation of /// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { // TODO(nweiz): remove these when issue 15042 is fixed. @@ -295,9 +295,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { case FileSystemEvent.CREATE: return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); case FileSystemEvent.DELETE: - // Issue 15458 means that DELETE events for directories can actually - // mean CREATE, so we always check the filesystem for them. - if (isDir) return null; return new ConstructableFileSystemCreateEvent(batch.first.path, false); case FileSystemEvent.MODIFY: return new ConstructableFileSystemModifyEvent( From 6939000ebdb5408fc3f1e76258c7f85d5275dd6f Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 13 Jan 2014 18:07:45 +0000 Subject: [PATCH 0110/1215] pkg/unittest: added LICENSE R=rnystrom@google.com Review URL: https://codereview.chromium.org//135343002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31750 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/LICENSE | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 pkgs/stack_trace/LICENSE diff --git a/pkgs/stack_trace/LICENSE b/pkgs/stack_trace/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/stack_trace/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 0812547c3fda4962a8abe43c3800bca242a020fd Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 13 Jan 2014 18:07:45 +0000 Subject: [PATCH 0111/1215] pkg/unittest: added LICENSE R=rnystrom@google.com Review URL: https://codereview.chromium.org//135343002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31750 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/LICENSE | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 pkgs/watcher/LICENSE diff --git a/pkgs/watcher/LICENSE b/pkgs/watcher/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/watcher/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 62cb2b98d679bec0efa966e58e6ef45a66a1ead4 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 13 Jan 2014 21:07:47 +0000 Subject: [PATCH 0112/1215] Support Safari 6.1 stack traces with blank lines in pkg/stack_trace. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//136693006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31756 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 1 + pkgs/stack_trace/test/trace_test.dart | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 45cb42c75..21e8afcfc 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -164,6 +164,7 @@ class Trace implements StackTrace { /// Parses a string representation of a Safari 6.1+ stack trace. Trace.parseSafari6_1(String trace) : this(trace.trim().split("\n") + .where((line) => line.isNotEmpty) .map((line) => new Frame.parseSafari6_1(line))); /// Parses a string representation of a Safari 6.0 stack trace. diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 4c3278f37..eeeff282d 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -160,6 +160,21 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); + test('parses a Safari 6.1 stack trace with an empty line correctly', () { + var trace = new Trace.parse( + 'http://pub.dartlang.org/stuff.js:42:43\n' + '\n' + 'zip@http://pub.dartlang.org/stuff.js:0:1\n' + 'zip\$zap@http://pub.dartlang.org/thing.js:1:2'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + }); + test('parses a package:stack_trace stack trace correctly', () { var trace = new Trace.parse( 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' From 6c6536909b60cbd52999629c4037b27cff19d567 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 13 Jan 2014 22:37:40 +0000 Subject: [PATCH 0113/1215] Validate that Trace.from's argument isn't null. R=rnystrom@google.com BUG=16071 Review URL: https://codereview.chromium.org//137443002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@31762 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/trace.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 21e8afcfc..c1d751fdd 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -92,6 +92,13 @@ class Trace implements StackTrace { /// If [trace] is a native [StackTrace], its data will be parsed out; if it's /// a [Trace], it will be returned as-is. factory Trace.from(StackTrace trace) { + // Normally explicitly validating null arguments is bad Dart style, but here + // the natural failure will only occur when the LazyTrace is materialized, + // and we want to provide an error that's more local to the actual problem. + if (trace == null) { + throw new ArgumentError("Cannot create a Trace from null."); + } + if (trace is Trace) return trace; if (trace is Chain) return trace.toTrace(); return new LazyTrace(() => new Trace.parse(trace.toString())); From 450bf11ae4ba8aa1bdbfa6021fd448555eedf7ce Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 14 Jan 2014 23:49:01 +0000 Subject: [PATCH 0114/1215] Fix a flaky test and work around issue 16003 in pkg/watcher. There's an additional flaky test that this CL is not likely to fix. Additional debugging is added to help track down the cause of that flake. R=rnystrom@google.com BUG=16079 Review URL: https://codereview.chromium.org//134963007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31815 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 40 +++++++++++------ .../test/directory_watcher/mac_os_test.dart | 43 +++++++++---------- pkgs/watcher/test/utils.dart | 23 +++++++++- 3 files changed, 69 insertions(+), 37 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 17c25adbc..bb82a4c3e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -24,7 +24,7 @@ import 'resubscribable.dart'; /// succession, it won't report them in the order they occurred. See issue /// 14373. /// -/// This also works around issue 14849 in the implementation of +/// This also works around issues 16003 and 14849 in the implementation of /// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { // TODO(nweiz): remove these when issue 15042 is fixed. @@ -56,7 +56,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// This is used to determine if the [Directory.watch] stream was falsely /// closed due to issue 14849. A close caused by events in the past will only /// happen before or immediately after the first batch of events. - int batches = 0; + int _batches = 0; /// The set of files that are known to exist recursively within the watched /// directory. @@ -129,12 +129,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } - batches++; + _batches++; _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] events for $relativePath:\n"); + print("[$_id] events for $relativePath:"); for (var event in events) { print("[$_id] ${_formatEvent(event)}"); } @@ -168,6 +168,8 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _listen(Chain.track(new Directory(path).list(recursive: true)), (entity) { if (entity is Directory) return; + if (_files.contains(path)) return; + _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); }, onError: (e, stackTrace) { @@ -293,9 +295,14 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { switch (type) { case FileSystemEvent.CREATE: - return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); - case FileSystemEvent.DELETE: + // Issue 16003 means that a CREATE event for a directory can indicate + // that the directory was moved and then re-created. + // [_eventsBasedOnFileSystem] will handle this correctly by producing a + // DELETE event followed by a CREATE event if the directory exists. + if (isDir) return null; return new ConstructableFileSystemCreateEvent(batch.first.path, false); + case FileSystemEvent.DELETE: + return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); case FileSystemEvent.MODIFY: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); @@ -317,10 +324,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var dirExists = new Directory(path).existsSync(); if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] file existed: $fileExisted"); - print("[$_id] dir existed: $dirExisted"); - print("[$_id] file exists: $fileExists"); - print("[$_id] dir exists: $dirExists"); + print("[$_id] checking file system for " + "${p.relative(path, from: directory)}"); + print("[$_id] file existed: $fileExisted"); + print("[$_id] dir existed: $dirExisted"); + print("[$_id] file exists: $fileExists"); + print("[$_id] dir exists: $dirExists"); } var events = []; @@ -353,19 +362,24 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when the [Directory.watch] stream is closed. void _onDone() { + if (MacOSDirectoryWatcher.logDebugInfo) print("[$_id] stream closed"); + _watchSubscription = null; // If the directory still exists and we haven't seen more than one batch, // this is probably issue 14849 rather than a real close event. We should // just restart the watcher. - if (batches < 2 && new Directory(directory).existsSync()) { + if (_batches < 2 && new Directory(directory).existsSync()) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] fake closure (issue 14849), re-opening stream"); + } _startWatch(); return; } // FSEvents can fail to report the contents of the directory being removed - // when the directory itself is removed, so we need to manually mark the as - // removed. + // when the directory itself is removed, so we need to manually mark the + // files as removed. for (var file in _files.toSet()) { _emitEvent(ChangeType.REMOVE, file); } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 43567f0e7..1e9bd7d10 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -36,26 +36,25 @@ main() { expectAddEvent("dir/newer.txt"); }); - // TODO(nweiz): re-enable this when issue 16003 is fixed. - // test('emits events for many nested files moved out then immediately back in', - // () { - // withPermutations((i, j, k) => - // writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - - // startWatcher(dir: "dir"); - - // renameDir("dir/sub", "sub"); - // renameDir("sub", "dir/sub"); - - // allowEither(() { - // inAnyOrder(withPermutations((i, j, k) => - // isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); - - // inAnyOrder(withPermutations((i, j, k) => - // isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); - // }, () { - // inAnyOrder(withPermutations((i, j, k) => - // isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); - // }); - // }); + test('emits events for many nested files moved out then immediately back in', + () { + withPermutations((i, j, k) => + writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + + startWatcher(dir: "dir"); + + renameDir("dir/sub", "sub"); + renameDir("sub", "dir/sub"); + + allowEither(() { + inAnyOrder(withPermutations((i, j, k) => + isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + + inAnyOrder(withPermutations((i, j, k) => + isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + }, () { + inAnyOrder(withPermutations((i, j, k) => + isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + }); + }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index f7e35f18a..885018bd1 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -116,7 +116,7 @@ ScheduledStream _watcherEvents; void startWatcher({String dir}) { var testCase = currentTestCase.description; if (MacOSDirectoryWatcher.logDebugInfo) { - print("starting watcher for $testCase"); + print("starting watcher for $testCase (${new DateTime.now()})"); } // We want to wait until we're ready *after* we subscribe to the watcher's @@ -129,7 +129,7 @@ void startWatcher({String dir}) { _watcherEvents = new ScheduledStream(futureStream(schedule(() { currentSchedule.onComplete.schedule(() { if (MacOSDirectoryWatcher.logDebugInfo) { - print("stopping watcher for $testCase"); + print("stopping watcher for $testCase (${new DateTime.now()})"); } _watcher = null; @@ -298,6 +298,9 @@ void writeFile(String path, {String contents, bool updateModified}) { dir.createSync(recursive: true); } + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] writing file $path"); + } new File(fullPath).writeAsStringSync(contents); // Manually update the mock modification time for the file. @@ -314,6 +317,9 @@ void writeFile(String path, {String contents, bool updateModified}) { /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] deleting file $path"); + } new File(p.join(_sandboxDir, path)).deleteSync(); }, "delete file $path"); } @@ -323,6 +329,10 @@ void deleteFile(String path) { /// If [contents] is omitted, creates an empty file. void renameFile(String from, String to) { schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] renaming file $from to $to"); + } + new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); // Make sure we always use the same separator on Windows. @@ -337,6 +347,9 @@ void renameFile(String from, String to) { /// Schedules creating a directory in the sandbox at [path]. void createDir(String path) { schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] creating directory $path"); + } new Directory(p.join(_sandboxDir, path)).createSync(); }, "create directory $path"); } @@ -344,6 +357,9 @@ void createDir(String path) { /// Schedules renaming a directory in the sandbox from [from] to [to]. void renameDir(String from, String to) { schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] renaming directory $from to $to"); + } new Directory(p.join(_sandboxDir, from)) .renameSync(p.join(_sandboxDir, to)); }, "rename directory $from to $to"); @@ -352,6 +368,9 @@ void renameDir(String from, String to) { /// Schedules deleting a directory in the sandbox at [path]. void deleteDir(String path) { schedule(() { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[test] deleting directory $path"); + } new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true); }, "delete directory $path"); } From d8c8244ce24f35a9da37c308ab687227e457e79b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 15 Jan 2014 21:49:31 +0000 Subject: [PATCH 0115/1215] Take a broader approach to filtering out bogus Mac OS watcher events. With luck, this should unflake the test. R=rnystrom@google.com BUG=16079 Review URL: https://codereview.chromium.org//140013002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@31853 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 129 ++++++++++++------ pkgs/watcher/test/utils.dart | 1 - 2 files changed, 87 insertions(+), 43 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index bb82a4c3e..ba0ede4cb 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -50,14 +50,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { Future get ready => _readyCompleter.future; final _readyCompleter = new Completer(); - /// The number of event batches that have been received from - /// [Directory.watch]. - /// - /// This is used to determine if the [Directory.watch] stream was falsely - /// closed due to issue 14849. A close caused by events in the past will only - /// happen before or immediately after the first batch of events. - int _batches = 0; - /// The set of files that are known to exist recursively within the watched /// directory. /// @@ -73,11 +65,17 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// needs to be resubscribed in order to work around issue 14849. StreamSubscription _watchSubscription; - /// A set of subscriptions that this watcher subscribes to. - /// - /// These are gathered together so that they may all be canceled when the - /// watcher is closed. This does not include [_watchSubscription]. - final _subscriptions = new Set(); + /// The subscription to the [Directory.list] call for the initial listing of + /// the directory to determine its initial state. + StreamSubscription _initialListSubscription; + + /// The subscription to the [Directory.list] call for listing the contents of + /// a subdirectory that was moved into the watched directory. + StreamSubscription _listSubscription; + + /// The timer for tracking how long we wait for an initial batch of bogus + /// events (see issue 14373). + Timer _bogusEventTimer; _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, @@ -85,12 +83,20 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _id = "$parentId/${_count++}" { _startWatch(); - _listen(Chain.track(new Directory(directory).list(recursive: true)), - (entity) { - if (entity is! Directory) _files.add(entity.path); - }, - onError: _emitError, - onDone: () { + // Before we're ready to emit events, wait for [_listDir] to complete and + // for enough time to elapse that if bogus events (issue 14373) would be + // emitted, they will be. + // + // If we do receive a batch of events, [_onBatch] will ensure that these + // futures don't fire and that the directory is re-listed. + Future.wait([ + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + }), + _waitForBogusEvents() + ]).then((_) { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -98,20 +104,19 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } _readyCompleter.complete(); - }, - cancelOnError: true); + }); } void close() { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is closed"); } - for (var subscription in _subscriptions) { - subscription.cancel(); - } - _subscriptions.clear(); if (_watchSubscription != null) _watchSubscription.cancel(); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + if (_listSubscription != null) _listSubscription.cancel(); _watchSubscription = null; + _initialListSubscription = null; + _listSubscription = null; _eventsController.close(); } @@ -129,7 +134,28 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } - _batches++; + // If we get a batch of events before we're ready to begin emitting events, + // it's probable that it's a batch of pre-watcher events (see issue 14373). + // Ignore those events and re-list the directory. + if (!isReady) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] not ready to emit events, re-listing directory"); + } + + // Cancel the timer because bogus events only occur in the first batch, so + // we can fire [ready] as soon as we're done listing the directory. + _bogusEventTimer.cancel(); + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + _readyCompleter.complete(); + }); + return; + } _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); @@ -165,8 +191,8 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (_files.containsDir(path)) continue; - _listen(Chain.track(new Directory(path).list(recursive: true)), - (entity) { + var stream = Chain.track(new Directory(path).list(recursive: true)); + _listSubscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -366,10 +392,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _watchSubscription = null; - // If the directory still exists and we haven't seen more than one batch, + // If the directory still exists and we're still expecting bogus events, // this is probably issue 14849 rather than a real close event. We should // just restart the watcher. - if (_batches < 2 && new Directory(directory).existsSync()) { + if (!isReady && new Directory(directory).existsSync()) { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] fake closure (issue 14849), re-opening stream"); } @@ -398,6 +424,37 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { onDone: _onDone); } + /// Starts or restarts listing the watched directory to get an initial picture + /// of its state. + Future _listDir() { + assert(!isReady); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + + _files.clear(); + var completer = new Completer(); + var stream = Chain.track(new Directory(directory).list(recursive: true)); + _initialListSubscription = stream.listen((entity) { + if (entity is! Directory) _files.add(entity.path); + }, + onError: _emitError, + onDone: completer.complete, + cancelOnError: true); + return completer.future; + } + + /// Wait 200ms for a batch of bogus events (issue 14373) to come in. + /// + /// 200ms is short in terms of human interaction, but longer than any Mac OS + /// watcher tests take on the bots, so it should be safe to assume that any + /// bogus events will be signaled in that time frame. + Future _waitForBogusEvents() { + var completer = new Completer(); + _bogusEventTimer = new Timer( + new Duration(milliseconds: 200), + completer.complete); + return completer.future; + } + /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; @@ -415,18 +472,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { close(); } - /// Like [Stream.listen], but automatically adds the subscription to - /// [_subscriptions] so that it can be canceled when [close] is called. - void _listen(Stream stream, void onData(event), {Function onError, - void onDone(), bool cancelOnError}) { - var subscription; - subscription = stream.listen(onData, onError: onError, onDone: () { - _subscriptions.remove(subscription); - if (onDone != null) onDone(); - }, cancelOnError: cancelOnError); - _subscriptions.add(subscription); - } - // TODO(nweiz): remove this when issue 15042 is fixed. /// Return a human-friendly string representation of [event]. String _formatEvent(FileSystemEvent event) { diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 885018bd1..b520bbd9a 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -5,7 +5,6 @@ library watcher.test.utils; import 'dart:async'; -import 'dart:collection'; import 'dart:io'; import 'package:path/path.dart' as p; From 3e9d97362d82040d44c247a736e52ad4b92c1942 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 29 Jan 2014 21:06:50 +0000 Subject: [PATCH 0116/1215] Add some additional debugging prints to the mac os watcher. R=rnystrom@google.com Review URL: https://codereview.chromium.org//146693014 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@32139 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index ba0ede4cb..e3efa2dd6 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -109,7 +109,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { void close() { if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is closed"); + print("[$_id] watcher is closed\n${new Chain.current().terse}"); } if (_watchSubscription != null) _watchSubscription.cancel(); if (_initialListSubscription != null) _initialListSubscription.cancel(); @@ -468,6 +468,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Emit an error, then close the watcher. void _emitError(error, StackTrace stackTrace) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] emitting error: $error\n" + + "${new Chain.forTrace(stackTrace).terse}"); + } _eventsController.addError(error, stackTrace); close(); } From 94acc441474c44a25971b64ea998827e3109a5fe Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 18 Feb 2014 22:56:58 +0000 Subject: [PATCH 0117/1215] Change ScheduledProcess's output streams over to be ScheduledStreams. This will help test "pub serve" with multiple entrypoints. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//164773003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@32770 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index bf00d9e31..1045bc56b 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -9,7 +9,7 @@ dependencies: path: ">=0.9.0 <2.0.0" stack_trace: ">=0.9.1 <0.10.0" dev_dependencies: - scheduled_test: ">=0.9.3-dev <0.10.0" + scheduled_test: ">=0.9.3-dev <0.11.0" unittest: ">=0.9.2 <0.10.0" environment: sdk: ">=0.8.10+6 <2.0.0" From 878a5f6118b4da10f88d693e97313957e6dfd07f Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 25 Feb 2014 22:35:49 +0000 Subject: [PATCH 0118/1215] Work around issue 17083 in pkg/stack_trace. This also properly reports timer_impl.dart as being in dart:io rather than dart:async. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//180363003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@33039 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 14 ++++++++++---- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 20 +++++++++++++++++++- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 7b9c7b1a9..96a5ec5e1 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -47,6 +47,15 @@ final _friendlyFrame = new RegExp( final _initialDot = new RegExp(r"^\."); +/// "dart:" libraries that are incorrectly reported without a "dart:" prefix. +/// +/// See issue 11901. All these libraries should be in "dart:io". +final _ioLibraries = new Set.from([ + new Uri(path: 'timer_impl.dart'), + new Uri(path: 'http_impl.dart'), + new Uri(path: 'http_parser.dart') +]); + /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { /// The URI of the file in which the code is located. @@ -130,10 +139,7 @@ class Frame { // always be found. The column is optional. var member = match[1].replaceAll("", ""); var uri = Uri.parse(match[2]); - // Work around issue 11901. - if (uri == new Uri(path: 'timer_impl.dart')) { - uri = Uri.parse('dart:async/timer_impl.dart'); - } + if (_ioLibraries.contains(uri)) uri = Uri.parse('dart:io/${uri.path}'); var line = int.parse(match[3]); var column = null; var columnMatch = match[4]; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 5a023c046..1e62ca69c 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.1-dev+1 +version: 0.9.2 author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 482794c31..b61e8bb89 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -33,7 +33,25 @@ void main() { test('parses a stack frame with timer_impl correctly', () { var frame = new Frame.parseVM("#1 Foo._bar " "(timer_impl.dart:24)"); - expect(frame.uri, equals(Uri.parse("dart:async/timer_impl.dart"))); + expect(frame.uri, equals(Uri.parse("dart:io/timer_impl.dart"))); + expect(frame.line, equals(24)); + expect(frame.column, null); + expect(frame.member, equals('Foo._bar')); + }); + + test('parses a stack frame with http_parser correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(http_parser.dart:24)"); + expect(frame.uri, equals(Uri.parse("dart:io/http_parser.dart"))); + expect(frame.line, equals(24)); + expect(frame.column, null); + expect(frame.member, equals('Foo._bar')); + }); + + test('parses a stack frame with http_impl correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(http_impl.dart:24)"); + expect(frame.uri, equals(Uri.parse("dart:io/http_impl.dart"))); expect(frame.line, equals(24)); expect(frame.column, null); expect(frame.member, equals('Foo._bar')); From 358de696972c3689eb3b7ba026de8bd344368658 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Tue, 25 Feb 2014 23:20:00 +0000 Subject: [PATCH 0119/1215] Add Chain.foldFrames to pkg/stack_trace. R=rnystrom@google.com BUG=17082 Review URL: https://codereview.chromium.org//180223005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@33041 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/chain.dart | 27 ++++++++++++ pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 63 ++++++++++++++++++++++++++- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 4055bc847..2500e5ed2 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -7,6 +7,7 @@ library stack_trace.chain; import 'dart:async'; import 'dart:collection'; +import 'frame.dart'; import 'stack_zone_specification.dart'; import 'trace.dart'; import 'utils.dart'; @@ -172,6 +173,32 @@ class Chain implements StackTrace { return new Chain(nonEmptyTraces); } + /// Returns a new [Chain] based on [this] where multiple stack frames matching + /// [predicate] are folded together. + /// + /// This means that whenever there are multiple frames in a row that match + /// [predicate], only the last one is kept. In addition, traces that are + /// composed entirely of frames matching [predicate] are omitted. + /// + /// This is useful for limiting the amount of library code that appears in a + /// stack trace by only showing user code and code that's called by user code. + Chain foldFrames(bool predicate(Frame frame)) { + var foldedTraces = traces.map((trace) => trace.foldFrames(predicate)); + var nonEmptyTraces = foldedTraces.where((trace) { + // Ignore traces that contain only folded frames. These traces will be + // folded into a single frame each. + return trace.frames.length > 1; + }); + + // If all the traces contain only internal processing, preserve the last + // (top-most) one so that the chain isn't empty. + if (nonEmptyTraces.isEmpty && foldedTraces.isNotEmpty) { + return new Chain([foldedTraces.last]); + } + + return new Chain(nonEmptyTraces); + } + /// Converts [this] to a [Trace]. /// /// The trace version of a chain is just the concatenation of all the traces diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index c1d751fdd..c540d78c6 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -229,7 +229,7 @@ class Trace implements StackTrace { /// /// This is useful for limiting the amount of library code that appears in a /// stack trace by only showing user code and code that's called by user code. - Trace foldFrames(bool predicate(frame)) { + Trace foldFrames(bool predicate(Frame frame)) { var newFrames = []; for (var frame in frames.reversed) { if (!predicate(frame)) { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1e62ca69c..1bd47768b 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.2 +version: 0.9.2-dev author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 9c166909e..d9915ebf1 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -387,7 +387,7 @@ void main() { 'dart:core Bar.baz\n')); }); - test("doesn't return in an empty chain", () { + test("doesn't return an empty chain", () { var chain = new Chain([ new Trace.parse( 'dart:core 10:11 Foo.bar\n' @@ -403,6 +403,67 @@ void main() { }); }); + group('Chain.foldFrames', () { + test('folds each trace', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'a.dart 10:11 Zop.zoop'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'a.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals( + 'a.dart 10:11 Bar.baz\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + + test('eliminates completely-folded traces', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'b.dart 10:11 Bang.qux'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bang.qux'), + new Trace.parse( + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals( + 'a.dart 10:11 Foo.bar\n' + 'b.dart 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + + test("doesn't return an empty trace", () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bang.qux') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals('a.dart 10:11 Bang.qux\n')); + }); + }); + test('Chain.toTrace eliminates asynchronous gaps', () { var trace = new Chain([ new Trace.parse( From 9c84f687cb6db5021df00afe2f4d966ea6b321ec Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 19 Mar 2014 20:24:29 +0000 Subject: [PATCH 0120/1215] Support IE10 stack traces in pkg/stack_trace. R=rnystrom@google.com BUG=17633 Review URL: https://codereview.chromium.org//197283039 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34135 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/frame.dart | 9 ++++++--- pkgs/stack_trace/test/frame_test.dart | 10 ++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 96a5ec5e1..67438c37e 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -180,9 +180,12 @@ class Frame { // V8 stack frames can be in two forms. if (match[2] != null) { - // The first form looks like " at FUNCTION (LOCATION)". - return parseLocation( - match[2], match[1].replaceAll("", "")); + // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists + // anonymous functions within eval as "", while IE10 lists them + // as "Anonymous function". + return parseLocation(match[2], + match[1].replaceAll("", "") + .replaceAll("Anonymous function", "")); } else { // The second form looks like " at LOCATION", and is used for anonymous // functions. diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index b61e8bb89..bbb905ad1 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -177,6 +177,16 @@ void main() { expect(frame.member, equals('eval')); }); + test('parses an IE10 eval stack frame correctly', () { + var frame = new Frame.parseV8(" at eval (eval at Anonymous function " + "(http://pub.dartlang.org/stuff.dart.js:560:28))"); + expect(frame.uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('eval')); + }); + test('parses an eval stack frame with inner position info correctly', () { var frame = new Frame.parseV8(" at eval (eval at " "(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)"); From 3ee2afc46bbbcaf98fdb1b65c5e0727ea8eaee23 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 20 Mar 2014 19:56:06 +0000 Subject: [PATCH 0121/1215] Add more docs about stack chains to the stack trace package. BUG= R=kathyw@google.com Review URL: https://codereview.chromium.org//201183006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34199 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/README.md | 160 ++++++++++++++++++++++++++++ pkgs/stack_trace/lib/src/chain.dart | 9 +- 2 files changed, 168 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 6a8112a55..492a52aaa 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -55,3 +55,163 @@ example: pkg/stack_trace/lib/stack_trace.dart 24:28 format test.dart 21:29 main. dart:async Timer.Timer. + +## Stack Chains + +This library also provides the ability to capture "stack chains" with the +`Chain` class. When writing asynchronous code, a single stack trace isn't very +useful, since the call stack is unwound every time something async happens. A +stack chain tracks stack traces through asynchronous calls, so that you can see +the full path from `main` down to the error. + +To use stack chains, just wrap the code that you want to track in +`Chain.capture`. This will create a new [Zone][] in which stack traces are +recorded and woven into chains every time an asynchronous call occurs. Zones are +sticky, too, so any asynchronous operations started in the `Chain.capture` +callback will have their chains tracked, as will asynchronous operations they +start and so on. + +Here's an example of some code that doesn't capture its stack chains: + +```dart +import 'dart:async'; + +void main() { + scheduleAsync(); +} + +void scheduleAsync() { + return new Future.delayed(new Duration(seconds: 1)) + .then((_) => runAsync()); +} + +void runAsync() { + throw 'oh no!'; +} +``` + +If we run this, it prints the following: + + Uncaught Error: oh no! + Stack Trace: + #0 runAsync (file:///usr/local/google-old/home/goog/dart/dart/test.dart:13:3) + #1 scheduleAsync. (file:///usr/local/google-old/home/goog/dart/dart/test.dart:9:28) + #2 _rootRunUnary (dart:async/zone.dart:717) + #3 _RootZone.runUnary (dart:async/zone.dart:854) + #4 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488) + #5 _Future._propagateToListeners (dart:async/future_impl.dart:571) + #6 _Future._complete (dart:async/future_impl.dart:317) + #7 _SyncCompleter.complete (dart:async/future_impl.dart:44) + #8 Future.Future.delayed. (dart:async/future.dart:219) + #9 _createTimer. (dart:async-patch/timer_patch.dart:11) + #10 _handleTimeout (dart:io/timer_impl.dart:292) + #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:115) + +Notice how there's no mention of `main` in that stack trace. All we know is that +the error was in `runAsync`; we don't know why `runAsync` was called. + +Now let's look at the same code with stack chains captured: + +```dart +import 'dart:async'; + +import 'package:stack_trace/stack_trace.dart'; + +void main() { + Chain.capture(() { + scheduleAsync(); + }); +} + +void scheduleAsync() { + new Future.delayed(new Duration(seconds: 1)) + .then((_) => runAsync()); +} + +void runAsync() { + throw 'oh no!'; +} +``` + +Now if we run it, it prints this: + + Uncaught Error: oh no! + Stack Trace: + test.dart 17:3 runAsync + test.dart 13:28 scheduleAsync. + package:stack_trace/src/stack_zone_specification.dart 129:26 registerUnaryCallback.. + package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 177:7 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 175:7 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 129:18 registerUnaryCallback. + dart:async/zone.dart 717 _rootRunUnary + dart:async/zone.dart 449 _ZoneDelegate.runUnary + dart:async/zone.dart 654 _CustomizedZone.runUnary + dart:async/future_impl.dart 488 _Future._propagateToListeners.handleValueCallback + dart:async/future_impl.dart 571 _Future._propagateToListeners + dart:async/future_impl.dart 317 _Future._complete + dart:async/future_impl.dart 44 _SyncCompleter.complete + dart:async/future.dart 219 Future.Future.delayed. + package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 119:52 registerCallback. + dart:async/zone.dart 706 _rootRun + dart:async/zone.dart 440 _ZoneDelegate.run + dart:async/zone.dart 650 _CustomizedZone.run + dart:async/zone.dart 561 _BaseZone.runGuarded + dart:async/zone.dart 586 _BaseZone.bindCallback. + package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 119:52 registerCallback. + dart:async/zone.dart 710 _rootRun + dart:async/zone.dart 440 _ZoneDelegate.run + dart:async/zone.dart 650 _CustomizedZone.run + dart:async/zone.dart 561 _BaseZone.runGuarded + dart:async/zone.dart 586 _BaseZone.bindCallback. + dart:async-patch/timer_patch.dart 11 _createTimer. + dart:io/timer_impl.dart 292 _handleTimeout + dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage + ===== asynchronous gap =========================== + dart:async/zone.dart 476 _ZoneDelegate.registerUnaryCallback + dart:async/zone.dart 666 _CustomizedZone.registerUnaryCallback + dart:async/future_impl.dart 164 _Future._Future._then + dart:async/future_impl.dart 187 _Future.then + test.dart 13:12 scheduleAsync + test.dart 7:18 main. + dart:async/zone.dart 710 _rootRun + dart:async/zone.dart 440 _ZoneDelegate.run + dart:async/zone.dart 650 _CustomizedZone.run + dart:async/zone.dart 944 runZoned + package:stack_trace/src/chain.dart 93:20 Chain.capture + test.dart 6:16 main + dart:isolate-patch/isolate_patch.dart 216 _startIsolate.isolateStartHandler + dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage + +That's a lot of text! If you look closely, though, you can see that `main` is +listed in the first trace in the chain. + +Thankfully, you can call `Chain.terse` just like `Trace.terse` to get rid of all +the frames you don't care about. The terse version of the stack chain above is +this: + + test.dart 17:3 runAsync + test.dart 13:28 scheduleAsync. + dart:isolate _RawReceivePortImpl._handleMessage + ===== asynchronous gap =========================== + dart:async _Future.then + test.dart 13:12 scheduleAsync + test.dart 7:18 main. + package:stack_trace/src/chain.dart 93:20 Chain.capture + test.dart 6:16 main + dart:isolate _RawReceivePortImpl._handleMessage + +That's a lot easier to understand! + +### `Chain.track` + +For the most part `Chain.capture` will notice when an error is thrown and +associate the correct stack chain with it. However, there are some cases where +exceptions won't be automatically detected: any `Future` constructor, +`Completer.completeError`, `Stream.addError`, and libraries that use these such +as `dart:io` and `dart:async`. For these, all you need to do is wrap the Future +or Stream in a call to `Chain.track` and the errors will be tracked correctly. + +[Zone]: https://api.dartlang.org/apidocs/channels/stable/#dart-async.Zone diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 2500e5ed2..a097bba34 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -27,7 +27,14 @@ typedef void ChainHandler(error, Chain chain); /// up a new [Zone] in which the current stack chain is tracked and can be /// accessed using [new Chain.current]. Any errors that would be top-leveled in /// the zone can be handled, along with their associated chains, with the -/// `onError` callback. +/// `onError` callback. For example: +/// +/// Chain.capture(() { +/// // ... +/// }, onError: (error, stackChain) { +/// print("Caught error $error\n" +/// "$stackChain"); +/// }); /// /// For the most part [Chain.capture] will notice when an error is thrown and /// associate the correct stack chain with it; the chain can be accessed using From b07a98033c8b1fcffd53fbfa8ae63216a3985641 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 20 Mar 2014 21:57:17 +0000 Subject: [PATCH 0122/1215] Release pkg/stack_trace 0.9.2. Also add a changelog. R=rnystrom@google.com Review URL: https://codereview.chromium.org//206803002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34211 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 pkgs/stack_trace/CHANGELOG.md diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md new file mode 100644 index 000000000..a8e02d3d7 --- /dev/null +++ b/pkgs/stack_trace/CHANGELOG.md @@ -0,0 +1,5 @@ +## 0.9.2 + +* Add a `Chain.foldFrames` method that parallels `Trace.foldFrames`. + +* Record anonymous method frames in IE10 as "". diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1bd47768b..1e62ca69c 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.2-dev +version: 0.9.2 author: "Dart Team " homepage: http://www.dartlang.org description: > From a2da3f2f347d397a0ff53d1de5b70f3aed4248c1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 20 Mar 2014 22:57:04 +0000 Subject: [PATCH 0123/1215] Change pkg/stack_trace's version to 0.9.3. Apparently I screwed up the versioning earlier and went from 0.9.2 to 0.9.2-dev instead of 0.9.3-dev. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//206833004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34214 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a8e02d3d7..5e2f2c7a6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.9.2 +## 0.9.3 * Add a `Chain.foldFrames` method that parallels `Trace.foldFrames`. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1e62ca69c..99abed703 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.2 +version: 0.9.3 author: "Dart Team " homepage: http://www.dartlang.org description: > From 1114fada122bd9ea67b151ef6b4bf3bef30f0695 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 2 Apr 2014 20:30:09 +0000 Subject: [PATCH 0124/1215] Add a string_scanner package. This code has been pulled out of the Shelf package. R=kevmoo@google.com Review URL: https://codereview.chromium.org//213833013 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@34665 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/LICENSE | 26 ++ pkgs/string_scanner/README.md | 37 +++ pkgs/string_scanner/lib/string_scanner.dart | 113 ++++++++ pkgs/string_scanner/pubspec.yaml | 10 + .../test/error_format_test.dart | 110 ++++++++ .../test/string_scanner_test.dart | 267 ++++++++++++++++++ 6 files changed, 563 insertions(+) create mode 100644 pkgs/string_scanner/LICENSE create mode 100644 pkgs/string_scanner/README.md create mode 100644 pkgs/string_scanner/lib/string_scanner.dart create mode 100644 pkgs/string_scanner/pubspec.yaml create mode 100644 pkgs/string_scanner/test/error_format_test.dart create mode 100644 pkgs/string_scanner/test/string_scanner_test.dart diff --git a/pkgs/string_scanner/LICENSE b/pkgs/string_scanner/LICENSE new file mode 100644 index 000000000..5c60afea3 --- /dev/null +++ b/pkgs/string_scanner/LICENSE @@ -0,0 +1,26 @@ +Copyright 2014, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/string_scanner/README.md b/pkgs/string_scanner/README.md new file mode 100644 index 000000000..90660fc8c --- /dev/null +++ b/pkgs/string_scanner/README.md @@ -0,0 +1,37 @@ +This package exposes a `StringScanner` type that makes it easy to parse a string +using a series of `Pattern`s. For example: + +```dart +import 'dart:math'; + +import 'package:string_scanner/string_scanner.dart'; + +num parseNumber(String source) { + // Scan a number ("1", "1.5", "-3"). + var scanner = new StringScanner(source); + + // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it + // succeeded. It will move the scan pointer past the end of the pattern. + var negative = scanner.scan("-"); + + // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it + // fails. Like [Scanner.scan], it will move the scan pointer forward. + scanner.expect(new RegExp(r"\d+")); + + // [Scanner.lastMatch] holds the [MatchData] for the most recent call to + // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. + var number = int.parse(scanner.lastMatch[0]); + + if (scanner.scan(".")) { + scanner.expect(new RegExp(r"\d+")); + var decimal = scanner.lastMatch[0]; + number += int.parse(decimal) / math.pow(10, decimal.length); + } + + // [Scanner.expectDone] will throw a [FormatError] if there's any input that + // hasn't yet been consumed. + scanner.expectDone(); + + return (negative ? -1 : 1) * number; +} +``` diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart new file mode 100644 index 000000000..624c090e8 --- /dev/null +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -0,0 +1,113 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +/// A library for parsing strings using a sequence of patterns. +library string_scanner; + +// TODO(nweiz): Add some integration between this and source maps. +/// A class that scans through a string using [Pattern]s. +class StringScanner { + /// The string being scanned through. + final String string; + + /// The current position of the scanner in the string, in characters. + int get position => _position; + set position(int position) { + if (position < 0 || position > string.length) { + throw new ArgumentError("Invalid position $position"); + } + + _position = position; + } + int _position = 0; + + /// The data about the previous match made by the scanner. + /// + /// If the last match failed, this will be `null`. + Match get lastMatch => _lastMatch; + Match _lastMatch; + + /// The portion of the string that hasn't yet been scanned. + String get rest => string.substring(position); + + /// Whether the scanner has completely consumed [string]. + bool get isDone => position == string.length; + + /// Creates a new [StringScanner] that starts scanning from [position]. + /// + /// [position] defaults to 0, the beginning of the string. + StringScanner(this.string, {int position}) { + if (position != null) this.position = position; + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// Returns whether or not [pattern] matched. + bool scan(Pattern pattern) { + var success = matches(pattern); + if (success) _position = _lastMatch.end; + return success; + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// If [pattern] did not match, throws a [FormatException] describing the + /// position of the failure. [name] is used in this error as the expected name + /// of the pattern being matched; if it's `null`, the pattern itself is used + /// instead. + void expect(Pattern pattern, {String name}) { + if (scan(pattern)) return; + + if (name == null) { + if (pattern is RegExp) { + name = "/${pattern.pattern.replaceAll("/", "\\/")}/"; + } else { + name = pattern.toString() + .replaceAll("\\", "\\\\").replaceAll('"', '\\"'); + name = '"$name"'; + } + } + _fail(name); + } + + /// If the string has not been fully consumed, this throws a + /// [FormatException]. + void expectDone() { + if (isDone) return; + _fail("no more input"); + } + + /// Returns whether or not [pattern] matches at the current position of the + /// string. + /// + /// This doesn't move the scan pointer forward. + bool matches(Pattern pattern) { + _lastMatch = pattern.matchAsPrefix(string, position); + return _lastMatch != null; + } + + // TODO(nweiz): Make this handle long lines more gracefully. + /// Throws a [FormatException] describing that [name] is expected at the + /// current position in the string. + void _fail(String name) { + var newlines = "\n".allMatches(string.substring(0, position)).toList(); + var line = newlines.length + 1; + var column; + var lastLine; + if (newlines.isEmpty) { + column = position + 1; + lastLine = string.substring(0, position); + } else { + column = position - newlines.last.end + 1; + lastLine = string.substring(newlines.last.end, position); + } + lastLine += rest.replaceFirst(new RegExp(r"\n.*"), ''); + throw new FormatException( + "Expected $name on line $line, column $column.\n" + "$lastLine\n" + "${new List.filled(column - 1, ' ').join()}^"); + } +} diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml new file mode 100644 index 000000000..3035901ea --- /dev/null +++ b/pkgs/string_scanner/pubspec.yaml @@ -0,0 +1,10 @@ +name: string_scanner +version: 0.0.1 +author: "Dart Team " +homepage: http://www.dartlang.org +description: > + A class for parsing strings using a sequence of patterns. +dev_dependencies: + unittest: ">=0.10.0 <0.11.0" +environment: + sdk: ">=1.2.0 <2.0.0" diff --git a/pkgs/string_scanner/test/error_format_test.dart b/pkgs/string_scanner/test/error_format_test.dart new file mode 100644 index 000000000..118734400 --- /dev/null +++ b/pkgs/string_scanner/test/error_format_test.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.error_format_test; + +import 'package:string_scanner/string_scanner.dart'; +import 'package:unittest/unittest.dart'; + +void main() { + test('points to the first unconsumed character', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + expect(() => scanner.expect('foo'), throwsFormattedError(''' +Expected "foo" on line 1, column 5. +foo bar baz + ^''')); + }); + + test('prints the correct line', () { + var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + scanner.expect('foo bar baz\ndo '); + expect(() => scanner.expect('foo'), throwsFormattedError(''' +Expected "foo" on line 2, column 4. +do re mi + ^''')); + }); + + test('handles the beginning of the string correctly', () { + var scanner = new StringScanner('foo bar baz'); + expect(() => scanner.expect('zap'), throwsFormattedError(''' +Expected "zap" on line 1, column 1. +foo bar baz +^''')); + }); + + test('handles the end of the string correctly', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo bar baz'); + expect(() => scanner.expect('bang'), throwsFormattedError(''' +Expected "bang" on line 1, column 12. +foo bar baz + ^''')); + }); + + test('handles an empty string correctly', () { + expect(() => new StringScanner('').expect('foo'), throwsFormattedError(''' +Expected "foo" on line 1, column 1. + +^''')); + }); + + group("expected name", () { + test("uses the provided name", () { + expect(() => new StringScanner('').expect('foo bar', name: 'zap'), + throwsFormattedError(''' +Expected zap on line 1, column 1. + +^''')); + }); + + test("escapes string quotes", () { + expect(() => new StringScanner('').expect('foo"bar'), + throwsFormattedError(''' +Expected "foo\\"bar" on line 1, column 1. + +^''')); + }); + + test("escapes string backslashes", () { + expect(() => new StringScanner('').expect('foo\\bar'), + throwsFormattedError(''' +Expected "foo\\\\bar" on line 1, column 1. + +^''')); + }); + + test("prints PERL-style regexps", () { + expect(() => new StringScanner('').expect(new RegExp(r'foo')), + throwsFormattedError(''' +Expected /foo/ on line 1, column 1. + +^''')); + }); + + test("escape regexp forward slashes", () { + expect(() => new StringScanner('').expect(new RegExp(r'foo/bar')), + throwsFormattedError(''' +Expected /foo\\/bar/ on line 1, column 1. + +^''')); + }); + + test("does not escape regexp backslashes", () { + expect(() => new StringScanner('').expect(new RegExp(r'foo\bar')), + throwsFormattedError(''' +Expected /foo\\bar/ on line 1, column 1. + +^''')); + }); + }); +} + +Matcher throwsFormattedError(String format) { + return throwsA(predicate((error) { + expect(error, isFormatException); + expect(error.message, equals(format)); + return true; + })); +} diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart new file mode 100644 index 000000000..0cab6273e --- /dev/null +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -0,0 +1,267 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.string_scanner_test; + +import 'package:string_scanner/string_scanner.dart'; +import 'package:unittest/unittest.dart'; + +void main() { + group('with an empty string', () { + var scanner; + setUp(() { + scanner = new StringScanner(''); + }); + + test('is done', () { + expect(scanner.isDone, isTrue); + expect(scanner.expectDone, isNot(throwsFormatException)); + }); + + test('rest is empty', () { + expect(scanner.rest, isEmpty); + }); + + test('lastMatch is null', () { + expect(scanner.lastMatch, isNull); + }); + + test('position is zero', () { + expect(scanner.position, equals(0)); + }); + + test("scan returns false and doesn't change the state", () { + expect(scanner.scan(new RegExp('.')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test("expect throws a FormatException and doesn't change the state", () { + expect(() => scanner.expect(new RegExp('.')), throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test("matches returns false and doesn't change the state", () { + expect(scanner.matches(new RegExp('.')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test('setting position to 1 throws an ArgumentError', () { + expect(() { + scanner.position = 1; + }, throwsArgumentError); + }); + + test('setting position to -1 throws an ArgumentError', () { + expect(() { + scanner.position = -1; + }, throwsArgumentError); + }); + }); + + group('at the beginning of a string', () { + var scanner; + setUp(() { + scanner = new StringScanner('foo bar'); + }); + + test('is not done', () { + expect(scanner.isDone, isFalse); + expect(scanner.expectDone, throwsFormatException); + }); + + test('rest is the whole string', () { + expect(scanner.rest, equals('foo bar')); + }); + + test('lastMatch is null', () { + expect(scanner.lastMatch, isNull); + }); + + test('position is zero', () { + expect(scanner.position, equals(0)); + }); + + test("a matching scan returns true and changes the state", () { + expect(scanner.scan(new RegExp('f(..)')), isTrue); + expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.position, equals(3)); + expect(scanner.rest, equals(' bar')); + }); + + test("a non-matching scan returns false and sets lastMatch to null", () { + expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.lastMatch, isNotNull); + + expect(scanner.scan(new RegExp('b(..)')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + expect(scanner.rest, equals('foo bar')); + }); + + test("a matching expect changes the state", () { + scanner.expect(new RegExp('f(..)')); + expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.position, equals(3)); + expect(scanner.rest, equals(' bar')); + }); + + test("a non-matching expect throws a FormatException and sets lastMatch to " + "null", () { + expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.lastMatch, isNotNull); + + expect(() => scanner.expect(new RegExp('b(..)')), throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + expect(scanner.rest, equals('foo bar')); + }); + + test("a matching matches returns true and only changes lastMatch", () { + expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.position, equals(0)); + expect(scanner.rest, equals('foo bar')); + }); + + test("a non-matching matches returns false and doesn't change the state", + () { + expect(scanner.matches(new RegExp('b(..)')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + expect(scanner.rest, equals('foo bar')); + }); + + test('setting position to 1 moves the cursor forward', () { + scanner.position = 1; + expect(scanner.position, equals(1)); + expect(scanner.rest, equals('oo bar')); + + expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.position, equals(4)); + expect(scanner.rest, equals('bar')); + }); + + test('setting position beyond the string throws an ArgumentError', () { + expect(() { + scanner.position = 8; + }, throwsArgumentError); + }); + + test('setting position to -1 throws an ArgumentError', () { + expect(() { + scanner.position = -1; + }, throwsArgumentError); + }); + + test('scan accepts any Pattern', () { + expect(scanner.scan('foo'), isTrue); + expect(scanner.lastMatch[0], equals('foo')); + expect(scanner.position, equals(3)); + expect(scanner.rest, equals(' bar')); + }); + + test('scans multiple times', () { + expect(scanner.scan(new RegExp('f(..)')), isTrue); + expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.position, equals(3)); + expect(scanner.rest, equals(' bar')); + + expect(scanner.scan(new RegExp(' b(..)')), isTrue); + expect(scanner.lastMatch[1], equals('ar')); + expect(scanner.position, equals(7)); + expect(scanner.rest, equals('')); + expect(scanner.isDone, isTrue); + expect(scanner.expectDone, isNot(throwsFormatException)); + }); + }); + + group('at the end of a string', () { + var scanner; + setUp(() { + scanner = new StringScanner('foo bar'); + expect(scanner.scan('foo bar'), isTrue); + }); + + test('is done', () { + expect(scanner.isDone, isTrue); + expect(scanner.expectDone, isNot(throwsFormatException)); + }); + + test('rest is empty', () { + expect(scanner.rest, isEmpty); + }); + + test('position is zero', () { + expect(scanner.position, equals(7)); + }); + + test("scan returns false and sets lastMatch to null", () { + expect(scanner.scan(new RegExp('.')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(7)); + }); + + test("expect throws a FormatException and sets lastMatch to null", () { + expect(() => scanner.expect(new RegExp('.')), throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(7)); + }); + + test("matches returns false sets lastMatch to null", () { + expect(scanner.matches(new RegExp('.')), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(7)); + }); + + test('setting position to 1 moves the cursor backward', () { + scanner.position = 1; + expect(scanner.position, equals(1)); + expect(scanner.rest, equals('oo bar')); + + expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.position, equals(4)); + expect(scanner.rest, equals('bar')); + }); + + test('setting position beyond the string throws an ArgumentError', () { + expect(() { + scanner.position = 8; + }, throwsArgumentError); + }); + + test('setting position to -1 throws an ArgumentError', () { + expect(() { + scanner.position = -1; + }, throwsArgumentError); + }); + }); + + group('a scanner constructed with a custom position', () { + test('starts scanning from that position', () { + var scanner = new StringScanner('foo bar', position: 1); + expect(scanner.position, equals(1)); + expect(scanner.rest, equals('oo bar')); + + expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.position, equals(4)); + expect(scanner.rest, equals('bar')); + }); + + test('throws an ArgumentError if the position is -1', () { + expect(() => new StringScanner('foo bar', position: -1), + throwsArgumentError); + }); + + test('throws an ArgumentError if the position is beyond the string', () { + expect(() => new StringScanner('foo bar', position: 8), + throwsArgumentError); + }); + }); +} From e15bced42f232fa37b4a162ecb877761308ebc4c Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 2 Apr 2014 20:58:47 +0000 Subject: [PATCH 0125/1215] Convert shelf to use the string_scanner package. This also adds support for [StringScanner.error], which produces a nicely-formatted scanning error. R=kevmoo@google.com Review URL: https://codereview.chromium.org//222843003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@34669 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/lib/string_scanner.dart | 63 ++++++- pkgs/string_scanner/test/error_test.dart | 168 ++++++++++++++++++ ...ormat_test.dart => expect_error_test.dart} | 34 ++-- pkgs/string_scanner/test/utils.dart | 17 ++ 4 files changed, 255 insertions(+), 27 deletions(-) create mode 100644 pkgs/string_scanner/test/error_test.dart rename pkgs/string_scanner/test/{error_format_test.dart => expect_error_test.dart} (78%) create mode 100644 pkgs/string_scanner/test/utils.dart diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart index 624c090e8..31ccd6266 100644 --- a/pkgs/string_scanner/lib/string_scanner.dart +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -5,6 +5,8 @@ /// A library for parsing strings using a sequence of patterns. library string_scanner; +import 'dart:math' as math; + // TODO(nweiz): Add some integration between this and source maps. /// A class that scans through a string using [Pattern]s. class StringScanner { @@ -89,10 +91,38 @@ class StringScanner { return _lastMatch != null; } - // TODO(nweiz): Make this handle long lines more gracefully. - /// Throws a [FormatException] describing that [name] is expected at the - /// current position in the string. - void _fail(String name) { + /// Throws a [FormatException] with [message] as well as a detailed + /// description of the location of the error in the string. + /// + /// [match] is the match information for the span of the string with which the + /// error is associated. This should be a match returned by this scanner's + /// [lastMatch] property. By default, the error is associated with the last + /// match. + /// + /// If [position] and/or [length] are passed, they are used as the error span + /// instead. If only [length] is passed, [position] defaults to the current + /// position; if only [position] is passed, [length] defaults to 1. + /// + /// It's an error to pass [match] at the same time as [position] or [length]. + void error(String message, {Match match, int position, int length}) { + if (match != null && (position != null || length != null)) { + throw new ArgumentError("Can't pass both match and position/length."); + } + + if (position != null && position < 0) { + throw new RangeError("position must be greater than or equal to 0."); + } + + if (length != null && length < 1) { + throw new RangeError("length must be greater than or equal to 0."); + } + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 1 : match.end - match.start; + var newlines = "\n".allMatches(string.substring(0, position)).toList(); var line = newlines.length + 1; var column; @@ -104,10 +134,29 @@ class StringScanner { column = position - newlines.last.end + 1; lastLine = string.substring(newlines.last.end, position); } - lastLine += rest.replaceFirst(new RegExp(r"\n.*"), ''); + + var remaining = string.substring(position); + var nextNewline = remaining.indexOf("\n"); + if (nextNewline == -1) { + lastLine += remaining; + } else { + length = math.min(length, nextNewline); + lastLine += remaining.substring(0, nextNewline); + } + + var spaces = new List.filled(column - 1, ' ').join(); + var underline = new List.filled(length, '^').join(); + throw new FormatException( - "Expected $name on line $line, column $column.\n" + "Error on line $line, column $column: $message\n" "$lastLine\n" - "${new List.filled(column - 1, ' ').join()}^"); + "$spaces$underline"); + } + + // TODO(nweiz): Make this handle long lines more gracefully. + /// Throws a [FormatException] describing that [name] is expected at the + /// current position in the string. + void _fail(String name) { + error("expected $name.", position: this.position, length: 1); } } diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart new file mode 100644 index 000000000..6432197b3 --- /dev/null +++ b/pkgs/string_scanner/test/error_test.dart @@ -0,0 +1,168 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.error_test; + +import 'package:string_scanner/string_scanner.dart'; +import 'package:unittest/unittest.dart'; + +import 'utils.dart'; + +void main() { + test('defaults to the last match', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + scanner.expect('bar'); + expect(() => scanner.error('oh no!'), throwsFormattedError(''' +Error on line 1, column 5: oh no! +foo bar baz + ^^^''')); + }); + + group("with match", () { + test('supports an earlier match', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + var match = scanner.lastMatch; + scanner.expect('bar'); + expect(() => scanner.error('oh no!', match: match), + throwsFormattedError(''' +Error on line 1, column 1: oh no! +foo bar baz +^^^^''')); + }); + + test('supports a match on a previous line', () { + var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + scanner.expect('foo bar baz\ndo '); + scanner.expect('re'); + var match = scanner.lastMatch; + scanner.expect(' mi\nearth '); + expect(() => scanner.error('oh no!', match: match), + throwsFormattedError(''' +Error on line 2, column 4: oh no! +do re mi + ^^''')); + }); + + test('supports a multiline match', () { + var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + scanner.expect('foo bar '); + scanner.expect('baz\ndo'); + var match = scanner.lastMatch; + scanner.expect(' re mi'); + expect(() => scanner.error('oh no!', match: match), + throwsFormattedError(''' +Error on line 1, column 9: oh no! +foo bar baz + ^^^''')); + }); + + test('supports a match after position', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + scanner.expect('bar'); + var match = scanner.lastMatch; + scanner.position = 0; + expect(() => scanner.error('oh no!', match: match), + throwsFormattedError(''' +Error on line 1, column 5: oh no! +foo bar baz + ^^^''')); + }); + }); + + group("with position and/or length", () { + test('defaults to length 1', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + expect(() => scanner.error('oh no!', position: 1), + throwsFormattedError(''' +Error on line 1, column 2: oh no! +foo bar baz + ^''')); + }); + + test('defaults to the current position', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + expect(() => scanner.error('oh no!', length: 3), + throwsFormattedError(''' +Error on line 1, column 5: oh no! +foo bar baz + ^^^''')); + }); + + test('supports an earlier position', () { + var scanner = new StringScanner('foo bar baz'); + scanner.expect('foo '); + expect(() => scanner.error('oh no!', position: 1, length: 2), + throwsFormattedError(''' +Error on line 1, column 2: oh no! +foo bar baz + ^^''')); + }); + + test('supports a position on a previous line', () { + var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + scanner.expect('foo bar baz\ndo re mi\nearth'); + expect(() => scanner.error('oh no!', position: 15, length: 2), + throwsFormattedError(''' +Error on line 2, column 4: oh no! +do re mi + ^^''')); + }); + + test('supports a multiline length', () { + var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + scanner.expect('foo bar baz\ndo re mi\nearth'); + expect(() => scanner.error('oh no!', position: 8, length: 8), + throwsFormattedError(''' +Error on line 1, column 9: oh no! +foo bar baz + ^^^''')); + }); + + test('supports a position after the current one', () { + var scanner = new StringScanner('foo bar baz'); + expect(() => scanner.error('oh no!', position: 4, length: 3), + throwsFormattedError(''' +Error on line 1, column 5: oh no! +foo bar baz + ^^^''')); + }); + }); + + group("argument errors", () { + var scanner; + setUp(() { + scanner = new StringScanner('foo bar baz'); + scanner.scan('foo'); + }); + + test("if match is passed with position", () { + expect( + () => scanner.error("oh no!", match: scanner.lastMatch, position: 1), + throwsArgumentError); + }); + + test("if match is passed with length", () { + expect( + () => scanner.error("oh no!", match: scanner.lastMatch, length: 1), + throwsArgumentError); + }); + + test("if position is negative", () { + expect(() => scanner.error("oh no!", position: -1), throwsArgumentError); + }); + + test("if position is outside the string", () { + expect(() => scanner.error("oh no!", position: 100), throwsArgumentError); + }); + + test("if length is zero", () { + expect(() => scanner.error("oh no!", length: 0), throwsArgumentError); + }); + }); +} diff --git a/pkgs/string_scanner/test/error_format_test.dart b/pkgs/string_scanner/test/expect_error_test.dart similarity index 78% rename from pkgs/string_scanner/test/error_format_test.dart rename to pkgs/string_scanner/test/expect_error_test.dart index 118734400..3596e15e5 100644 --- a/pkgs/string_scanner/test/error_format_test.dart +++ b/pkgs/string_scanner/test/expect_error_test.dart @@ -2,17 +2,19 @@ // 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. -library string_scanner.error_format_test; +library string_scanner.expect_error_test; import 'package:string_scanner/string_scanner.dart'; import 'package:unittest/unittest.dart'; +import 'utils.dart'; + void main() { test('points to the first unconsumed character', () { var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.expect('foo'), throwsFormattedError(''' -Expected "foo" on line 1, column 5. +Error on line 1, column 5: expected "foo". foo bar baz ^''')); }); @@ -21,7 +23,7 @@ foo bar baz var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo '); expect(() => scanner.expect('foo'), throwsFormattedError(''' -Expected "foo" on line 2, column 4. +Error on line 2, column 4: expected "foo". do re mi ^''')); }); @@ -29,7 +31,7 @@ do re mi test('handles the beginning of the string correctly', () { var scanner = new StringScanner('foo bar baz'); expect(() => scanner.expect('zap'), throwsFormattedError(''' -Expected "zap" on line 1, column 1. +Error on line 1, column 1: expected "zap". foo bar baz ^''')); }); @@ -38,14 +40,14 @@ foo bar baz var scanner = new StringScanner('foo bar baz'); scanner.expect('foo bar baz'); expect(() => scanner.expect('bang'), throwsFormattedError(''' -Expected "bang" on line 1, column 12. +Error on line 1, column 12: expected "bang". foo bar baz ^''')); }); test('handles an empty string correctly', () { expect(() => new StringScanner('').expect('foo'), throwsFormattedError(''' -Expected "foo" on line 1, column 1. +Error on line 1, column 1: expected "foo". ^''')); }); @@ -54,7 +56,7 @@ Expected "foo" on line 1, column 1. test("uses the provided name", () { expect(() => new StringScanner('').expect('foo bar', name: 'zap'), throwsFormattedError(''' -Expected zap on line 1, column 1. +Error on line 1, column 1: expected zap. ^''')); }); @@ -62,7 +64,7 @@ Expected zap on line 1, column 1. test("escapes string quotes", () { expect(() => new StringScanner('').expect('foo"bar'), throwsFormattedError(''' -Expected "foo\\"bar" on line 1, column 1. +Error on line 1, column 1: expected "foo\\"bar". ^''')); }); @@ -70,7 +72,7 @@ Expected "foo\\"bar" on line 1, column 1. test("escapes string backslashes", () { expect(() => new StringScanner('').expect('foo\\bar'), throwsFormattedError(''' -Expected "foo\\\\bar" on line 1, column 1. +Error on line 1, column 1: expected "foo\\\\bar". ^''')); }); @@ -78,7 +80,7 @@ Expected "foo\\\\bar" on line 1, column 1. test("prints PERL-style regexps", () { expect(() => new StringScanner('').expect(new RegExp(r'foo')), throwsFormattedError(''' -Expected /foo/ on line 1, column 1. +Error on line 1, column 1: expected /foo/. ^''')); }); @@ -86,7 +88,7 @@ Expected /foo/ on line 1, column 1. test("escape regexp forward slashes", () { expect(() => new StringScanner('').expect(new RegExp(r'foo/bar')), throwsFormattedError(''' -Expected /foo\\/bar/ on line 1, column 1. +Error on line 1, column 1: expected /foo\\/bar/. ^''')); }); @@ -94,17 +96,9 @@ Expected /foo\\/bar/ on line 1, column 1. test("does not escape regexp backslashes", () { expect(() => new StringScanner('').expect(new RegExp(r'foo\bar')), throwsFormattedError(''' -Expected /foo\\bar/ on line 1, column 1. +Error on line 1, column 1: expected /foo\\bar/. ^''')); }); }); } - -Matcher throwsFormattedError(String format) { - return throwsA(predicate((error) { - expect(error, isFormatException); - expect(error.message, equals(format)); - return true; - })); -} diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart new file mode 100644 index 000000000..eee93d89d --- /dev/null +++ b/pkgs/string_scanner/test/utils.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.test.utils; + +import 'package:unittest/unittest.dart'; + +/// Returns a matcher that asserts that a closure throws a [FormatException] +/// with the given [message]. +Matcher throwsFormattedError(String message) { + return throwsA(predicate((error) { + expect(error, isFormatException); + expect(error.message, equals(message)); + return true; + })); +} From 7117aa325aff7bc6653947e45700b887877c0c37 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 3 Apr 2014 00:27:11 +0000 Subject: [PATCH 0126/1215] Fix the StringScanner tests under dart2js. R=kevmoo@google.com Review URL: https://codereview.chromium.org//222613006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@34677 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/lib/string_scanner.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart index 31ccd6266..3e3913b50 100644 --- a/pkgs/string_scanner/lib/string_scanner.dart +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -7,6 +7,11 @@ library string_scanner; import 'dart:math' as math; +/// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. +/// +/// See issue 17998. +final _slashAutoEscape = new RegExp("/").pattern == "\\/"; + // TODO(nweiz): Add some integration between this and source maps. /// A class that scans through a string using [Pattern]s. class StringScanner { @@ -65,7 +70,9 @@ class StringScanner { if (name == null) { if (pattern is RegExp) { - name = "/${pattern.pattern.replaceAll("/", "\\/")}/"; + var source = pattern.pattern; + if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); + name = "/$source/"; } else { name = pattern.toString() .replaceAll("\\", "\\\\").replaceAll('"', '\\"'); From 35aa0c30b7fddadcea2fa61a45a310c66dc6be5e Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 9 Apr 2014 23:49:16 +0000 Subject: [PATCH 0127/1215] Properly handle errors thrown in [Chain.capture]'s [onError] handler. The Zone infrastructure apparently doesn't automatically pipe errors to the parent Zone (issue 18134). R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//232123003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34904 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 6 +++++ .../lib/src/stack_zone_specification.dart | 17 +++++++++++--- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 23 +++++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 5e2f2c7a6..0b4520848 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.9.3+1 + +* If an error is thrown in `Chain.capture`'s `onError` handler, that error is + handled by the parent zone. This matches the behavior of `runZoned` in + `dart:async`. + ## 0.9.3 * Add a `Chain.foldFrames` method that parallels `Trace.foldFrames`. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 36e0717d2..9a4f7c05a 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -145,10 +145,21 @@ class StackZoneSpecification { /// [_onError] or [parent]'s error handler. handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { + var stackChain = chainFor(stackTrace); if (_onError == null) { - return parent.handleUncaughtError(zone, error, chainFor(stackTrace)); - } else { - _onError(error, chainFor(stackTrace)); + return parent.handleUncaughtError(zone, error, stackChain); + } + + // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just + // allow [runBinary] to throw instead once issue 18134 is fixed. + try { + return parent.runBinary(zone, _onError, error, stackChain); + } catch (newError, newStackTrace) { + if (identical(newError, error)) { + return parent.handleUncaughtError(zone, error, stackChain); + } else { + return parent.handleUncaughtError(zone, newError, newStackTrace); + } } } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 99abed703..d0cc30f25 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.3 +version: 0.9.3+1 author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index d9915ebf1..683544f1d 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -107,6 +107,29 @@ void main() { return completer.future; }); + + test('and relays them to the parent zone', () { + var completer = new Completer(); + + runZoned(() { + Chain.capture(() { + inMicrotask(() => throw 'error'); + }, onError: (error, chain) { + expect(error, equals('error')); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + throw error; + }); + }, onError: (error, chain) { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + completer.complete(); + }); + + return completer.future; + }); }); test('capture() without onError passes exceptions to parent zone', () { From 4572ba12e39f9a272651a0da602f1d4cf3a0eb82 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 10 Apr 2014 19:45:20 +0000 Subject: [PATCH 0128/1215] Avoid timeouts in stack_trace's chain_test. R=rnystrom@google.com BUG=18142 Review URL: https://codereview.chromium.org//232783008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@34940 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/chain_test.dart | 52 ++++++++++++++++----------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 683544f1d..3347deb2b 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -92,16 +92,20 @@ void main() { inMicrotask(() => throw 'first error'); inPeriodicTimer(() => throw 'second error'); }, onError: (error, chain) { - if (first) { - expect(error, equals('first error')); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inMicrotask')))); - first = false; - } else { - expect(error, equals('second error')); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inPeriodicTimer')))); - completer.complete(); + try { + if (first) { + expect(error, equals('first error')); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + first = false; + } else { + expect(error, equals('second error')); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inPeriodicTimer')))); + completer.complete(); + } + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); } }); @@ -121,11 +125,15 @@ void main() { throw error; }); }, onError: (error, chain) { - expect(error, equals('error')); - expect(chain, new isInstanceOf()); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inMicrotask')))); - completer.complete(); + try { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + completer.complete(); + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); + } }); return completer.future; @@ -138,11 +146,15 @@ void main() { runZoned(() { Chain.capture(() => inMicrotask(() => throw 'error')); }, onError: (error, chain) { - expect(error, equals('error')); - expect(chain, new isInstanceOf()); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inMicrotask')))); - completer.complete(); + try { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + completer.complete(); + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); + } }); return completer.future; From c25e34c0c89f020e710613bf061019aa8efd7c73 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 24 May 2014 00:08:21 +0000 Subject: [PATCH 0129/1215] Use path.prettyUri in stack_trace. R=rnystrom@google.com Review URL: https://codereview.chromium.org//298873011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@36599 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 6 ++++++ pkgs/stack_trace/lib/src/frame.dart | 6 +----- pkgs/stack_trace/pubspec.yaml | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 0b4520848..36c7d3cce 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.9.3+2 + +* Update the dependency on path. + +* Improve the formatting of library URIs in stack traces. + ## 0.9.3+1 * If an error is thrown in `Chain.capture`'s `onError` handler, that error is diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 67438c37e..5b376e2ee 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -88,11 +88,7 @@ class Frame { /// /// This will usually be the string form of [uri], but a relative URI will be /// used if possible. - String get library { - if (uri.scheme != Uri.base.scheme) return uri.toString(); - if (path.style == path.Style.url) return path.relative(uri.toString()); - return path.relative(path.fromUri(uri)); - } + String get library => path.prettyUri(uri); /// Returns the name of the package this stack frame comes from, or `null` if /// this stack frame doesn't come from a `package:` URL. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index d0cc30f25..e75d33850 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,14 +1,14 @@ name: stack_trace -version: 0.9.3+1 +version: 0.9.3+2 author: "Dart Team " homepage: http://www.dartlang.org description: > A package for manipulating stack traces and printing them readably. dependencies: - path: ">=1.0.0-rc.1 <2.0.0" + path: ">=1.2.0 <2.0.0" dev_dependencies: - unittest: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.12.0" environment: - sdk: ">=0.8.10+6 <2.0.0" + sdk: ">=1.0.0 <2.0.0" From f78a69e220bc227243b436a1b17594d00c119d16 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Sat, 24 May 2014 00:50:31 +0000 Subject: [PATCH 0130/1215] Fix stack_trace tests on Windows. R=rnystrom@google.com Review URL: https://codereview.chromium.org//295323002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@36602 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/frame_test.dart | 4 ++-- pkgs/stack_trace/test/trace_test.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index bbb905ad1..b800b0cf4 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -503,7 +503,7 @@ void main() { test('returns the relative path for file URIs', () { expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, - equals('foo/bar.dart')); + equals(path.join('foo', 'bar.dart'))); }); }); @@ -514,7 +514,7 @@ void main() { '(http://dartlang.org/thing.dart:5:10)').location, equals('http://dartlang.org/thing.dart 5:10')); expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, - equals('foo/bar.dart 1:2')); + equals('${path.join('foo', 'bar.dart')} 1:2')); }); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index eeeff282d..bc2db6b85 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -224,7 +224,7 @@ void main() { '''); expect(trace.toString(), equals(''' -foo/bar.dart 42:21 Foo._bar +${path.join('foo', 'bar.dart')} 42:21 Foo._bar dart:async/future.dart 0:2 zip..zap http://pub.dartlang.org/thing.dart 1:100 zip..zap ''')); From 075137e05e28359156c44fd56706cb2685c11cf1 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 30 May 2014 00:52:40 +0000 Subject: [PATCH 0131/1215] Add LineScanner and SpanScanner classes to string_scanner. R=rnystrom@google.com Review URL: https://codereview.chromium.org//299973002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@36815 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 19 ++ pkgs/string_scanner/lib/src/exception.dart | 37 ++++ pkgs/string_scanner/lib/src/line_scanner.dart | 108 +++++++++++ pkgs/string_scanner/lib/src/span_scanner.dart | 95 ++++++++++ .../lib/src/string_scanner.dart | 168 ++++++++++++++++++ pkgs/string_scanner/lib/src/utils.dart | 30 ++++ pkgs/string_scanner/lib/string_scanner.dart | 166 +---------------- pkgs/string_scanner/pubspec.yaml | 5 +- pkgs/string_scanner/test/error_test.dart | 70 +++----- .../test/expect_error_test.dart | 104 ----------- .../test/line_scanner_test.dart | 106 +++++++++++ .../test/span_scanner_test.dart | 60 +++++++ .../test/string_scanner_test.dart | 42 +++++ pkgs/string_scanner/test/utils.dart | 7 +- 14 files changed, 701 insertions(+), 316 deletions(-) create mode 100644 pkgs/string_scanner/CHANGELOG.md create mode 100644 pkgs/string_scanner/lib/src/exception.dart create mode 100644 pkgs/string_scanner/lib/src/line_scanner.dart create mode 100644 pkgs/string_scanner/lib/src/span_scanner.dart create mode 100644 pkgs/string_scanner/lib/src/string_scanner.dart create mode 100644 pkgs/string_scanner/lib/src/utils.dart delete mode 100644 pkgs/string_scanner/test/expect_error_test.dart create mode 100644 pkgs/string_scanner/test/line_scanner_test.dart create mode 100644 pkgs/string_scanner/test/span_scanner_test.dart diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md new file mode 100644 index 000000000..2c41c9d64 --- /dev/null +++ b/pkgs/string_scanner/CHANGELOG.md @@ -0,0 +1,19 @@ +## 0.0.2 + +* `new StringScanner()` now takes an optional `sourceUrl` argument that provides + the URL of the source file. This is used for error reporting. + +* Add `StringScanner.readChar()` and `StringScanner.peekChar()` methods for + doing character-by-character scanning. + +* Scanners now throw `StringScannerException`s which provide more detailed + access to information about the errors that were thrown and can provide + terminal-colored messages. + +* Add a `LineScanner` subclass of `StringScanner` that automatically tracks line + and column information of the text being scanned. + +* Add a `SpanScanner` subclass of `LineScanner` that exposes matched ranges as + [source map][] `Span` objects. + +[source_map]: http://pub.dartlang.org/packages/source_maps diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart new file mode 100644 index 000000000..c3986871a --- /dev/null +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.exception; + +import 'package:source_maps/source_maps.dart'; + +/// An exception thrown by a [StringScanner] that failed to parse a string. +class StringScannerException implements FormatException { + /// The error message. + final String message; + + /// The source string being parsed. + final String string; + + /// The URL of the source file being parsed. + /// + /// This may be `null`, indicating that the source URL is unknown. + final Uri sourceUrl; + + /// The span within [string] that caused the exception. + final Span span; + + StringScannerException(this.message, this.string, this.sourceUrl, this.span); + + /// Returns a detailed description of this exception. + /// + /// If [useColors] is true, the section of the source that caused the + /// exception will be colored using ANSI color codes. By default, it's colored + /// red, but a different ANSI code may passed via [color]. + String toString({bool useColors: false, String color}) { + return "Error on " + span.getLocationMessage( + message, useColors: useColors, color: color); + } +} + diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart new file mode 100644 index 000000000..4e1217305 --- /dev/null +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -0,0 +1,108 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.line_scanner; + +import 'string_scanner.dart'; + +/// A subclass of [StringScanner] that tracks line and column information. +class LineScanner extends StringScanner { + /// The scanner's current (zero-based) line number. + int get line => _line; + int _line = 0; + + /// The scanner's current (zero-based) column number. + int get column => _column; + int _column = 0; + + /// The scanner's state, including line and column information. + /// + /// This can be used to efficiently save and restore the state of the scanner + /// when backtracking. A given [LineScannerState] is only valid for the + /// [LineScanner] that created it. + LineScannerState get state => + new LineScannerState._(this, position, line, column); + + set state(LineScannerState state) { + if (!identical(state._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + super.position = state.position; + _line = state.line; + _column = state.column; + } + + set position(int newPosition) { + var oldPosition = position; + super.position = newPosition; + + if (newPosition > oldPosition) { + var newlines = "\n".allMatches(string.substring(oldPosition, newPosition)) + .toList(); + _line += newlines.length; + if (newlines.isEmpty) { + _column += newPosition - oldPosition; + } else { + _column = newPosition - newlines.last.end; + } + } else { + var newlines = "\n".allMatches(string.substring(newPosition, oldPosition)) + .toList(); + _line -= newlines.length; + if (newlines.isEmpty) { + _column -= oldPosition - newPosition; + } else { + _column = newPosition - string.lastIndexOf("\n", newPosition) - 1; + } + } + } + + LineScanner(String string, {sourceUrl, int position}) + : super(string, sourceUrl: sourceUrl, position: position); + + int readChar() { + var char = super.readChar(); + if (char == 0xA) { + _line += 1; + _column = 0; + } else { + _column += 1; + } + return char; + } + + bool scan(Pattern pattern) { + var oldPosition = position; + if (!super.scan(pattern)) return false; + + var newlines = "\n".allMatches(lastMatch[0]).toList(); + _line += newlines.length; + if (newlines.isEmpty) { + _column += lastMatch[0].length; + } else { + _column = lastMatch[0].length - newlines.last.end; + } + + return true; + } +} + +/// A class representing the state of a [LineScanner]. +class LineScannerState { + /// The [LineScanner] that created this. + final LineScanner _scanner; + + /// The position of the scanner in this state. + final int position; + + /// The zero-based line number of the scanner in this state. + final int line; + + /// The zero-based column number of the scanner in this state. + final int column; + + LineScannerState._(this._scanner, this.position, this.line, this.column); +} diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart new file mode 100644 index 000000000..9060e62f0 --- /dev/null +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -0,0 +1,95 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.span_scanner; + +import 'package:source_maps/source_maps.dart'; + +import 'exception.dart'; +import 'line_scanner.dart'; +import 'string_scanner.dart'; +import 'utils.dart'; + +/// A subclass of [LineScanner] that exposes matched ranges as source map +/// [Span]s. +class SpanScanner extends StringScanner implements LineScanner { + /// The source of the scanner. + /// + /// This caches line break information and is used to generate [Span]s. + final SourceFile _sourceFile; + + int get line => _sourceFile.getLine(position); + int get column => _sourceFile.getColumn(line, position); + + LineScannerState get state => new _SpanScannerState(this, position); + + set state(LineScannerState state) { + if (state is! _SpanScannerState || + !identical((state as _SpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + this.position = state.position; + } + + /// The [Span] for [lastMatch]. + /// + /// This is the span for the entire match. There's no way to get spans for + /// subgroups since [Match] exposes no information about their positions. + Span get lastSpan => _lastSpan; + Span _lastSpan; + + /// Returns an empty span at the current location. + Span get emptySpan => _sourceFile.span(position); + + /// Creates a new [SpanScanner] that starts scanning from [position]. + /// + /// [sourceUrl] is used as [Location.sourceUrl] for the returned [Span]s as + /// well as for error reporting. + SpanScanner(String string, sourceUrl, {int position}) + : _sourceFile = new SourceFile.text( + sourceUrl is Uri ? sourceUrl.toString() : sourceUrl, string), + super(string, sourceUrl: sourceUrl, position: position); + + /// Creates a [Span] representing the source range between [startState] and + /// the current position. + Span spanFrom(LineScannerState startState) => + _sourceFile.span(startState.position, position); + + bool matches(Pattern pattern) { + if (!super.matches(pattern)) { + _lastSpan = null; + return false; + } + + _lastSpan = _sourceFile.span(position, lastMatch.end); + return true; + } + + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 1 : match.end - match.start; + + var span = _sourceFile.span(position, position + length); + throw new StringScannerException(message, string, sourceUrl, span); + } +} + +/// A class representing the state of a [SpanScanner]. +class _SpanScannerState implements LineScannerState { + /// The [SpanScanner] that created this. + final SpanScanner _scanner; + + final int position; + int get line => _scanner._sourceFile.getLine(position); + int get column => _scanner._sourceFile.getColumn(line, position); + + _SpanScannerState(this._scanner, this.position); +} diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart new file mode 100644 index 000000000..c9e74594a --- /dev/null +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -0,0 +1,168 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.string_scanner; + +import 'package:source_maps/source_maps.dart'; + +import 'exception.dart'; +import 'utils.dart'; + +/// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. +/// +/// See issue 17998. +final _slashAutoEscape = new RegExp("/").pattern == "\\/"; + +/// A class that scans through a string using [Pattern]s. +class StringScanner { + /// The URL of the source of the string being scanned. + /// + /// This is used for error reporting. It may be `null`, indicating that the + /// source URL is unknown or unavailable. + final Uri sourceUrl; + + /// The string being scanned through. + final String string; + + /// The current position of the scanner in the string, in characters. + int get position => _position; + set position(int position) { + if (position < 0 || position > string.length) { + throw new ArgumentError("Invalid position $position"); + } + + _position = position; + } + int _position = 0; + + /// The data about the previous match made by the scanner. + /// + /// If the last match failed, this will be `null`. + Match get lastMatch => _lastMatch; + Match _lastMatch; + + /// The portion of the string that hasn't yet been scanned. + String get rest => string.substring(position); + + /// Whether the scanner has completely consumed [string]. + bool get isDone => position == string.length; + + /// Creates a new [StringScanner] that starts scanning from [position]. + /// + /// [position] defaults to 0, the beginning of the string. [sourceUrl] is the + /// URL of the source of the string being scanned, if available. It can be + /// either a [String] or a [Uri]. + StringScanner(this.string, {sourceUrl, int position}) + : sourceUrl = sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl { + if (position != null) this.position = position; + } + + /// Consumes a single character and returns its character code. + /// + /// This throws a [FormatException] if the string has been fully consumed. It + /// doesn't affect [lastMatch]. + int readChar() { + if (isDone) _fail("more input"); + return string.codeUnitAt(_position++); + } + + /// Returns the character code of the character [offset] away from [position]. + /// + /// [offset] defaults to zero, and may be negative to inspect already-consumed + /// characters. + /// + /// This returns `null` if [offset] points outside the string. It doesn't + /// affect [lastMatch]. + int peekChar([int offset]) { + if (offset == null) offset = 0; + var index = position + offset; + if (index < 0 || index >= string.length) return null; + return string.codeUnitAt(index); + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// Returns whether or not [pattern] matched. + bool scan(Pattern pattern) { + var success = matches(pattern); + if (success) _position = _lastMatch.end; + return success; + } + + /// If [pattern] matches at the current position of the string, scans forward + /// until the end of the match. + /// + /// If [pattern] did not match, throws a [FormatException] describing the + /// position of the failure. [name] is used in this error as the expected name + /// of the pattern being matched; if it's `null`, the pattern itself is used + /// instead. + void expect(Pattern pattern, {String name}) { + if (scan(pattern)) return; + + if (name == null) { + if (pattern is RegExp) { + var source = pattern.pattern; + if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); + name = "/$source/"; + } else { + name = pattern.toString() + .replaceAll("\\", "\\\\").replaceAll('"', '\\"'); + name = '"$name"'; + } + } + _fail(name); + } + + /// If the string has not been fully consumed, this throws a + /// [FormatException]. + void expectDone() { + if (isDone) return; + _fail("no more input"); + } + + /// Returns whether or not [pattern] matches at the current position of the + /// string. + /// + /// This doesn't move the scan pointer forward. + bool matches(Pattern pattern) { + _lastMatch = pattern.matchAsPrefix(string, position); + return _lastMatch != null; + } + + /// Throws a [FormatException] with [message] as well as a detailed + /// description of the location of the error in the string. + /// + /// [match] is the match information for the span of the string with which the + /// error is associated. This should be a match returned by this scanner's + /// [lastMatch] property. By default, the error is associated with the last + /// match. + /// + /// If [position] and/or [length] are passed, they are used as the error span + /// instead. If only [length] is passed, [position] defaults to the current + /// position; if only [position] is passed, [length] defaults to 1. + /// + /// It's an error to pass [match] at the same time as [position] or [length]. + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 1 : match.end - match.start; + + var url = sourceUrl == null ? null : sourceUrl.toString(); + var sourceFile = new SourceFile.text(url, string); + var span = sourceFile.span(position, position + length); + throw new StringScannerException(message, string, sourceUrl, span); + } + + // TODO(nweiz): Make this handle long lines more gracefully. + /// Throws a [FormatException] describing that [name] is expected at the + /// current position in the string. + void _fail(String name) { + error("expected $name.", position: this.position, length: 0); + } +} diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart new file mode 100644 index 000000000..e556236e8 --- /dev/null +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.utils; + +/// Validates the arguments passed to [StringScanner.error]. +void validateErrorArgs(String string, Match match, int position, int length) { + if (match != null && (position != null || length != null)) { + throw new ArgumentError("Can't pass both match and position/length."); + } + + if (position != null) { + if (position < 0) { + throw new RangeError("position must be greater than or equal to 0."); + } else if (position > string.length) { + throw new RangeError("position must be less than or equal to the " + "string length."); + } + } + + if (length != null && length < 0) { + throw new RangeError("length must be greater than or equal to 0."); + } + + if (position != null && length != null && position + length > string.length) { + throw new RangeError("position plus length must not go beyond the end of " + "the string."); + } +} \ No newline at end of file diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart index 3e3913b50..be294f4f6 100644 --- a/pkgs/string_scanner/lib/string_scanner.dart +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -5,165 +5,7 @@ /// A library for parsing strings using a sequence of patterns. library string_scanner; -import 'dart:math' as math; - -/// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. -/// -/// See issue 17998. -final _slashAutoEscape = new RegExp("/").pattern == "\\/"; - -// TODO(nweiz): Add some integration between this and source maps. -/// A class that scans through a string using [Pattern]s. -class StringScanner { - /// The string being scanned through. - final String string; - - /// The current position of the scanner in the string, in characters. - int get position => _position; - set position(int position) { - if (position < 0 || position > string.length) { - throw new ArgumentError("Invalid position $position"); - } - - _position = position; - } - int _position = 0; - - /// The data about the previous match made by the scanner. - /// - /// If the last match failed, this will be `null`. - Match get lastMatch => _lastMatch; - Match _lastMatch; - - /// The portion of the string that hasn't yet been scanned. - String get rest => string.substring(position); - - /// Whether the scanner has completely consumed [string]. - bool get isDone => position == string.length; - - /// Creates a new [StringScanner] that starts scanning from [position]. - /// - /// [position] defaults to 0, the beginning of the string. - StringScanner(this.string, {int position}) { - if (position != null) this.position = position; - } - - /// If [pattern] matches at the current position of the string, scans forward - /// until the end of the match. - /// - /// Returns whether or not [pattern] matched. - bool scan(Pattern pattern) { - var success = matches(pattern); - if (success) _position = _lastMatch.end; - return success; - } - - /// If [pattern] matches at the current position of the string, scans forward - /// until the end of the match. - /// - /// If [pattern] did not match, throws a [FormatException] describing the - /// position of the failure. [name] is used in this error as the expected name - /// of the pattern being matched; if it's `null`, the pattern itself is used - /// instead. - void expect(Pattern pattern, {String name}) { - if (scan(pattern)) return; - - if (name == null) { - if (pattern is RegExp) { - var source = pattern.pattern; - if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); - name = "/$source/"; - } else { - name = pattern.toString() - .replaceAll("\\", "\\\\").replaceAll('"', '\\"'); - name = '"$name"'; - } - } - _fail(name); - } - - /// If the string has not been fully consumed, this throws a - /// [FormatException]. - void expectDone() { - if (isDone) return; - _fail("no more input"); - } - - /// Returns whether or not [pattern] matches at the current position of the - /// string. - /// - /// This doesn't move the scan pointer forward. - bool matches(Pattern pattern) { - _lastMatch = pattern.matchAsPrefix(string, position); - return _lastMatch != null; - } - - /// Throws a [FormatException] with [message] as well as a detailed - /// description of the location of the error in the string. - /// - /// [match] is the match information for the span of the string with which the - /// error is associated. This should be a match returned by this scanner's - /// [lastMatch] property. By default, the error is associated with the last - /// match. - /// - /// If [position] and/or [length] are passed, they are used as the error span - /// instead. If only [length] is passed, [position] defaults to the current - /// position; if only [position] is passed, [length] defaults to 1. - /// - /// It's an error to pass [match] at the same time as [position] or [length]. - void error(String message, {Match match, int position, int length}) { - if (match != null && (position != null || length != null)) { - throw new ArgumentError("Can't pass both match and position/length."); - } - - if (position != null && position < 0) { - throw new RangeError("position must be greater than or equal to 0."); - } - - if (length != null && length < 1) { - throw new RangeError("length must be greater than or equal to 0."); - } - - if (match == null && position == null && length == null) match = lastMatch; - if (position == null) { - position = match == null ? this.position : match.start; - } - if (length == null) length = match == null ? 1 : match.end - match.start; - - var newlines = "\n".allMatches(string.substring(0, position)).toList(); - var line = newlines.length + 1; - var column; - var lastLine; - if (newlines.isEmpty) { - column = position + 1; - lastLine = string.substring(0, position); - } else { - column = position - newlines.last.end + 1; - lastLine = string.substring(newlines.last.end, position); - } - - var remaining = string.substring(position); - var nextNewline = remaining.indexOf("\n"); - if (nextNewline == -1) { - lastLine += remaining; - } else { - length = math.min(length, nextNewline); - lastLine += remaining.substring(0, nextNewline); - } - - var spaces = new List.filled(column - 1, ' ').join(); - var underline = new List.filled(length, '^').join(); - - throw new FormatException( - "Error on line $line, column $column: $message\n" - "$lastLine\n" - "$spaces$underline"); - } - - // TODO(nweiz): Make this handle long lines more gracefully. - /// Throws a [FormatException] describing that [name] is expected at the - /// current position in the string. - void _fail(String name) { - error("expected $name.", position: this.position, length: 1); - } -} +export 'src/exception.dart'; +export 'src/line_scanner.dart'; +export 'src/span_scanner.dart'; +export 'src/string_scanner.dart'; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 3035901ea..86ae238a6 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,9 +1,12 @@ name: string_scanner -version: 0.0.1 +version: 0.0.2 author: "Dart Team " homepage: http://www.dartlang.org description: > A class for parsing strings using a sequence of patterns. +dependencies: + path: ">=1.2.0 <2.0.0" + source_maps: ">=0.9.0 <0.10.0" dev_dependencies: unittest: ">=0.10.0 <0.11.0" environment: diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index 6432197b3..4fe9083df 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -14,10 +14,7 @@ void main() { var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); scanner.expect('bar'); - expect(() => scanner.error('oh no!'), throwsFormattedError(''' -Error on line 1, column 5: oh no! -foo bar baz - ^^^''')); + expect(() => scanner.error('oh no!'), throwsStringScannerException('bar')); }); group("with match", () { @@ -27,10 +24,7 @@ foo bar baz var match = scanner.lastMatch; scanner.expect('bar'); expect(() => scanner.error('oh no!', match: match), - throwsFormattedError(''' -Error on line 1, column 1: oh no! -foo bar baz -^^^^''')); + throwsStringScannerException('foo ')); }); test('supports a match on a previous line', () { @@ -40,10 +34,7 @@ foo bar baz var match = scanner.lastMatch; scanner.expect(' mi\nearth '); expect(() => scanner.error('oh no!', match: match), - throwsFormattedError(''' -Error on line 2, column 4: oh no! -do re mi - ^^''')); + throwsStringScannerException('re')); }); test('supports a multiline match', () { @@ -53,10 +44,7 @@ do re mi var match = scanner.lastMatch; scanner.expect(' re mi'); expect(() => scanner.error('oh no!', match: match), - throwsFormattedError(''' -Error on line 1, column 9: oh no! -foo bar baz - ^^^''')); + throwsStringScannerException('baz\ndo')); }); test('supports a match after position', () { @@ -66,10 +54,7 @@ foo bar baz var match = scanner.lastMatch; scanner.position = 0; expect(() => scanner.error('oh no!', match: match), - throwsFormattedError(''' -Error on line 1, column 5: oh no! -foo bar baz - ^^^''')); + throwsStringScannerException('bar')); }); }); @@ -78,59 +63,47 @@ foo bar baz var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1), - throwsFormattedError(''' -Error on line 1, column 2: oh no! -foo bar baz - ^''')); + throwsStringScannerException('o')); }); test('defaults to the current position', () { var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', length: 3), - throwsFormattedError(''' -Error on line 1, column 5: oh no! -foo bar baz - ^^^''')); + throwsStringScannerException('bar')); }); test('supports an earlier position', () { var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1, length: 2), - throwsFormattedError(''' -Error on line 1, column 2: oh no! -foo bar baz - ^^''')); + throwsStringScannerException('oo')); }); test('supports a position on a previous line', () { var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 15, length: 2), - throwsFormattedError(''' -Error on line 2, column 4: oh no! -do re mi - ^^''')); + throwsStringScannerException('re')); }); test('supports a multiline length', () { var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 8, length: 8), - throwsFormattedError(''' -Error on line 1, column 9: oh no! -foo bar baz - ^^^''')); + throwsStringScannerException('baz\ndo r')); }); test('supports a position after the current one', () { var scanner = new StringScanner('foo bar baz'); expect(() => scanner.error('oh no!', position: 4, length: 3), - throwsFormattedError(''' -Error on line 1, column 5: oh no! -foo bar baz - ^^^''')); + throwsStringScannerException('bar')); + }); + + test('supports a length of zero', () { + var scanner = new StringScanner('foo bar baz'); + expect(() => scanner.error('oh no!', position: 4, length: 0), + throwsStringScannerException('')); }); }); @@ -161,8 +134,13 @@ foo bar baz expect(() => scanner.error("oh no!", position: 100), throwsArgumentError); }); - test("if length is zero", () { - expect(() => scanner.error("oh no!", length: 0), throwsArgumentError); + test("if position + length is outside the string", () { + expect(() => scanner.error("oh no!", position: 7, length: 7), + throwsArgumentError); + }); + + test("if length is negative", () { + expect(() => scanner.error("oh no!", length: -1), throwsArgumentError); }); }); } diff --git a/pkgs/string_scanner/test/expect_error_test.dart b/pkgs/string_scanner/test/expect_error_test.dart deleted file mode 100644 index 3596e15e5..000000000 --- a/pkgs/string_scanner/test/expect_error_test.dart +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// 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. - -library string_scanner.expect_error_test; - -import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; - -import 'utils.dart'; - -void main() { - test('points to the first unconsumed character', () { - var scanner = new StringScanner('foo bar baz'); - scanner.expect('foo '); - expect(() => scanner.expect('foo'), throwsFormattedError(''' -Error on line 1, column 5: expected "foo". -foo bar baz - ^''')); - }); - - test('prints the correct line', () { - var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); - scanner.expect('foo bar baz\ndo '); - expect(() => scanner.expect('foo'), throwsFormattedError(''' -Error on line 2, column 4: expected "foo". -do re mi - ^''')); - }); - - test('handles the beginning of the string correctly', () { - var scanner = new StringScanner('foo bar baz'); - expect(() => scanner.expect('zap'), throwsFormattedError(''' -Error on line 1, column 1: expected "zap". -foo bar baz -^''')); - }); - - test('handles the end of the string correctly', () { - var scanner = new StringScanner('foo bar baz'); - scanner.expect('foo bar baz'); - expect(() => scanner.expect('bang'), throwsFormattedError(''' -Error on line 1, column 12: expected "bang". -foo bar baz - ^''')); - }); - - test('handles an empty string correctly', () { - expect(() => new StringScanner('').expect('foo'), throwsFormattedError(''' -Error on line 1, column 1: expected "foo". - -^''')); - }); - - group("expected name", () { - test("uses the provided name", () { - expect(() => new StringScanner('').expect('foo bar', name: 'zap'), - throwsFormattedError(''' -Error on line 1, column 1: expected zap. - -^''')); - }); - - test("escapes string quotes", () { - expect(() => new StringScanner('').expect('foo"bar'), - throwsFormattedError(''' -Error on line 1, column 1: expected "foo\\"bar". - -^''')); - }); - - test("escapes string backslashes", () { - expect(() => new StringScanner('').expect('foo\\bar'), - throwsFormattedError(''' -Error on line 1, column 1: expected "foo\\\\bar". - -^''')); - }); - - test("prints PERL-style regexps", () { - expect(() => new StringScanner('').expect(new RegExp(r'foo')), - throwsFormattedError(''' -Error on line 1, column 1: expected /foo/. - -^''')); - }); - - test("escape regexp forward slashes", () { - expect(() => new StringScanner('').expect(new RegExp(r'foo/bar')), - throwsFormattedError(''' -Error on line 1, column 1: expected /foo\\/bar/. - -^''')); - }); - - test("does not escape regexp backslashes", () { - expect(() => new StringScanner('').expect(new RegExp(r'foo\bar')), - throwsFormattedError(''' -Error on line 1, column 1: expected /foo\\bar/. - -^''')); - }); - }); -} diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart new file mode 100644 index 000000000..8cc79a65c --- /dev/null +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -0,0 +1,106 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.line_scanner_test; + +import 'package:string_scanner/string_scanner.dart'; +import 'package:unittest/unittest.dart'; + +void main() { + var scanner; + setUp(() { + scanner = new LineScanner('foo\nbar\nbaz'); + }); + + test('begins with line and column 0', () { + expect(scanner.line, equals(0)); + expect(scanner.column, equals(0)); + }); + + group("scan()", () { + test("consuming no newlines increases the column but not the line", () { + scanner.scan('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + }); + + test("consuming a newline resets the column and increases the line", () { + scanner.expect('foo\nba'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(2)); + }); + + test("consuming multiple newlines resets the column and increases the line", + () { + scanner.expect('foo\nbar\nb'); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + }); + + group("readChar()", () { + test("on a non-newline character increases the column but not the line", + () { + scanner.readChar(); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(1)); + }); + + test("consuming a newline resets the column and increases the line", () { + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.readChar(); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + }); + + group("position=", () { + test("forward through newlines sets the line and column", () { + scanner.position = 9; // "foo\nbar\nb" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test("forward through no newlines sets the column", () { + scanner.position = 2; // "fo" + expect(scanner.line, equals(0)); + expect(scanner.column, equals(2)); + }); + + test("backward through newlines sets the line and column", () { + scanner.scan("foo\nbar\nbaz"); + scanner.position = 2; // "fo" + expect(scanner.line, equals(0)); + expect(scanner.column, equals(2)); + }); + + test("backward through no newlines sets the column", () { + scanner.scan("foo\nbar\nbaz"); + scanner.position = 9; // "foo\nbar\nb" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + }); + + test("state= restores the line, column, and position", () { + scanner.scan('foo\nb'); + var state = scanner.state; + + scanner.scan('ar\nba'); + scanner.state = state; + expect(scanner.rest, equals('ar\nbaz')); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(1)); + }); + + test("state= rejects a foreign state", () { + scanner.scan('foo\nb'); + + expect(() => new LineScanner(scanner.string).state = scanner.state, + throwsArgumentError); + }); +} diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart new file mode 100644 index 000000000..93ba0b659 --- /dev/null +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -0,0 +1,60 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.span_scanner_test; + +import 'package:string_scanner/string_scanner.dart'; +import 'package:unittest/unittest.dart'; + +void main() { + var scanner; + setUp(() { + scanner = new SpanScanner('foo\nbar\nbaz', 'source'); + }); + + test("tracks the span for the last match", () { + scanner.scan('fo'); + scanner.scan('o\nba'); + + var span = scanner.lastSpan; + expect(span.start.offset, equals(2)); + expect(span.start.line, equals(0)); + expect(span.start.column, equals(2)); + expect(span.start.sourceUrl, equals('source')); + + expect(span.end.offset, equals(6)); + expect(span.end.line, equals(1)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals('source')); + + expect(span.text, equals('o\nba')); + }); + + test(".spanFrom() returns a span from a previous state", () { + scanner.scan('fo'); + var state = scanner.state; + scanner.scan('o\nba'); + scanner.scan('r\nba'); + + var span = scanner.spanFrom(state); + expect(span.text, equals('o\nbar\nba')); + }); + + test(".emptySpan returns an empty span at the current location", () { + scanner.scan('foo\nba'); + + var span = scanner.emptySpan; + expect(span.start.offset, equals(6)); + expect(span.start.line, equals(1)); + expect(span.start.column, equals(2)); + expect(span.start.sourceUrl, equals('source')); + + expect(span.end.offset, equals(6)); + expect(span.end.line, equals(1)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals('source')); + + expect(span.text, equals('')); + }); +} diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 0cab6273e..6144bf9c0 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -31,6 +31,18 @@ void main() { expect(scanner.position, equals(0)); }); + test("readChar fails and doesn't change the state", () { + expect(scanner.readChar, throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test("peekChar returns null and doesn't change the state", () { + expect(scanner.peekChar(), isNull); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("scan returns false and doesn't change the state", () { expect(scanner.scan(new RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); @@ -85,6 +97,24 @@ void main() { expect(scanner.position, equals(0)); }); + test('readChar returns the first character and moves forward', () { + expect(scanner.readChar(), equals(0x66)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(1)); + }); + + test('peekChar returns the first character', () { + expect(scanner.peekChar(), equals(0x66)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test('peekChar with an argument returns the nth character', () { + expect(scanner.peekChar(4), equals(0x62)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("a matching scan returns true and changes the state", () { expect(scanner.scan(new RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); @@ -200,6 +230,18 @@ void main() { expect(scanner.position, equals(7)); }); + test("readChar fails and doesn't change the state", () { + expect(scanner.readChar, throwsFormatException); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + + test("peekChar returns null and doesn't change the state", () { + expect(scanner.peekChar(), isNull); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + test("scan returns false and sets lastMatch to null", () { expect(scanner.scan(new RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index eee93d89d..3de601cf1 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -4,14 +4,15 @@ library string_scanner.test.utils; +import 'package:string_scanner/string_scanner.dart'; import 'package:unittest/unittest.dart'; /// Returns a matcher that asserts that a closure throws a [FormatException] /// with the given [message]. -Matcher throwsFormattedError(String message) { +Matcher throwsStringScannerException(String text) { return throwsA(predicate((error) { - expect(error, isFormatException); - expect(error.message, equals(message)); + expect(error, new isInstanceOf()); + expect(error.span.text, equals(text)); return true; })); } From 9e3e710cb2812177b51e68e361b59bbf65e35e67 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 2 Jun 2014 18:40:25 +0000 Subject: [PATCH 0132/1215] Release stack_trace 1.0.0. R=kevmoo@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//308763003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@36891 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 1045bc56b..51ba562a6 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -7,7 +7,7 @@ description: > notifies you when files have been added, removed, or modified. dependencies: path: ">=0.9.0 <2.0.0" - stack_trace: ">=0.9.1 <0.10.0" + stack_trace: ">=0.9.1 <2.0.0" dev_dependencies: scheduled_test: ">=0.9.3-dev <0.11.0" unittest: ">=0.9.2 <0.10.0" From 36a7d65d61856ff296a9f443638a22ebe957d769 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 2 Jun 2014 18:40:25 +0000 Subject: [PATCH 0133/1215] Release stack_trace 1.0.0. R=kevmoo@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//308763003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@36891 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 36c7d3cce..0b3553f0e 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0 + +* No API changes, just declared stable. + ## 0.9.3+2 * Update the dependency on path. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index e75d33850..ddad7f971 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 0.9.3+2 +version: 1.0.0 author: "Dart Team " homepage: http://www.dartlang.org description: > From 0de56c44b1d3896c0e119e4927b19152fc39fd96 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 4 Jun 2014 10:23:32 +0000 Subject: [PATCH 0134/1215] Use 'Directory.watch' on Windows in pkg/watcher, instead of pooling. This is a close copy of MacOS, except for the special handling on mac, and the extra watcher on Windows for detecting if the watched folder is deleted. BUG=https://code.google.com/p/dart/issues/detail?id=14428,https://code.google.com/p/dart/issues/detail?id=18108,http://code.google.com/p/dart/issues/detail?id=19189 R=kasperl@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//312743002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@36988 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 2 + .../lib/src/directory_watcher/windows.dart | 419 ++++++++++++++++++ .../test/directory_watcher/windows_test.dart | 41 ++ pkgs/watcher/test/utils.dart | 5 + 4 files changed, 467 insertions(+) create mode 100644 pkgs/watcher/lib/src/directory_watcher/windows.dart create mode 100644 pkgs/watcher/test/directory_watcher/windows_test.dart diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 78b1174e1..27dbb3f51 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -10,6 +10,7 @@ import 'dart:io'; import 'watch_event.dart'; import 'directory_watcher/linux.dart'; import 'directory_watcher/mac_os.dart'; +import 'directory_watcher/windows.dart'; import 'directory_watcher/polling.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something @@ -56,6 +57,7 @@ abstract class DirectoryWatcher { factory DirectoryWatcher(String directory, {Duration pollingDelay}) { if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); if (Platform.isMacOS) return new MacOSDirectoryWatcher(directory); + if (Platform.isWindows) return new WindowsDirectoryWatcher(directory); return new PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); } } diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart new file mode 100644 index 000000000..ddcf897d3 --- /dev/null +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -0,0 +1,419 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. +// TODO(rnystrom): Merge with mac_os version. + +library watcher.directory_watcher.windows; + +import 'dart:async'; +import 'dart:collection'; +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:stack_trace/stack_trace.dart'; + +import '../constructable_file_system_event.dart'; +import '../path_set.dart'; +import '../utils.dart'; +import '../watch_event.dart'; +import 'resubscribable.dart'; + +class WindowsDirectoryWatcher extends ResubscribableDirectoryWatcher { + WindowsDirectoryWatcher(String directory) + : super(directory, () => new _WindowsDirectoryWatcher(directory)); +} + +class _EventBatcher { + static const Duration _BATCH_DELAY = const Duration(milliseconds: 100); + final List events = []; + Timer timer; + + void addEvent(FileSystemEvent event) { + events.add(event); + } + + void startTimer(void callback()) { + if (timer != null) { + timer.cancel(); + } + timer = new Timer(_BATCH_DELAY, callback); + } + + void cancelTimer() { + timer.cancel(); + } +} + +class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { + final String directory; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + final Map _eventBatchers = + new HashMap(); + + /// The set of files that are known to exist recursively within the watched + /// directory. + /// + /// The state of files on the filesystem is compared against this to determine + /// the real change that occurred. This is also used to emit REMOVE events + /// when subdirectories are moved out of the watched directory. + final PathSet _files; + + /// The subscription to the stream returned by [Directory.watch]. + StreamSubscription _watchSubscription; + + /// The subscription to the stream returned by [Directory.watch] of the + /// parent directory to [directory]. This is needed to detect changes to + /// [directory], as they are not included on Windows. + StreamSubscription _parentWatchSubscription; + + /// The subscription to the [Directory.list] call for the initial listing of + /// the directory to determine its initial state. + StreamSubscription _initialListSubscription; + + /// The subscriptions to the [Directory.list] call for listing the contents of + /// subdirectories that was moved into the watched directory. + final Set> _listSubscriptions + = new HashSet>(); + + _WindowsDirectoryWatcher(String directory) + : directory = directory, _files = new PathSet(directory) { + _startWatch(); + _startParentWatcher(); + + // Before we're ready to emit events, wait for [_listDir] to complete. + _listDir().then(_readyCompleter.complete); + } + + void close() { + if (_watchSubscription != null) _watchSubscription.cancel(); + if (_parentWatchSubscription != null) _parentWatchSubscription.cancel(); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + for (var sub in _listSubscriptions) { + sub.cancel(); + } + _listSubscriptions.clear(); + for (var batcher in _eventBatchers.values) { + batcher.cancelTimer(); + } + _eventBatchers.clear(); + _watchSubscription = null; + _parentWatchSubscription = null; + _initialListSubscription = null; + _eventsController.close(); + } + + /// On Windows, if [directory] is deleted, we will not receive any event. + /// Instead, we add a watcher on the parent folder (if any), that can notify + /// us about [directory]. + /// This also includes events such as moves. + void _startParentWatcher() { + var absoluteDir = p.absolute(directory); + var parent = p.dirname(absoluteDir); + // Check if we [directory] is already the root directory. + if (FileSystemEntity.identicalSync(parent, directory)) return; + var parentStream = Chain.track( + new Directory(parent).watch(recursive: false)); + _parentWatchSubscription = parentStream.listen((event) { + // Only look at events for 'directory'. + if (p.basename(event.path) != p.basename(absoluteDir)) return; + // Test if the directory is removed. FileSystemEntity.typeSync will + // return NOT_FOUND if it's unable to decide upon the type, including + // access denied issues, which may happen when the directory is deleted. + // FileSystemMoveEvent and FileSystemDeleteEvent events will always mean + // the directory is now gone. + if (event is FileSystemMoveEvent || + event is FileSystemDeleteEvent || + (FileSystemEntity.typeSync(directory) == + FileSystemEntityType.NOT_FOUND)) { + for (var path in _files.toSet()) { + _emitEvent(ChangeType.REMOVE, path); + } + _files.clear(); + close(); + } + }, onError: (error) { + // Ignore errors, simply close the stream. + _parentWatchSubscription.cancel(); + _parentWatchSubscription = null; + }); + } + + void _onEvent(FileSystemEvent event) { + // If we get a event before we're ready to begin emitting events, + // ignore those events and re-list the directory. + if (!isReady) { + _listDir().then((_) { + _readyCompleter.complete(); + }); + return; + } + + _EventBatcher batcher = _eventBatchers.putIfAbsent( + event.path, () => new _EventBatcher()); + batcher.addEvent(event); + batcher.startTimer(() { + _eventBatchers.remove(event.path); + _onBatch(batcher.events); + }); + } + + /// The callback that's run when [Directory.watch] emits a batch of events. + void _onBatch(List batch) { + _sortEvents(batch).forEach((path, events) { + var relativePath = p.relative(path, from: directory); + + var canonicalEvent = _canonicalEvent(events); + events = canonicalEvent == null ? + _eventsBasedOnFileSystem(path) : [canonicalEvent]; + + for (var event in events) { + if (event is FileSystemCreateEvent) { + if (!event.isDirectory) { + if (_files.contains(path)) continue; + + _emitEvent(ChangeType.ADD, path); + _files.add(path); + continue; + } + + if (_files.containsDir(path)) continue; + + var stream = Chain.track(new Directory(path).list(recursive: true)); + var sub; + sub = stream.listen((entity) { + if (entity is Directory) return; + if (_files.contains(path)) return; + + _emitEvent(ChangeType.ADD, entity.path); + _files.add(entity.path); + }, onDone: () { + _listSubscriptions.remove(sub); + }, onError: (e, stackTrace) { + _listSubscriptions.remove(sub); + _emitError(e, stackTrace); + }, cancelOnError: true); + _listSubscriptions.add(sub); + } else if (event is FileSystemModifyEvent) { + if (!event.isDirectory) { + _emitEvent(ChangeType.MODIFY, path); + } + } else { + assert(event is FileSystemDeleteEvent); + for (var removedPath in _files.remove(path)) { + _emitEvent(ChangeType.REMOVE, removedPath); + } + } + } + }); + } + + /// Sort all the events in a batch into sets based on their path. + /// + /// A single input event may result in multiple events in the returned map; + /// for example, a MOVE event becomes a DELETE event for the source and a + /// CREATE event for the destination. + /// + /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it + /// contain any events relating to [directory]. + Map> _sortEvents(List batch) { + var eventsForPaths = {}; + + // Events within directories that already have events are superfluous; the + // directory's full contents will be examined anyway, so we ignore such + // events. Emitting them could cause useless or out-of-order events. + var directories = unionAll(batch.map((event) { + if (!event.isDirectory) return new Set(); + if (event is! FileSystemMoveEvent) return new Set.from([event.path]); + return new Set.from([event.path, event.destination]); + })); + + isInModifiedDirectory(path) => + directories.any((dir) => path != dir && path.startsWith(dir)); + + addEvent(path, event) { + if (isInModifiedDirectory(path)) return; + var set = eventsForPaths.putIfAbsent(path, () => new Set()); + set.add(event); + } + + for (var event in batch) { + if (event is FileSystemMoveEvent) { + FileSystemMoveEvent moveEvent = event; + addEvent(moveEvent.destination, event); + } + addEvent(event.path, event); + } + + return eventsForPaths; + } + + /// Returns the canonical event from a batch of events on the same path, if + /// one exists. + /// + /// If [batch] doesn't contain any contradictory events (e.g. DELETE and + /// CREATE, or events with different values for [isDirectory]), this returns a + /// single event that describes what happened to the path in question. + /// + /// If [batch] does contain contradictory events, this returns `null` to + /// indicate that the state of the path on the filesystem should be checked to + /// determine what occurred. + FileSystemEvent _canonicalEvent(Set batch) { + // An empty batch indicates that we've learned earlier that the batch is + // contradictory (e.g. because of a move). + if (batch.isEmpty) return null; + + var type = batch.first.type; + var isDir = batch.first.isDirectory; + var hadModifyEvent = false; + + for (var event in batch.skip(1)) { + // If one event reports that the file is a directory and another event + // doesn't, that's a contradiction. + if (isDir != event.isDirectory) return null; + + // Modify events don't contradict either CREATE or REMOVE events. We can + // safely assume the file was modified after a CREATE or before the + // REMOVE; otherwise there will also be a REMOVE or CREATE event + // (respectively) that will be contradictory. + if (event is FileSystemModifyEvent) { + hadModifyEvent = true; + continue; + } + assert(event is FileSystemCreateEvent || + event is FileSystemDeleteEvent || + event is FileSystemMoveEvent); + + // If we previously thought this was a MODIFY, we now consider it to be a + // CREATE or REMOVE event. This is safe for the same reason as above. + if (type == FileSystemEvent.MODIFY) { + type = event.type; + continue; + } + + // A CREATE event contradicts a REMOVE event and vice versa. + assert(type == FileSystemEvent.CREATE || + type == FileSystemEvent.DELETE || + type == FileSystemEvent.MOVE); + if (type != event.type) return null; + } + + switch (type) { + case FileSystemEvent.CREATE: + return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); + case FileSystemEvent.DELETE: + return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + case FileSystemEvent.MODIFY: + return new ConstructableFileSystemModifyEvent( + batch.first.path, isDir, false); + case FileSystemEvent.MOVE: + return null; + default: assert(false); + } + } + + /// Returns one or more events that describe the change between the last known + /// state of [path] and its current state on the filesystem. + /// + /// This returns a list whose order should be reflected in the events emitted + /// to the user, unlike the batched events from [Directory.watch]. The + /// returned list may be empty, indicating that no changes occurred to [path] + /// (probably indicating that it was created and then immediately deleted). + List _eventsBasedOnFileSystem(String path) { + var fileExisted = _files.contains(path); + var dirExisted = _files.containsDir(path); + var fileExists = new File(path).existsSync(); + var dirExists = new Directory(path).existsSync(); + + var events = []; + if (fileExisted) { + if (fileExists) { + events.add(new ConstructableFileSystemModifyEvent(path, false, false)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, false)); + } + } else if (dirExisted) { + if (dirExists) { + // If we got contradictory events for a directory that used to exist and + // still exists, we need to rescan the whole thing in case it was + // replaced with a different directory. + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + } + } + + if (!fileExisted && fileExists) { + events.add(new ConstructableFileSystemCreateEvent(path, false)); + } else if (!dirExisted && dirExists) { + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } + + return events; + } + + /// The callback that's run when the [Directory.watch] stream is closed. + /// Note that this is unlikely to happen on Windows, unless the system itself + /// closes the handle. + void _onDone() { + _watchSubscription = null; + + // Emit remove-events for any remaining files. + for (var file in _files.toSet()) { + _emitEvent(ChangeType.REMOVE, file); + } + _files.clear(); + close(); + } + + /// Start or restart the underlying [Directory.watch] stream. + void _startWatch() { + // Batch the events changes together so that we can dedup events. + var innerStream = + Chain.track(new Directory(directory).watch(recursive: true)); + _watchSubscription = innerStream.listen(_onEvent, + onError: _eventsController.addError, + onDone: _onDone); + } + + /// Starts or restarts listing the watched directory to get an initial picture + /// of its state. + Future _listDir() { + assert(!isReady); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + + _files.clear(); + var completer = new Completer(); + var stream = Chain.track(new Directory(directory).list(recursive: true)); + void handleEntity(entity) { + if (entity is! Directory) _files.add(entity.path); + } + _initialListSubscription = stream.listen( + handleEntity, + onError: _emitError, + onDone: completer.complete, + cancelOnError: true); + return completer.future; + } + + /// Emit an event with the given [type] and [path]. + void _emitEvent(ChangeType type, String path) { + if (!isReady) return; + + _eventsController.add(new WatchEvent(type, path)); + } + + /// Emit an error, then close the watcher. + void _emitError(error, StackTrace stackTrace) { + _eventsController.addError(error, stackTrace); + close(); + } +} diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart new file mode 100644 index 000000000..3e9a854a9 --- /dev/null +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:path/path.dart' as p; +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/windows.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +main() { + initConfig(); + + watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); + + test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { + expect(new DirectoryWatcher('.'), + new isInstanceOf()); + }); + + test('when the watched directory is moved, removes all files', () { + writeFile("dir/a.txt"); + writeFile("dir/b.txt"); + + startWatcher(dir: "dir"); + + renameDir("dir", "moved_dir"); + createDir("dir"); + inAnyOrder([ + isRemoveEvent("dir/a.txt"), + isRemoveEvent("dir/b.txt") + ]); + }); +} + diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index b520bbd9a..8b660e845 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -71,6 +71,11 @@ void createSandbox() { // Delete the sandbox when done. currentSchedule.onComplete.schedule(() { if (_sandboxDir != null) { + // TODO(rnystrom): Issue 19155. The watcher should already be closed when + // we clean up the sandbox. + if (_watcherEvents != null) { + _watcherEvents.close(); + } new Directory(_sandboxDir).deleteSync(recursive: true); _sandboxDir = null; } From c6b489a4e144770dc411dede5d12177775f56108 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Wed, 4 Jun 2014 17:57:45 +0000 Subject: [PATCH 0135/1215] Fall back to PollingDirectoryWatcher if FileSystemEntity:watch is not supported. BUG= R=rnystrom@google.com Review URL: https://codereview.chromium.org//313743004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@37003 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/directory_watcher.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 27dbb3f51..605eaea48 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -55,9 +55,11 @@ abstract class DirectoryWatcher { /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. factory DirectoryWatcher(String directory, {Duration pollingDelay}) { - if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); - if (Platform.isMacOS) return new MacOSDirectoryWatcher(directory); - if (Platform.isWindows) return new WindowsDirectoryWatcher(directory); + if (FileSystemEntity.isWatchSupported) { + if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); + if (Platform.isMacOS) return new MacOSDirectoryWatcher(directory); + if (Platform.isWindows) return new WindowsDirectoryWatcher(directory); + } return new PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); } } From 271ee990408bae4c0f57ca39c5a251b82c92299e Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 10 Jun 2014 06:48:31 +0000 Subject: [PATCH 0136/1215] Clean up the Windows watcher. BUG= R=rnystrom@google.com Review URL: https://codereview.chromium.org//313353003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@37159 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/windows.dart | 50 ++++++++----------- .../test/directory_watcher/shared.dart | 14 ++++++ .../test/directory_watcher/windows_test.dart | 14 ------ 3 files changed, 34 insertions(+), 44 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index ddcf897d3..4f41d3395 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -28,11 +28,8 @@ class _EventBatcher { final List events = []; Timer timer; - void addEvent(FileSystemEvent event) { + void addEvent(FileSystemEvent event, void callback()) { events.add(event); - } - - void startTimer(void callback()) { if (timer != null) { timer.cancel(); } @@ -78,18 +75,19 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// the directory to determine its initial state. StreamSubscription _initialListSubscription; - /// The subscriptions to the [Directory.list] call for listing the contents of - /// subdirectories that was moved into the watched directory. + /// The subscriptions to the [Directory.list] calls for listing the contents + /// of subdirectories that were moved into the watched directory. final Set> _listSubscriptions = new HashSet>(); _WindowsDirectoryWatcher(String directory) : directory = directory, _files = new PathSet(directory) { - _startWatch(); - _startParentWatcher(); - // Before we're ready to emit events, wait for [_listDir] to complete. - _listDir().then(_readyCompleter.complete); + _listDir().then((_) { + _startWatch(); + _startParentWatcher(); + _readyCompleter.complete(); + }); } void close() { @@ -111,13 +109,13 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } /// On Windows, if [directory] is deleted, we will not receive any event. + /// /// Instead, we add a watcher on the parent folder (if any), that can notify - /// us about [directory]. - /// This also includes events such as moves. + /// us about [directory]. This also includes events such as moves. void _startParentWatcher() { var absoluteDir = p.absolute(directory); var parent = p.dirname(absoluteDir); - // Check if we [directory] is already the root directory. + // Check if [directory] is already the root directory. if (FileSystemEntity.identicalSync(parent, directory)) return; var parentStream = Chain.track( new Directory(parent).watch(recursive: false)); @@ -140,26 +138,19 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { close(); } }, onError: (error) { - // Ignore errors, simply close the stream. + // Ignore errors, simply close the stream. The user listens on + // [directory], and while it can fail to listen on the parent, we may + // still be able to listen on the path requested. _parentWatchSubscription.cancel(); _parentWatchSubscription = null; }); } void _onEvent(FileSystemEvent event) { - // If we get a event before we're ready to begin emitting events, - // ignore those events and re-list the directory. - if (!isReady) { - _listDir().then((_) { - _readyCompleter.complete(); - }); - return; - } - - _EventBatcher batcher = _eventBatchers.putIfAbsent( + assert(isReady); + final batcher = _eventBatchers.putIfAbsent( event.path, () => new _EventBatcher()); - batcher.addEvent(event); - batcher.startTimer(() { + batcher.addEvent(event, () { _eventBatchers.remove(event.path); _onBatch(batcher.events); }); @@ -246,8 +237,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { for (var event in batch) { if (event is FileSystemMoveEvent) { - FileSystemMoveEvent moveEvent = event; - addEvent(moveEvent.destination, event); + addEvent(event.destination, event); } addEvent(event.path, event); } @@ -366,7 +356,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { void _onDone() { _watchSubscription = null; - // Emit remove-events for any remaining files. + // Emit remove events for any remaining files. for (var file in _files.toSet()) { _emitEvent(ChangeType.REMOVE, file); } @@ -376,7 +366,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { - // Batch the events changes together so that we can dedup events. + // Batch the events together so that we can dedup events. var innerStream = Chain.track(new Directory(directory).watch(recursive: true)); _watchSubscription = innerStream.listen(_onEvent, diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 849cea00d..d3575ea4d 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -78,6 +78,20 @@ sharedTests() { ]); }); + test('when the watched directory is moved, removes all files', () { + writeFile("dir/a.txt"); + writeFile("dir/b.txt"); + + startWatcher(dir: "dir"); + + renameDir("dir", "moved_dir"); + createDir("dir"); + inAnyOrder([ + isRemoveEvent("dir/a.txt"), + isRemoveEvent("dir/b.txt") + ]); + }); + group("moves", () { test('notifies when a file is moved within the watched directory', () { writeFile("old.txt"); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 3e9a854a9..6bfb88b44 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -23,19 +23,5 @@ main() { expect(new DirectoryWatcher('.'), new isInstanceOf()); }); - - test('when the watched directory is moved, removes all files', () { - writeFile("dir/a.txt"); - writeFile("dir/b.txt"); - - startWatcher(dir: "dir"); - - renameDir("dir", "moved_dir"); - createDir("dir"); - inAnyOrder([ - isRemoveEvent("dir/a.txt"), - isRemoveEvent("dir/b.txt") - ]); - }); } From 33592ea196c412b640dd0a3eeb3ced12a7eb0c55 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 10 Jun 2014 07:03:53 +0000 Subject: [PATCH 0137/1215] Mac no longer fire bogus events. Fix Mac watcher. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//319433003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@37162 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 72 ++----------------- pkgs/watcher/pubspec.yaml | 4 +- 2 files changed, 7 insertions(+), 69 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index e3efa2dd6..65f07fa92 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -73,30 +73,15 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// a subdirectory that was moved into the watched directory. StreamSubscription _listSubscription; - /// The timer for tracking how long we wait for an initial batch of bogus - /// events (see issue 14373). - Timer _bogusEventTimer; - _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, _files = new PathSet(directory), _id = "$parentId/${_count++}" { - _startWatch(); - - // Before we're ready to emit events, wait for [_listDir] to complete and - // for enough time to elapse that if bogus events (issue 14373) would be - // emitted, they will be. - // - // If we do receive a batch of events, [_onBatch] will ensure that these - // futures don't fire and that the directory is re-listed. - Future.wait([ - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - }), - _waitForBogusEvents() - ]).then((_) { + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + _startWatch(); if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -134,29 +119,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } - // If we get a batch of events before we're ready to begin emitting events, - // it's probable that it's a batch of pre-watcher events (see issue 14373). - // Ignore those events and re-list the directory. - if (!isReady) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] not ready to emit events, re-listing directory"); - } - - // Cancel the timer because bogus events only occur in the first batch, so - // we can fire [ready] as soon as we're done listing the directory. - _bogusEventTimer.cancel(); - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is ready, known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - _readyCompleter.complete(); - }); - return; - } - _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { @@ -392,17 +354,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _watchSubscription = null; - // If the directory still exists and we're still expecting bogus events, - // this is probably issue 14849 rather than a real close event. We should - // just restart the watcher. - if (!isReady && new Directory(directory).existsSync()) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] fake closure (issue 14849), re-opening stream"); - } - _startWatch(); - return; - } - // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. @@ -442,19 +393,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { return completer.future; } - /// Wait 200ms for a batch of bogus events (issue 14373) to come in. - /// - /// 200ms is short in terms of human interaction, but longer than any Mac OS - /// watcher tests take on the bots, so it should be safe to assume that any - /// bogus events will be signaled in that time frame. - Future _waitForBogusEvents() { - var completer = new Completer(); - _bogusEventTimer = new Timer( - new Duration(milliseconds: 200), - completer.complete); - return completer.future; - } - /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 51ba562a6..a0e0ce4e2 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.3-dev +version: 0.9.4-dev author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -12,4 +12,4 @@ dev_dependencies: scheduled_test: ">=0.9.3-dev <0.11.0" unittest: ">=0.9.2 <0.10.0" environment: - sdk: ">=0.8.10+6 <2.0.0" + sdk: ">=1.3.0 <2.0.0" From e213974f86b614e96b6a48efb070a2e259645e8f Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 10 Jun 2014 10:44:20 +0000 Subject: [PATCH 0138/1215] Don't use kFSEventStreamCreateFlagNoDefer as it messes with event flushing. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//321133002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@37171 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index a0e0ce4e2..adf8ddb6f 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -12,4 +12,4 @@ dev_dependencies: scheduled_test: ">=0.9.3-dev <0.11.0" unittest: ">=0.9.2 <0.10.0" environment: - sdk: ">=1.3.0 <2.0.0" + sdk: ">=1.6.0 <2.0.0" From 16349628fa49955c4ecff4858ac53e700c55d085 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 10 Jun 2014 12:35:56 +0000 Subject: [PATCH 0139/1215] Revert watcher changes for mac. We ended up with a 1.6 dependency, which I don't know if is a good idea or not. Revert "Mac no longer fire bogus events. Fix Mac watcher." Revert "Don't use kFSEventStreamCreateFlagNoDefer as it messes with event flushing." BUG= Review URL: https://codereview.chromium.org//325963005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@37173 260f80e4-7a28-3924-810f-c04153c831b5 --- .../lib/src/directory_watcher/mac_os.dart | 72 +++++++++++++++++-- pkgs/watcher/pubspec.yaml | 4 +- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 65f07fa92..e3efa2dd6 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -73,15 +73,30 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// a subdirectory that was moved into the watched directory. StreamSubscription _listSubscription; + /// The timer for tracking how long we wait for an initial batch of bogus + /// events (see issue 14373). + Timer _bogusEventTimer; + _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, _files = new PathSet(directory), _id = "$parentId/${_count++}" { - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - _startWatch(); + _startWatch(); + + // Before we're ready to emit events, wait for [_listDir] to complete and + // for enough time to elapse that if bogus events (issue 14373) would be + // emitted, they will be. + // + // If we do receive a batch of events, [_onBatch] will ensure that these + // futures don't fire and that the directory is re-listed. + Future.wait([ + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + }), + _waitForBogusEvents() + ]).then((_) { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -119,6 +134,29 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } + // If we get a batch of events before we're ready to begin emitting events, + // it's probable that it's a batch of pre-watcher events (see issue 14373). + // Ignore those events and re-list the directory. + if (!isReady) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] not ready to emit events, re-listing directory"); + } + + // Cancel the timer because bogus events only occur in the first batch, so + // we can fire [ready] as soon as we're done listing the directory. + _bogusEventTimer.cancel(); + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + _readyCompleter.complete(); + }); + return; + } + _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { @@ -354,6 +392,17 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _watchSubscription = null; + // If the directory still exists and we're still expecting bogus events, + // this is probably issue 14849 rather than a real close event. We should + // just restart the watcher. + if (!isReady && new Directory(directory).existsSync()) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] fake closure (issue 14849), re-opening stream"); + } + _startWatch(); + return; + } + // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. @@ -393,6 +442,19 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { return completer.future; } + /// Wait 200ms for a batch of bogus events (issue 14373) to come in. + /// + /// 200ms is short in terms of human interaction, but longer than any Mac OS + /// watcher tests take on the bots, so it should be safe to assume that any + /// bogus events will be signaled in that time frame. + Future _waitForBogusEvents() { + var completer = new Completer(); + _bogusEventTimer = new Timer( + new Duration(milliseconds: 200), + completer.complete); + return completer.future; + } + /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index adf8ddb6f..51ba562a6 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.4-dev +version: 0.9.3-dev author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -12,4 +12,4 @@ dev_dependencies: scheduled_test: ">=0.9.3-dev <0.11.0" unittest: ">=0.9.2 <0.10.0" environment: - sdk: ">=1.6.0 <2.0.0" + sdk: ">=0.8.10+6 <2.0.0" From 88acb12fa8b3570c419299c622d45cc8cb0875ed Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 19 Jun 2014 21:12:35 +0000 Subject: [PATCH 0140/1215] Properly handle synchronous errors in Chain.capture. R=rnystrom@google.com BUG=19542 Review URL: https://codereview.chromium.org//344953002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@37520 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 9 ++++++++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 0b3553f0e..a58190fc6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Synchronous errors in the [Chain.capture] callback are now handled correctly. + ## 1.0.0 * No API changes, just declared stable. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index a097bba34..78c6ae401 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -90,7 +90,14 @@ class Chain implements StackTrace { /// [15105]: https://code.google.com/p/dart/issues/detail?id=15105 static capture(callback(), {ChainHandler onError}) { var spec = new StackZoneSpecification(onError); - return runZoned(callback, zoneSpecification: spec.toSpec(), zoneValues: { + return runZoned(() { + try { + return callback(); + } catch (error, stackTrace) { + // TODO(nweiz): Don't special-case this when issue 19566 is fixed. + return Zone.current.handleUncaughtError(error, stackTrace); + } + }, zoneSpecification: spec.toSpec(), zoneValues: { #stack_trace.stack_zone.spec: spec }); } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ddad7f971..1c43efdf8 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.0.0 +version: 1.0.1 author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 3347deb2b..beb4721cf 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -14,6 +14,15 @@ import 'utils.dart'; void main() { group('capture() with onError catches exceptions', () { + test('thrown synchronously', () { + return captureFuture(() => throw 'error') + .then((chain) { + expect(chain.traces, hasLength(1)); + expect(chain.traces.single.frames.first, + frameMember(startsWith('main'))); + }); + }); + test('thrown in a microtask', () { return captureFuture(() => inMicrotask(() => throw 'error')) .then((chain) { From 80a0a0304bef5834a6752c4cd734963307c4b686 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Mon, 23 Jun 2014 21:10:55 +0000 Subject: [PATCH 0141/1215] Make StringScannerException extend SpanFormatException. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//343043002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@37619 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 7 +++++++ pkgs/string_scanner/lib/src/exception.dart | 22 +++------------------- pkgs/string_scanner/pubspec.yaml | 4 ++-- 3 files changed, 12 insertions(+), 21 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 2c41c9d64..a5d551888 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.0.3 + +* Make `StringScannerException` inherit from source_map's + [`SpanFormatException`][]. + +[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) + ## 0.0.2 * `new StringScanner()` now takes an optional `sourceUrl` argument that provides diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index c3986871a..44ec9a3e7 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -7,10 +7,7 @@ library string_scanner.exception; import 'package:source_maps/source_maps.dart'; /// An exception thrown by a [StringScanner] that failed to parse a string. -class StringScannerException implements FormatException { - /// The error message. - final String message; - +class StringScannerException extends SpanFormatException { /// The source string being parsed. final String string; @@ -19,19 +16,6 @@ class StringScannerException implements FormatException { /// This may be `null`, indicating that the source URL is unknown. final Uri sourceUrl; - /// The span within [string] that caused the exception. - final Span span; - - StringScannerException(this.message, this.string, this.sourceUrl, this.span); - - /// Returns a detailed description of this exception. - /// - /// If [useColors] is true, the section of the source that caused the - /// exception will be colored using ANSI color codes. By default, it's colored - /// red, but a different ANSI code may passed via [color]. - String toString({bool useColors: false, String color}) { - return "Error on " + span.getLocationMessage( - message, useColors: useColors, color: color); - } + StringScannerException(String message, this.string, this.sourceUrl, Span span) + : super(message, span); } - diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 86ae238a6..f6d7ab9ef 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 0.0.2 +version: 0.0.3 author: "Dart Team " homepage: http://www.dartlang.org description: > A class for parsing strings using a sequence of patterns. dependencies: path: ">=1.2.0 <2.0.0" - source_maps: ">=0.9.0 <0.10.0" + source_maps: ">=0.9.2 <0.10.0" dev_dependencies: unittest: ">=0.10.0 <0.11.0" environment: From 673dbf7817fb2b9a5794d111719c8c9d6bfcc624 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 26 Jun 2014 20:04:05 +0000 Subject: [PATCH 0142/1215] Add implicit constraints from pub onto stack_trace and source_maps. These packages are used in pub's plugin isolate, so pub needs to have a dependency on them to ensure their APIs don't change out from under it. R=rnystrom@google.com BUG=19574 Review URL: https://codereview.chromium.org//356523003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@37751 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/pubspec.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1c43efdf8..a0fa39697 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,4 +1,12 @@ name: stack_trace + +# Note! This version number is referenced directly in the pub source code in +# lib/src/barback.dart. Pub implicitly places a version constraint on +# stack_trace to ensure users only select a version of stack_trace that works +# with their current version of pub. +# +# When the major version is upgraded, you *must* update that version constraint +# in pub to stay in sync with this. version: 1.0.1 author: "Dart Team " homepage: http://www.dartlang.org From 1452aefa743bd398e72b9fbcf28c2a406ff1f465 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 26 Jun 2014 21:42:23 +0000 Subject: [PATCH 0143/1215] Stop working around issue 17083 in stack_trace. R=rnystrom@google.com Review URL: https://codereview.chromium.org//353073004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@37762 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 6 ++++++ pkgs/stack_trace/lib/src/frame.dart | 10 ---------- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a58190fc6..a5d594a9c 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.2 + +* Remove a workaround for [issue 17083][]. + +[issue 17083]: http://code.google.com/p/dart/issues/detail?id=17083 + ## 1.0.1 * Synchronous errors in the [Chain.capture] callback are now handled correctly. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 5b376e2ee..b1db23042 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -47,15 +47,6 @@ final _friendlyFrame = new RegExp( final _initialDot = new RegExp(r"^\."); -/// "dart:" libraries that are incorrectly reported without a "dart:" prefix. -/// -/// See issue 11901. All these libraries should be in "dart:io". -final _ioLibraries = new Set.from([ - new Uri(path: 'timer_impl.dart'), - new Uri(path: 'http_impl.dart'), - new Uri(path: 'http_parser.dart') -]); - /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { /// The URI of the file in which the code is located. @@ -135,7 +126,6 @@ class Frame { // always be found. The column is optional. var member = match[1].replaceAll("", ""); var uri = Uri.parse(match[2]); - if (_ioLibraries.contains(uri)) uri = Uri.parse('dart:io/${uri.path}'); var line = int.parse(match[3]); var column = null; var columnMatch = match[4]; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index a0fa39697..5226cf8c1 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.0.1 +version: 1.0.2 author: "Dart Team " homepage: http://www.dartlang.org description: > From 92c272baabbc71332077368c48674fd489195b7b Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 26 Jun 2014 22:43:58 +0000 Subject: [PATCH 0144/1215] Remove tests of a workaround that no longer exists in stack_trace. R=rnystrom@google.com Review URL: https://codereview.chromium.org//351283004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@37768 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/test/frame_test.dart | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index b800b0cf4..1205d7484 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -30,33 +30,6 @@ void main() { expect(frame.member, equals('Foo._bar')); }); - test('parses a stack frame with timer_impl correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " - "(timer_impl.dart:24)"); - expect(frame.uri, equals(Uri.parse("dart:io/timer_impl.dart"))); - expect(frame.line, equals(24)); - expect(frame.column, null); - expect(frame.member, equals('Foo._bar')); - }); - - test('parses a stack frame with http_parser correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " - "(http_parser.dart:24)"); - expect(frame.uri, equals(Uri.parse("dart:io/http_parser.dart"))); - expect(frame.line, equals(24)); - expect(frame.column, null); - expect(frame.member, equals('Foo._bar')); - }); - - test('parses a stack frame with http_impl correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " - "(http_impl.dart:24)"); - expect(frame.uri, equals(Uri.parse("dart:io/http_impl.dart"))); - expect(frame.line, equals(24)); - expect(frame.column, null); - expect(frame.member, equals('Foo._bar')); - }); - test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseVM('#0 $member (foo:0:0)').member; From a3708fa9f88d21016125320ad923b4cabe3506a0 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 23 Jul 2014 23:44:09 +0000 Subject: [PATCH 0145/1215] Move a number of packages and some of pub over to using source_span. R=efortuna@google.com, rnystrom@google.com, sigmund@google.com BUG=19930 Review URL: https://codereview.chromium.org//401753002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@38526 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 13 ++++++++ pkgs/string_scanner/lib/src/exception.dart | 13 ++++---- pkgs/string_scanner/lib/src/span_scanner.dart | 32 +++++++++---------- .../lib/src/string_scanner.dart | 9 +++--- pkgs/string_scanner/pubspec.yaml | 4 +-- .../test/span_scanner_test.dart | 10 +++--- 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index a5d551888..f1d876301 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,16 @@ +## 0.1.0 + +* Switch from `source_maps`' `Span` class to `source_span`'s `SourceSpan` class. + +* `new StringScanner()`'s `sourceUrl` parameter is now named to make it clear + that it can be safely `null`. + +* `new StringScannerException()` takes different arguments in a different order + to match `SpanFormatException`. + +* `StringScannerException.string` has been renamed to + `StringScannerException.source` to match the `FormatException` interface. + ## 0.0.3 * Make `StringScannerException` inherit from source_map's diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 44ec9a3e7..50177d657 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -4,18 +4,17 @@ library string_scanner.exception; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; /// An exception thrown by a [StringScanner] that failed to parse a string. -class StringScannerException extends SpanFormatException { - /// The source string being parsed. - final String string; +class StringScannerException extends SourceSpanFormatException { + String get source => super.source; /// The URL of the source file being parsed. /// /// This may be `null`, indicating that the source URL is unknown. - final Uri sourceUrl; + Uri get sourceUrl => span.sourceUrl; - StringScannerException(String message, this.string, this.sourceUrl, Span span) - : super(message, span); + StringScannerException(String message, SourceSpan span, String source) + : super(message, span, source); } diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 9060e62f0..d8dc230a8 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -4,7 +4,7 @@ library string_scanner.span_scanner; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'exception.dart'; import 'line_scanner.dart'; @@ -20,7 +20,7 @@ class SpanScanner extends StringScanner implements LineScanner { final SourceFile _sourceFile; int get line => _sourceFile.getLine(position); - int get column => _sourceFile.getColumn(line, position); + int get column => _sourceFile.getColumn(position); LineScannerState get state => new _SpanScannerState(this, position); @@ -34,28 +34,28 @@ class SpanScanner extends StringScanner implements LineScanner { this.position = state.position; } - /// The [Span] for [lastMatch]. + /// The [SourceSpan] for [lastMatch]. /// /// This is the span for the entire match. There's no way to get spans for /// subgroups since [Match] exposes no information about their positions. - Span get lastSpan => _lastSpan; - Span _lastSpan; + SourceSpan get lastSpan => _lastSpan; + SourceSpan _lastSpan; /// Returns an empty span at the current location. - Span get emptySpan => _sourceFile.span(position); + SourceSpan get emptySpan => _sourceFile.location(position).pointSpan(); /// Creates a new [SpanScanner] that starts scanning from [position]. /// - /// [sourceUrl] is used as [Location.sourceUrl] for the returned [Span]s as - /// well as for error reporting. - SpanScanner(String string, sourceUrl, {int position}) - : _sourceFile = new SourceFile.text( - sourceUrl is Uri ? sourceUrl.toString() : sourceUrl, string), + /// [sourceUrl] is used as [SourceLocation.sourceUrl] for the returned + /// [SourceSpan]s as well as for error reporting. It can be a [String], a + /// [Uri], or `null`. + SpanScanner(String string, {sourceUrl, int position}) + : _sourceFile = new SourceFile(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); - /// Creates a [Span] representing the source range between [startState] and - /// the current position. - Span spanFrom(LineScannerState startState) => + /// Creates a [SourceSpan] representing the source range between [startState] + /// and the current position. + SourceSpan spanFrom(LineScannerState startState) => _sourceFile.span(startState.position, position); bool matches(Pattern pattern) { @@ -78,7 +78,7 @@ class SpanScanner extends StringScanner implements LineScanner { if (length == null) length = match == null ? 1 : match.end - match.start; var span = _sourceFile.span(position, position + length); - throw new StringScannerException(message, string, sourceUrl, span); + throw new StringScannerException(message, span, string); } } @@ -89,7 +89,7 @@ class _SpanScannerState implements LineScannerState { final int position; int get line => _scanner._sourceFile.getLine(position); - int get column => _scanner._sourceFile.getColumn(line, position); + int get column => _scanner._sourceFile.getColumn(position); _SpanScannerState(this._scanner, this.position); } diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index c9e74594a..44d5d2d87 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -4,7 +4,7 @@ library string_scanner.string_scanner; -import 'package:source_maps/source_maps.dart'; +import 'package:source_span/source_span.dart'; import 'exception.dart'; import 'utils.dart'; @@ -52,7 +52,7 @@ class StringScanner { /// /// [position] defaults to 0, the beginning of the string. [sourceUrl] is the /// URL of the source of the string being scanned, if available. It can be - /// either a [String] or a [Uri]. + /// a [String], a [Uri], or `null`. StringScanner(this.string, {sourceUrl, int position}) : sourceUrl = sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl { if (position != null) this.position = position; @@ -153,10 +153,9 @@ class StringScanner { } if (length == null) length = match == null ? 1 : match.end - match.start; - var url = sourceUrl == null ? null : sourceUrl.toString(); - var sourceFile = new SourceFile.text(url, string); + var sourceFile = new SourceFile(string, url: sourceUrl); var span = sourceFile.span(position, position + length); - throw new StringScannerException(message, string, sourceUrl, span); + throw new StringScannerException(message, span, string); } // TODO(nweiz): Make this handle long lines more gracefully. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index f6d7ab9ef..1451fc518 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 0.0.3 +version: 0.1.0 author: "Dart Team " homepage: http://www.dartlang.org description: > A class for parsing strings using a sequence of patterns. dependencies: path: ">=1.2.0 <2.0.0" - source_maps: ">=0.9.2 <0.10.0" + source_span: ">=1.0.0 <2.0.0" dev_dependencies: unittest: ">=0.10.0 <0.11.0" environment: diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 93ba0b659..796df2968 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -10,7 +10,7 @@ import 'package:unittest/unittest.dart'; void main() { var scanner; setUp(() { - scanner = new SpanScanner('foo\nbar\nbaz', 'source'); + scanner = new SpanScanner('foo\nbar\nbaz', sourceUrl: 'source'); }); test("tracks the span for the last match", () { @@ -21,12 +21,12 @@ void main() { expect(span.start.offset, equals(2)); expect(span.start.line, equals(0)); expect(span.start.column, equals(2)); - expect(span.start.sourceUrl, equals('source')); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); expect(span.end.offset, equals(6)); expect(span.end.line, equals(1)); expect(span.end.column, equals(2)); - expect(span.start.sourceUrl, equals('source')); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); expect(span.text, equals('o\nba')); }); @@ -48,12 +48,12 @@ void main() { expect(span.start.offset, equals(6)); expect(span.start.line, equals(1)); expect(span.start.column, equals(2)); - expect(span.start.sourceUrl, equals('source')); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); expect(span.end.offset, equals(6)); expect(span.end.line, equals(1)); expect(span.end.column, equals(2)); - expect(span.start.sourceUrl, equals('source')); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); expect(span.text, equals('')); }); From b5dd0d76d385aeae3fcbf4fd8ad1a788779561bf Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Mon, 4 Aug 2014 07:25:05 +0000 Subject: [PATCH 0146/1215] Add check to watcher, to avoid null-error if unknown path is removed. BUG= R=kevmoo@google.com Review URL: https://codereview.chromium.org//428493004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@38846 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/lib/src/path_set.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 01d4208f4..e9f7d32d2 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -71,7 +71,7 @@ class PathSet { // the next level. var part = parts.removeFirst(); var entry = dir[part]; - if (entry.isEmpty) return new Set(); + if (entry == null || entry.isEmpty) return new Set(); partialPath = p.join(partialPath, part); var paths = recurse(entry, partialPath); From 747f891829ed7cd173449ffdbd51d50c17404fb0 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 4 Aug 2014 15:55:05 +0000 Subject: [PATCH 0147/1215] pkg/watcher: prepare for 0.9.3 added changelog updated pubspec code formatting removed unused imports R=ajohnsen@google.com Review URL: https://codereview.chromium.org//441483004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@38862 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/CHANGELOG.md | 7 +++++++ pkgs/watcher/example/watch.dart | 2 -- pkgs/watcher/lib/src/async_queue.dart | 2 +- .../lib/src/constructable_file_system_event.dart | 6 +++--- pkgs/watcher/lib/src/utils.dart | 4 ++-- pkgs/watcher/lib/src/watch_event.dart | 2 +- pkgs/watcher/pubspec.yaml | 14 +++++++------- .../watcher/test/directory_watcher/linux_test.dart | 2 +- .../test/directory_watcher/mac_os_test.dart | 2 +- .../test/directory_watcher/polling_test.dart | 2 +- pkgs/watcher/test/directory_watcher/shared.dart | 2 +- .../test/directory_watcher/windows_test.dart | 4 +--- pkgs/watcher/test/no_subscription/linux_test.dart | 5 ++--- pkgs/watcher/test/no_subscription/mac_os_test.dart | 5 ++--- .../watcher/test/no_subscription/polling_test.dart | 4 ++-- pkgs/watcher/test/no_subscription/shared.dart | 3 +-- pkgs/watcher/test/ready/linux_test.dart | 5 ++--- pkgs/watcher/test/ready/mac_os_test.dart | 5 ++--- pkgs/watcher/test/ready/polling_test.dart | 4 ++-- pkgs/watcher/test/ready/shared.dart | 2 +- pkgs/watcher/test/utils.dart | 13 ++++++------- 21 files changed, 46 insertions(+), 49 deletions(-) create mode 100644 pkgs/watcher/CHANGELOG.md diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md new file mode 100644 index 000000000..eb544f61e --- /dev/null +++ b/pkgs/watcher/CHANGELOG.md @@ -0,0 +1,7 @@ +# 0.9.3 + +* Improved support for Windows via `WindowsDirectoryWatcher`. + +* Simplified `PollingDirectoryWatcher`. + +* Fixed bugs in `MacOSDirectoryWatcher` diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index aba127d6d..da3c2633c 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -5,8 +5,6 @@ /// Watches the given directory and prints each modification to it. library watch; -import 'dart:io'; - import 'package:path/path.dart' as p; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 8ac0cdfe1..b83493d73 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -70,4 +70,4 @@ class AsyncQueue { _isProcessing = false; }); } -} \ No newline at end of file +} diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index 010d2979d..d00a1dce7 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -40,11 +40,11 @@ class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent final type = FileSystemEvent.MODIFY; ConstructableFileSystemModifyEvent(String path, bool isDirectory, - this.contentChanged) + this.contentChanged) : super(path, isDirectory); String toString() => - "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; + "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; } class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent @@ -53,7 +53,7 @@ class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent final type = FileSystemEvent.MOVE; ConstructableFileSystemMoveEvent(String path, bool isDirectory, - this.destination) + this.destination) : super(path, isDirectory); String toString() => "FileSystemMoveEvent('$path', '$destination')"; diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 163e9f445..007c84c19 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -20,7 +20,7 @@ bool isDirectoryNotFoundException(error) { /// Returns the union of all elements in each set in [sets]. Set unionAll(Iterable sets) => - sets.fold(new Set(), (union, set) => union.union(set)); + sets.fold(new Set(), (union, set) => union.union(set)); /// Returns a buffered stream that will emit the same values as the stream /// returned by [future] once [future] completes. @@ -76,7 +76,7 @@ Future newFuture(callback()) => new Future.value().then((_) => callback()); /// Returns a [Future] that completes after pumping the event queue [times] /// times. By default, this should pump the event queue enough times to allow /// any code to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times=20]) { +Future pumpEventQueue([int times = 20]) { if (times == 0) return new Future.value(); // We use a delayed future to allow microtask events to finish. The // Future.value or Future() constructors use scheduleMicrotask themselves and diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart index d998a2532..be6d70c92 100644 --- a/pkgs/watcher/lib/src/watch_event.dart +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -32,4 +32,4 @@ class ChangeType { const ChangeType(this._name); String toString() => _name; -} \ No newline at end of file +} diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 51ba562a6..d517e8f6a 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,15 +1,15 @@ name: watcher version: 0.9.3-dev -author: "Dart Team " +author: Dart Team homepage: http://www.dartlang.org description: > A file watcher. It monitors for changes to contents of directories and notifies you when files have been added, removed, or modified. +environment: + sdk: '>=1.0.0 <2.0.0' dependencies: - path: ">=0.9.0 <2.0.0" - stack_trace: ">=0.9.1 <2.0.0" + path: '>=0.9.0 <2.0.0' + stack_trace: '>=0.9.1 <2.0.0' dev_dependencies: - scheduled_test: ">=0.9.3-dev <0.11.0" - unittest: ">=0.9.2 <0.10.0" -environment: - sdk: ">=0.8.10+6 <2.0.0" + scheduled_test: '>=0.9.3 <0.12.0' + unittest: '>=0.9.2 <0.12.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index cae38adf8..c17eb534c 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -9,7 +9,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 1e9bd7d10..bbf966aa9 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -9,7 +9,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); MacOSDirectoryWatcher.logDebugInfo = true; diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index da292073c..1ef49b57a 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -8,7 +8,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); // Use a short delay to make the tests run quickly. diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index d3575ea4d..86324014b 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -7,7 +7,7 @@ import 'package:watcher/src/utils.dart'; import '../utils.dart'; -sharedTests() { +void sharedTests() { test('does not notify for files that already exist when started', () { // Make some pre-existing files. writeFile("a.txt"); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 6bfb88b44..ea5c8c5a5 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -2,7 +2,6 @@ // 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. -import 'package:path/path.dart' as p; import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; import 'package:watcher/watcher.dart'; @@ -10,7 +9,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); @@ -24,4 +23,3 @@ main() { new isInstanceOf()); }); } - diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart index 7978830bc..f7f1b49c1 100644 --- a/pkgs/watcher/test/no_subscription/linux_test.dart +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -4,12 +4,11 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; -import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); @@ -17,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index e0275c4ee..721d3e7a0 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -4,12 +4,11 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; -import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); @@ -17,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart index fa4f0cbe2..c71b5ceec 100644 --- a/pkgs/watcher/test/no_subscription/polling_test.dart +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -8,7 +8,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new PollingDirectoryWatcher(dir); @@ -16,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 99172a2e8..9ba5c98ed 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -3,14 +3,13 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:io'; import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; import '../utils.dart'; -sharedTests() { +void sharedTests() { test('does not notify for changes when there are no subscribers', () { // Note that this test doesn't rely as heavily on the test functions in // utils.dart because it needs to be very explicit about when the event diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart index 7978830bc..f7f1b49c1 100644 --- a/pkgs/watcher/test/ready/linux_test.dart +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -4,12 +4,11 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; -import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); @@ -17,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart index e0275c4ee..721d3e7a0 100644 --- a/pkgs/watcher/test/ready/mac_os_test.dart +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -4,12 +4,11 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; -import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); @@ -17,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart index fa4f0cbe2..c71b5ceec 100644 --- a/pkgs/watcher/test/ready/polling_test.dart +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -8,7 +8,7 @@ import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; -main() { +void main() { initConfig(); watcherFactory = (dir) => new PollingDirectoryWatcher(dir); @@ -16,4 +16,4 @@ main() { setUp(createSandbox); sharedTests(); -} \ No newline at end of file +} diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index af1b58f99..7be48331e 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -6,7 +6,7 @@ import 'package:scheduled_test/scheduled_test.dart'; import '../utils.dart'; -sharedTests() { +void sharedTests() { test('ready does not complete until after subscription', () { var watcher = createWatcher(waitForReady: false); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 8b660e845..6758dae0c 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -4,7 +4,6 @@ library watcher.test.utils; -import 'dart:async'; import 'dart:io'; import 'package:path/path.dart' as p; @@ -250,16 +249,16 @@ Matcher isRemoveEvent(String path) => isWatchEvent(ChangeType.REMOVE, path); /// Expects that the next event emitted will be for an add event for [path]. void expectAddEvent(String path) => - _expectOrCollect(isWatchEvent(ChangeType.ADD, path)); + _expectOrCollect(isWatchEvent(ChangeType.ADD, path)); /// Expects that the next event emitted will be for a modification event for /// [path]. void expectModifyEvent(String path) => - _expectOrCollect(isWatchEvent(ChangeType.MODIFY, path)); + _expectOrCollect(isWatchEvent(ChangeType.MODIFY, path)); /// Expects that the next event emitted will be for a removal event for [path]. void expectRemoveEvent(String path) => - _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path)); + _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path)); /// Consumes an add event for [path] if one is emitted at this point in the /// schedule, but doesn't throw an error if it isn't. @@ -267,7 +266,7 @@ void expectRemoveEvent(String path) => /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. void allowAddEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path))); + _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path))); /// Consumes a modification event for [path] if one is emitted at this point in /// the schedule, but doesn't throw an error if it isn't. @@ -275,7 +274,7 @@ void allowAddEvent(String path) => /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. void allowModifyEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path))); + _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path))); /// Consumes a removal event for [path] if one is emitted at this point in the /// schedule, but doesn't throw an error if it isn't. @@ -283,7 +282,7 @@ void allowModifyEvent(String path) => /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. void allowRemoveEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path))); + _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path))); /// Schedules writing a file in the sandbox at [path] with [contents]. /// From 249da16589359b9bfe1f7af245368a9176fcc7d4 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 4 Aug 2014 16:06:37 +0000 Subject: [PATCH 0148/1215] pkg/watcher: update REAME descriptions TBR Review URL: https://codereview.chromium.org//439713007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@38863 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/README.md b/pkgs/watcher/README.md index 75b0470f0..61cc1f9f9 100644 --- a/pkgs/watcher/README.md +++ b/pkgs/watcher/README.md @@ -1,2 +1,4 @@ -A file watcher. It monitors (currently by polling) for changes to contents of -directories and notifies you when files have been added, removed, or modified. \ No newline at end of file +A file system watcher. + +It monitors changes to contents of directories and sends notifications when +files have been added, removed, or modified. From a8b8e3f313d329230a9385e19bf88b560d5b4303 Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" Date: Mon, 4 Aug 2014 16:10:07 +0000 Subject: [PATCH 0149/1215] pkg/watcher: actually flag for release align package description with recent README updates TBR Review URL: https://codereview.chromium.org//439713008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@38864 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index d517e8f6a..6f96a56a5 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,10 +1,10 @@ name: watcher -version: 0.9.3-dev +version: 0.9.3 author: Dart Team homepage: http://www.dartlang.org description: > - A file watcher. It monitors for changes to contents of directories and - notifies you when files have been added, removed, or modified. + A file system watcher. It monitors changes to contents of directories and + sends notifications when files have been added, removed, or modified. environment: sdk: '>=1.0.0 <2.0.0' dependencies: From 7e324162691b93071d9508e53d883e5b8da1aa80 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 17 Sep 2014 18:10:55 +0000 Subject: [PATCH 0150/1215] Add an error callback to StackZoneSpecification. This releases stack_trace 1.0.3. R=rnystrom@google.com Review URL: https://codereview.chromium.org//556363004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@40383 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 5 + pkgs/stack_trace/README.md | 9 - pkgs/stack_trace/lib/src/chain.dart | 34 +--- .../lib/src/stack_zone_specification.dart | 31 ++- pkgs/stack_trace/pubspec.yaml | 4 +- pkgs/stack_trace/test/chain_test.dart | 192 ++++++++++-------- 6 files changed, 154 insertions(+), 121 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a5d594a9c..56c614a64 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.3 + +* Use `Zone.errorCallback` to attach stack chains to all errors without the need + for `Chain.track`, which is now deprecated. + ## 1.0.2 * Remove a workaround for [issue 17083][]. diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 492a52aaa..38b768d68 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -205,13 +205,4 @@ this: That's a lot easier to understand! -### `Chain.track` - -For the most part `Chain.capture` will notice when an error is thrown and -associate the correct stack chain with it. However, there are some cases where -exceptions won't be automatically detected: any `Future` constructor, -`Completer.completeError`, `Stream.addError`, and libraries that use these such -as `dart:io` and `dart:async`. For these, all you need to do is wrap the Future -or Stream in a call to `Chain.track` and the errors will be tracked correctly. - [Zone]: https://api.dartlang.org/apidocs/channels/stable/#dart-async.Zone diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 78c6ae401..e4ac53436 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -102,33 +102,13 @@ class Chain implements StackTrace { }); } - /// Ensures that any errors emitted by [futureOrStream] have the correct stack - /// chain information associated with them. - /// - /// For the most part an error thrown within a [capture] zone will have the - /// correct stack chain automatically associated with it. However, there are - /// some cases where exceptions won't be automatically detected: any [Future] - /// constructor, [Completer.completeError], [Stream.addError], and libraries - /// that use these. - /// - /// This returns a [Future] or [Stream] that will emit the same values and - /// errors as [futureOrStream]. The only exception is that if [futureOrStream] - /// emits an error without a stack trace, one will be added in the return - /// value. - /// - /// If this is called outside of a [capture] zone, it just returns - /// [futureOrStream] as-is. - /// - /// As the name suggests, [futureOrStream] may be either a [Future] or a - /// [Stream]. - static track(futureOrStream) { - if (_currentSpec == null) return futureOrStream; - if (futureOrStream is Future) { - return _currentSpec.trackFuture(futureOrStream, 1); - } else { - return _currentSpec.trackStream(futureOrStream, 1); - } - } + /// Returns [futureOrStream] unmodified. + /// + /// Prior to Dart 1.7, this was necessary to ensure that stack traces for + /// exceptions reported with [Completer.completeError] and + /// [StreamController.addError] were tracked correctly. + @Deprecated("Chain.track is not necessary in Dart 1.7+.") + static track(futureOrStream) => futureOrStream; /// Returns the current stack chain. /// diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 9a4f7c05a..292da6528 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -56,7 +56,8 @@ class StackZoneSpecification { handleUncaughtError: handleUncaughtError, registerCallback: registerCallback, registerUnaryCallback: registerUnaryCallback, - registerBinaryCallback: registerBinaryCallback); + registerBinaryCallback: registerBinaryCallback, + errorCallback: errorCallback); } /// Returns the current stack chain. @@ -88,7 +89,9 @@ class StackZoneSpecification { var node = _createNode(level + 1); future.then(completer.complete).catchError((e, stackTrace) { if (stackTrace == null) stackTrace = new Trace.current(); - if (_chains[stackTrace] == null) _chains[stackTrace] = node; + if (stackTrace is! Chain && _chains[stackTrace] == null) { + _chains[stackTrace] = node; + } completer.completeError(e, stackTrace); }); return completer.future; @@ -105,7 +108,9 @@ class StackZoneSpecification { return stream.transform(new StreamTransformer.fromHandlers( handleError: (error, stackTrace, sink) { if (stackTrace == null) stackTrace = new Trace.current(); - if (_chains[stackTrace] == null) _chains[stackTrace] = node; + if (stackTrace is! Chain && _chains[stackTrace] == null) { + _chains[stackTrace] = node; + } sink.addError(error, stackTrace); })); } @@ -163,6 +168,26 @@ class StackZoneSpecification { } } + /// Attaches the current stack chain to [stackTrace], replacing it if + /// necessary. + AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, + Object error, StackTrace stackTrace) { + var asyncError = parent.errorCallback(zone, error, stackTrace); + if (asyncError != null) { + error = asyncError.error; + stackTrace = asyncError.stackTrace; + } + + // Go up two levels to get through [_CustomZone.errorCallback]. + if (stackTrace == null) { + stackTrace = _createNode(2).toChain(); + } else { + if (_chains[stackTrace] == null) _chains[stackTrace] = _createNode(2); + } + + return new AsyncError(error, stackTrace); + } + /// Creates a [_Node] with the current stack trace and linked to /// [_currentNode]. /// diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 5226cf8c1..bf28770ca 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.0.2 +version: 1.0.3 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -19,4 +19,4 @@ dependencies: dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: - sdk: ">=1.0.0 <2.0.0" + sdk: ">=1.7.0-edge.40308 <2.0.0" diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index beb4721cf..6af3c6b13 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -93,6 +93,37 @@ void main() { }); }); + test('thrown in new Future()', () { + return captureFuture(() => inNewFuture(() => throw 'error')) + .then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + + // The second trace is the one captured by + // [StackZoneSpecification.errorCallback]. Because that runs + // asynchronously within [new Future], it doesn't actually refer to the + // source file at all. + expect(chain.traces[1].frames, + everyElement(frameLibrary(isNot(contains('chain_test'))))); + + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inNewFuture')))); + }); + }); + + test('thrown in new Future.sync()', () { + return captureFuture(() { + inMicrotask(() => inSyncFuture(() => throw 'error')); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames.first, frameMember(startsWith('main'))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inSyncFuture')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + test('multiple times', () { var completer = new Completer(); var first = true; @@ -121,6 +152,73 @@ void main() { return completer.future; }); + test('passed to a completer', () { + var trace = new Trace.current(); + return captureFuture(() { + inMicrotask(() => completerErrorFuture(trace)); + }).then((chain) { + expect(chain.traces, hasLength(3)); + + // The first trace is the trace that was manually reported for the + // error. + expect(chain.traces.first.toString(), equals(trace.toString())); + + // The second trace is the trace that was captured when + // [Completer.addError] was called. + expect(chain.traces[1].frames, + contains(frameMember(startsWith('completerErrorFuture')))); + + // The third trace is the automatically-captured trace from when the + // microtask was scheduled. + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('passed to a completer with no stack trace', () { + return captureFuture(() { + inMicrotask(() => completerErrorFuture()); + }).then((chain) { + expect(chain.traces, hasLength(2)); + + // The first trace is the one captured when [Completer.addError] was + // called. + expect(chain.traces[0].frames, + contains(frameMember(startsWith('completerErrorFuture')))); + + // The second trace is the automatically-captured trace from when the + // microtask was scheduled. + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('passed to a stream controller', () { + var trace = new Trace.current(); + return captureFuture(() { + inMicrotask(() => controllerErrorStream(trace).listen(null)); + }).then((chain) { + expect(chain.traces, hasLength(3)); + expect(chain.traces.first.toString(), equals(trace.toString())); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('controllerErrorStream')))); + expect(chain.traces[2].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + + test('passed to a stream controller with no stack trace', () { + return captureFuture(() { + inMicrotask(() => controllerErrorStream().listen(null)); + }).then((chain) { + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames, + contains(frameMember(startsWith('controllerErrorStream')))); + expect(chain.traces[1].frames, + contains(frameMember(startsWith('inMicrotask')))); + }); + }); + test('and relays them to the parent zone', () { var completer = new Completer(); @@ -526,50 +624,6 @@ void main() { }); group('Chain.track(Future)', () { - test('associates the current chain with a manually-reported exception with ' - 'a stack trace', () { - var trace = new Trace.current(); - return captureFuture(() { - inMicrotask(() => trackedErrorFuture(trace)); - }).then((chain) { - expect(chain.traces, hasLength(3)); - - // The first trace is the trace that was manually reported for the - // error. - expect(chain.traces.first.toString(), equals(trace.toString())); - - // The second trace is the trace that was captured when [Chain.track] - // was called. - expect(chain.traces[1].frames.first, - frameMember(startsWith('trackedErrorFuture'))); - - // The third trace is the automatically-captured trace from when the - // microtask was scheduled. - expect(chain.traces[2].frames, - contains(frameMember(startsWith('inMicrotask')))); - }); - }); - - test('associates the current chain with a manually-reported exception with ' - 'no stack trace', () { - return captureFuture(() { - inMicrotask(() => trackedErrorFuture()); - }).then((chain) { - expect(chain.traces, hasLength(3)); - - // The first trace is the one captured by - // [StackZoneSpecification.trackFuture], which should contain only - // stack_trace and dart: frames. - expect(chain.traces.first.frames, - everyElement(frameLibrary(isNot(contains('chain_test'))))); - - expect(chain.traces[1].frames.first, - frameMember(startsWith('trackedErrorFuture'))); - expect(chain.traces[2].frames, - contains(frameMember(startsWith('inMicrotask')))); - }); - }); - test('forwards the future value within Chain.capture()', () { Chain.capture(() { expect(Chain.track(new Future.value('value')), @@ -598,36 +652,6 @@ void main() { }); group('Chain.track(Stream)', () { - test('associates the current chain with a manually-reported exception with ' - 'a stack trace', () { - var trace = new Trace.current(); - return captureFuture(() { - inMicrotask(() => trackedErrorStream(trace).listen(null)); - }).then((chain) { - expect(chain.traces, hasLength(3)); - expect(chain.traces.first.toString(), equals(trace.toString())); - expect(chain.traces[1].frames.first, - frameMember(startsWith('trackedErrorStream'))); - expect(chain.traces[2].frames, - contains(frameMember(startsWith('inMicrotask')))); - }); - }); - - test('associates the current chain with a manually-reported exception with ' - 'no stack trace', () { - return captureFuture(() { - inMicrotask(() => trackedErrorStream().listen(null)); - }).then((chain) { - expect(chain.traces, hasLength(3)); - expect(chain.traces.first.frames, - everyElement(frameLibrary(isNot(contains('chain_test'))))); - expect(chain.traces[1].frames.first, - frameMember(startsWith('trackedErrorStream'))); - expect(chain.traces[2].frames, - contains(frameMember(startsWith('inMicrotask')))); - }); - }); - test('forwards stream values within Chain.capture()', () { Chain.capture(() { var controller = new StreamController() @@ -692,22 +716,30 @@ void inFutureChain(callback()) { .then((_) => new Future(() {})); } -/// Returns a Future that completes to an error and is wrapped in [Chain.track]. +void inNewFuture(callback()) { + new Future(callback); +} + +void inSyncFuture(callback()) { + new Future.sync(callback); +} + +/// Returns a Future that completes to an error using a completer. /// /// If [trace] is passed, it's used as the stack trace for the error. -Future trackedErrorFuture([StackTrace trace]) { +Future completerErrorFuture([StackTrace trace]) { var completer = new Completer(); completer.completeError('error', trace); - return Chain.track(completer.future); + return completer.future; } -/// Returns a Stream that emits an error and is wrapped in [Chain.track]. +/// Returns a Stream that emits an error using a controller. /// /// If [trace] is passed, it's used as the stack trace for the error. -Stream trackedErrorStream([StackTrace trace]) { +Stream controllerErrorStream([StackTrace trace]) { var controller = new StreamController(); controller.addError('error', trace); - return Chain.track(controller.stream); + return controller.stream; } /// Runs [callback] within [asyncFn], then converts any errors raised into a From 88509a8bba28454df7d9468e08bf8f47f12a8322 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 17 Sep 2014 21:43:28 +0000 Subject: [PATCH 0151/1215] Remove some additional Chain.track documentation. R=rnystrom@google.com Review URL: https://codereview.chromium.org//581693003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@40404 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/lib/src/chain.dart | 15 --------------- .../lib/src/stack_zone_specification.dart | 6 +++--- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index e4ac53436..f027025be 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -35,14 +35,6 @@ typedef void ChainHandler(error, Chain chain); /// print("Caught error $error\n" /// "$stackChain"); /// }); -/// -/// For the most part [Chain.capture] will notice when an error is thrown and -/// associate the correct stack chain with it; the chain can be accessed using -/// [new Chain.forTrace]. However, there are some cases where exceptions won't -/// be automatically detected: any [Future] constructor, -/// [Completer.completeError], [Stream.addError], and libraries that use these. -/// For these, all you need to do is wrap the Future or Stream in a call to -/// [Chain.track] and the errors will be tracked correctly. class Chain implements StackTrace { /// The line used in the string representation of stack chains to represent /// the gap between traces. @@ -69,13 +61,6 @@ class Chain implements StackTrace { /// parent Zone's `unhandledErrorHandler` will be called with the error and /// its chain. /// - /// For the most part an error thrown in the zone will have the correct stack - /// chain associated with it. However, there are some cases where exceptions - /// won't be automatically detected: any [Future] constructor, - /// [Completer.completeError], [Stream.addError], and libraries that use - /// these. For these, all you need to do is wrap the Future or Stream in a - /// call to [Chain.track] and the errors will be tracked correctly. - /// /// Note that even if [onError] isn't passed, this zone will still be an error /// zone. This means that any errors that would cross the zone boundary are /// considered unhandled. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 292da6528..0c1c7d228 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -22,9 +22,9 @@ import 'chain.dart'; /// it can be available to [Chain.current] and to be linked into additional /// chains when more callbacks are scheduled. /// -/// * When a callback throws an error or a [Chain.track]ed Future or Stream -/// emits an error, the current node is associated with that error's stack -/// trace using the [_chains] expando. +/// * When a callback throws an error or a Future or Stream emits an error, the +/// current node is associated with that error's stack trace using the +/// [_chains] expando. /// /// Since [ZoneSpecification] can't be extended or even implemented, in order to /// get a real [ZoneSpecification] instance it's necessary to call [toSpec]. From 9e3d4945d71cbaf62c05e0c294b9237c03029f76 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Thu, 18 Sep 2014 22:19:59 +0000 Subject: [PATCH 0152/1215] Unify parsing of Firefox and Safari stack traces. This releases stack_trace 1.1.0. R=rnystrom@google.com Review URL: https://codereview.chromium.org//578993002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@40470 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 10 ++++ pkgs/stack_trace/lib/src/frame.dart | 75 +++++++++++++++------------ pkgs/stack_trace/lib/src/trace.dart | 61 ++++++++++------------ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 14 +++-- pkgs/stack_trace/test/trace_test.dart | 41 +++++++++++---- 6 files changed, 117 insertions(+), 86 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 56c614a64..bbb7eb5d9 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,13 @@ +## 1.1.0 + +* Unify the parsing of Safari and Firefox stack traces. This fixes an error in + Firefox trace parsing. + +* Deprecate `Trace.parseSafari6_0`, `Trace.parseSafari6_1`, + `Frame.parseSafari6_0`, and `Frame.parseSafari6_1`. + +* Add `Frame.parseSafari`. + ## 1.0.3 * Use `Zone.errorCallback` to attach stack chains to all errors without the need diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index b1db23042..4f5b16c2e 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -30,15 +30,26 @@ final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$'); final _v8EvalLocation = new RegExp( r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); -// foo$bar$0@http://pub.dartlang.org/stuff.dart.js:560:28 -// http://pub.dartlang.org/stuff.dart.js:560:28 -final _safariFrame = new RegExp(r"^(?:([0-9A-Za-z_$]*)@)?(.*):(\d*):(\d*)$"); - // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 -final _firefoxFrame = new RegExp( - r'^([^@(/]*)(?:\(.*\))?((?:/[^/]*)*)(?:\(.*\))?@(.*):(\d+)$'); +// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36 +// http://pub.dartlang.org/stuff.dart.js:560 +final _firefoxSafariFrame = new RegExp( + r'^' + r'(?:' // Member description. Not present in some Safari frames. + r'([^@(/]*)' // The actual name of the member. + r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. + r'((?:/[^/]*)*)' // Extra characters indicating a nested closure. + r'(?:\(.*\))?' // Arguments to the closure. + r'@' + r')?' + r'(.*?)' // The frame's URL. + r':' + r'(\d*)' // The line number. Empty in Safari if it's unknown. + r'(?::(\d*))?' // The column number. Not present in older browsers and + // empty in Safari if it's unknown. + r'$'); // foo/bar.dart 10:11 in Foo._bar // http://dartlang.org/foo/bar.dart in Foo._bar @@ -187,45 +198,45 @@ class Frame { /// Parses a string representation of a Firefox stack frame. factory Frame.parseFirefox(String frame) { - var match = _firefoxFrame.firstMatch(frame); + var match = _firefoxSafariFrame.firstMatch(frame); if (match == null) { throw new FormatException( - "Couldn't parse Firefox stack trace line '$frame'."); + "Couldn't parse Firefox/Safari stack trace line '$frame'."); } // Normally this is a URI, but in a jsshell trace it can be a path. var uri = _uriOrPathToUri(match[3]); - var member = match[1]; - member += new List.filled('/'.allMatches(match[2]).length, ".").join(); - if (member == '') member = ''; - - // Some Firefox members have initial dots. We remove them for consistency - // with other platforms. - member = member.replaceFirst(_initialDot, ''); - return new Frame(uri, int.parse(match[4]), null, member); + + var member; + if (match[1] != null) { + member = match[1]; + member += + new List.filled('/'.allMatches(match[2]).length, ".").join(); + if (member == '') member = ''; + + // Some Firefox members have initial dots. We remove them for consistency + // with other platforms. + member = member.replaceFirst(_initialDot, ''); + } else { + member = ''; + } + + var line = match[4] == '' ? null : int.parse(match[4]); + var column = match[5] == null || match[5] == '' ? + null : int.parse(match[5]); + return new Frame(uri, line, column, member); } /// Parses a string representation of a Safari 6.0 stack frame. - /// - /// Safari 6.0 frames look just like Firefox frames. Prior to Safari 6.0, - /// stack traces can't be retrieved. + @Deprecated("Use Frame.parseSafari instead.") factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame); /// Parses a string representation of a Safari 6.1+ stack frame. - factory Frame.parseSafari6_1(String frame) { - var match = _safariFrame.firstMatch(frame); - if (match == null) { - throw new FormatException( - "Couldn't parse Safari stack trace line '$frame'."); - } + @Deprecated("Use Frame.parseSafari instead.") + factory Frame.parseSafari6_1(String frame) => new Frame.parseFirefox(frame); - var uri = Uri.parse(match[2]); - var member = match[1]; - if (member == null) member = ''; - var line = match[3] == '' ? null : int.parse(match[3]); - var column = match[4] == '' ? null : int.parse(match[4]); - return new Frame(uri, line, column, member); - } + /// Parses a string representation of a Safari stack frame. + factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); /// Parses this package's string representation of a stack frame. factory Frame.parseFriendly(String frame) { diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index c540d78c6..2690ece17 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -29,25 +29,28 @@ final _v8Trace = new RegExp(r"\n ?at "); /// though it is possible for the message to match this as well. final _v8TraceLine = new RegExp(r" ?at "); -/// A RegExp to match Safari's stack traces. +/// A RegExp to match Firefox and Safari's stack traces. /// -/// Prior to version 6, Safari's stack traces were uncapturable. In v6 they were -/// almost identical to Firefox traces, and so are handled by the Firefox code. -/// In v6.1+, they have their own format that's similar to Firefox but distinct -/// enough to warrant handling separately. -/// -/// Most notably, Safari traces occasionally don't include the initial method -/// name followed by "@", and they always have both the line and column number -/// (or just a trailing colon if no column number is available). -final _safariTrace = new RegExp(r"^([0-9A-Za-z_$]*@)?.*:\d*:\d*$", - multiLine: true); - -/// A RegExp to match Firefox's stack traces. +/// Firefox and Safari have very similar stack trace formats, so we use the same +/// logic for parsing them. /// /// Firefox's trace frames start with the name of the function in which the /// error occurred, possibly including its parameters inside `()`. For example, /// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. -final _firefoxTrace = new RegExp(r"^([.0-9A-Za-z_$/<]|\(.*\))*@"); +/// +/// Safari traces occasionally don't include the initial method name followed by +/// "@", and they always have both the line and column number (or just a +/// trailing colon if no column number is available). They can also contain +/// empty lines or lines consisting only of `[native code]`. +final _firefoxSafariTrace = new RegExp( + r"^" + r"(" // Member description. Not present in some Safari frames. + r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. + r"@" + r")?" + r"[^\s]*" // Frame URL. + r":\d*" // Line or column number. Some older frames only have a line number. + r"$", multiLine: true); /// A RegExp to match this package's stack traces. final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?[ \t]+[^\s]+$", @@ -112,12 +115,9 @@ class Trace implements StackTrace { try { if (trace.isEmpty) return new Trace([]); if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); - // Safari 6.1+ traces could be misinterpreted as Firefox traces, so we - // check for them first. - if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace); - // Safari 6.0 traces are a superset of Firefox traces, so we parse those - // two together. - if (trace.contains(_firefoxTrace)) return new Trace.parseSafari6_0(trace); + if (trace.contains(_firefoxSafariTrace)) { + return new Trace.parseFirefox(trace); + } if (trace.contains(_friendlyTrace)) { return new Trace.parseFriendly(trace); } @@ -157,29 +157,20 @@ class Trace implements StackTrace { /// Parses a string representation of a Firefox stack trace. Trace.parseFirefox(String trace) : this(trace.trim().split("\n") + .where((line) => line.isNotEmpty && line != '[native code]') .map((line) => new Frame.parseFirefox(line))); /// Parses a string representation of a Safari stack trace. - /// - /// This will automatically decide between [parseSafari6_0] and - /// [parseSafari6_1] based on the contents of [trace]. - factory Trace.parseSafari(String trace) { - if (trace.contains(_safariTrace)) return new Trace.parseSafari6_1(trace); - return new Trace.parseSafari6_0(trace); - } + Trace.parseSafari(String trace) + : this.parseFirefox(trace); /// Parses a string representation of a Safari 6.1+ stack trace. + @Deprecated("Use Trace.parseSafari instead.") Trace.parseSafari6_1(String trace) - : this(trace.trim().split("\n") - .where((line) => line.isNotEmpty) - .map((line) => new Frame.parseSafari6_1(line))); + : this.parseSafari(trace); /// Parses a string representation of a Safari 6.0 stack trace. - /// - /// Safari 6.0 stack traces look just like Firefox traces, except that they - /// sometimes (e.g. in isolates) have a "[native code]" frame. We just ignore - /// this frame to make the stack format more consistent between browsers. - /// Prior to Safari 6.0, stack traces can't be retrieved. + @Deprecated("Use Trace.parseSafari instead.") Trace.parseSafari6_0(String trace) : this(trace.trim().split("\n") .where((line) => line != '[native code]') diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index bf28770ca..cd798bff3 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.0.3 +version: 1.1.0 author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 1205d7484..b132368ca 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -210,7 +210,7 @@ void main() { }); }); - group('.parseFirefox', () { + group('.parseFirefox/.parseSafari', () { test('parses a simple stack frame correctly', () { var frame = new Frame.parseFirefox( ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); @@ -356,11 +356,9 @@ void main() { expect(() => new Frame.parseFirefox('@dart:async/future.dart'), throwsFormatException); }); - }); - group('.parseSafari6_1', () { test('parses a simple stack frame correctly', () { - var frame = new Frame.parseSafari6_1( + var frame = new Frame.parseFirefox( "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); @@ -369,7 +367,7 @@ void main() { }); test('parses an anonymous stack frame correctly', () { - var frame = new Frame.parseSafari6_1( + var frame = new Frame.parseFirefox( "http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); @@ -378,7 +376,7 @@ void main() { }); test('parses a stack frame with no line correctly', () { - var frame = new Frame.parseSafari6_1( + var frame = new Frame.parseFirefox( "foo\$bar@http://dartlang.org/foo/bar.dart::11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, isNull); @@ -387,7 +385,7 @@ void main() { }); test('parses a stack frame with no column correctly', () { - var frame = new Frame.parseSafari6_1( + var frame = new Frame.parseFirefox( "foo\$bar@http://dartlang.org/foo/bar.dart:10:"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); @@ -396,7 +394,7 @@ void main() { }); test('parses a stack frame with no line or column correctly', () { - var frame = new Frame.parseSafari6_1( + var frame = new Frame.parseFirefox( "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index bc2db6b85..17f9c22e9 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -92,7 +92,7 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); - test('parses a Firefox stack trace correctly', () { + test('parses a Firefox/Safari stack trace correctly', () { var trace = new Trace.parse( 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' @@ -130,7 +130,8 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); }); - test('parses a Safari 6.0 stack trace correctly', () { + test('parses a Firefox/Safari stack trace containing native code correctly', + () { var trace = new Trace.parse( 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' @@ -146,29 +147,49 @@ void main() { expect(trace.frames.length, equals(3)); }); - test('parses a Safari 6.1 stack trace correctly', () { + test('parses a Firefox/Safari stack trace without a method name correctly', + () { var trace = new Trace.parse( - 'http://pub.dartlang.org/stuff.js:42:43\n' - 'zip@http://pub.dartlang.org/stuff.js:0:1\n' - 'zip\$zap@http://pub.dartlang.org/thing.js:1:2'); + 'http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[0].member, equals('')); expect(trace.frames[1].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); - test('parses a Safari 6.1 stack trace with an empty line correctly', () { + test('parses a Firefox/Safari stack trace with an empty line correctly', + () { var trace = new Trace.parse( - 'http://pub.dartlang.org/stuff.js:42:43\n' + 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' '\n' - 'zip@http://pub.dartlang.org/stuff.js:0:1\n' - 'zip\$zap@http://pub.dartlang.org/thing.js:1:2'); + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + }); + + test('parses a Firefox/Safari stack trace with a column number correctly', + () { + var trace = new Trace.parse( + 'Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[0].line, equals(42)); + expect(trace.frames[0].column, equals(2)); expect(trace.frames[1].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, From 8bef7e4c8b8d6d16524b8bc1b433439d55f356eb Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 26 Sep 2014 00:41:39 +0000 Subject: [PATCH 0153/1215] Widen the stack_trace SDK constraint. R=rnystrom@google.com Review URL: https://codereview.chromium.org//603623005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/stack_trace@40701 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index bbb7eb5d9..2850cfca4 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.1 + +* Widen the SDK constraint to include 1.7.0-dev.4.0. + ## 1.1.0 * Unify the parsing of Safari and Firefox stack traces. This fixes an error in diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index cd798bff3..4d9793d85 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.1.0 +version: 1.1.1 author: "Dart Team " homepage: http://www.dartlang.org description: > @@ -19,4 +19,4 @@ dependencies: dev_dependencies: unittest: ">=0.9.0 <0.12.0" environment: - sdk: ">=1.7.0-edge.40308 <2.0.0" + sdk: ">=1.7.0-dev.4.0 <2.0.0" From 8dd6edf923b2827bee6a4a1c63abb29db6be925e Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 21 Oct 2014 06:06:19 +0000 Subject: [PATCH 0154/1215] Mac no longer fire bogus events. Fix Mac watcher. This is a re-apply of r37162. BUG= R=nweiz@google.com Review URL: https://codereview.chromium.org//621813002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@41220 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/CHANGELOG.md | 4 ++ .../lib/src/directory_watcher/mac_os.dart | 72 ++----------------- pkgs/watcher/pubspec.yaml | 4 +- 3 files changed, 12 insertions(+), 68 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index eb544f61e..175a86025 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.4 + +* Remove delay-fixes in MacOSDirectoryWatcher, by depending on sdk 1.6. + # 0.9.3 * Improved support for Windows via `WindowsDirectoryWatcher`. diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index e3efa2dd6..65f07fa92 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -73,30 +73,15 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// a subdirectory that was moved into the watched directory. StreamSubscription _listSubscription; - /// The timer for tracking how long we wait for an initial batch of bogus - /// events (see issue 14373). - Timer _bogusEventTimer; - _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, _files = new PathSet(directory), _id = "$parentId/${_count++}" { - _startWatch(); - - // Before we're ready to emit events, wait for [_listDir] to complete and - // for enough time to elapse that if bogus events (issue 14373) would be - // emitted, they will be. - // - // If we do receive a batch of events, [_onBatch] will ensure that these - // futures don't fire and that the directory is re-listed. - Future.wait([ - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - }), - _waitForBogusEvents() - ]).then((_) { + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + _startWatch(); if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -134,29 +119,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } - // If we get a batch of events before we're ready to begin emitting events, - // it's probable that it's a batch of pre-watcher events (see issue 14373). - // Ignore those events and re-list the directory. - if (!isReady) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] not ready to emit events, re-listing directory"); - } - - // Cancel the timer because bogus events only occur in the first batch, so - // we can fire [ready] as soon as we're done listing the directory. - _bogusEventTimer.cancel(); - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is ready, known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - _readyCompleter.complete(); - }); - return; - } - _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { @@ -392,17 +354,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _watchSubscription = null; - // If the directory still exists and we're still expecting bogus events, - // this is probably issue 14849 rather than a real close event. We should - // just restart the watcher. - if (!isReady && new Directory(directory).existsSync()) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] fake closure (issue 14849), re-opening stream"); - } - _startWatch(); - return; - } - // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. @@ -442,19 +393,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { return completer.future; } - /// Wait 200ms for a batch of bogus events (issue 14373) to come in. - /// - /// 200ms is short in terms of human interaction, but longer than any Mac OS - /// watcher tests take on the bots, so it should be safe to assume that any - /// bogus events will be signaled in that time frame. - Future _waitForBogusEvents() { - var completer = new Completer(); - _bogusEventTimer = new Timer( - new Duration(milliseconds: 200), - completer.complete); - return completer.future; - } - /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 6f96a56a5..473e1c962 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.3 +version: 0.9.4 author: Dart Team homepage: http://www.dartlang.org description: > @@ -13,3 +13,5 @@ dependencies: dev_dependencies: scheduled_test: '>=0.9.3 <0.12.0' unittest: '>=0.9.2 <0.12.0' +environment: + sdk: ">=1.6.0 <2.0.0" From c4150c42bf927dc6e7a3716ffe4dbfe048b7c2f1 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" Date: Tue, 21 Oct 2014 07:43:59 +0000 Subject: [PATCH 0155/1215] Revert "Mac no longer fire bogus events. Fix Mac watcher." BUG= Review URL: https://codereview.chromium.org//670653003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/watcher@41221 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/watcher/CHANGELOG.md | 4 -- .../lib/src/directory_watcher/mac_os.dart | 72 +++++++++++++++++-- pkgs/watcher/pubspec.yaml | 4 +- 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 175a86025..eb544f61e 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,7 +1,3 @@ -# 0.9.4 - -* Remove delay-fixes in MacOSDirectoryWatcher, by depending on sdk 1.6. - # 0.9.3 * Improved support for Windows via `WindowsDirectoryWatcher`. diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 65f07fa92..e3efa2dd6 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -73,15 +73,30 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// a subdirectory that was moved into the watched directory. StreamSubscription _listSubscription; + /// The timer for tracking how long we wait for an initial batch of bogus + /// events (see issue 14373). + Timer _bogusEventTimer; + _MacOSDirectoryWatcher(String directory, int parentId) : directory = directory, _files = new PathSet(directory), _id = "$parentId/${_count++}" { - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - _startWatch(); + _startWatch(); + + // Before we're ready to emit events, wait for [_listDir] to complete and + // for enough time to elapse that if bogus events (issue 14373) would be + // emitted, they will be. + // + // If we do receive a batch of events, [_onBatch] will ensure that these + // futures don't fire and that the directory is re-listed. + Future.wait([ + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] finished initial directory list"); + } + }), + _waitForBogusEvents() + ]).then((_) { if (MacOSDirectoryWatcher.logDebugInfo) { print("[$_id] watcher is ready, known files:"); for (var file in _files.toSet()) { @@ -119,6 +134,29 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } + // If we get a batch of events before we're ready to begin emitting events, + // it's probable that it's a batch of pre-watcher events (see issue 14373). + // Ignore those events and re-list the directory. + if (!isReady) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] not ready to emit events, re-listing directory"); + } + + // Cancel the timer because bogus events only occur in the first batch, so + // we can fire [ready] as soon as we're done listing the directory. + _bogusEventTimer.cancel(); + _listDir().then((_) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] watcher is ready, known files:"); + for (var file in _files.toSet()) { + print("[$_id] ${p.relative(file, from: directory)}"); + } + } + _readyCompleter.complete(); + }); + return; + } + _sortEvents(batch).forEach((path, events) { var relativePath = p.relative(path, from: directory); if (MacOSDirectoryWatcher.logDebugInfo) { @@ -354,6 +392,17 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _watchSubscription = null; + // If the directory still exists and we're still expecting bogus events, + // this is probably issue 14849 rather than a real close event. We should + // just restart the watcher. + if (!isReady && new Directory(directory).existsSync()) { + if (MacOSDirectoryWatcher.logDebugInfo) { + print("[$_id] fake closure (issue 14849), re-opening stream"); + } + _startWatch(); + return; + } + // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. @@ -393,6 +442,19 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { return completer.future; } + /// Wait 200ms for a batch of bogus events (issue 14373) to come in. + /// + /// 200ms is short in terms of human interaction, but longer than any Mac OS + /// watcher tests take on the bots, so it should be safe to assume that any + /// bogus events will be signaled in that time frame. + Future _waitForBogusEvents() { + var completer = new Completer(); + _bogusEventTimer = new Timer( + new Duration(milliseconds: 200), + completer.complete); + return completer.future; + } + /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 473e1c962..6f96a56a5 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.4 +version: 0.9.3 author: Dart Team homepage: http://www.dartlang.org description: > @@ -13,5 +13,3 @@ dependencies: dev_dependencies: scheduled_test: '>=0.9.3 <0.12.0' unittest: '>=0.9.2 <0.12.0' -environment: - sdk: ">=1.6.0 <2.0.0" From 34d0e8f51aea32285dbae09cabdd44f0887844cd Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 29 Oct 2014 00:53:21 +0000 Subject: [PATCH 0156/1215] Add SpanScanner.location. Also explicitly expose FileSpans and FileLocations. R=rnystrom@google.com Review URL: https://codereview.chromium.org//683323002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@41383 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 9 +++++++++ pkgs/string_scanner/lib/src/span_scanner.dart | 17 ++++++++++------- pkgs/string_scanner/pubspec.yaml | 2 +- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index f1d876301..d7f09f303 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.1.1 + +* Declare `SpanScanner`'s exposed `SourceSpan`s and `SourceLocation`s to be + `FileSpan`s and `FileLocation`s. They always were underneath, but callers may + now rely on it. + +* Add `SpanScanner.location`, which returns the scanner's current + `SourceLocation`. + ## 0.1.0 * Switch from `source_maps`' `Span` class to `source_span`'s `SourceSpan` class. diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index d8dc230a8..a70d5fd74 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -34,28 +34,31 @@ class SpanScanner extends StringScanner implements LineScanner { this.position = state.position; } - /// The [SourceSpan] for [lastMatch]. + /// The [FileSpan] for [lastMatch]. /// /// This is the span for the entire match. There's no way to get spans for /// subgroups since [Match] exposes no information about their positions. - SourceSpan get lastSpan => _lastSpan; - SourceSpan _lastSpan; + FileSpan get lastSpan => _lastSpan; + FileSpan _lastSpan; + + /// The current location of the scanner. + FileLocation get location => _sourceFile.location(position); /// Returns an empty span at the current location. - SourceSpan get emptySpan => _sourceFile.location(position).pointSpan(); + FileSpan get emptySpan => location.pointSpan(); /// Creates a new [SpanScanner] that starts scanning from [position]. /// /// [sourceUrl] is used as [SourceLocation.sourceUrl] for the returned - /// [SourceSpan]s as well as for error reporting. It can be a [String], a + /// [FileSpan]s as well as for error reporting. It can be a [String], a /// [Uri], or `null`. SpanScanner(String string, {sourceUrl, int position}) : _sourceFile = new SourceFile(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); - /// Creates a [SourceSpan] representing the source range between [startState] + /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. - SourceSpan spanFrom(LineScannerState startState) => + FileSpan spanFrom(LineScannerState startState) => _sourceFile.span(startState.position, position); bool matches(Pattern pattern) { diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 1451fc518..831dfac9a 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.0 +version: 0.1.1 author: "Dart Team " homepage: http://www.dartlang.org description: > From f82411c45085fc1a177996299601fbec9e29586e Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Wed, 5 Nov 2014 23:41:30 +0000 Subject: [PATCH 0157/1215] Add StringScanner.substring. R=rnystrom@google.com Review URL: https://codereview.chromium.org//701723002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@41536 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 4 +++ .../lib/src/string_scanner.dart | 9 ++++++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/string_scanner_test.dart | 28 +++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index d7f09f303..d27374809 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2 + +* Add `StringScanner.substring`, which returns a substring of the source string. + ## 0.1.1 * Declare `SpanScanner`'s exposed `SourceSpan`s and `SourceLocation`s to be diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 44d5d2d87..bc5e1f58d 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -131,6 +131,15 @@ class StringScanner { return _lastMatch != null; } + /// Returns the substring of [string] between [start] and [end]. + /// + /// Unlike [String.substring], [end] defaults to [position] rather than the + /// end of the string. + String substring(int start, [int end]) { + if (end == null) end = position; + return string.substring(start, end); + } + /// Throws a [FormatException] with [message] as well as a detailed /// description of the location of the error in the string. /// diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 831dfac9a..d14a43e2d 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.1 +version: 0.1.2 author: "Dart Team " homepage: http://www.dartlang.org description: > diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 6144bf9c0..fcd904aba 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -61,6 +61,10 @@ void main() { expect(scanner.position, equals(0)); }); + test("substring returns the empty string", () { + expect(scanner.substring(0), isEmpty); + }); + test('setting position to 1 throws an ArgumentError', () { expect(() { scanner.position = 1; @@ -165,6 +169,18 @@ void main() { expect(scanner.rest, equals('foo bar')); }); + test("substring from the beginning returns the empty string", () { + expect(scanner.substring(0), isEmpty); + }); + + test("substring with a custom end returns the substring", () { + expect(scanner.substring(0, 3), equals('foo')); + }); + + test("substring with the string length returns the whole string", () { + expect(scanner.substring(0, 7), equals('foo bar')); + }); + test('setting position to 1 moves the cursor forward', () { scanner.position = 1; expect(scanner.position, equals(1)); @@ -260,6 +276,18 @@ void main() { expect(scanner.position, equals(7)); }); + test("substring from the beginning returns the whole string", () { + expect(scanner.substring(0), equals('foo bar')); + }); + + test("substring with a custom start returns a substring from there", () { + expect(scanner.substring(4), equals('bar')); + }); + + test("substring with a custom start and end returns that substring", () { + expect(scanner.substring(3, 5), equals(' b')); + }); + test('setting position to 1 moves the cursor backward', () { scanner.position = 1; expect(scanner.position, equals(1)); From 62e2a3c6d759adbb62eff3479caf086aae88724e Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" Date: Fri, 12 Dec 2014 01:39:22 +0000 Subject: [PATCH 0158/1215] Add an additional optional argument to SpanScanner.spanFrom. R=rnystrom@google.com Review URL: https://codereview.chromium.org//795343003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/string_scanner@42305 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/lib/src/span_scanner.dart | 6 ++++-- pkgs/string_scanner/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index d27374809..9c03874dc 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.3 + +* Add an optional `endState` argument to `SpanScanner.spanFrom`. + ## 0.1.2 * Add `StringScanner.substring`, which returns a substring of the source string. diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index a70d5fd74..2a78b5bc0 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -58,8 +58,10 @@ class SpanScanner extends StringScanner implements LineScanner { /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. - FileSpan spanFrom(LineScannerState startState) => - _sourceFile.span(startState.position, position); + FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + var endPosition = endState == null ? position : endState.position; + return _sourceFile.span(startState.position, endPosition); + } bool matches(Pattern pattern) { if (!super.matches(pattern)) { diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index d14a43e2d..da93ead05 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.2 +version: 0.1.3 author: "Dart Team " homepage: http://www.dartlang.org description: > From 524a29281fd751f03dfae6a909422554e3e7d7c3 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:52:32 -0800 Subject: [PATCH 0159/1215] Add gitignore, status, and codereview files. --- pkgs/stack_trace/.gitignore | 14 ++++++++++++++ pkgs/stack_trace/.status | 18 ++++++++++++++++++ pkgs/stack_trace/codereview.settings | 3 +++ 3 files changed, 35 insertions(+) create mode 100644 pkgs/stack_trace/.gitignore create mode 100644 pkgs/stack_trace/.status create mode 100644 pkgs/stack_trace/codereview.settings diff --git a/pkgs/stack_trace/.gitignore b/pkgs/stack_trace/.gitignore new file mode 100644 index 000000000..388eff0ba --- /dev/null +++ b/pkgs/stack_trace/.gitignore @@ -0,0 +1,14 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file diff --git a/pkgs/stack_trace/.status b/pkgs/stack_trace/.status new file mode 100644 index 000000000..fea219328 --- /dev/null +++ b/pkgs/stack_trace/.status @@ -0,0 +1,18 @@ +# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +# 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. + +# Skip non-test files ending with "_test". +*/packages/*: Skip + +# Only run tests from the build directory, since we don't care about the +# difference between transformed an untransformed code. +test/*: Skip + +[ $runtime == d8 || $runtime == jsshell ] +*/chain_test: Fail # Issues 15171 and 15105 +*/vm_test: RuntimeError, OK # VM-specific traces + +[ $compiler == dart2js && $browser ] +*/vm_test: Fail, OK # VM-specific traces +*/chain_test: Fail # Issues 15171 and 15105 diff --git a/pkgs/stack_trace/codereview.settings b/pkgs/stack_trace/codereview.settings new file mode 100644 index 000000000..aff5c3747 --- /dev/null +++ b/pkgs/stack_trace/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/stack_trace/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From f751f8bd55ea21c1a83eb3ec8a510971414b90a6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:52:44 -0800 Subject: [PATCH 0160/1215] Update the pubspec's homepage link. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 4d9793d85..8adfb2fb0 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -9,7 +9,7 @@ name: stack_trace # in pub to stay in sync with this. version: 1.1.1 author: "Dart Team " -homepage: http://www.dartlang.org +homepage: http://github.com/dart-lang/stack_trace description: > A package for manipulating stack traces and printing them readably. From e3f991b872f093959c9610b32048528927615bd2 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:56:21 -0800 Subject: [PATCH 0161/1215] Add gitignore, status, and codereview files. --- pkgs/string_scanner/.gitignore | 14 ++++++++++++++ pkgs/string_scanner/.status | 3 +++ pkgs/string_scanner/codereview.settings | 3 +++ 3 files changed, 20 insertions(+) create mode 100644 pkgs/string_scanner/.gitignore create mode 100644 pkgs/string_scanner/.status create mode 100644 pkgs/string_scanner/codereview.settings diff --git a/pkgs/string_scanner/.gitignore b/pkgs/string_scanner/.gitignore new file mode 100644 index 000000000..388eff0ba --- /dev/null +++ b/pkgs/string_scanner/.gitignore @@ -0,0 +1,14 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file diff --git a/pkgs/string_scanner/.status b/pkgs/string_scanner/.status new file mode 100644 index 000000000..e9f2b0049 --- /dev/null +++ b/pkgs/string_scanner/.status @@ -0,0 +1,3 @@ +# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +# 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. diff --git a/pkgs/string_scanner/codereview.settings b/pkgs/string_scanner/codereview.settings new file mode 100644 index 000000000..31c557fbd --- /dev/null +++ b/pkgs/string_scanner/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/string_scanner/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From a2fc7783c71f0787657332da3eedee8a2660edb2 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 16:56:34 -0800 Subject: [PATCH 0162/1215] Update the pubspec's homepage link. --- pkgs/string_scanner/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index da93ead05..2a712b8cc 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,7 +1,7 @@ name: string_scanner version: 0.1.3 author: "Dart Team " -homepage: http://www.dartlang.org +homepage: http://github.com/dart-lang/string_scanner description: > A class for parsing strings using a sequence of patterns. dependencies: From 14c9b780be03469c088fed927f6cce211be93646 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 17:00:20 -0800 Subject: [PATCH 0163/1215] Add gitignore, status, and codereview files. --- pkgs/watcher/.gitignore | 14 ++++++++++++++ pkgs/watcher/.status | 25 +++++++++++++++++++++++++ pkgs/watcher/codereview.settings | 3 +++ 3 files changed, 42 insertions(+) create mode 100644 pkgs/watcher/.gitignore create mode 100644 pkgs/watcher/.status create mode 100644 pkgs/watcher/codereview.settings diff --git a/pkgs/watcher/.gitignore b/pkgs/watcher/.gitignore new file mode 100644 index 000000000..388eff0ba --- /dev/null +++ b/pkgs/watcher/.gitignore @@ -0,0 +1,14 @@ +# Don’t commit the following directories created by pub. +.buildlog +.pub/ +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.js_ +*.js.deps +*.js.map + +# Include when developing application packages. +pubspec.lock \ No newline at end of file diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status new file mode 100644 index 000000000..728f81631 --- /dev/null +++ b/pkgs/watcher/.status @@ -0,0 +1,25 @@ +# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +# 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. + +# Skip non-test files ending with "_test". +*/packages/*: Skip + +# Only run tests from the build directory, since we don't care about the +# difference between transformed an untransformed code. +test/*: Skip + +[ $browser ] +*: Fail, OK # Uses dart:io. + +[ $arch == simarm && $checked ] +*/directory_watcher/linux_test: Skip # Issue 16118 + +[ $runtime == vm && ($system == windows || $system == macos) ] +*/linux_test: Skip + +[ $runtime == vm && ($system == windows || $system == linux) ] +*/mac_os_test: Skip + +[ $runtime == vm && ($system == macos || $system == linux) ] +*/windows_test: Skip diff --git a/pkgs/watcher/codereview.settings b/pkgs/watcher/codereview.settings new file mode 100644 index 000000000..25367dd29 --- /dev/null +++ b/pkgs/watcher/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/watcher/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From 1aa48de52271ed877874f074702173a88d9c678b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 17 Dec 2014 17:00:32 -0800 Subject: [PATCH 0164/1215] Update the pubspec's homepage link. --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 6f96a56a5..658ef78c5 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,7 +1,7 @@ name: watcher version: 0.9.3 author: Dart Team -homepage: http://www.dartlang.org +homepage: http://github.com/dart-lang/watcher description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. From cfc8731fc445030690dde871d5e13c6828e1f42a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 18 Dec 2014 17:42:34 -0800 Subject: [PATCH 0165/1215] Properly skip tests in packages directories. --- pkgs/stack_trace/.status | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/stack_trace/.status b/pkgs/stack_trace/.status index fea219328..7bf881aed 100644 --- a/pkgs/stack_trace/.status +++ b/pkgs/stack_trace/.status @@ -3,7 +3,12 @@ # BSD-style license that can be found in the LICENSE file. # Skip non-test files ending with "_test". +packages/*: Skip */packages/*: Skip +*/*/packages/*: Skip +*/*/*/packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip # Only run tests from the build directory, since we don't care about the # difference between transformed an untransformed code. From 3938793bffe2048054150c515aaf87fbb67e1b95 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 18 Dec 2014 17:42:49 -0800 Subject: [PATCH 0166/1215] Properly skip tests in packages directories. --- pkgs/watcher/.status | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status index 728f81631..cc13f00fa 100644 --- a/pkgs/watcher/.status +++ b/pkgs/watcher/.status @@ -3,7 +3,22 @@ # BSD-style license that can be found in the LICENSE file. # Skip non-test files ending with "_test". +packages/*: Skip +packages/*: Skip */packages/*: Skip +*/*/packages/*: Skip +*/*/*/packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip +*/*/packages/*: Skip +*/*/packages/*: Skip +*/packages/*: Skip +*/*/packages/*: Skip +*/*/*/packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip +*/*/*/*packages/*: Skip +*/*/*/*/*packages/*: Skip # Only run tests from the build directory, since we don't care about the # difference between transformed an untransformed code. From 4f38cacad56a0c78cc161fb79814edb5581b5f0b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 18 Dec 2014 17:52:12 -0800 Subject: [PATCH 0167/1215] Remove initial */s in .status. --- pkgs/watcher/.status | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status index cc13f00fa..b160ec0f7 100644 --- a/pkgs/watcher/.status +++ b/pkgs/watcher/.status @@ -4,21 +4,11 @@ # Skip non-test files ending with "_test". packages/*: Skip -packages/*: Skip -*/packages/*: Skip -*/*/packages/*: Skip -*/*/*/packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip -*/*/packages/*: Skip -*/*/packages/*: Skip */packages/*: Skip */*/packages/*: Skip */*/*/packages/*: Skip */*/*/*packages/*: Skip */*/*/*/*packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip # Only run tests from the build directory, since we don't care about the # difference between transformed an untransformed code. @@ -28,13 +18,13 @@ test/*: Skip *: Fail, OK # Uses dart:io. [ $arch == simarm && $checked ] -*/directory_watcher/linux_test: Skip # Issue 16118 +build/test/directory_watcher/linux_test: Skip # Issue 16118 [ $runtime == vm && ($system == windows || $system == macos) ] -*/linux_test: Skip +build/test/linux_test: Skip [ $runtime == vm && ($system == windows || $system == linux) ] -*/mac_os_test: Skip +build/test/mac_os_test: Skip [ $runtime == vm && ($system == macos || $system == linux) ] -*/windows_test: Skip +build/test/windows_test: Skip From 47aaf66353c69e822d7de6fb192fee0f8f8d2252 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 18 Dec 2014 17:55:26 -0800 Subject: [PATCH 0168/1215] Remove initial */s in .status. --- pkgs/stack_trace/.status | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/.status b/pkgs/stack_trace/.status index 7bf881aed..56ba102fe 100644 --- a/pkgs/stack_trace/.status +++ b/pkgs/stack_trace/.status @@ -15,9 +15,9 @@ packages/*: Skip test/*: Skip [ $runtime == d8 || $runtime == jsshell ] -*/chain_test: Fail # Issues 15171 and 15105 -*/vm_test: RuntimeError, OK # VM-specific traces +build/test/chain_test: Fail # Issues 15171 and 15105 +build/test/vm_test: RuntimeError, OK # VM-specific traces [ $compiler == dart2js && $browser ] -*/vm_test: Fail, OK # VM-specific traces -*/chain_test: Fail # Issues 15171 and 15105 +build/test/vm_test: Fail, OK # VM-specific traces +build/test/chain_test: Fail # Issues 15171 and 15105 From 8616fff0d36ec7133421a5c1c31ff822160c27b5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 19 Dec 2014 13:03:59 -0800 Subject: [PATCH 0169/1215] Update .status to properly skip tests. --- pkgs/watcher/.status | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status index b160ec0f7..40ed64ce1 100644 --- a/pkgs/watcher/.status +++ b/pkgs/watcher/.status @@ -21,10 +21,10 @@ test/*: Skip build/test/directory_watcher/linux_test: Skip # Issue 16118 [ $runtime == vm && ($system == windows || $system == macos) ] -build/test/linux_test: Skip +build/test/directory_watcher/linux_test: Skip [ $runtime == vm && ($system == windows || $system == linux) ] -build/test/mac_os_test: Skip +build/test/directory_watcher/mac_os_test: Skip [ $runtime == vm && ($system == macos || $system == linux) ] -build/test/windows_test: Skip +build/test/directory_watcher/windows_test: Skip From 38a2b19568c0dc8f07a86f55868e7c9a156e2d08 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 19 Dec 2014 13:47:30 -0800 Subject: [PATCH 0170/1215] Skip tests even more properly. --- pkgs/watcher/.status | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status index 40ed64ce1..e79b8e04a 100644 --- a/pkgs/watcher/.status +++ b/pkgs/watcher/.status @@ -21,10 +21,10 @@ test/*: Skip build/test/directory_watcher/linux_test: Skip # Issue 16118 [ $runtime == vm && ($system == windows || $system == macos) ] -build/test/directory_watcher/linux_test: Skip +build/test/*: Skip [ $runtime == vm && ($system == windows || $system == linux) ] -build/test/directory_watcher/mac_os_test: Skip +build/test/*: Skip [ $runtime == vm && ($system == macos || $system == linux) ] -build/test/directory_watcher/windows_test: Skip +build/test/*: Skip From 9a301f7ca14d6f99321cef41f6926912055f19f1 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Thu, 22 Jan 2015 09:48:54 -0800 Subject: [PATCH 0171/1215] Treat add events for known files as modifications instead of discarding them on Mac OS. Fixes pub serve not seeing files saved in IntelliJ or other tools that use "safe" writes. https://code.google.com/p/dart/issues/detail?id=21402 R=ajohnsen@google.com, nweiz@google.com Review URL: https://codereview.chromium.org//861313006 --- pkgs/watcher/CHANGELOG.md | 5 +++++ .../watcher/lib/src/directory_watcher/mac_os.dart | 15 +++++++++------ pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/directory_watcher/shared.dart | 12 ++++++++++++ 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index eb544f61e..2ff887ebe 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.4 + +* Treat add events for known files as modifications instead of discarding them + on Mac OS. + # 0.9.3 * Improved support for Windows via `WindowsDirectoryWatcher`. diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index e3efa2dd6..ee2013665 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -179,12 +179,15 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { for (var event in events) { if (event is FileSystemCreateEvent) { if (!event.isDirectory) { - // Don't emit ADD events for files or directories that we already - // know about. Such an event comes from FSEvents reporting an add - // that happened prior to the watch beginning. - if (_files.contains(path)) continue; - - _emitEvent(ChangeType.ADD, path); + // If we already know about the file, treat it like a modification. + // This can happen if a file is copied on top of an existing one. + // We'll see an ADD event for the latter file when from the user's + // perspective, the file's contents just changed. + var type = _files.contains(path) + ? ChangeType.MODIFY + : ChangeType.ADD; + + _emitEvent(type, path); _files.add(path); continue; } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 658ef78c5..c0c71eb1a 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.3 +version: 0.9.4 author: Dart Team homepage: http://github.com/dart-lang/watcher description: > diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 86324014b..a4cec5e11 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -121,6 +121,18 @@ void sharedTests() { renameFile("dir/old.txt", "new.txt"); expectRemoveEvent("dir/old.txt"); }); + + test('notifies when a file is moved onto an existing one', () { + writeFile("from.txt"); + writeFile("to.txt"); + startWatcher(); + + renameFile("from.txt", "to.txt"); + inAnyOrder([ + isRemoveEvent("from.txt"), + isModifyEvent("to.txt") + ]); + }); }); // Most of the time, when multiple filesystem actions happen in sequence, From 9072d93a058499e19bc4509c569e2a93a79a775b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 Feb 2015 16:20:08 -0800 Subject: [PATCH 0172/1215] Better support for async VM frames. Closes dart-lang/stack_trace#1 R=kevmoo@google.com Review URL: https://codereview.chromium.org//912043002 --- pkgs/stack_trace/CHANGELOG.md | 8 ++++++++ pkgs/stack_trace/lib/src/frame.dart | 19 ++++++++++--------- pkgs/stack_trace/lib/src/vm_trace.dart | 4 +++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 25 +++++++++++++++++++++++-- 5 files changed, 45 insertions(+), 13 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 2850cfca4..25abd8a48 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.1.2 + +* Support VM frames without line *or* column numbers, which async/await programs + occasionally generate. + +* Replace `<_async_body>` in VM frames' members with the + terser ``. + ## 1.1.1 * Widen the SDK constraint to include 1.7.0-dev.4.0. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 4f5b16c2e..8ecd19fb1 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -10,8 +10,9 @@ import 'package:path/path.dart' as path; import 'trace.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) -final _vmFrame = new RegExp( - r'^#\d+\s+(\S.*) \((.+?):(\d+)(?::(\d+))?\)$'); +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42) +// #1 Foo._bar (file:///home/nweiz/code/stuff.dart) +final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) // at VW.call$0 (eval as fn @@ -135,14 +136,14 @@ class Frame { // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. - var member = match[1].replaceAll("", ""); + var member = match[1] + .replaceAll("<_async_body>", "") + .replaceAll("", ""); var uri = Uri.parse(match[2]); - var line = int.parse(match[3]); - var column = null; - var columnMatch = match[4]; - if (columnMatch != null) { - column = int.parse(columnMatch); - } + + var lineAndColumn = match[3].split(':'); + var line = lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; + var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; return new Frame(uri, line, column, member); } diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 811601529..89474f583 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -22,7 +22,9 @@ class VMTrace implements StackTrace { var i = 1; return frames.map((frame) { var number = padRight("#${i++}", 8); - var member = frame.member.replaceAll("", ""); + var member = frame.member + .replaceAll("", "") + .replaceAll("", "<_async_body>"); var line = frame.line == null ? 0 : frame.line; var column = frame.column == null ? 0 : frame.column; return "$number$member (${frame.uri}:$line:$column)\n"; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 8adfb2fb0..2fee06129 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.1.1 +version: 1.1.2 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index b132368ca..638d1d7f6 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -30,6 +30,17 @@ void main() { expect(frame.member, equals('Foo._bar')); }); + // This can happen with async stack traces. See issue 22009. + test('parses a stack frame without line or column correctly', () { + var frame = new Frame.parseVM("#1 Foo._bar " + "(file:///home/nweiz/code/stuff.dart)"); + expect(frame.uri, + equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('Foo._bar')); + }); + test('converts "" to ""', () { String parsedMember(String member) => new Frame.parseVM('#0 $member (foo:0:0)').member; @@ -39,6 +50,18 @@ void main() { equals('..bar')); }); + test('converts "<_async_body>" to ""', () { + var frame = new Frame.parseVM( + '#0 Foo.<_async_body> (foo:0:0)'); + expect(frame.member, equals('Foo.')); + }); + + test('converts "<_async_body>" to ""', () { + var frame = new Frame.parseVM( + '#0 Foo.<_async_body> (foo:0:0)'); + expect(frame.member, equals('Foo.')); + }); + test('parses a folded frame correctly', () { var frame = new Frame.parseVM('...'); @@ -52,8 +75,6 @@ void main() { expect(() => new Frame.parseVM(''), throwsFormatException); expect(() => new Frame.parseVM('#1'), throwsFormatException); expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo (dart:async/future.dart)'), - throwsFormatException); expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), throwsFormatException); expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), From 24fc993688d0f5a4689f479a41f3b85ebf9ae821 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 12 Feb 2015 11:57:07 -0800 Subject: [PATCH 0173/1215] Fold empty async frames when generating a terse stack trace. This avoids having stack chains with a bunch of useless empty frames. R=rnystrom@google.com, kevmoo@google.com Review URL: https://codereview.chromium.org//921553006 --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/trace.dart | 13 ++++++++++++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/trace_test.dart | 14 ++++++++++++++ 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 25abd8a48..edd8ba6ef 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.3 + +* Produce nicer-looking stack chains when using the VM's async/await + implementation. + ## 1.1.2 * Support VM frames without line *or* column numbers, which async/await programs diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 2690ece17..5cd09e9bb 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -205,7 +205,18 @@ class Trace implements StackTrace { /// removed. Trace get terse { return new Trace(foldFrames((frame) { - return frame.isCore || frame.package == 'stack_trace'; + if (frame.isCore) return true; + if (frame.package == 'stack_trace') return true; + + // Ignore async stack frames without any line or column information. These + // come from the VM's async/await implementation and represent internal + // frames. They only ever show up in stack chains and are always + // surrounded by other traces that are actually useful, so we can just get + // rid of them. + // TODO(nweiz): Get rid of this logic some time after issue 22009 is + // fixed. + if (!frame.member.contains('')) return false; + return frame.line == null; }).frames.map((frame) { if (!frame.isCore) return frame; var library = frame.library.replaceAll(_terseRegExp, ''); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 2fee06129..ded96f6ea 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.1.2 +version: 1.1.3 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 17f9c22e9..c8a848bd3 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -283,6 +283,20 @@ dart:async bottom ''')); }); + test('.terse folds empty async frames', () { + var trace = new Trace.parse(''' +#0 notCore (foo.dart:42:21) +#1 top (dart:async/future.dart:0:2) +#2 empty.<_async_body> (bar.dart) +#3 bottom (dart:async-patch/future.dart:9:11) +'''); + + expect(trace.terse.toString(), equals(''' +foo.dart 42:21 notCore +dart:async bottom +''')); + }); + test('.foldFrames folds frames together bottom-up', () { var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) From 0ab2caab5156c0fbab3996ec154ff21b8e86e311 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 17 Feb 2015 13:42:40 -0800 Subject: [PATCH 0174/1215] Add a "terse" argument to foldFrames(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//917423002 --- pkgs/stack_trace/CHANGELOG.md | 6 +++ pkgs/stack_trace/lib/src/chain.dart | 25 ++++------ pkgs/stack_trace/lib/src/trace.dart | 69 ++++++++++++++++----------- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 27 +++++++++++ pkgs/stack_trace/test/trace_test.dart | 20 ++++++++ 6 files changed, 104 insertions(+), 45 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index edd8ba6ef..47bd9b1eb 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.2.0 + +* Add a `terse` argument to `Trace.foldFrames()` and `Chain.foldFrames()`. This + allows them to inherit the behavior of `Trace.terse` and `Chain.terse` without + having to duplicate the logic. + ## 1.1.3 * Produce nicer-looking stack chains when using the VM's async/await diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index f027025be..99726f389 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -136,21 +136,7 @@ class Chain implements StackTrace { /// /// This calls [Trace.terse] on every trace in [traces], and discards any /// trace that contain only internal frames. - Chain get terse { - var terseTraces = traces.map((trace) => trace.terse); - var nonEmptyTraces = terseTraces.where((trace) { - // Ignore traces that contain only internal processing. - return trace.frames.length > 1; - }); - - // If all the traces contain only internal processing, preserve the last - // (top-most) one so that the chain isn't empty. - if (nonEmptyTraces.isEmpty && terseTraces.isNotEmpty) { - return new Chain([terseTraces.last]); - } - - return new Chain(nonEmptyTraces); - } + Chain get terse => foldFrames((_) => false, terse: true); /// Returns a new [Chain] based on [this] where multiple stack frames matching /// [predicate] are folded together. @@ -161,8 +147,13 @@ class Chain implements StackTrace { /// /// This is useful for limiting the amount of library code that appears in a /// stack trace by only showing user code and code that's called by user code. - Chain foldFrames(bool predicate(Frame frame)) { - var foldedTraces = traces.map((trace) => trace.foldFrames(predicate)); + /// + /// If [terse] is true, this will also fold together frames from the core + /// library or from this package, and simplify core library frames as in + /// [Trace.terse]. + Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) { + var foldedTraces = traces.map( + (trace) => trace.foldFrames(predicate, terse: terse)); var nonEmptyTraces = foldedTraces.where((trace) { // Ignore traces that contain only folded frames. These traces will be // folded into a single frame each. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 5cd09e9bb..53dbe33e4 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -203,36 +203,43 @@ class Trace implements StackTrace { /// core library or from this package, as in [foldFrames]. Remaining core /// library frames have their libraries, "-patch" suffixes, and line numbers /// removed. - Trace get terse { - return new Trace(foldFrames((frame) { - if (frame.isCore) return true; - if (frame.package == 'stack_trace') return true; - - // Ignore async stack frames without any line or column information. These - // come from the VM's async/await implementation and represent internal - // frames. They only ever show up in stack chains and are always - // surrounded by other traces that are actually useful, so we can just get - // rid of them. - // TODO(nweiz): Get rid of this logic some time after issue 22009 is - // fixed. - if (!frame.member.contains('')) return false; - return frame.line == null; - }).frames.map((frame) { - if (!frame.isCore) return frame; - var library = frame.library.replaceAll(_terseRegExp, ''); - return new Frame(Uri.parse(library), null, null, frame.member); - })); - } + /// + /// For custom folding, see [foldFrames]. + Trace get terse => foldFrames((_) => false, terse: true); /// Returns a new [Trace] based on [this] where multiple stack frames matching - /// [predicate] are folded together. This means that whenever there are - /// multiple frames in a row that match [predicate], only the last one is - /// kept. + /// [predicate] are folded together. /// - /// This is useful for limiting the amount of library code that appears in a - /// stack trace by only showing user code and code that's called by user code. - Trace foldFrames(bool predicate(Frame frame)) { - var newFrames = []; + /// This means that whenever there are multiple frames in a row that match + /// [predicate], only the last one is kept. This is useful for limiting the + /// amount of library code that appears in a stack trace by only showing user + /// code and code that's called by user code. + /// + /// If [terse] is true, this will also fold together frames from the core + /// library or from this package, and simplify core library frames as in + /// [Trace.terse]. + Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) { + if (terse) { + var oldPredicate = predicate; + predicate = (frame) { + if (oldPredicate(frame)) return true; + + if (frame.isCore) return true; + if (frame.package == 'stack_trace') return true; + + // Ignore async stack frames without any line or column information. + // These come from the VM's async/await implementation and represent + // internal frames. They only ever show up in stack chains and are + // always surrounded by other traces that are actually useful, so we can + // just get rid of them. + // TODO(nweiz): Get rid of this logic some time after issue 22009 is + // fixed. + if (!frame.member.contains('')) return false; + return frame.line == null; + }; + } + + var newFrames = []; for (var frame in frames.reversed) { if (!predicate(frame)) { newFrames.add(frame); @@ -242,6 +249,14 @@ class Trace implements StackTrace { } } + if (terse) { + newFrames = newFrames.map((frame) { + if (!frame.isCore) return frame; + var library = frame.library.replaceAll(_terseRegExp, ''); + return new Frame(Uri.parse(library), null, null, frame.member); + }).toList(); + } + return new Trace(newFrames.reversed); } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ded96f6ea..01b15509f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.1.3 +version: 1.2.0 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 6af3c6b13..54bc5f59e 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -572,6 +572,33 @@ void main() { 'b.dart 10:11 Zop.zoop\n')); }); + test('with terse: true, folds core frames as well', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'dart:async-patch/future.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Bar.baz\n' + 'a.dart 10:11 Zop.zoop'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'a.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart', + terse: true); + expect(folded.toString(), equals( + 'dart:async Zip.zap\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + test('eliminates completely-folded traces', () { var chain = new Chain([ new Trace.parse( diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index c8a848bd3..125ba954a 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -313,6 +313,26 @@ foo.dart 42:21 notFoo foo.dart 1:100 fooBottom bar.dart 10:20 alsoNotFoo dart:async-patch/future.dart 9:11 fooBottom +''')); + }); + + test('.foldFrames with terse: true, folds core frames as well', () { + var trace = new Trace.parse(''' +#0 notFoo (foo.dart:42:21) +#1 fooTop (bar.dart:0:2) +#2 coreBottom (dart:async/future.dart:0:2) +#3 alsoNotFoo (bar.dart:10:20) +#4 fooTop (foo.dart:9:11) +#5 coreBottom (dart:async-patch/future.dart:9:11) +'''); + + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' +foo.dart 42:21 notFoo +dart:async coreBottom +bar.dart 10:20 alsoNotFoo +dart:async coreBottom ''')); }); } From 4d88dd5c4c271d3cf23c1393cf1cd64a53043a78 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 17 Feb 2015 17:13:39 -0800 Subject: [PATCH 0175/1215] Even better stack chains with VM async/await. It turns out the VM can generate frames that have the previous method's name in the <..._async_body> member. R=rnystrom@google.com Review URL: https://codereview.chromium.org//936643002 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 6 +++++- pkgs/stack_trace/lib/src/vm_trace.dart | 5 +++-- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 47bd9b1eb..43d547a7b 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.1 + +* Further improve stack chains when using the VM's async/await implementation. + ## 1.2.0 * Add a `terse` argument to `Trace.foldFrames()` and `Chain.foldFrames()`. This diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8ecd19fb1..c06fd6034 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -57,6 +57,10 @@ final _firefoxSafariFrame = new RegExp( final _friendlyFrame = new RegExp( r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$'); +/// A regular expression that matches asynchronous member names generated by the +/// VM. +final _asyncBody = new RegExp(r'<(|[^>]+)_async_body>'); + final _initialDot = new RegExp(r"^\."); /// A single stack frame. Each frame points to a precise location in Dart code. @@ -137,7 +141,7 @@ class Frame { // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. var member = match[1] - .replaceAll("<_async_body>", "") + .replaceAll(_asyncBody, "") .replaceAll("", ""); var uri = Uri.parse(match[2]); diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 89474f583..79911602a 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -23,8 +23,9 @@ class VMTrace implements StackTrace { return frames.map((frame) { var number = padRight("#${i++}", 8); var member = frame.member - .replaceAll("", "") - .replaceAll("", "<_async_body>"); + .replaceAllMapped(new RegExp(r"[^.]+\."), + (match) => "${match[1]}.<${match[1]}_async_body>") + .replaceAll("", ""); var line = frame.line == null ? 0 : frame.line; var column = frame.column == null ? 0 : frame.column; return "$number$member (${frame.uri}:$line:$column)\n"; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 01b15509f..35c419e78 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.0 +version: 1.2.1-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 638d1d7f6..c2cb80e94 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -56,9 +56,9 @@ void main() { expect(frame.member, equals('Foo.')); }); - test('converts "<_async_body>" to ""', () { + test('converts "" to ""', () { var frame = new Frame.parseVM( - '#0 Foo.<_async_body> (foo:0:0)'); + '#0 Foo. (foo:0:0)'); expect(frame.member, equals('Foo.')); }); From 8502e94aaa0c30da1b912b5bed4b75e9db4fc4ef Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 17 Feb 2015 17:14:29 -0800 Subject: [PATCH 0176/1215] Add terse to LazyTrace.foldFrames(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//937433003 --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/lib/src/lazy_trace.dart | 4 ++-- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 43d547a7b..ddaf22886 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.2.1 +* Add `terse` to `LazyTrace.foldFrames()`. + * Further improve stack chains when using the VM's async/await implementation. ## 1.2.0 diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 874123ef4..21bb67ffa 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -27,8 +27,8 @@ class LazyTrace implements Trace { List get frames => _trace.frames; StackTrace get vmTrace => _trace.vmTrace; Trace get terse => new LazyTrace(() => _trace.terse); - Trace foldFrames(bool predicate(frame)) => - new LazyTrace(() => _trace.foldFrames(predicate)); + Trace foldFrames(bool predicate(frame), {bool terse: false}) => + new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); String toString() => _trace.toString(); // Work around issue 14075. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 35c419e78..1134a703a 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.1-dev +version: 1.2.1 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 512bf3b7b9b8d3e63b8459058f6ca7923746e416 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 27 Feb 2015 12:06:11 -0800 Subject: [PATCH 0177/1215] Remove the outermost folded frame for terse stack traces. R=rnystrom@google.com Review URL: https://codereview.chromium.org//962913002 --- pkgs/stack_trace/CHANGELOG.md | 6 ++++ pkgs/stack_trace/lib/src/chain.dart | 11 +++++-- pkgs/stack_trace/lib/src/trace.dart | 8 +++-- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 5 +-- pkgs/stack_trace/test/trace_test.dart | 46 ++++++++++++++++++++------- 6 files changed, 56 insertions(+), 22 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ddaf22886..403cd65e0 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.2.2 + +* Don't print the first folded frame of terse stack traces. This frame + is always just an internal isolate message handler anyway. This + improves the readability of stack traces, especially in stack chains. + ## 1.2.1 * Add `terse` to `LazyTrace.foldFrames()`. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 99726f389..9555e76fa 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -155,9 +155,14 @@ class Chain implements StackTrace { var foldedTraces = traces.map( (trace) => trace.foldFrames(predicate, terse: terse)); var nonEmptyTraces = foldedTraces.where((trace) { - // Ignore traces that contain only folded frames. These traces will be - // folded into a single frame each. - return trace.frames.length > 1; + // Ignore traces that contain only folded frames. + if (trace.frames.length > 1) return true; + + // In terse mode, the trace may have removed an outer folded frame, + // leaving a single non-folded frame. We can detect a folded frame because + // it has no line information. + if (!terse) return false; + return trace.frames.single.line != null; }); // If all the traces contain only internal processing, preserve the last diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 53dbe33e4..e0cb21be8 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -202,7 +202,8 @@ class Trace implements StackTrace { /// This is accomplished by folding together multiple stack frames from the /// core library or from this package, as in [foldFrames]. Remaining core /// library frames have their libraries, "-patch" suffixes, and line numbers - /// removed. + /// removed. If the outermost frame of the stack trace is a core library + /// frame, it's removed entirely. /// /// For custom folding, see [foldFrames]. Trace get terse => foldFrames((_) => false, terse: true); @@ -216,8 +217,8 @@ class Trace implements StackTrace { /// code and code that's called by user code. /// /// If [terse] is true, this will also fold together frames from the core - /// library or from this package, and simplify core library frames as in - /// [Trace.terse]. + /// library or from this package, simplify core library frames, and + /// potentially remove the outermost frame as in [Trace.terse]. Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) { if (terse) { var oldPredicate = predicate; @@ -255,6 +256,7 @@ class Trace implements StackTrace { var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); }).toList(); + if (newFrames.first.isCore && newFrames.length > 1) newFrames.removeAt(0); } return new Trace(newFrames.reversed); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1134a703a..24acfbcb4 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.1 +version: 1.2.2-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 54bc5f59e..c5f8efb81 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -500,7 +500,6 @@ void main() { expect(chain.terse.toString(), equals( 'dart:core Bar.baz\n' '$userSlashCode 10:11 Bang.qux\n' - 'dart:core Zop.zoop\n' '===== asynchronous gap ===========================\n' '$userSlashCode 10:11 Bang.qux\n' 'dart:core Zip.zap\n' @@ -523,10 +522,8 @@ void main() { expect(chain.terse.toString(), equals( '$userSlashCode 10:11 Foo.bar\n' - 'dart:core Bar.baz\n' '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Foo.bar\n' - 'dart:core Bar.baz\n')); + '$userSlashCode 10:11 Foo.bar\n')); }); test("doesn't return an empty chain", () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 125ba954a..10c931c8b 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -267,33 +267,58 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap test('.terse folds core frames together bottom-up', () { var trace = new Trace.parse(''' -#0 notCore (foo.dart:42:21) #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) -#3 alsoNotCore (bar.dart:10:20) -#4 top (dart:io:5:10) -#5 bottom (dart:async-patch/future.dart:9:11) +#0 notCore (foo.dart:42:21) +#3 top (dart:io:5:10) +#4 bottom (dart:async-patch/future.dart:9:11) +#5 alsoNotCore (bar.dart:10:20) '''); expect(trace.terse.toString(), equals(''' -foo.dart 42:21 notCore dart:core bottom -bar.dart 10:20 alsoNotCore +foo.dart 42:21 notCore dart:async bottom +bar.dart 10:20 alsoNotCore ''')); }); test('.terse folds empty async frames', () { var trace = new Trace.parse(''' +#0 top (dart:async/future.dart:0:2) +#1 empty.<_async_body> (bar.dart) +#2 bottom (dart:async-patch/future.dart:9:11) +#3 notCore (foo.dart:42:21) +'''); + + expect(trace.terse.toString(), equals(''' +dart:async bottom +foo.dart 42:21 notCore +''')); + }); + + test('.terse removes the bottom-most async frame', () { + var trace = new Trace.parse(''' #0 notCore (foo.dart:42:21) #1 top (dart:async/future.dart:0:2) -#2 empty.<_async_body> (bar.dart) -#3 bottom (dart:async-patch/future.dart:9:11) +#2 bottom (dart:core/uri.dart:1:100) +#3 top (dart:io:5:10) +#4 bottom (dart:async-patch/future.dart:9:11) '''); expect(trace.terse.toString(), equals(''' foo.dart 42:21 notCore -dart:async bottom +''')); + }); + + test(".terse won't make a trace empty", () { + var trace = new Trace.parse(''' +#1 top (dart:async/future.dart:0:2) +#2 bottom (dart:core/uri.dart:1:100) +'''); + + expect(trace.terse.toString(), equals(''' +dart:core bottom ''')); }); @@ -316,7 +341,7 @@ dart:async-patch/future.dart 9:11 fooBottom ''')); }); - test('.foldFrames with terse: true, folds core frames as well', () { + test('.foldFrames with terse: true folds core frames as well', () { var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) @@ -332,7 +357,6 @@ dart:async-patch/future.dart 9:11 fooBottom foo.dart 42:21 notFoo dart:async coreBottom bar.dart 10:20 alsoNotFoo -dart:async coreBottom ''')); }); } From ed738f118a1e0865b061eebd0d82ca275b91d9a2 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 27 Feb 2015 13:18:35 -0800 Subject: [PATCH 0178/1215] Remove the line number and file information from *all* folded frames. Previously this was just done for core library frames, but the same logic applies to libraries like unittest where the implementation is irrelevant to user code. R=rnystrom@google.com BUG= Review URL: https://codereview.chromium.org//967633002 --- pkgs/stack_trace/CHANGELOG.md | 3 +++ pkgs/stack_trace/README.md | 13 +++++-------- pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/test/chain_test.dart | 4 ++-- pkgs/stack_trace/test/trace_test.dart | 20 ++++++++++++++++++++ 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 403cd65e0..42c6d8b16 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -4,6 +4,9 @@ is always just an internal isolate message handler anyway. This improves the readability of stack traces, especially in stack chains. +* Remove the line numbers and specific files in all terse folded frames, not + just those from core libraries. + ## 1.2.1 * Add `terse` to `LazyTrace.foldFrames()`. diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 38b768d68..24da03cb7 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -54,7 +54,6 @@ example: pkg/stack_trace/lib/src/trace.dart 40:35 Trace.terse pkg/stack_trace/lib/stack_trace.dart 24:28 format test.dart 21:29 main. - dart:async Timer.Timer. ## Stack Chains @@ -194,14 +193,12 @@ this: test.dart 17:3 runAsync test.dart 13:28 scheduleAsync. - dart:isolate _RawReceivePortImpl._handleMessage ===== asynchronous gap =========================== - dart:async _Future.then - test.dart 13:12 scheduleAsync - test.dart 7:18 main. - package:stack_trace/src/chain.dart 93:20 Chain.capture - test.dart 6:16 main - dart:isolate _RawReceivePortImpl._handleMessage + dart:async _Future.then + test.dart 13:12 scheduleAsync + test.dart 7:18 main. + package:stack_trace Chain.capture + test.dart 6:16 main That's a lot easier to understand! diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index e0cb21be8..954cf453e 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -252,7 +252,7 @@ class Trace implements StackTrace { if (terse) { newFrames = newFrames.map((frame) { - if (!frame.isCore) return frame; + if (!predicate(frame)) return frame; var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); }).toList(); diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index c5f8efb81..cf8a61fa7 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -590,9 +590,9 @@ void main() { expect(folded.toString(), equals( 'dart:async Zip.zap\n' 'b.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zop.zoop\n' + 'a.dart Zop.zoop\n' '===== asynchronous gap ===========================\n' - 'a.dart 10:11 Zip.zap\n' + 'a.dart Zip.zap\n' 'b.dart 10:11 Zop.zoop\n')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 10c931c8b..18875096a 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -357,6 +357,26 @@ dart:async-patch/future.dart 9:11 fooBottom foo.dart 42:21 notFoo dart:async coreBottom bar.dart 10:20 alsoNotFoo +''')); + }); + + test('.foldFrames with terse: true shortens folded frames', () { + var trace = new Trace.parse(''' +#0 notFoo (foo.dart:42:21) +#1 fooTop (bar.dart:0:2) +#2 fooBottom (package:foo/bar.dart:0:2) +#3 alsoNotFoo (bar.dart:10:20) +#4 fooTop (foo.dart:9:11) +#5 fooBottom (foo/bar.dart:9:11) +'''); + + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' +foo.dart 42:21 notFoo +package:foo fooBottom +bar.dart 10:20 alsoNotFoo +foo fooBottom ''')); }); } From 1f4f56723ce06351d5299987cbfa607350056ab1 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 Mar 2015 14:41:43 -0800 Subject: [PATCH 0179/1215] Make padding consistent across all stack traces for Chain.toString(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//963893002 --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/README.md | 32 +++++++++++++-------------- pkgs/stack_trace/lib/src/chain.dart | 24 ++++++++++++++++---- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain_test.dart | 12 ++++++++++ 5 files changed, 51 insertions(+), 21 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 42c6d8b16..aaa409ab4 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -7,6 +7,8 @@ * Remove the line numbers and specific files in all terse folded frames, not just those from core libraries. +* Make padding consistent across all stack traces for `Chain.toString()`. + ## 1.2.1 * Add `terse` to `LazyTrace.foldFrames()`. diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 24da03cb7..fe85adbae 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -169,20 +169,20 @@ Now if we run it, it prints this: dart:io/timer_impl.dart 292 _handleTimeout dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage ===== asynchronous gap =========================== - dart:async/zone.dart 476 _ZoneDelegate.registerUnaryCallback - dart:async/zone.dart 666 _CustomizedZone.registerUnaryCallback - dart:async/future_impl.dart 164 _Future._Future._then - dart:async/future_impl.dart 187 _Future.then - test.dart 13:12 scheduleAsync - test.dart 7:18 main. - dart:async/zone.dart 710 _rootRun - dart:async/zone.dart 440 _ZoneDelegate.run - dart:async/zone.dart 650 _CustomizedZone.run - dart:async/zone.dart 944 runZoned - package:stack_trace/src/chain.dart 93:20 Chain.capture - test.dart 6:16 main - dart:isolate-patch/isolate_patch.dart 216 _startIsolate.isolateStartHandler - dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage + dart:async/zone.dart 476 _ZoneDelegate.registerUnaryCallback + dart:async/zone.dart 666 _CustomizedZone.registerUnaryCallback + dart:async/future_impl.dart 164 _Future._Future._then + dart:async/future_impl.dart 187 _Future.then + test.dart 13:12 scheduleAsync + test.dart 7:18 main. + dart:async/zone.dart 710 _rootRun + dart:async/zone.dart 440 _ZoneDelegate.run + dart:async/zone.dart 650 _CustomizedZone.run + dart:async/zone.dart 944 runZoned + package:stack_trace/src/chain.dart 93:20 Chain.capture + test.dart 6:16 main + dart:isolate-patch/isolate_patch.dart 216 _startIsolate.isolateStartHandler + dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage That's a lot of text! If you look closely, though, you can see that `main` is listed in the first trace in the chain. @@ -191,8 +191,8 @@ Thankfully, you can call `Chain.terse` just like `Trace.terse` to get rid of all the frames you don't care about. The terse version of the stack chain above is this: - test.dart 17:3 runAsync - test.dart 13:28 scheduleAsync. + test.dart 17:3 runAsync + test.dart 13:28 scheduleAsync. ===== asynchronous gap =========================== dart:async _Future.then test.dart 13:12 scheduleAsync diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 9555e76fa..03dbed63f 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -6,6 +6,7 @@ library stack_trace.chain; import 'dart:async'; import 'dart:collection'; +import 'dart:math' as math; import 'frame.dart'; import 'stack_zone_specification.dart'; @@ -15,6 +16,10 @@ import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. typedef void ChainHandler(error, Chain chain); +/// The line used in the string representation of stack chains to represent +/// the gap between traces. +const _gap = '===== asynchronous gap ===========================\n'; + /// A chain of stack traces. /// /// A stack chain is a collection of one or more stack traces that collectively @@ -36,9 +41,6 @@ typedef void ChainHandler(error, Chain chain); /// "$stackChain"); /// }); class Chain implements StackTrace { - /// The line used in the string representation of stack chains to represent - /// the gap between traces. - static const _GAP = '===== asynchronous gap ===========================\n'; /// The stack traces that make up this chain. /// @@ -180,5 +182,19 @@ class Chain implements StackTrace { /// in the chain. Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames))); - String toString() => traces.join(_GAP); + String toString() { + // Figure out the longest path so we know how much to pad. + var longest = traces.map((trace) { + return trace.frames.map((frame) => frame.location.length) + .fold(0, math.max); + }).fold(0, math.max); + + // Don't call out to [Trace.toString] here because that doesn't ensure that + // padding is consistent across all traces. + return traces.map((trace) { + return trace.frames.map((frame) { + return '${padRight(frame.location, longest)} ${frame.member}\n'; + }).join(); + }).join(_gap); + } } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 24acfbcb4..1ac6caf09 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.2-dev +version: 1.2.2 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index cf8a61fa7..bfe322ce2 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -479,6 +479,18 @@ void main() { }); }); + test("toString() ensures that all traces are aligned", () { + var chain = new Chain([ + new Trace.parse('short 10:11 Foo.bar\n'), + new Trace.parse('loooooooooooong 10:11 Zop.zoop') + ]); + + expect(chain.toString(), equals( + 'short 10:11 Foo.bar\n' + '===== asynchronous gap ===========================\n' + 'loooooooooooong 10:11 Zop.zoop\n')); + }); + var userSlashCode = p.join('user', 'code.dart'); group('Chain.terse', () { test('makes each trace terse', () { From 9cc998453b91a41c565179b9309e97721bcc5abd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 Mar 2015 16:33:04 -0800 Subject: [PATCH 0180/1215] Fix a lingering reference to _GAP in chain.dart. R=rnystrom@google.com Review URL: https://codereview.chromium.org//969933002 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index aaa409ab4..9e31d68a6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.3 + +* Fix a crash in `Chain.parse`. + ## 1.2.2 * Don't print the first folded frame of terse stack traces. This frame diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 03dbed63f..87cc6be99 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -128,7 +128,7 @@ class Chain implements StackTrace { /// /// Specifically, this parses the output of [Chain.toString]. factory Chain.parse(String chain) => - new Chain(chain.split(_GAP).map((trace) => new Trace.parseFriendly(trace))); + new Chain(chain.split(_gap).map((trace) => new Trace.parseFriendly(trace))); /// Returns a new [Chain] comprised of [traces]. Chain(Iterable traces) From 5a0d0028520133263251602ab40dc4c3c0dfa72b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 Mar 2015 16:33:45 -0800 Subject: [PATCH 0181/1215] Update pubspec version. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1ac6caf09..499b27e83 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.2 +version: 1.2.3 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 674e2ef7714860d02181bc95537a075d8c508f5f Mon Sep 17 00:00:00 2001 From: Vijay Menon Date: Mon, 9 Mar 2015 12:51:59 -0700 Subject: [PATCH 0182/1215] Fix type mismatch This is tripping in DDC. Trace and LazyTrace did not match. R=nweiz@google.com Review URL: https://codereview.chromium.org/992703002/ --- pkgs/stack_trace/lib/src/lazy_trace.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 21bb67ffa..6bfe51c73 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -27,7 +27,7 @@ class LazyTrace implements Trace { List get frames => _trace.frames; StackTrace get vmTrace => _trace.vmTrace; Trace get terse => new LazyTrace(() => _trace.terse); - Trace foldFrames(bool predicate(frame), {bool terse: false}) => + Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) => new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); String toString() => _trace.toString(); From e60beacd9ce78aa065c296738b6de35c1dca1d3b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 9 Mar 2015 12:53:17 -0700 Subject: [PATCH 0183/1215] Update version and add CHANGELOG entry. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 9e31d68a6..53f5cd1ce 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.4 + +* Fix a type annotation in `LazyTrace`. + ## 1.2.3 * Fix a crash in `Chain.parse`. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 499b27e83..296cd2c7e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.3 +version: 1.2.4 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From da5d8d338bb564ddb435ef789e6d1c02f279ee8b Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 Mar 2015 12:47:52 -0700 Subject: [PATCH 0184/1215] Fix bugs where events could be added after watchers were closed. R=rnystrom@google.com BUG=dartbug.com/22653 Review URL: https://codereview.chromium.org//995623002 --- pkgs/watcher/CHANGELOG.md | 4 ++++ .../lib/src/directory_watcher/linux.dart | 2 +- .../lib/src/directory_watcher/mac_os.dart | 22 +++++++++++++------ pkgs/watcher/pubspec.yaml | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 2ff887ebe..77729800c 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.5 + +* Fix bugs where events could be added after watchers were closed. + # 0.9.4 * Treat add events for known files as modifications instead of discarding them diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 76558dd27..870faa760 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -134,7 +134,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (isReady) _eventsController.add(event); }, onError: (error, stackTrace) { _eventsController.addError(error, stackTrace); - _eventsController.close(); + close(); }, onDone: () { if (_subWatchers[path] == watcher) _subWatchers.remove(path); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index ee2013665..c242c75da 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -69,9 +69,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// the directory to determine its initial state. StreamSubscription _initialListSubscription; - /// The subscription to the [Directory.list] call for listing the contents of - /// a subdirectory that was moved into the watched directory. - StreamSubscription _listSubscription; + /// The subscriptions to [Directory.list] calls for listing the contents of a + /// subdirectory that was moved into the watched directory. + final _listSubscriptions = new Set>(); /// The timer for tracking how long we wait for an initial batch of bogus /// events (see issue 14373). @@ -113,10 +113,14 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } if (_watchSubscription != null) _watchSubscription.cancel(); if (_initialListSubscription != null) _initialListSubscription.cancel(); - if (_listSubscription != null) _listSubscription.cancel(); _watchSubscription = null; _initialListSubscription = null; - _listSubscription = null; + + for (var subscription in _listSubscriptions) { + subscription.cancel(); + } + _listSubscriptions.clear(); + _eventsController.close(); } @@ -194,8 +198,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (_files.containsDir(path)) continue; - var stream = Chain.track(new Directory(path).list(recursive: true)); - _listSubscription = stream.listen((entity) { + var subscription; + subscription = Chain.track(new Directory(path).list(recursive: true)) + .listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -206,7 +211,10 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { print("[$_id] got error listing $relativePath: $e"); } _emitError(e, stackTrace); + }, onDone: () { + _listSubscriptions.remove(subscription); }, cancelOnError: true); + _listSubscriptions.add(subscription); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); _emitEvent(ChangeType.MODIFY, path); diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index c0c71eb1a..a16a0200e 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.4 +version: 0.9.5 author: Dart Team homepage: http://github.com/dart-lang/watcher description: > From 4b44fc699fbc491bec33efa44da5fe1656a3cb55 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 30 Mar 2015 15:20:46 -0700 Subject: [PATCH 0185/1215] code format, expanded dependency constraint on unittest, removed unused variable fixed homepage URL R=nweiz@google.com Review URL: https://codereview.chromium.org//1045533002 --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/lib/src/line_scanner.dart | 9 ++++----- pkgs/string_scanner/lib/src/string_scanner.dart | 4 ++-- pkgs/string_scanner/lib/src/utils.dart | 2 +- pkgs/string_scanner/pubspec.yaml | 6 +++--- pkgs/string_scanner/test/error_test.dart | 15 +++++++++------ pkgs/string_scanner/test/string_scanner_test.dart | 4 ++-- 7 files changed, 25 insertions(+), 19 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 9c03874dc..ce1e01212 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.3+1 + +* Fixed the homepage URL. + ## 0.1.3 * Add an optional `endState` argument to `SpanScanner.spanFrom`. diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 4e1217305..54ecf7bf9 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -40,8 +40,8 @@ class LineScanner extends StringScanner { super.position = newPosition; if (newPosition > oldPosition) { - var newlines = "\n".allMatches(string.substring(oldPosition, newPosition)) - .toList(); + var newlines = + "\n".allMatches(string.substring(oldPosition, newPosition)).toList(); _line += newlines.length; if (newlines.isEmpty) { _column += newPosition - oldPosition; @@ -49,8 +49,8 @@ class LineScanner extends StringScanner { _column = newPosition - newlines.last.end; } } else { - var newlines = "\n".allMatches(string.substring(newPosition, oldPosition)) - .toList(); + var newlines = + "\n".allMatches(string.substring(newPosition, oldPosition)).toList(); _line -= newlines.length; if (newlines.isEmpty) { _column -= oldPosition - newPosition; @@ -75,7 +75,6 @@ class LineScanner extends StringScanner { } bool scan(Pattern pattern) { - var oldPosition = position; if (!super.scan(pattern)) return false; var newlines = "\n".allMatches(lastMatch[0]).toList(); diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index bc5e1f58d..d9c1c2fd3 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -107,8 +107,8 @@ class StringScanner { if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); name = "/$source/"; } else { - name = pattern.toString() - .replaceAll("\\", "\\\\").replaceAll('"', '\\"'); + name = + pattern.toString().replaceAll("\\", "\\\\").replaceAll('"', '\\"'); name = '"$name"'; } } diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index e556236e8..107c4c52e 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -27,4 +27,4 @@ void validateErrorArgs(String string, Match match, int position, int length) { throw new RangeError("position plus length must not go beyond the end of " "the string."); } -} \ No newline at end of file +} diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 2a712b8cc..ffd4ccc2a 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,13 +1,13 @@ name: string_scanner -version: 0.1.3 +version: 0.1.3+1 author: "Dart Team " -homepage: http://github.com/dart-lang/string_scanner +homepage: https://github.com/dart-lang/string_scanner description: > A class for parsing strings using a sequence of patterns. dependencies: path: ">=1.2.0 <2.0.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: - unittest: ">=0.10.0 <0.11.0" + unittest: ">=0.10.0 <0.12.0" environment: sdk: ">=1.2.0 <2.0.0" diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index 4fe9083df..d7b81e812 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -28,7 +28,8 @@ void main() { }); test('supports a match on a previous line', () { - var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = + new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo '); scanner.expect('re'); var match = scanner.lastMatch; @@ -38,7 +39,8 @@ void main() { }); test('supports a multiline match', () { - var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = + new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar '); scanner.expect('baz\ndo'); var match = scanner.lastMatch; @@ -81,14 +83,16 @@ void main() { }); test('supports a position on a previous line', () { - var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = + new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 15, length: 2), throwsStringScannerException('re')); }); test('supports a multiline length', () { - var scanner = new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = + new StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 8, length: 8), throwsStringScannerException('baz\ndo r')); @@ -121,8 +125,7 @@ void main() { }); test("if match is passed with length", () { - expect( - () => scanner.error("oh no!", match: scanner.lastMatch, length: 1), + expect(() => scanner.error("oh no!", match: scanner.lastMatch, length: 1), throwsArgumentError); }); diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index fcd904aba..7b00796ce 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -330,8 +330,8 @@ void main() { }); test('throws an ArgumentError if the position is beyond the string', () { - expect(() => new StringScanner('foo bar', position: 8), - throwsArgumentError); + expect( + () => new StringScanner('foo bar', position: 8), throwsArgumentError); }); }); } From 5b5a4482619289945be8ba3eaea95ef453559962 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 13 Apr 2015 16:27:24 -0700 Subject: [PATCH 0186/1215] Support JavaScriptCore stack traces. R=kevmoo@google.com Review URL: https://codereview.chromium.org//1062123003 --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/frame.dart | 3 +++ pkgs/stack_trace/lib/src/trace.dart | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/trace_test.dart | 17 +++++++++++++++++ 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 53f5cd1ce..57ff590e0 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.3.0 + +* Support stack traces generated by JavaScriptCore. They can be explicitly + parsed via `new Trace.parseJSCore` and `new Frame.parseJSCore`. + ## 1.2.4 * Fix a type annotation in `LazyTrace`. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index c06fd6034..9043d2baa 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -195,6 +195,9 @@ class Frame { } } + /// Parses a string representation of a JavaScriptCore stack trace. + factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame); + /// Parses a string representation of an IE stack frame. /// /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 954cf453e..bf26c5175 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -115,6 +115,7 @@ class Trace implements StackTrace { try { if (trace.isEmpty) return new Trace([]); if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); + if (trace.startsWith("\tat ")) return new Trace.parseJSCore(trace); if (trace.contains(_firefoxSafariTrace)) { return new Trace.parseFirefox(trace); } @@ -147,6 +148,10 @@ class Trace implements StackTrace { .skipWhile((line) => !line.startsWith(_v8TraceLine)) .map((line) => new Frame.parseV8(line))); + /// Parses a string representation of a JavaScriptCore stack trace. + Trace.parseJSCore(String trace) + : this(trace.split("\n").map((line) => new Frame.parseV8(line))); + /// Parses a string representation of an Internet Explorer stack trace. /// /// IE10+ traces look just like V8 traces. Prior to IE10, stack traces can't diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 296cd2c7e..912fbd7f7 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.2.4 +version: 1.3.0 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 18875096a..e8f749a22 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -92,6 +92,23 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); + // JavaScriptCore traces are just like V8, except that it doesn't have a + // header and it starts with a tab rather than spaces. + test('parses a JavaScriptCore stack trace correctly', () { + var trace = new Trace.parse( + '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + '\tat http://pub.dartlang.org/stuff.js:0:2\n' + '\tat zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + }); + test('parses a Firefox/Safari stack trace correctly', () { var trace = new Trace.parse( 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' From 8f5c9a384d8f812f60a39e3ce238a54e270e614f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 13 Apr 2015 17:20:09 -0700 Subject: [PATCH 0187/1215] Support more types of JavaScriptCore stack frames. R=kevmoo@google.com Review URL: https://codereview.chromium.org//1080083004 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/trace.dart | 4 +++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/trace_test.dart | 11 +++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 57ff590e0..29b0527d8 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +* Support more types of JavaScriptCore stack frames. + ## 1.3.0 * Support stack traces generated by JavaScriptCore. They can be explicitly diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index bf26c5175..2fce0c7c3 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -150,7 +150,9 @@ class Trace implements StackTrace { /// Parses a string representation of a JavaScriptCore stack trace. Trace.parseJSCore(String trace) - : this(trace.split("\n").map((line) => new Frame.parseV8(line))); + : this(trace.split("\n") + .where((line) => line != "\tat ") + .map((line) => new Frame.parseV8(line))); /// Parses a string representation of an Internet Explorer stack trace. /// diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 912fbd7f7..85dfe45cc 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.0 +version: 1.3.1 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index e8f749a22..249e9f6f2 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -107,6 +107,17 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + '\tat \n' + '\tat zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); }); test('parses a Firefox/Safari stack trace correctly', () { From 5a21d30702bbccbdccb9e53004bf9ceffa8ec5b0 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 20 Apr 2015 20:30:43 -0700 Subject: [PATCH 0188/1215] Initial commit. --- pkgs/test_reflective_loader/.gitignore | 8 ++ pkgs/test_reflective_loader/.status | 4 + pkgs/test_reflective_loader/AUTHORS | 6 + pkgs/test_reflective_loader/CHANGELOG.md | 5 + pkgs/test_reflective_loader/CONTRIBUTING.md | 33 +++++ pkgs/test_reflective_loader/LICENSE | 26 ++++ pkgs/test_reflective_loader/README.md | 26 ++++ .../lib/test_reflective_loader.dart | 121 ++++++++++++++++++ pkgs/test_reflective_loader/pubspec.yaml | 11 ++ 9 files changed, 240 insertions(+) create mode 100644 pkgs/test_reflective_loader/.gitignore create mode 100644 pkgs/test_reflective_loader/.status create mode 100644 pkgs/test_reflective_loader/AUTHORS create mode 100644 pkgs/test_reflective_loader/CHANGELOG.md create mode 100644 pkgs/test_reflective_loader/CONTRIBUTING.md create mode 100644 pkgs/test_reflective_loader/LICENSE create mode 100644 pkgs/test_reflective_loader/README.md create mode 100644 pkgs/test_reflective_loader/lib/test_reflective_loader.dart create mode 100644 pkgs/test_reflective_loader/pubspec.yaml diff --git a/pkgs/test_reflective_loader/.gitignore b/pkgs/test_reflective_loader/.gitignore new file mode 100644 index 000000000..89f7747cd --- /dev/null +++ b/pkgs/test_reflective_loader/.gitignore @@ -0,0 +1,8 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +pubspec.lock diff --git a/pkgs/test_reflective_loader/.status b/pkgs/test_reflective_loader/.status new file mode 100644 index 000000000..364ca4b46 --- /dev/null +++ b/pkgs/test_reflective_loader/.status @@ -0,0 +1,4 @@ +# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +# 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. + diff --git a/pkgs/test_reflective_loader/AUTHORS b/pkgs/test_reflective_loader/AUTHORS new file mode 100644 index 000000000..0b1c48aa2 --- /dev/null +++ b/pkgs/test_reflective_loader/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. scheglov@google.com diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md new file mode 100644 index 000000000..2a2d63cf8 --- /dev/null +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.0.1 + +- Initial version diff --git a/pkgs/test_reflective_loader/CONTRIBUTING.md b/pkgs/test_reflective_loader/CONTRIBUTING.md new file mode 100644 index 000000000..6f5e0ea67 --- /dev/null +++ b/pkgs/test_reflective_loader/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/test_reflective_loader/LICENSE b/pkgs/test_reflective_loader/LICENSE new file mode 100644 index 000000000..de31e1a0a --- /dev/null +++ b/pkgs/test_reflective_loader/LICENSE @@ -0,0 +1,26 @@ +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md new file mode 100644 index 000000000..cbc7e632c --- /dev/null +++ b/pkgs/test_reflective_loader/README.md @@ -0,0 +1,26 @@ +# test_reflective_loader + +Support for discovering tests and test suites using reflection. + +It follows the xUnit style where each class is a test suite, and each method +with the name prefix "test_" is a single text. + +Methods with names starting with "test_" are are run using test() function with +the corresponding name. If the class defines methods setUp() or tearDown(), +they are executed before / after each test correspondingly, even the test fails. + +Methods with names starting with "solo_test_" are run using solo_test() function. + +Methods with names starting with "fail_" are expected to fail. + +Methods with names starting with "solo_fail_" are run using solo_test() function +and expected to fail. + +Method returning Future class instances are asynchronous, so tearDown() is +executed after the returned Future completes. + +## Features and bugs + +Please file feature requests and bugs at the [issue tracker][tracker]. + +[tracker]: https://github.com/dart-lang/test_reflective_loader/issues diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart new file mode 100644 index 000000000..6ea195ad1 --- /dev/null +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -0,0 +1,121 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library test_reflective_loader; + +@MirrorsUsed(metaTargets: 'ReflectiveTest') +import 'dart:mirrors'; +import 'dart:async'; + +import 'package:unittest/unittest.dart'; + +/** + * Runs test methods existing in the given [type]. + * + * Methods with names starting with `test` are run using [test] function. + * Methods with names starting with `solo_test` are run using [solo_test] function. + * + * Each method is run with a new instance of [type]. + * So, [type] should have a default constructor. + * + * If [type] declares method `setUp`, it methods will be invoked before any test + * method invocation. + * + * If [type] declares method `tearDown`, it will be invoked after any test + * method invocation. If method returns [Future] to test some asyncronous + * behavior, then `tearDown` will be invoked in `Future.complete`. + */ +void runReflectiveTests(Type type) { + ClassMirror classMirror = reflectClass(type); + if (!classMirror.metadata.any((InstanceMirror annotation) => + annotation.type.reflectedType == ReflectiveTest)) { + String name = MirrorSystem.getName(classMirror.qualifiedName); + throw new Exception('Class $name must have annotation "@reflectiveTest" ' + 'in order to be run by runReflectiveTests.'); + } + String className = MirrorSystem.getName(classMirror.simpleName); + group(className, () { + classMirror.instanceMembers.forEach((symbol, memberMirror) { + // we need only methods + if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) { + return; + } + String memberName = MirrorSystem.getName(symbol); + // test_ + if (memberName.startsWith('test_')) { + test(memberName, () { + return _runTest(classMirror, symbol); + }); + return; + } + // solo_test_ + if (memberName.startsWith('solo_test_')) { + solo_test(memberName, () { + return _runTest(classMirror, symbol); + }); + } + // fail_test_ + if (memberName.startsWith('fail_')) { + test(memberName, () { + return _runFailingTest(classMirror, symbol); + }); + } + // solo_fail_test_ + if (memberName.startsWith('solo_fail_')) { + solo_test(memberName, () { + return _runFailingTest(classMirror, symbol); + }); + } + }); + }); +} + +Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { + var invocationResult = null; + try { + invocationResult = instanceMirror.invoke(symbol, []).reflectee; + } on NoSuchMethodError {} + if (invocationResult is Future) { + return invocationResult; + } else { + return new Future.value(invocationResult); + } +} + +/** + * Run a test that is expected to fail, and confirm that it fails. + * + * This properly handles the following cases: + * - The test fails by throwing an exception + * - The test returns a future which completes with an error. + * + * However, it does not handle the case where the test creates an asynchronous + * callback using expectAsync(), and that callback generates a failure. + */ +Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { + return new Future(() => _runTest(classMirror, symbol)).then((_) { + fail('Test passed - expected to fail.'); + }, onError: (_) {}); +} + +_runTest(ClassMirror classMirror, Symbol symbol) { + InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); + return _invokeSymbolIfExists(instanceMirror, #setUp) + .then((_) => instanceMirror.invoke(symbol, []).reflectee) + .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); +} + +/** + * A marker annotation used to instruct dart2js to keep reflection information + * for the annotated classes. + */ +class ReflectiveTest { + const ReflectiveTest(); +} + +/** + * A marker annotation used to instruct dart2js to keep reflection information + * for the annotated classes. + */ +const ReflectiveTest reflectiveTest = const ReflectiveTest(); diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml new file mode 100644 index 000000000..b741dfcb3 --- /dev/null +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -0,0 +1,11 @@ +name: test_reflective_loader +version: 0.0.1 +description: Support for discovering tests and test suites using reflection. +author: Dart Team +homepage: https://github.com/dart-lang/test_reflective_loader + +environment: + sdk: '>=1.0.0 <2.0.0' + +dev_dependencies: + unittest: '>=0.9.0 <0.12.0' From b579ec016234986ed4e1e6d1a7343be8259b00e2 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 20 Apr 2015 21:15:46 -0700 Subject: [PATCH 0189/1215] Update AUTHORS Update the AUTHORS file --- pkgs/test_reflective_loader/AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/AUTHORS b/pkgs/test_reflective_loader/AUTHORS index 0b1c48aa2..e8063a8cd 100644 --- a/pkgs/test_reflective_loader/AUTHORS +++ b/pkgs/test_reflective_loader/AUTHORS @@ -3,4 +3,4 @@ # # Name/Organization -Google Inc. scheglov@google.com +Google Inc. From 4dfedd10086fe9fa0b28526e47d7eb43b3cc9d89 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 20 Apr 2015 21:31:43 -0700 Subject: [PATCH 0190/1215] Update version before publishing. --- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index b741dfcb3..d1c014eb3 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.0.1 +version: 0.0.2 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From 963318473007032f902c3b06732fdda574b0b609 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 20 Apr 2015 21:35:14 -0700 Subject: [PATCH 0191/1215] Update README.md --- pkgs/test_reflective_loader/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index cbc7e632c..e65e6fc90 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -2,22 +2,22 @@ Support for discovering tests and test suites using reflection. -It follows the xUnit style where each class is a test suite, and each method -with the name prefix "test_" is a single text. +This package follows the xUnit style where each class is a test suite, and each +method with the name prefix `test_` is a single test. -Methods with names starting with "test_" are are run using test() function with -the corresponding name. If the class defines methods setUp() or tearDown(), -they are executed before / after each test correspondingly, even the test fails. +Methods with names starting with `test_` are run using the `test()` function with +the corresponding name. If the class defines methods `setUp()` or `tearDown()`, +they are executed before / after each test correspondingly, even if the test fails. -Methods with names starting with "solo_test_" are run using solo_test() function. +Methods with names starting with `solo_test_` are run using the `solo_test()` function. -Methods with names starting with "fail_" are expected to fail. +Methods with names starting with `fail_` are expected to fail. -Methods with names starting with "solo_fail_" are run using solo_test() function +Methods with names starting with `solo_fail_` are run using the `solo_test()` function and expected to fail. -Method returning Future class instances are asynchronous, so tearDown() is -executed after the returned Future completes. +Method returning `Future` class instances are asynchronous, so `tearDown()` is +executed after the returned `Future` completes. ## Features and bugs From 76b8c7596d5378c24d0901da7f9589609cbc28cb Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Wed, 22 Apr 2015 12:24:18 -0700 Subject: [PATCH 0192/1215] Rename runReflectiveTests -> defineReflectiveTests. --- pkgs/test_reflective_loader/.gitignore | 1 + .../lib/test_reflective_loader.dart | 12 ++++++------ pkgs/test_reflective_loader/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pkgs/test_reflective_loader/.gitignore b/pkgs/test_reflective_loader/.gitignore index 89f7747cd..65b96beca 100644 --- a/pkgs/test_reflective_loader/.gitignore +++ b/pkgs/test_reflective_loader/.gitignore @@ -2,6 +2,7 @@ .DS_Store .idea .pub/ +.project .settings/ build/ packages diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 6ea195ad1..f8387e34c 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -11,7 +11,7 @@ import 'dart:async'; import 'package:unittest/unittest.dart'; /** - * Runs test methods existing in the given [type]. + * Define tests using methods existing in the given [type]. * * Methods with names starting with `test` are run using [test] function. * Methods with names starting with `solo_test` are run using [solo_test] function. @@ -26,13 +26,13 @@ import 'package:unittest/unittest.dart'; * method invocation. If method returns [Future] to test some asyncronous * behavior, then `tearDown` will be invoked in `Future.complete`. */ -void runReflectiveTests(Type type) { +void defineReflectiveTests(Type type) { ClassMirror classMirror = reflectClass(type); if (!classMirror.metadata.any((InstanceMirror annotation) => - annotation.type.reflectedType == ReflectiveTest)) { + annotation.type.reflectedType == ReflectiveTest)) { String name = MirrorSystem.getName(classMirror.qualifiedName); throw new Exception('Class $name must have annotation "@reflectiveTest" ' - 'in order to be run by runReflectiveTests.'); + 'in order to be run by runReflectiveTests.'); } String className = MirrorSystem.getName(classMirror.simpleName); group(className, () { @@ -102,8 +102,8 @@ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { _runTest(ClassMirror classMirror, Symbol symbol) { InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); return _invokeSymbolIfExists(instanceMirror, #setUp) - .then((_) => instanceMirror.invoke(symbol, []).reflectee) - .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); + .then((_) => instanceMirror.invoke(symbol, []).reflectee) + .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); } /** diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index d1c014eb3..60d4ec8d0 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.0.2 +version: 0.0.3 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From 176220ab54def3d5d2ea96a5c811fbc7f637b56e Mon Sep 17 00:00:00 2001 From: Winston Ewert Date: Mon, 27 Apr 2015 10:55:41 -0700 Subject: [PATCH 0193/1215] Handles empty traces. Previously .terse() would die if it processes an empty stack trace. --- pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/test/trace_test.dart | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 2fce0c7c3..84a19ef22 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -263,7 +263,7 @@ class Trace implements StackTrace { var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); }).toList(); - if (newFrames.first.isCore && newFrames.length > 1) newFrames.removeAt(0); + if (newFrames.length > 1 && newFrames.first.isCore) newFrames.removeAt(0); } return new Trace(newFrames.reversed); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 249e9f6f2..7fb9b5b19 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -350,6 +350,14 @@ dart:core bottom ''')); }); + test(".terse won't panic on an empty trace", () { + var trace = new Trace.parse(''' +'''); + + expect(trace.terse.toString(), equals(''' +''')); + }); + test('.foldFrames folds frames together bottom-up', () { var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) From 29b9fd42485f3510f8952f42fbe49ecee6922623 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 27 Apr 2015 16:26:35 -0700 Subject: [PATCH 0194/1215] Bump version to 1.3.2. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 29b0527d8..665eb30ff 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.2 + +* Don't crash when running `Trace.terse` on empty stack traces. + ## 1.3.1 * Support more types of JavaScriptCore stack frames. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 85dfe45cc..bc3bc8d61 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.1 +version: 1.3.2 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From f0ca3ad921efe27742384f69dddd32ffdbf625b3 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jun 2015 12:14:40 -0700 Subject: [PATCH 0195/1215] Fix an edge case with nested Chain.capture blocks. Specifically, when a null stack trace is passed to a completer or stream controller in nested Chain.capture blocks, substitute the inner block's chain rather than the outer block's. This is consistent with other nested capture behavior, and it's useful for migrating to the new test runner. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1171863002. --- pkgs/stack_trace/CHANGELOG.md | 6 ++++++ pkgs/stack_trace/lib/src/stack_zone_specification.dart | 9 ++------- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 665eb30ff..d4696eca5 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.3.3 + +* When a `null` stack trace is passed to a completer or stream controller in + nested `Chain.capture()` blocks, substitute the inner block's chain rather + than the outer block's. + ## 1.3.2 * Don't crash when running `Trace.terse` on empty stack traces. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 0c1c7d228..25d964271 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -172,12 +172,6 @@ class StackZoneSpecification { /// necessary. AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace) { - var asyncError = parent.errorCallback(zone, error, stackTrace); - if (asyncError != null) { - error = asyncError.error; - stackTrace = asyncError.stackTrace; - } - // Go up two levels to get through [_CustomZone.errorCallback]. if (stackTrace == null) { stackTrace = _createNode(2).toChain(); @@ -185,7 +179,8 @@ class StackZoneSpecification { if (_chains[stackTrace] == null) _chains[stackTrace] = _createNode(2); } - return new AsyncError(error, stackTrace); + var asyncError = parent.errorCallback(zone, error, stackTrace); + return asyncError == null ? new AsyncError(error, stackTrace) : asyncError; } /// Creates a [_Node] with the current stack trace and linked to diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index bc3bc8d61..f69417d71 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.2 +version: 1.3.3-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 439d99816cacdbe8fbe1ba514d541cdbc20ca9cd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jun 2015 12:15:48 -0700 Subject: [PATCH 0196/1215] Support parsing empty stack chains. Closes dart-lang/stack_trace#4 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1171873002. --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/lib/src/chain.dart | 7 +++++-- pkgs/stack_trace/lib/src/trace.dart | 10 ++++++---- pkgs/stack_trace/test/chain_test.dart | 26 ++++++++++++++++++++++---- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index d4696eca5..8615187f9 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -4,6 +4,8 @@ nested `Chain.capture()` blocks, substitute the inner block's chain rather than the outer block's. +* Add support for empty chains and chains of empty traces to `Chain.parse()`. + ## 1.3.2 * Don't crash when running `Trace.terse` on empty stack traces. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 87cc6be99..3e2100e46 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -127,8 +127,11 @@ class Chain implements StackTrace { /// Parses a string representation of a stack chain. /// /// Specifically, this parses the output of [Chain.toString]. - factory Chain.parse(String chain) => - new Chain(chain.split(_gap).map((trace) => new Trace.parseFriendly(trace))); + factory Chain.parse(String chain) { + if (chain.isEmpty) return new Chain([]); + return new Chain( + chain.split(_gap).map((trace) => new Trace.parseFriendly(trace))); + } /// Returns a new [Chain] comprised of [traces]. Chain(Iterable traces) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 84a19ef22..418c4ab3e 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -188,10 +188,12 @@ class Trace implements StackTrace { /// This also parses string representations of [Chain]s. They parse to the /// same trace that [Chain.toTrace] would return. Trace.parseFriendly(String trace) - : this(trace.trim().split("\n") - // Filter out asynchronous gaps from [Chain]s. - .where((line) => !line.startsWith('=====')) - .map((line) => new Frame.parseFriendly(line))); + : this(trace.isEmpty + ? [] + : trace.trim().split("\n") + // Filter out asynchronous gaps from [Chain]s. + .where((line) => !line.startsWith('=====')) + .map((line) => new Frame.parseFriendly(line))); /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index bfe322ce2..0b6f36e38 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -472,10 +472,28 @@ void main() { equals(new Trace.from(trace).toString())); }); - test('Chain.parse() parses a real Chain', () { - return captureFuture(() => inMicrotask(() => throw 'error')).then((chain) { - expect(new Chain.parse(chain.toString()).toString(), - equals(chain.toString())); + group('Chain.parse()', () { + test('parses a real Chain', () { + return captureFuture(() => inMicrotask(() => throw 'error')) + .then((chain) { + expect(new Chain.parse(chain.toString()).toString(), + equals(chain.toString())); + }); + }); + + test('parses an empty string', () { + var chain = new Chain.parse(''); + expect(chain.traces, isEmpty); + }); + + test('parses a chain containing empty traces', () { + var chain = new Chain.parse( + '===== asynchronous gap ===========================\n' + '===== asynchronous gap ===========================\n'); + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames, isEmpty); + expect(chain.traces[1].frames, isEmpty); + expect(chain.traces[2].frames, isEmpty); }); }); From 292b0e00e2b083a8aa32bd231428ac616c40c379 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jun 2015 12:58:34 -0700 Subject: [PATCH 0197/1215] Use the new test package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1172523003. --- pkgs/stack_trace/.status | 23 ---------------------- pkgs/stack_trace/pubspec.yaml | 6 +++--- pkgs/stack_trace/test/chain_test.dart | 28 ++++++++++++++++----------- pkgs/stack_trace/test/frame_test.dart | 2 +- pkgs/stack_trace/test/trace_test.dart | 2 +- pkgs/stack_trace/test/utils.dart | 2 +- pkgs/stack_trace/test/vm_test.dart | 3 ++- 7 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 pkgs/stack_trace/.status diff --git a/pkgs/stack_trace/.status b/pkgs/stack_trace/.status deleted file mode 100644 index 56ba102fe..000000000 --- a/pkgs/stack_trace/.status +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -# 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. - -# Skip non-test files ending with "_test". -packages/*: Skip -*/packages/*: Skip -*/*/packages/*: Skip -*/*/*/packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip - -# Only run tests from the build directory, since we don't care about the -# difference between transformed an untransformed code. -test/*: Skip - -[ $runtime == d8 || $runtime == jsshell ] -build/test/chain_test: Fail # Issues 15171 and 15105 -build/test/vm_test: RuntimeError, OK # VM-specific traces - -[ $compiler == dart2js && $browser ] -build/test/vm_test: Fail, OK # VM-specific traces -build/test/chain_test: Fail # Issues 15171 and 15105 diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index f69417d71..9b8413d24 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -14,9 +14,9 @@ description: > A package for manipulating stack traces and printing them readably. dependencies: - path: ">=1.2.0 <2.0.0" + path: "^1.2.0" dev_dependencies: - unittest: ">=0.9.0 <0.12.0" + test: "^0.12.0" environment: - sdk: ">=1.7.0-dev.4.0 <2.0.0" + sdk: ">=1.8.0 <2.0.0" diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain_test.dart index 0b6f36e38..65d6790f9 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain_test.dart @@ -2,13 +2,14 @@ // 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. -library chain_test; +// dart2js currently doesn't support chain-capturing. See sdk#15171. +@TestOn('vm') import 'dart:async'; import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'utils.dart'; @@ -349,16 +350,21 @@ void main() { test('current() outside of capture() returns a chain wrapping the current ' 'trace', () { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + // The test runner runs all tests with chains enabled, so to test without we + // have to do some zone munging. + return runZoned(() { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); - return completer.future.then((chain) { - // Since the chain wasn't loaded within [Chain.capture], the full stack - // chain isn't available and it just returns the current stack when - // called. - expect(chain.traces, hasLength(1)); - expect(chain.traces.first.frames.first, frameMember(startsWith('main'))); - }); + return completer.future.then((chain) { + // Since the chain wasn't loaded within [Chain.capture], the full stack + // chain isn't available and it just returns the current stack when + // called. + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.frames.first, + frameMember(startsWith('main'))); + }); + }, zoneValues: {#stack_trace.stack_zone.spec: null}); }); group('forTrace() within capture()', () { diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index c2cb80e94..01177f0d7 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -6,7 +6,7 @@ library frame_test; import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; void main() { group('.parseVM', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 7fb9b5b19..14e1e2bd1 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -6,7 +6,7 @@ library trace_test; import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; String getStackTraceString() { try { diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index ed756313c..912f8f4ed 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -4,7 +4,7 @@ library stack_trace.test.utils; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; /// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. Matcher frameMember(matcher) => diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 7e00b7a61..48ca375f3 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -6,10 +6,11 @@ /// dual of dartium_test.dart, since method names can differ somewhat from /// platform to platform. No similar file exists for dart2js since the specific /// method names there are implementation details. +@TestOn('vm') import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; String getStackTraceString() { try { From 657de1443eb714e2b348031a894d502160305b5f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jun 2015 13:00:32 -0700 Subject: [PATCH 0198/1215] Don't crash on stack overflow traces. Closes dart-lang/stack_trace#5 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1169883004. --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/lib/src/trace.dart | 19 +++++++++++++++---- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/vm_test.dart | 13 +++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 8615187f9..36e9aa8a4 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -6,6 +6,8 @@ * Add support for empty chains and chains of empty traces to `Chain.parse()`. +* Don't crash when parsing stack traces from Dart VM stack overflows. + ## 1.3.2 * Don't crash when running `Trace.terse` on empty stack traces. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 418c4ab3e..4415161cb 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -134,10 +134,21 @@ class Trace implements StackTrace { /// Parses a string representation of a Dart VM stack trace. Trace.parseVM(String trace) - : this(trace.trim().split("\n"). - // TODO(nweiz): remove this when issue 15920 is fixed. - where((line) => line.isNotEmpty). - map((line) => new Frame.parseVM(line))); + : this(_parseVM(trace)); + + static List _parseVM(String trace) { + var lines = trace.trim().split("\n"); + var frames = lines.take(lines.length - 1) + .map((line) => new Frame.parseVM(line)) + .toList(); + + // TODO(nweiz): Remove this when issue 23614 is fixed. + if (!lines.last.endsWith(".da")) { + frames.add(new Frame.parseVM(lines.last)); + } + + return frames; + } /// Parses a string representation of a Chrome/V8 stack trace. Trace.parseV8(String trace) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 9b8413d24..578ecc9c1 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.3-dev +version: 1.3.3 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 48ca375f3..947f14bd7 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -56,6 +56,19 @@ void main() { expect(trace.frames.first.member, equals('getStackTraceObject')); }); + test('.from handles a stack overflow trace correctly', () { + overflow() => overflow(); + + var trace; + try { + overflow(); + } catch (_, stackTrace) { + trace = new Trace.from(stackTrace); + } + + expect(trace.frames.first.member, equals('main...overflow')); + }); + group('.current()', () { test('with no argument returns a trace starting at the current frame', () { From 23edaac9648df77d17db057a49b4b47ff041f6c6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jun 2015 16:00:26 -0700 Subject: [PATCH 0199/1215] Remove debug prints. As far as I know, the issue that required these was fixed a while ago. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1187553003. --- .../lib/src/directory_watcher/mac_os.dart | 124 +----------------- pkgs/watcher/pubspec.yaml | 2 +- .../test/directory_watcher/mac_os_test.dart | 2 - pkgs/watcher/test/utils.dart | 28 ---- 4 files changed, 7 insertions(+), 149 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index c242c75da..89ac905ab 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,7 +7,6 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; -import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import '../constructable_file_system_event.dart'; @@ -27,19 +26,11 @@ import 'resubscribable.dart'; /// This also works around issues 16003 and 14849 in the implementation of /// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { - // TODO(nweiz): remove these when issue 15042 is fixed. - static var logDebugInfo = false; - static var _count = 0; - MacOSDirectoryWatcher(String directory) - : super(directory, () => new _MacOSDirectoryWatcher(directory, _count++)); + : super(directory, () => new _MacOSDirectoryWatcher(directory)); } class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - // TODO(nweiz): remove these when issue 15042 is fixed. - static var _count = 0; - final String _id; - final String directory; Stream get events => _eventsController.stream; @@ -77,10 +68,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// events (see issue 14373). Timer _bogusEventTimer; - _MacOSDirectoryWatcher(String directory, int parentId) + _MacOSDirectoryWatcher(String directory) : directory = directory, - _files = new PathSet(directory), - _id = "$parentId/${_count++}" { + _files = new PathSet(directory) { _startWatch(); // Before we're ready to emit events, wait for [_listDir] to complete and @@ -90,27 +80,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // If we do receive a batch of events, [_onBatch] will ensure that these // futures don't fire and that the directory is re-listed. Future.wait([ - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] finished initial directory list"); - } - }), + _listDir(), _waitForBogusEvents() - ]).then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is ready, known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - _readyCompleter.complete(); - }); + ]).then((_) => _readyCompleter.complete()); } void close() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is closed\n${new Chain.current().terse}"); - } if (_watchSubscription != null) _watchSubscription.cancel(); if (_initialListSubscription != null) _initialListSubscription.cancel(); _watchSubscription = null; @@ -126,59 +101,21 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] ======== batch:"); - for (var event in batch) { - print("[$_id] ${_formatEvent(event)}"); - } - - print("[$_id] known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - // If we get a batch of events before we're ready to begin emitting events, // it's probable that it's a batch of pre-watcher events (see issue 14373). // Ignore those events and re-list the directory. if (!isReady) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] not ready to emit events, re-listing directory"); - } - // Cancel the timer because bogus events only occur in the first batch, so // we can fire [ready] as soon as we're done listing the directory. _bogusEventTimer.cancel(); - _listDir().then((_) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] watcher is ready, known files:"); - for (var file in _files.toSet()) { - print("[$_id] ${p.relative(file, from: directory)}"); - } - } - _readyCompleter.complete(); - }); + _listDir().then((_) => _readyCompleter.complete()); return; } _sortEvents(batch).forEach((path, events) { - var relativePath = p.relative(path, from: directory); - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] events for $relativePath:"); - for (var event in events) { - print("[$_id] ${_formatEvent(event)}"); - } - } - var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] canonical event for $relativePath: " - "${_formatEvent(canonicalEvent)}"); - print("[$_id] actionable events for $relativePath: " - "${events.map(_formatEvent)}"); - } for (var event in events) { if (event is FileSystemCreateEvent) { @@ -207,9 +144,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); }, onError: (e, stackTrace) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] got error listing $relativePath: $e"); - } _emitError(e, stackTrace); }, onDone: () { _listSubscriptions.remove(subscription); @@ -226,10 +160,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { } } }); - - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] ======== batch complete"); - } } /// Sort all the events in a batch into sets based on their path. @@ -360,15 +290,6 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] checking file system for " - "${p.relative(path, from: directory)}"); - print("[$_id] file existed: $fileExisted"); - print("[$_id] dir existed: $dirExisted"); - print("[$_id] file exists: $fileExists"); - print("[$_id] dir exists: $dirExists"); - } - var events = []; if (fileExisted) { if (fileExists) { @@ -399,17 +320,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when the [Directory.watch] stream is closed. void _onDone() { - if (MacOSDirectoryWatcher.logDebugInfo) print("[$_id] stream closed"); - _watchSubscription = null; // If the directory still exists and we're still expecting bogus events, // this is probably issue 14849 rather than a real close event. We should // just restart the watcher. if (!isReady && new Directory(directory).existsSync()) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] fake closure (issue 14849), re-opening stream"); - } _startWatch(); return; } @@ -469,40 +385,12 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; - - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] emitting $type ${p.relative(path, from: directory)}"); - } - _eventsController.add(new WatchEvent(type, path)); } /// Emit an error, then close the watcher. void _emitError(error, StackTrace stackTrace) { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[$_id] emitting error: $error\n" + - "${new Chain.forTrace(stackTrace).terse}"); - } _eventsController.addError(error, stackTrace); close(); } - - // TODO(nweiz): remove this when issue 15042 is fixed. - /// Return a human-friendly string representation of [event]. - String _formatEvent(FileSystemEvent event) { - if (event == null) return 'null'; - - var path = p.relative(event.path, from: directory); - var type = event.isDirectory ? 'directory' : 'file'; - if (event is FileSystemCreateEvent) { - return "create $type $path"; - } else if (event is FileSystemDeleteEvent) { - return "delete $type $path"; - } else if (event is FileSystemModifyEvent) { - return "modify $type $path"; - } else if (event is FileSystemMoveEvent) { - return "move $type $path to " - "${p.relative(event.destination, from: directory)}"; - } - } } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index a16a0200e..a0d3000a0 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.5 +version: 0.9.6-dev author: Dart Team homepage: http://github.com/dart-lang/watcher description: > diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index bbf966aa9..0320e3c57 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -11,8 +11,6 @@ import '../utils.dart'; void main() { initConfig(); - MacOSDirectoryWatcher.logDebugInfo = true; - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 6758dae0c..2953c988c 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -117,11 +117,6 @@ ScheduledStream _watcherEvents; /// /// If [dir] is provided, watches a subdirectory in the sandbox with that name. void startWatcher({String dir}) { - var testCase = currentTestCase.description; - if (MacOSDirectoryWatcher.logDebugInfo) { - print("starting watcher for $testCase (${new DateTime.now()})"); - } - // We want to wait until we're ready *after* we subscribe to the watcher's // events. _watcher = createWatcher(dir: dir, waitForReady: false); @@ -131,10 +126,6 @@ void startWatcher({String dir}) { // that it can be accessed synchronously after this. _watcherEvents = new ScheduledStream(futureStream(schedule(() { currentSchedule.onComplete.schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("stopping watcher for $testCase (${new DateTime.now()})"); - } - _watcher = null; if (!_closePending) _watcherEvents.close(); @@ -301,9 +292,6 @@ void writeFile(String path, {String contents, bool updateModified}) { dir.createSync(recursive: true); } - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] writing file $path"); - } new File(fullPath).writeAsStringSync(contents); // Manually update the mock modification time for the file. @@ -320,9 +308,6 @@ void writeFile(String path, {String contents, bool updateModified}) { /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] deleting file $path"); - } new File(p.join(_sandboxDir, path)).deleteSync(); }, "delete file $path"); } @@ -332,10 +317,6 @@ void deleteFile(String path) { /// If [contents] is omitted, creates an empty file. void renameFile(String from, String to) { schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] renaming file $from to $to"); - } - new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); // Make sure we always use the same separator on Windows. @@ -350,9 +331,6 @@ void renameFile(String from, String to) { /// Schedules creating a directory in the sandbox at [path]. void createDir(String path) { schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] creating directory $path"); - } new Directory(p.join(_sandboxDir, path)).createSync(); }, "create directory $path"); } @@ -360,9 +338,6 @@ void createDir(String path) { /// Schedules renaming a directory in the sandbox from [from] to [to]. void renameDir(String from, String to) { schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] renaming directory $from to $to"); - } new Directory(p.join(_sandboxDir, from)) .renameSync(p.join(_sandboxDir, to)); }, "rename directory $from to $to"); @@ -371,9 +346,6 @@ void renameDir(String from, String to) { /// Schedules deleting a directory in the sandbox at [path]. void deleteDir(String path) { schedule(() { - if (MacOSDirectoryWatcher.logDebugInfo) { - print("[test] deleting directory $path"); - } new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true); }, "delete directory $path"); } From 16db63bb8d9d9bd0be68e792c1f65d051ba5daa3 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jun 2015 16:01:40 -0700 Subject: [PATCH 0200/1215] Fix analysis errors, warnings, and hints. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1184763005. --- .../lib/src/directory_watcher/linux.dart | 8 +++----- .../lib/src/directory_watcher/mac_os.dart | 11 ++++------ .../lib/src/directory_watcher/polling.dart | 4 +--- .../lib/src/directory_watcher/windows.dart | 20 ++++++------------- pkgs/watcher/lib/src/stat.dart | 4 +--- 5 files changed, 15 insertions(+), 32 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 870faa760..04d88e66c 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.linux; import 'dart:async'; import 'dart:io'; -import 'package:stack_trace/stack_trace.dart'; - import '../utils.dart'; import '../watch_event.dart'; import 'resubscribable.dart'; @@ -58,13 +56,13 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _LinuxDirectoryWatcher(String directory) : directory = directory { // Batch the inotify changes together so that we can dedup events. - var innerStream = Chain.track(new Directory(directory).watch()) + var innerStream = new Directory(directory).watch() .transform(new BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError, onDone: _onDone); - _listen(Chain.track(new Directory(directory).list()), (entity) { + _listen(new Directory(directory).list(), (entity) { _entries[entity.path] = new _EntryState(entity is Directory); if (entity is! Directory) return; _watchSubdir(entity.path); @@ -159,7 +157,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // event for every new file. watcher.ready.then((_) { if (!isReady || _eventsController.isClosed) return; - _listen(Chain.track(new Directory(path).list(recursive: true)), (entry) { + _listen(new Directory(path).list(recursive: true), (entry) { if (entry is Directory) return; _eventsController.add(new WatchEvent(ChangeType.ADD, entry.path)); }, onError: (error, stackTrace) { diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 89ac905ab..f3de72711 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; -import 'package:stack_trace/stack_trace.dart'; - import '../constructable_file_system_event.dart'; import '../path_set.dart'; import '../utils.dart'; @@ -136,7 +134,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (_files.containsDir(path)) continue; var subscription; - subscription = Chain.track(new Directory(path).list(recursive: true)) + subscription = new Directory(path).list(recursive: true) .listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -273,7 +271,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { case FileSystemEvent.MODIFY: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); - default: assert(false); + default: throw 'unreachable'; } } @@ -343,8 +341,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = - Chain.track(new Directory(directory).watch(recursive: true)) + var innerStream = new Directory(directory).watch(recursive: true) .transform(new BatchedStreamTransformer()); _watchSubscription = innerStream.listen(_onBatch, onError: _eventsController.addError, @@ -359,7 +356,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files.clear(); var completer = new Completer(); - var stream = Chain.track(new Directory(directory).list(recursive: true)); + var stream = new Directory(directory).list(recursive: true); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); }, diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 12a32458e..144391fda 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -7,8 +7,6 @@ library watcher.directory_watcher.polling; import 'dart:async'; import 'dart:io'; -import 'package:stack_trace/stack_trace.dart'; - import '../async_queue.dart'; import '../stat.dart'; import '../utils.dart'; @@ -105,7 +103,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _filesToProcess.add(null); } - var stream = Chain.track(new Directory(directory).list(recursive: true)); + var stream = new Directory(directory).list(recursive: true); _listSubscription = stream.listen((entity) { assert(!_events.isClosed); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 4f41d3395..bd17cf48a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -10,7 +10,6 @@ import 'dart:collection'; import 'dart:io'; import 'package:path/path.dart' as p; -import 'package:stack_trace/stack_trace.dart'; import '../constructable_file_system_event.dart'; import '../path_set.dart'; @@ -117,8 +116,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var parent = p.dirname(absoluteDir); // Check if [directory] is already the root directory. if (FileSystemEntity.identicalSync(parent, directory)) return; - var parentStream = Chain.track( - new Directory(parent).watch(recursive: false)); + var parentStream = new Directory(parent).watch(recursive: false); _parentWatchSubscription = parentStream.listen((event) { // Only look at events for 'directory'. if (p.basename(event.path) != p.basename(absoluteDir)) return; @@ -159,7 +157,6 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { _sortEvents(batch).forEach((path, events) { - var relativePath = p.relative(path, from: directory); var canonicalEvent = _canonicalEvent(events); events = canonicalEvent == null ? @@ -177,7 +174,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { if (_files.containsDir(path)) continue; - var stream = Chain.track(new Directory(path).list(recursive: true)); + var stream = new Directory(path).list(recursive: true); var sub; sub = stream.listen((entity) { if (entity is Directory) return; @@ -262,7 +259,6 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { var type = batch.first.type; var isDir = batch.first.isDirectory; - var hadModifyEvent = false; for (var event in batch.skip(1)) { // If one event reports that the file is a directory and another event @@ -273,10 +269,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // safely assume the file was modified after a CREATE or before the // REMOVE; otherwise there will also be a REMOVE or CREATE event // (respectively) that will be contradictory. - if (event is FileSystemModifyEvent) { - hadModifyEvent = true; - continue; - } + if (event is FileSystemModifyEvent) continue; assert(event is FileSystemCreateEvent || event is FileSystemDeleteEvent || event is FileSystemMoveEvent); @@ -305,7 +298,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { batch.first.path, isDir, false); case FileSystemEvent.MOVE: return null; - default: assert(false); + default: throw 'unreachable'; } } @@ -367,8 +360,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the events together so that we can dedup events. - var innerStream = - Chain.track(new Directory(directory).watch(recursive: true)); + var innerStream = new Directory(directory).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, onError: _eventsController.addError, onDone: _onDone); @@ -382,7 +374,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files.clear(); var completer = new Completer(); - var stream = Chain.track(new Directory(directory).list(recursive: true)); + var stream = new Directory(directory).list(recursive: true); void handleEntity(entity) { if (entity is! Directory) _files.add(entity.path); } diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 166d78988..d36eff3bd 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -7,8 +7,6 @@ library watcher.stat; import 'dart:async'; import 'dart:io'; -import 'package:stack_trace/stack_trace.dart'; - /// A function that takes a file path and returns the last modified time for /// the file at that path. typedef DateTime MockTimeCallback(String path); @@ -31,5 +29,5 @@ Future getModificationTime(String path) { return new Future.value(_mockTimeCallback(path)); } - return Chain.track(FileStat.stat(path)).then((stat) => stat.modified); + return FileStat.stat(path).then((stat) => stat.modified); } From 22e2f6c7570b8f934db3c7a8ae5ea35621ae35bb Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jun 2015 16:02:41 -0700 Subject: [PATCH 0201/1215] Use the new test runner. Closes dart-lang/watcher#11 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1183723003. --- pkgs/watcher/pubspec.yaml | 6 +++--- pkgs/watcher/test/directory_watcher/linux_test.dart | 4 ++-- pkgs/watcher/test/directory_watcher/mac_os_test.dart | 3 ++- pkgs/watcher/test/directory_watcher/polling_test.dart | 2 -- pkgs/watcher/test/directory_watcher/windows_test.dart | 4 ++-- pkgs/watcher/test/no_subscription/linux_test.dart | 4 ++-- pkgs/watcher/test/no_subscription/mac_os_test.dart | 4 ++-- pkgs/watcher/test/no_subscription/polling_test.dart | 2 -- pkgs/watcher/test/no_subscription/shared.dart | 4 ++-- pkgs/watcher/test/path_set_test.dart | 4 +--- pkgs/watcher/test/ready/linux_test.dart | 4 ++-- pkgs/watcher/test/ready/mac_os_test.dart | 4 ++-- pkgs/watcher/test/ready/polling_test.dart | 2 -- pkgs/watcher/test/utils.dart | 6 ------ 14 files changed, 20 insertions(+), 33 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index a0d3000a0..08695c98f 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -6,10 +6,10 @@ description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' dependencies: path: '>=0.9.0 <2.0.0' stack_trace: '>=0.9.1 <2.0.0' dev_dependencies: - scheduled_test: '>=0.9.3 <0.12.0' - unittest: '>=0.9.2 <0.12.0' + scheduled_test: '^0.12.0' + test: '^0.12.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index c17eb534c..15eb0cee3 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('linux') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; import 'package:watcher/watcher.dart'; @@ -10,8 +12,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 0320e3c57..e9a1696aa 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('mac-os') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'package:watcher/watcher.dart'; @@ -10,7 +12,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 1ef49b57a..0192b2592 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -9,8 +9,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - // Use a short delay to make the tests run quickly. watcherFactory = (dir) => new PollingDirectoryWatcher(dir, pollingDelay: new Duration(milliseconds: 100)); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index ea5c8c5a5..4c77ced50 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('windows') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; import 'package:watcher/watcher.dart'; @@ -10,8 +12,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart index f7f1b49c1..c8e8ae91c 100644 --- a/pkgs/watcher/test/no_subscription/linux_test.dart +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('linux') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; @@ -9,8 +11,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index 721d3e7a0..d5b1c8e3f 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('mac-os') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; @@ -9,8 +11,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart index c71b5ceec..5c99bc061 100644 --- a/pkgs/watcher/test/no_subscription/polling_test.dart +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -9,8 +9,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new PollingDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 9ba5c98ed..52649f1a7 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -18,7 +18,7 @@ void sharedTests() { // Subscribe to the events. var completer = new Completer(); - var subscription = watcher.events.listen(wrapAsync((event) { + var subscription = watcher.events.listen(expectAsync((event) { expect(event, isWatchEvent(ChangeType.ADD, "file.txt")); completer.complete(); })); @@ -39,7 +39,7 @@ void sharedTests() { // Then start listening again. schedule(() { completer = new Completer(); - subscription = watcher.events.listen(wrapAsync((event) { + subscription = watcher.events.listen(expectAsync((event) { // We should get an event for the third file, not the one added while // we weren't subscribed. expect(event, isWatchEvent(ChangeType.ADD, "added.txt")); diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index f433ad3c3..13e797c20 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:path/path.dart' as p; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/path_set.dart'; import 'utils.dart'; @@ -17,8 +17,6 @@ Matcher containsDir(String path) => predicate((set) => 'set contains directory "$path"'); void main() { - initConfig(); - var set; setUp(() => set = new PathSet("root")); diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart index f7f1b49c1..c8e8ae91c 100644 --- a/pkgs/watcher/test/ready/linux_test.dart +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('linux') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; @@ -9,8 +11,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart index 721d3e7a0..d5b1c8e3f 100644 --- a/pkgs/watcher/test/ready/mac_os_test.dart +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('mac-os') + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; @@ -9,8 +11,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart index c71b5ceec..5c99bc061 100644 --- a/pkgs/watcher/test/ready/polling_test.dart +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -9,8 +9,6 @@ import 'shared.dart'; import '../utils.dart'; void main() { - initConfig(); - watcherFactory = (dir) => new PollingDirectoryWatcher(dir); setUp(createSandbox); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 2953c988c..85fe6d3c5 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -9,7 +9,6 @@ import 'dart:io'; import 'package:path/path.dart' as p; import 'package:scheduled_test/scheduled_stream.dart'; import 'package:scheduled_test/scheduled_test.dart'; -import 'package:unittest/compact_vm_config.dart'; import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; import 'package:watcher/src/utils.dart'; @@ -43,11 +42,6 @@ set watcherFactory(WatcherFactory factory) { } WatcherFactory _watcherFactory; -void initConfig() { - useCompactVMConfiguration(); - filterStacks = true; -} - /// Creates the sandbox directory the other functions in this library use and /// ensures it's deleted when the test ends. /// From 63de467a5a85f73563f6a641eb222fb80e72dbbe Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jun 2015 16:37:30 -0700 Subject: [PATCH 0202/1215] Add a Watcher interface. Unlike DirectoryWatcher, this interface isn't directory-specific. This also allows ResubscribableDirectoryWatcher to become ResubscribableWatcher, which will make it easier to implement single-file watching. See dart-lang/watcher#17 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1180233003. --- pkgs/watcher/CHANGELOG.md | 7 ++++ pkgs/watcher/lib/src/directory_watcher.dart | 30 ++-------------- .../lib/src/directory_watcher/linux.dart | 23 +++++++----- .../lib/src/directory_watcher/mac_os.dart | 30 +++++++++------- .../lib/src/directory_watcher/polling.dart | 18 ++++++---- .../lib/src/directory_watcher/windows.dart | 35 +++++++++++-------- .../resubscribable.dart | 26 +++++++------- pkgs/watcher/lib/watcher.dart | 34 ++++++++++++++++++ pkgs/watcher/pubspec.yaml | 1 - .../test/directory_watcher/linux_test.dart | 2 +- .../test/directory_watcher/mac_os_test.dart | 4 +-- .../test/directory_watcher/shared.dart | 16 ++++----- pkgs/watcher/test/utils.dart | 35 +++++++++---------- 13 files changed, 150 insertions(+), 111 deletions(-) rename pkgs/watcher/lib/src/{directory_watcher => }/resubscribable.dart (74%) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 77729800c..f8c54bf6c 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,10 @@ +# 0.9.6 + +* Add a `Watcher` interface that encompasses watching both files and + directories. + +* Deprecate `DirectoryWatcher.directory`. Use `DirectoryWatcher.path` instead. + # 0.9.5 * Fix bugs where events could be added after watchers were closed. diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 605eaea48..6979536a9 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -4,10 +4,10 @@ library watcher.directory_watcher; -import 'dart:async'; import 'dart:io'; import 'watch_event.dart'; +import '../watcher.dart'; import 'directory_watcher/linux.dart'; import 'directory_watcher/mac_os.dart'; import 'directory_watcher/windows.dart'; @@ -15,35 +15,11 @@ import 'directory_watcher/polling.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something /// in the directory has changed. -abstract class DirectoryWatcher { +abstract class DirectoryWatcher implements Watcher { /// The directory whose contents are being monitored. + @Deprecated("Expires in 1.0.0. Use DirectoryWatcher.path instead.") String get directory; - /// The broadcast [Stream] of events that have occurred to files in - /// [directory]. - /// - /// Changes will only be monitored while this stream has subscribers. Any - /// file changes that occur during periods when there are no subscribers - /// will not be reported the next time a subscriber is added. - Stream get events; - - /// Whether the watcher is initialized and watching for file changes. - /// - /// This is true if and only if [ready] is complete. - bool get isReady; - - /// A [Future] that completes when the watcher is initialized and watching - /// for file changes. - /// - /// If the watcher is not currently monitoring the directory (because there - /// are no subscribers to [events]), this returns a future that isn't - /// complete yet. It will complete when a subscriber starts listening and - /// the watcher finishes any initialization work it needs to do. - /// - /// If the watcher is already monitoring, this returns an already complete - /// future. - Future get ready; - /// Creates a new [DirectoryWatcher] monitoring [directory]. /// /// If a native directory watcher is available for this platform, this will diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 04d88e66c..a747839d2 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -7,9 +7,10 @@ library watcher.directory_watcher.linux; import 'dart:async'; import 'dart:io'; +import '../directory_watcher.dart'; +import '../resubscribable.dart'; import '../utils.dart'; import '../watch_event.dart'; -import 'resubscribable.dart'; /// Uses the inotify subsystem to watch for filesystem events. /// @@ -21,13 +22,18 @@ import 'resubscribable.dart'; /// [Directory.watch] producing multiple events for a single logical action /// (issue 14372) and providing insufficient information about move events /// (issue 14424). -class LinuxDirectoryWatcher extends ResubscribableDirectoryWatcher { +class LinuxDirectoryWatcher extends ResubscribableWatcher + implements DirectoryWatcher { + String get directory => path; + LinuxDirectoryWatcher(String directory) : super(directory, () => new _LinuxDirectoryWatcher(directory)); } -class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - final String directory; +class _LinuxDirectoryWatcher + implements DirectoryWatcher, ManuallyClosedWatcher { + String get directory => path; + final String path; Stream get events => _eventsController.stream; final _eventsController = new StreamController.broadcast(); @@ -53,16 +59,15 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// watcher is closed. final _subscriptions = new Set(); - _LinuxDirectoryWatcher(String directory) - : directory = directory { + _LinuxDirectoryWatcher(this.path) { // Batch the inotify changes together so that we can dedup events. - var innerStream = new Directory(directory).watch() + var innerStream = new Directory(path).watch() .transform(new BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError, onDone: _onDone); - _listen(new Directory(directory).list(), (entity) { + _listen(new Directory(path).list(), (entity) { _entries[entity.path] = new _EntryState(entity is Directory); if (entity is! Directory) return; _watchSubdir(entity.path); @@ -182,7 +187,7 @@ class _LinuxDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // If the watched directory is deleted or moved, we'll get a deletion // event for it. Ignore it; we handle closing [this] when the underlying // stream is closed. - if (event.path == directory) continue; + if (event.path == path) continue; changedEntries.add(event.path); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index f3de72711..487225eb4 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,11 +7,12 @@ library watcher.directory_watcher.mac_os; import 'dart:async'; import 'dart:io'; +import '../directory_watcher.dart'; import '../constructable_file_system_event.dart'; import '../path_set.dart'; +import '../resubscribable.dart'; import '../utils.dart'; import '../watch_event.dart'; -import 'resubscribable.dart'; /// Uses the FSEvents subsystem to watch for filesystem events. /// @@ -23,13 +24,18 @@ import 'resubscribable.dart'; /// /// This also works around issues 16003 and 14849 in the implementation of /// [Directory.watch]. -class MacOSDirectoryWatcher extends ResubscribableDirectoryWatcher { +class MacOSDirectoryWatcher extends ResubscribableWatcher + implements DirectoryWatcher { + String get directory => path; + MacOSDirectoryWatcher(String directory) : super(directory, () => new _MacOSDirectoryWatcher(directory)); } -class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - final String directory; +class _MacOSDirectoryWatcher + implements DirectoryWatcher, ManuallyClosedWatcher { + String get directory => path; + final String path; Stream get events => _eventsController.stream; final _eventsController = new StreamController.broadcast(); @@ -66,9 +72,9 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// events (see issue 14373). Timer _bogusEventTimer; - _MacOSDirectoryWatcher(String directory) - : directory = directory, - _files = new PathSet(directory) { + _MacOSDirectoryWatcher(String path) + : path = path, + _files = new PathSet(path) { _startWatch(); // Before we're ready to emit events, wait for [_listDir] to complete and @@ -167,14 +173,14 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// CREATE event for the destination. /// /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it - /// contain any events relating to [directory]. + /// contain any events relating to [path]. Map> _sortEvents(List batch) { var eventsForPaths = {}; // FSEvents can report past events, including events on the root directory // such as it being created. We want to ignore these. If the directory is // really deleted, that's handled by [_onDone]. - batch = batch.where((event) => event.path != directory).toList(); + batch = batch.where((event) => event.path != path).toList(); // Events within directories that already have events are superfluous; the // directory's full contents will be examined anyway, so we ignore such @@ -323,7 +329,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // If the directory still exists and we're still expecting bogus events, // this is probably issue 14849 rather than a real close event. We should // just restart the watcher. - if (!isReady && new Directory(directory).existsSync()) { + if (!isReady && new Directory(path).existsSync()) { _startWatch(); return; } @@ -341,7 +347,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = new Directory(directory).watch(recursive: true) + var innerStream = new Directory(path).watch(recursive: true) .transform(new BatchedStreamTransformer()); _watchSubscription = innerStream.listen(_onBatch, onError: _eventsController.addError, @@ -356,7 +362,7 @@ class _MacOSDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files.clear(); var completer = new Completer(); - var stream = new Directory(directory).list(recursive: true); + var stream = new Directory(path).list(recursive: true); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); }, diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 144391fda..7f417d630 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -8,13 +8,17 @@ import 'dart:async'; import 'dart:io'; import '../async_queue.dart'; +import '../directory_watcher.dart'; +import '../resubscribable.dart'; import '../stat.dart'; import '../utils.dart'; import '../watch_event.dart'; -import 'resubscribable.dart'; /// Periodically polls a directory for changes. -class PollingDirectoryWatcher extends ResubscribableDirectoryWatcher { +class PollingDirectoryWatcher extends ResubscribableWatcher + implements DirectoryWatcher { + String get directory => path; + /// Creates a new polling watcher monitoring [directory]. /// /// If [_pollingDelay] is passed, it specifies the amount of time the watcher @@ -28,8 +32,10 @@ class PollingDirectoryWatcher extends ResubscribableDirectoryWatcher { }); } -class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - final String directory; +class _PollingDirectoryWatcher + implements DirectoryWatcher, ManuallyClosedWatcher { + String get directory => path; + final String path; Stream get events => _events.stream; final _events = new StreamController.broadcast(); @@ -68,7 +74,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// but not in here when a poll completes have been removed. final _polledFiles = new Set(); - _PollingDirectoryWatcher(this.directory, this._pollingDelay) { + _PollingDirectoryWatcher(this.path, this._pollingDelay) { _filesToProcess = new AsyncQueue(_processFile, onError: (e, stackTrace) { if (!_events.isClosed) _events.addError(e, stackTrace); @@ -103,7 +109,7 @@ class _PollingDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _filesToProcess.add(null); } - var stream = new Directory(directory).list(recursive: true); + var stream = new Directory(path).list(recursive: true); _listSubscription = stream.listen((entity) { assert(!_events.isClosed); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index bd17cf48a..089951964 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -12,12 +12,16 @@ import 'dart:io'; import 'package:path/path.dart' as p; import '../constructable_file_system_event.dart'; +import '../directory_watcher.dart'; import '../path_set.dart'; +import '../resubscribable.dart'; import '../utils.dart'; import '../watch_event.dart'; -import 'resubscribable.dart'; -class WindowsDirectoryWatcher extends ResubscribableDirectoryWatcher { +class WindowsDirectoryWatcher extends ResubscribableWatcher + implements DirectoryWatcher { + String get directory => path; + WindowsDirectoryWatcher(String directory) : super(directory, () => new _WindowsDirectoryWatcher(directory)); } @@ -40,8 +44,10 @@ class _EventBatcher { } } -class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { - final String directory; +class _WindowsDirectoryWatcher + implements DirectoryWatcher, ManuallyClosedWatcher { + String get directory => path; + final String path; Stream get events => _eventsController.stream; final _eventsController = new StreamController.broadcast(); @@ -79,8 +85,9 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { final Set> _listSubscriptions = new HashSet>(); - _WindowsDirectoryWatcher(String directory) - : directory = directory, _files = new PathSet(directory) { + _WindowsDirectoryWatcher(String path) + : path = path, + _files = new PathSet(path) { // Before we're ready to emit events, wait for [_listDir] to complete. _listDir().then((_) { _startWatch(); @@ -110,12 +117,12 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// On Windows, if [directory] is deleted, we will not receive any event. /// /// Instead, we add a watcher on the parent folder (if any), that can notify - /// us about [directory]. This also includes events such as moves. + /// us about [path]. This also includes events such as moves. void _startParentWatcher() { - var absoluteDir = p.absolute(directory); + var absoluteDir = p.absolute(path); var parent = p.dirname(absoluteDir); - // Check if [directory] is already the root directory. - if (FileSystemEntity.identicalSync(parent, directory)) return; + // Check if [path] is already the root directory. + if (FileSystemEntity.identicalSync(parent, path)) return; var parentStream = new Directory(parent).watch(recursive: false); _parentWatchSubscription = parentStream.listen((event) { // Only look at events for 'directory'. @@ -127,7 +134,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { // the directory is now gone. if (event is FileSystemMoveEvent || event is FileSystemDeleteEvent || - (FileSystemEntity.typeSync(directory) == + (FileSystemEntity.typeSync(path) == FileSystemEntityType.NOT_FOUND)) { for (var path in _files.toSet()) { _emitEvent(ChangeType.REMOVE, path); @@ -210,7 +217,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// CREATE event for the destination. /// /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it - /// contain any events relating to [directory]. + /// contain any events relating to [path]. Map> _sortEvents(List batch) { var eventsForPaths = {}; @@ -360,7 +367,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the events together so that we can dedup events. - var innerStream = new Directory(directory).watch(recursive: true); + var innerStream = new Directory(path).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, onError: _eventsController.addError, onDone: _onDone); @@ -374,7 +381,7 @@ class _WindowsDirectoryWatcher implements ManuallyClosedDirectoryWatcher { _files.clear(); var completer = new Completer(); - var stream = new Directory(directory).list(recursive: true); + var stream = new Directory(path).list(recursive: true); void handleEntity(entity) { if (entity is! Directory) _files.add(entity.path); } diff --git a/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart similarity index 74% rename from pkgs/watcher/lib/src/directory_watcher/resubscribable.dart rename to pkgs/watcher/lib/src/resubscribable.dart index 7d99fc05b..2844c1e2c 100644 --- a/pkgs/watcher/lib/src/directory_watcher/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -2,33 +2,33 @@ // 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. -library watcher.directory_watcher.resubscribable; +library watcher.resubscribable; import 'dart:async'; -import '../directory_watcher.dart'; -import '../watch_event.dart'; +import '../watcher.dart'; +import 'watch_event.dart'; -typedef ManuallyClosedDirectoryWatcher WatcherFactory(); +typedef ManuallyClosedWatcher WatcherFactory(); -/// A wrapper for [ManuallyClosedDirectoryWatcher] that encapsulates support for -/// closing the watcher when it has no subscribers and re-opening it when it's +/// A wrapper for [ManuallyClosedWatcher] that encapsulates support for closing +/// the watcher when it has no subscribers and re-opening it when it's /// re-subscribed. /// /// It's simpler to implement watchers without worrying about this behavior. /// This class wraps a watcher class which can be written with the simplifying /// assumption that it can continue emitting events until an explicit `close` /// method is called, at which point it will cease emitting events entirely. The -/// [ManuallyClosedDirectoryWatcher] interface is used for these watchers. +/// [ManuallyClosedWatcher] interface is used for these watchers. /// /// This would be more cleanly implemented as a function that takes a class and /// emits a new class, but Dart doesn't support that sort of thing. Instead it /// takes a factory function that produces instances of the inner class. -abstract class ResubscribableDirectoryWatcher implements DirectoryWatcher { +abstract class ResubscribableWatcher implements Watcher { /// The factory function that produces instances of the inner class. final WatcherFactory _factory; - final String directory; + final String path; Stream get events => _eventsController.stream; StreamController _eventsController; @@ -38,9 +38,9 @@ abstract class ResubscribableDirectoryWatcher implements DirectoryWatcher { Future get ready => _readyCompleter.future; var _readyCompleter = new Completer(); - /// Creates a new [ResubscribableDirectoryWatcher] wrapping the watchers + /// Creates a new [ResubscribableWatcher] wrapping the watchers /// emitted by [_factory]. - ResubscribableDirectoryWatcher(this.directory, this._factory) { + ResubscribableWatcher(this.path, this._factory) { var watcher; var subscription; @@ -67,8 +67,8 @@ abstract class ResubscribableDirectoryWatcher implements DirectoryWatcher { /// An interface for watchers with an explicit, manual [close] method. /// -/// See [ResubscribableDirectoryWatcher]. -abstract class ManuallyClosedDirectoryWatcher implements DirectoryWatcher { +/// See [ResubscribableWatcher]. +abstract class ManuallyClosedWatcher implements Watcher { /// Closes the watcher. /// /// Subclasses should close their [events] stream and release any internal diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 88531f203..a07805824 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -4,6 +4,40 @@ library watcher; +import 'dart:async'; + +import 'src/watch_event.dart'; + export 'src/watch_event.dart'; export 'src/directory_watcher.dart'; export 'src/directory_watcher/polling.dart'; + +abstract class Watcher { + /// The path to the file or directory whose contents are being monitored. + String get path; + + /// The broadcast [Stream] of events that have occurred to the watched file or + /// files in the watched directory. + /// + /// Changes will only be monitored while this stream has subscribers. Any + /// changes that occur during periods when there are no subscribers will not + /// be reported the next time a subscriber is added. + Stream get events; + + /// Whether the watcher is initialized and watching for changes. + /// + /// This is true if and only if [ready] is complete. + bool get isReady; + + /// A [Future] that completes when the watcher is initialized and watching for + /// changes. + /// + /// If the watcher is not currently monitoring the file or directory (because + /// there are no subscribers to [events]), this returns a future that isn't + /// complete yet. It will complete when a subscriber starts listening and the + /// watcher finishes any initialization work it needs to do. + /// + /// If the watcher is already monitoring, this returns an already complete + /// future. + Future get ready; +} diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 08695c98f..88539956f 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -9,7 +9,6 @@ environment: sdk: '>=1.8.0 <2.0.0' dependencies: path: '>=0.9.0 <2.0.0' - stack_trace: '>=0.9.1 <2.0.0' dev_dependencies: scheduled_test: '^0.12.0' test: '^0.12.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 15eb0cee3..897b1301b 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -27,7 +27,7 @@ void main() { () { withPermutations((i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index e9a1696aa..2c82f34c5 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -30,7 +30,7 @@ void main() { deleteDir("dir"); createDir("dir"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); writeFile("dir/newer.txt"); expectAddEvent("dir/newer.txt"); }); @@ -40,7 +40,7 @@ void main() { withPermutations((i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index a4cec5e11..ff48cb2aa 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -69,7 +69,7 @@ void sharedTests() { writeFile("dir/a.txt"); writeFile("dir/b.txt"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); deleteDir("dir"); inAnyOrder([ @@ -82,7 +82,7 @@ void sharedTests() { writeFile("dir/a.txt"); writeFile("dir/b.txt"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameDir("dir", "moved_dir"); createDir("dir"); @@ -108,7 +108,7 @@ void sharedTests() { () { writeFile("old.txt"); createDir("dir"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameFile("old.txt", "dir/new.txt"); expectAddEvent("dir/new.txt"); @@ -116,7 +116,7 @@ void sharedTests() { test('notifies when a file is moved outside the watched directory', () { writeFile("dir/old.txt"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameFile("dir/old.txt", "new.txt"); expectRemoveEvent("dir/old.txt"); @@ -251,7 +251,7 @@ void sharedTests() { writeFile("sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameDir("sub", "dir/sub"); inAnyOrder(withPermutations((i, j, k) => @@ -263,7 +263,7 @@ void sharedTests() { writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); // Rename the directory rather than deleting it because native watchers // report a rename as a single DELETE event for the directory, whereas @@ -280,7 +280,7 @@ void sharedTests() { writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); renameDir("dir/old", "dir/new"); inAnyOrder(unionAll(withPermutations((i, j, k) { @@ -296,7 +296,7 @@ void sharedTests() { writeFile("dir/sub"); withPermutations((i, j, k) => writeFile("old/sub-$i/sub-$j/file-$k.txt")); - startWatcher(dir: "dir"); + startWatcher(path: "dir"); deleteFile("dir/sub"); renameDir("old", "dir/sub"); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 85fe6d3c5..7dd833231 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -20,8 +20,8 @@ import 'package:watcher/src/directory_watcher/mac_os.dart'; /// operations are implicitly relative to this directory. String _sandboxDir; -/// The [DirectoryWatcher] being used for the current scheduled test. -DirectoryWatcher _watcher; +/// The [Watcher] being used for the current scheduled test. +Watcher _watcher; /// The mock modification times (in milliseconds since epoch) for each file. /// @@ -34,9 +34,9 @@ DirectoryWatcher _watcher; /// increment the mod time for that file instantly. Map _mockFileModificationTimes; -typedef DirectoryWatcher WatcherFactory(String directory); +typedef Watcher WatcherFactory(String directory); -/// Sets the function used to create the directory watcher. +/// Sets the function used to create the watcher. set watcherFactory(WatcherFactory factory) { _watcherFactory = factory; } @@ -78,21 +78,21 @@ void createSandbox() { }, "delete sandbox"); } -/// Creates a new [DirectoryWatcher] that watches a temporary directory. +/// Creates a new [Watcher] that watches a temporary file or directory. /// /// Normally, this will pause the schedule until the watcher is done scanning /// and is polling for changes. If you pass `false` for [waitForReady], it will /// not schedule this delay. /// -/// If [dir] is provided, watches a subdirectory in the sandbox with that name. -DirectoryWatcher createWatcher({String dir, bool waitForReady}) { - if (dir == null) { - dir = _sandboxDir; +/// If [path] is provided, watches a subdirectory in the sandbox with that name. +Watcher createWatcher({String path, bool waitForReady}) { + if (path == null) { + path = _sandboxDir; } else { - dir = p.join(_sandboxDir, dir); + path = p.join(_sandboxDir, path); } - var watcher = _watcherFactory(dir); + var watcher = _watcherFactory(path); // Wait until the scan is finished so that we don't miss changes to files // that could occur before the scan completes. @@ -106,17 +106,17 @@ DirectoryWatcher createWatcher({String dir, bool waitForReady}) { /// The stream of events from the watcher started with [startWatcher]. ScheduledStream _watcherEvents; -/// Creates a new [DirectoryWatcher] that watches a temporary directory and +/// Creates a new [Watcher] that watches a temporary file or directory and /// starts monitoring it for events. /// -/// If [dir] is provided, watches a subdirectory in the sandbox with that name. -void startWatcher({String dir}) { +/// If [path] is provided, watches a path in the sandbox with that name. +void startWatcher({String path}) { // We want to wait until we're ready *after* we subscribe to the watcher's // events. - _watcher = createWatcher(dir: dir, waitForReady: false); + _watcher = createWatcher(path: path, waitForReady: false); // Schedule [_watcher.events.listen] so that the watcher doesn't start - // watching [dir] before it exists. Expose [_watcherEvents] immediately so + // watching [path] before it exists. Expose [_watcherEvents] immediately so // that it can be accessed synchronously after this. _watcherEvents = new ScheduledStream(futureStream(schedule(() { currentSchedule.onComplete.schedule(() { @@ -139,8 +139,7 @@ void startWatcher({String dir}) { /// Whether an event to close [_watcherEvents] has been scheduled. bool _closePending = false; -/// Schedule closing the directory watcher stream after the event queue has been -/// pumped. +/// Schedule closing the watcher stream after the event queue has been pumped. /// /// This is necessary when events are allowed to occur, but don't have to occur, /// at the end of a test. Otherwise, if they don't occur, the test will wait From 0ecfafab1ae85aeac1fcced5ad0f08f20b33c4de Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 12 Jun 2015 16:52:24 -0700 Subject: [PATCH 0203/1215] Add support for watching individual files. Closes dart-lang/watcher#17 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1187553007. --- pkgs/watcher/CHANGELOG.md | 3 + pkgs/watcher/lib/src/directory_watcher.dart | 2 +- pkgs/watcher/lib/src/file_watcher.dart | 43 +++++++++ pkgs/watcher/lib/src/file_watcher/native.dart | 80 +++++++++++++++++ .../watcher/lib/src/file_watcher/polling.dart | 87 +++++++++++++++++++ pkgs/watcher/lib/watcher.dart | 26 ++++++ pkgs/watcher/pubspec.yaml | 4 +- .../test/file_watcher/native_test.dart | 23 +++++ .../test/file_watcher/polling_test.dart | 23 +++++ pkgs/watcher/test/file_watcher/shared.dart | 58 +++++++++++++ 10 files changed, 346 insertions(+), 3 deletions(-) create mode 100644 pkgs/watcher/lib/src/file_watcher.dart create mode 100644 pkgs/watcher/lib/src/file_watcher/native.dart create mode 100644 pkgs/watcher/lib/src/file_watcher/polling.dart create mode 100644 pkgs/watcher/test/file_watcher/native_test.dart create mode 100644 pkgs/watcher/test/file_watcher/polling_test.dart create mode 100644 pkgs/watcher/test/file_watcher/shared.dart diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index f8c54bf6c..4ff6cfaf6 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -3,6 +3,9 @@ * Add a `Watcher` interface that encompasses watching both files and directories. +* Add `FileWatcher` and `PollingFileWatcher` classes for watching changes to + individual files. + * Deprecate `DirectoryWatcher.directory`. Use `DirectoryWatcher.path` instead. # 0.9.5 diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 6979536a9..82837855b 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -25,7 +25,7 @@ abstract class DirectoryWatcher implements Watcher { /// If a native directory watcher is available for this platform, this will /// use it. Otherwise, it will fall back to a [PollingDirectoryWatcher]. /// - /// If [_pollingDelay] is passed, it specifies the amount of time the watcher + /// If [pollingDelay] is passed, it specifies the amount of time the watcher /// will pause between successive polls of the directory contents. Making this /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. Ignored for non-polling diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart new file mode 100644 index 000000000..9b315378d --- /dev/null +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -0,0 +1,43 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.file_watcher; + +import 'dart:io'; + +import 'watch_event.dart'; +import '../watcher.dart'; +import 'file_watcher/native.dart'; +import 'file_watcher/polling.dart'; + +/// Watches a file and emits [WatchEvent]s when the file has changed. +/// +/// Note that since each watcher only watches a single file, it will only emit +/// [ChangeType.MODIFY] events, except when the file is deleted at which point +/// it will emit a single [ChangeType.REMOVE] event and then close the stream. +/// +/// If the file is deleted and quickly replaced (when a new file is moved in its +/// place, for example) this will emit a [ChangeTime.MODIFY] event. +abstract class FileWatcher implements Watcher { + /// Creates a new [FileWatcher] monitoring [file]. + /// + /// If a native file watcher is available for this platform, this will use it. + /// Otherwise, it will fall back to a [PollingFileWatcher]. Notably, native + /// file watching is *not* supported on Windows. + /// + /// If [pollingDelay] is passed, it specifies the amount of time the watcher + /// will pause between successive polls of the directory contents. Making this + /// shorter will give more immediate feedback at the expense of doing more IO + /// and higher CPU usage. Defaults to one second. Ignored for non-polling + /// watchers. + factory FileWatcher(String file, {Duration pollingDelay}) { + // [File.watch] doesn't work on Windows, but + // [FileSystemEntity.isWatchSupported] is still true because directory + // watching does work. + if (FileSystemEntity.isWatchSupported && !Platform.isWindows) { + return new NativeFileWatcher(file); + } + return new PollingFileWatcher(file, pollingDelay: pollingDelay); + } +} diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart new file mode 100644 index 000000000..f5699bbb4 --- /dev/null +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -0,0 +1,80 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.file_watcher.native; + +import 'dart:async'; +import 'dart:io'; + +import '../file_watcher.dart'; +import '../resubscribable.dart'; +import '../utils.dart'; +import '../watch_event.dart'; + +/// Uses the native file system notifications to watch for filesystem events. +/// +/// Single-file notifications are much simpler than those for multiple files, so +/// this doesn't need to be split out into multiple OS-specific classes. +class NativeFileWatcher extends ResubscribableWatcher implements FileWatcher { + NativeFileWatcher(String path) + : super(path, () => new _NativeFileWatcher(path)); +} + +class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { + final String path; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + StreamSubscription _subscription; + + _NativeFileWatcher(this.path) { + _listen(); + + // We don't need to do any initial set-up, so we're ready immediately after + // being listened to. + _readyCompleter.complete(); + } + + void _listen() { + // Batch the events together so that we can dedup them. + _subscription = new File(path).watch() + .transform(new BatchedStreamTransformer()) + .listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); + } + + void _onBatch(List batch) { + if (batch.any((event) => event.type == FileSystemEvent.DELETE)) { + // If the file is deleted, the underlying stream will close. We handle + // emitting our own REMOVE event in [_onDone]. + return; + } + + _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + } + + _onDone() async { + // If the file exists now, it was probably removed and quickly replaced; + // this can happen for example when another file is moved on top of it. + // Re-subscribe and report a modify event. + if (await new File(path).exists()) { + _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + _listen(); + } else { + _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + close(); + } + } + + void close() { + if (_subscription != null) _subscription.cancel(); + _subscription = null; + _eventsController.close(); + } +} diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart new file mode 100644 index 000000000..a44f80cdb --- /dev/null +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library watcher.file_watcher.polling; + +import 'dart:async'; +import 'dart:io'; + +import '../file_watcher.dart'; +import '../resubscribable.dart'; +import '../stat.dart'; +import '../watch_event.dart'; + +/// Periodically polls a file for changes. +class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { + PollingFileWatcher(String path, {Duration pollingDelay}) + : super(path, () { + return new _PollingFileWatcher(path, + pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + }); +} + +class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { + final String path; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + /// The timer that controls polling. + Timer _timer; + + /// The previous modification time of the file. + /// + /// Used to tell when the file was modified. This is `null` before the file's + /// mtime has first been checked. + DateTime _lastModified; + + _PollingFileWatcher(this.path, Duration pollingDelay) { + _timer = new Timer.periodic(pollingDelay, (_) => _poll()); + _poll(); + } + + /// Checks the mtime of the file and whether it's been removed. + Future _poll() async { + // We don't mark the file as removed if this is the first poll (indicated by + // [_lastModified] being null). Instead, below we forward the dart:io error + // that comes from trying to read the mtime below. + if (_lastModified != null && !await new File(path).exists()) { + _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + close(); + return; + } + + var modified; + try { + modified = await getModificationTime(path); + } on FileSystemException catch (error, stackTrace) { + _eventsController.addError(error, stackTrace); + close(); + return; + } + + if (_eventsController.isClosed) return; + if (_lastModified == modified) return; + + if (_lastModified == null) { + // If this is the first poll, don't emit an event, just set the last mtime + // and complete the completer. + _lastModified = modified; + _readyCompleter.complete(); + } else { + _lastModified = modified; + _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + } + } + + void close() { + _timer.cancel(); + _eventsController.close(); + } +} diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index a07805824..79dcc0dae 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -5,12 +5,17 @@ library watcher; import 'dart:async'; +import 'dart:io'; import 'src/watch_event.dart'; +import 'src/directory_watcher.dart'; +import 'src/file_watcher.dart'; export 'src/watch_event.dart'; export 'src/directory_watcher.dart'; export 'src/directory_watcher/polling.dart'; +export 'src/file_watcher.dart'; +export 'src/file_watcher/polling.dart'; abstract class Watcher { /// The path to the file or directory whose contents are being monitored. @@ -40,4 +45,25 @@ abstract class Watcher { /// If the watcher is already monitoring, this returns an already complete /// future. Future get ready; + + /// Creates a new [DirectoryWatcher] or [FileWatcher] monitoring [path], + /// depending on whether it's a file or directory. + /// + /// If a native watcher is available for this platform, this will use it. + /// Otherwise, it will fall back to a polling watcher. Notably, watching + /// individual files is not natively supported on Windows, although watching + /// directories is. + /// + /// If [pollingDelay] is passed, it specifies the amount of time the watcher + /// will pause between successive polls of the contents of [path]. Making this + /// shorter will give more immediate feedback at the expense of doing more IO + /// and higher CPU usage. Defaults to one second. Ignored for non-polling + /// watchers. + factory Watcher(String path, {Duration pollingDelay}) { + if (new File(path).existsSync()) { + return new FileWatcher(path, pollingDelay: pollingDelay); + } else { + return new DirectoryWatcher(path, pollingDelay: pollingDelay); + } + } } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 88539956f..f62248da2 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,12 +1,12 @@ name: watcher -version: 0.9.6-dev +version: 0.9.6 author: Dart Team homepage: http://github.com/dart-lang/watcher description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.9.0 <2.0.0' dependencies: path: '>=0.9.0 <2.0.0' dev_dependencies: diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart new file mode 100644 index 000000000..30d0eca42 --- /dev/null +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -0,0 +1,23 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('linux || mac-os') + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/file_watcher/native.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +void main() { + watcherFactory = (file) => new NativeFileWatcher(file); + + setUp(() { + createSandbox(); + writeFile("file.txt"); + }); + + sharedTests(); +} diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart new file mode 100644 index 000000000..e5025447f --- /dev/null +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -0,0 +1,23 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('linux || mac-os') + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +void main() { + watcherFactory = (file) => new PollingFileWatcher(file, + pollingDelay: new Duration(milliseconds: 100)); + + setUp(() { + createSandbox(); + writeFile("file.txt"); + }); + + sharedTests(); +} diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart new file mode 100644 index 000000000..2931d8022 --- /dev/null +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/utils.dart'; + +import '../utils.dart'; + +void sharedTests() { + test("doesn't notify if the file isn't modified", () { + startWatcher(path: "file.txt"); + // Give the watcher time to fire events if it's going to. + schedule(() => pumpEventQueue()); + deleteFile("file.txt"); + expectRemoveEvent("file.txt"); + }); + + test("notifies when a file is modified", () { + startWatcher(path: "file.txt"); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + }); + + test("notifies when a file is removed", () { + startWatcher(path: "file.txt"); + deleteFile("file.txt"); + expectRemoveEvent("file.txt"); + }); + + test("notifies when a file is modified multiple times", () { + startWatcher(path: "file.txt"); + writeFile("file.txt", contents: "modified"); + expectModifyEvent("file.txt"); + writeFile("file.txt", contents: "modified again"); + expectModifyEvent("file.txt"); + }); + + test("notifies even if the file contents are unchanged", () { + startWatcher(path: "file.txt"); + writeFile("file.txt"); + expectModifyEvent("file.txt"); + }); + + test("emits a remove event when the watched file is moved away", () { + startWatcher(path: "file.txt"); + renameFile("file.txt", "new.txt"); + expectRemoveEvent("file.txt"); + }); + + test("emits a modify event when another file is moved on top of the watched " + "file", () { + writeFile("old.txt"); + startWatcher(path: "file.txt"); + renameFile("old.txt", "file.txt"); + expectModifyEvent("file.txt"); + }); +} From 4ebee52f25f6d053f7283602fd61201ddddfdc2f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 29 Jun 2015 16:28:11 -0700 Subject: [PATCH 0204/1215] Add tests for stack chains in the browser. Now that dart-lang/sdkdart-lang/stack_trace#15171 is fixed, this works! R=rnystrom@google.com Review URL: https://codereview.chromium.org//1218903003. --- pkgs/stack_trace/CHANGELOG.md | 7 + pkgs/stack_trace/lib/src/chain.dart | 7 - pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 282 ++++++++++++++ pkgs/stack_trace/test/chain/dart2js_test.dart | 338 ++++++++++++++++ pkgs/stack_trace/test/chain/utils.dart | 93 +++++ .../{chain_test.dart => chain/vm_test.dart} | 361 +----------------- 7 files changed, 726 insertions(+), 364 deletions(-) create mode 100644 pkgs/stack_trace/test/chain/chain_test.dart create mode 100644 pkgs/stack_trace/test/chain/dart2js_test.dart create mode 100644 pkgs/stack_trace/test/chain/utils.dart rename pkgs/stack_trace/test/{chain_test.dart => chain/vm_test.dart} (58%) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 36e9aa8a4..3fdf46eda 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.3.4 + +* No longer say that stack chains aren't supported on dart2js now that + [sdk#15171][] is fixed. Note that this fix only applies to Dart 1.12. + +[sdk#15171]: https://github.com/dart-lang/sdk/issues/15171 + ## 1.3.3 * When a `null` stack trace is passed to a completer or stream controller in diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 3e2100e46..acd17e9d5 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -68,13 +68,6 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - /// - /// Currently, capturing stack chains doesn't work when using dart2js due to - /// issues [15171] and [15105]. Stack chains reported on dart2js will contain - /// only one trace. - /// - /// [15171]: https://code.google.com/p/dart/issues/detail?id=15171 - /// [15105]: https://code.google.com/p/dart/issues/detail?id=15105 static capture(callback(), {ChainHandler onError}) { var spec = new StackZoneSpecification(onError); return runZoned(() { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 578ecc9c1..93b081746 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.3 +version: 1.3.4 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart new file mode 100644 index 000000000..0eb3f0087 --- /dev/null +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -0,0 +1,282 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:path/path.dart' as p; +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + group('Chain.parse()', () { + test('parses a real Chain', () { + return captureFuture(() => inMicrotask(() => throw 'error')) + .then((chain) { + expect(new Chain.parse(chain.toString()).toString(), + equals(chain.toString())); + }); + }); + + test('parses an empty string', () { + var chain = new Chain.parse(''); + expect(chain.traces, isEmpty); + }); + + test('parses a chain containing empty traces', () { + var chain = new Chain.parse( + '===== asynchronous gap ===========================\n' + '===== asynchronous gap ===========================\n'); + expect(chain.traces, hasLength(3)); + expect(chain.traces[0].frames, isEmpty); + expect(chain.traces[1].frames, isEmpty); + expect(chain.traces[2].frames, isEmpty); + }); + }); + + test("toString() ensures that all traces are aligned", () { + var chain = new Chain([ + new Trace.parse('short 10:11 Foo.bar\n'), + new Trace.parse('loooooooooooong 10:11 Zop.zoop') + ]); + + expect(chain.toString(), equals( + 'short 10:11 Foo.bar\n' + '===== asynchronous gap ===========================\n' + 'loooooooooooong 10:11 Zop.zoop\n')); + }); + + var userSlashCode = p.join('user', 'code.dart'); + group('Chain.terse', () { + test('makes each trace terse', () { + var chain = new Chain([ + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n' + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Zip.zap\n' + 'dart:core 10:11 Zop.zoop'), + new Trace.parse( + 'user/code.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap\n' + 'user/code.dart 10:11 Zop.zoop') + ]); + + expect(chain.terse.toString(), equals( + 'dart:core Bar.baz\n' + '$userSlashCode 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Bang.qux\n' + 'dart:core Zip.zap\n' + '$userSlashCode 10:11 Zop.zoop\n')); + }); + + test('eliminates internal-only traces', () { + var chain = new Chain([ + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz'), + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap'), + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz') + ]); + + expect(chain.terse.toString(), equals( + '$userSlashCode 10:11 Foo.bar\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Foo.bar\n')); + }); + + test("doesn't return an empty chain", () { + var chain = new Chain([ + new Trace.parse( + 'dart:core 10:11 Foo.bar\n' + 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' + 'dart:core 10:11 Zip.zap'), + new Trace.parse( + 'dart:core 10:11 A.b\n' + 'package:stack_trace/stack_trace.dart 10:11 C.d\n' + 'dart:core 10:11 E.f') + ]); + + expect(chain.terse.toString(), equals('dart:core E.f\n')); + }); + }); + + group('Chain.foldFrames', () { + test('folds each trace', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'a.dart 10:11 Zop.zoop'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'a.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals( + 'a.dart 10:11 Bar.baz\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + + test('with terse: true, folds core frames as well', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'dart:async-patch/future.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Bang.qux\n' + 'dart:core 10:11 Bar.baz\n' + 'a.dart 10:11 Zop.zoop'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bar.baz\n' + 'a.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart', + terse: true); + expect(folded.toString(), equals( + 'dart:async Zip.zap\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'a.dart Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + + test('eliminates completely-folded traces', () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'b.dart 10:11 Bang.qux'), + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bang.qux'), + new Trace.parse( + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals( + 'a.dart 10:11 Foo.bar\n' + 'b.dart 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); + }); + + test("doesn't return an empty trace", () { + var chain = new Chain([ + new Trace.parse( + 'a.dart 10:11 Foo.bar\n' + 'a.dart 10:11 Bang.qux') + ]); + + var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); + expect(folded.toString(), equals('a.dart 10:11 Bang.qux\n')); + }); + }); + + test('Chain.toTrace eliminates asynchronous gaps', () { + var trace = new Chain([ + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz'), + new Trace.parse( + 'user/code.dart 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz') + ]).toTrace(); + + expect(trace.toString(), equals( + '$userSlashCode 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n' + '$userSlashCode 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n')); + }); + + group('Chain.track(Future)', () { + test('forwards the future value within Chain.capture()', () { + Chain.capture(() { + expect(Chain.track(new Future.value('value')), + completion(equals('value'))); + + var trace = new Trace.current(); + expect(Chain.track(new Future.error('error', trace)) + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + test('forwards the future value outside of Chain.capture()', () { + expect(Chain.track(new Future.value('value')), + completion(equals('value'))); + + var trace = new Trace.current(); + expect(Chain.track(new Future.error('error', trace)) + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + group('Chain.track(Stream)', () { + test('forwards stream values within Chain.capture()', () { + Chain.capture(() { + var controller = new StreamController() + ..add(1)..add(2)..add(3)..close(); + expect(Chain.track(controller.stream).toList(), + completion(equals([1, 2, 3]))); + + var trace = new Trace.current(); + controller = new StreamController()..addError('error', trace); + expect(Chain.track(controller.stream).toList() + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + + test('forwards stream values outside of Chain.capture()', () { + Chain.capture(() { + var controller = new StreamController() + ..add(1)..add(2)..add(3)..close(); + expect(Chain.track(controller.stream).toList(), + completion(equals([1, 2, 3]))); + + var trace = new Trace.current(); + controller = new StreamController()..addError('error', trace); + expect(Chain.track(controller.stream).toList() + .catchError((e, stackTrace) { + expect(e, equals('error')); + expect(stackTrace.toString(), equals(trace.toString())); + }), completes); + }); + }); + }); +} \ No newline at end of file diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart new file mode 100644 index 000000000..afb27fa04 --- /dev/null +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -0,0 +1,338 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +// dart2js chain tests are separated out because dart2js stack traces are +// inconsistent due to inlining and browser differences. These tests don't +// assert anything about the content of the traces, just the number of traces in +// a chain. +@TestOn('js') + +import 'dart:async'; + +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + group('capture() with onError catches exceptions', () { + test('thrown synchronously', () async { + var chain = await captureFuture(() => throw 'error'); + expect(chain.traces, hasLength(1)); + }); + + test('thrown in a microtask', () async { + var chain = await captureFuture(() => inMicrotask(() => throw 'error')); + expect(chain.traces, hasLength(2)); + }); + + test('thrown in a one-shot timer', () async { + var chain = await captureFuture( + () => inOneShotTimer(() => throw 'error')); + expect(chain.traces, hasLength(2)); + }); + + test('thrown in a periodic timer', () async { + var chain = await captureFuture( + () => inPeriodicTimer(() => throw 'error')); + expect(chain.traces, hasLength(2)); + }); + + test('thrown in a nested series of asynchronous operations', () async { + var chain = await captureFuture(() { + inPeriodicTimer(() { + inOneShotTimer(() => inMicrotask(() => throw 'error')); + }); + }); + + expect(chain.traces, hasLength(4)); + }); + + test('thrown in a long future chain', () async { + var chain = await captureFuture(() => inFutureChain(() => throw 'error')); + + // Despite many asynchronous operations, there's only one level of + // nested calls, so there should be only two traces in the chain. This + // is important; programmers expect stack trace memory consumption to be + // O(depth of program), not O(length of program). + expect(chain.traces, hasLength(2)); + }); + + test('thrown in new Future()', () async { + var chain = await captureFuture(() => inNewFuture(() => throw 'error')); + expect(chain.traces, hasLength(3)); + }); + + test('thrown in new Future.sync()', () async { + var chain = await captureFuture(() { + inMicrotask(() => inSyncFuture(() => throw 'error')); + }); + + expect(chain.traces, hasLength(3)); + }); + + test('multiple times', () { + var completer = new Completer(); + var first = true; + + Chain.capture(() { + inMicrotask(() => throw 'first error'); + inPeriodicTimer(() => throw 'second error'); + }, onError: (error, chain) { + try { + if (first) { + expect(error, equals('first error')); + expect(chain.traces, hasLength(2)); + first = false; + } else { + expect(error, equals('second error')); + expect(chain.traces, hasLength(2)); + completer.complete(); + } + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); + } + }); + + return completer.future; + }); + + test('passed to a completer', () async { + var trace = new Trace.current(); + var chain = await captureFuture(() { + inMicrotask(() => completerErrorFuture(trace)); + }); + + expect(chain.traces, hasLength(3)); + + // The first trace is the trace that was manually reported for the + // error. + expect(chain.traces.first.toString(), equals(trace.toString())); + }); + + test('passed to a completer with no stack trace', () async { + var chain = await captureFuture(() { + inMicrotask(() => completerErrorFuture()); + }); + + expect(chain.traces, hasLength(2)); + }); + + test('passed to a stream controller', () async { + var trace = new Trace.current(); + var chain = await captureFuture(() { + inMicrotask(() => controllerErrorStream(trace).listen(null)); + }); + + expect(chain.traces, hasLength(3)); + expect(chain.traces.first.toString(), equals(trace.toString())); + }); + + test('passed to a stream controller with no stack trace', () async { + var chain = await captureFuture(() { + inMicrotask(() => controllerErrorStream().listen(null)); + }); + + expect(chain.traces, hasLength(2)); + }); + + test('and relays them to the parent zone', () { + var completer = new Completer(); + + runZoned(() { + Chain.capture(() { + inMicrotask(() => throw 'error'); + }, onError: (error, chain) { + expect(error, equals('error')); + expect(chain.traces, hasLength(2)); + throw error; + }); + }, onError: (error, chain) { + try { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces, hasLength(2)); + completer.complete(); + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); + } + }); + + return completer.future; + }); + }); + + test('capture() without onError passes exceptions to parent zone', () { + var completer = new Completer(); + + runZoned(() { + Chain.capture(() => inMicrotask(() => throw 'error')); + }, onError: (error, chain) { + try { + expect(error, equals('error')); + expect(chain, new isInstanceOf()); + expect(chain.traces, hasLength(2)); + completer.complete(); + } catch (error, stackTrace) { + completer.completeError(error, stackTrace); + } + }); + + return completer.future; + }); + + group('current() within capture()', () { + test('called in a microtask', () async { + var completer = new Completer(); + Chain.capture(() { + inMicrotask(() => completer.complete(new Chain.current())); + }); + + var chain = await completer.future; + expect(chain.traces, hasLength(2)); + }); + + test('called in a one-shot timer', () async { + var completer = new Completer(); + Chain.capture(() { + inOneShotTimer(() => completer.complete(new Chain.current())); + }); + + var chain = await completer.future; + expect(chain.traces, hasLength(2)); + }); + + test('called in a periodic timer', () async { + var completer = new Completer(); + Chain.capture(() { + inPeriodicTimer(() => completer.complete(new Chain.current())); + }); + + var chain = await completer.future; + expect(chain.traces, hasLength(2)); + }); + + test('called in a nested series of asynchronous operations', () async { + var completer = new Completer(); + Chain.capture(() { + inPeriodicTimer(() { + inOneShotTimer(() { + inMicrotask(() => completer.complete(new Chain.current())); + }); + }); + }); + + var chain = await completer.future; + expect(chain.traces, hasLength(4)); + }); + + test('called in a long future chain', () async { + var completer = new Completer(); + Chain.capture(() { + inFutureChain(() => completer.complete(new Chain.current())); + }); + + var chain = await completer.future; + expect(chain.traces, hasLength(2)); + }); + }); + + test('current() outside of capture() returns a chain wrapping the current ' + 'trace', () { + // The test runner runs all tests with chains enabled, so to test without we + // have to do some zone munging. + return runZoned(() async { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); + + var chain = await completer.future; + // Since the chain wasn't loaded within [Chain.capture], the full stack + // chain isn't available and it just returns the current stack when + // called. + expect(chain.traces, hasLength(1)); + }, zoneValues: {#stack_trace.stack_zone.spec: null}); + }); + + group('forTrace() within capture()', () { + test('called for a stack trace from a microtask', () async { + var chain = await Chain.capture(() { + return chainForTrace(inMicrotask, () => throw 'error'); + }); + + // Because [chainForTrace] has to set up a future chain to capture the + // stack trace while still showing it to the zone specification, it adds + // an additional level of async nesting and so an additional trace. + expect(chain.traces, hasLength(3)); + }); + + test('called for a stack trace from a one-shot timer', () async { + var chain = await Chain.capture(() { + return chainForTrace(inOneShotTimer, () => throw 'error'); + }); + + expect(chain.traces, hasLength(3)); + }); + + test('called for a stack trace from a periodic timer', () async { + var chain = await Chain.capture(() { + return chainForTrace(inPeriodicTimer, () => throw 'error'); + }); + + expect(chain.traces, hasLength(3)); + }); + + test('called for a stack trace from a nested series of asynchronous ' + 'operations', () async { + var chain = await Chain.capture(() { + return chainForTrace((callback) { + inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); + }, () => throw 'error'); + }); + + expect(chain.traces, hasLength(5)); + }); + + test('called for a stack trace from a long future chain', () async { + var chain = await Chain.capture(() { + return chainForTrace(inFutureChain, () => throw 'error'); + }); + + expect(chain.traces, hasLength(3)); + }); + + test('called for an unregistered stack trace returns a chain wrapping that ' + 'trace', () { + var trace; + var chain = Chain.capture(() { + try { + throw 'error'; + } catch (_, stackTrace) { + trace = stackTrace; + return new Chain.forTrace(stackTrace); + } + }); + + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.toString(), + equals(new Trace.from(trace).toString())); + }); + }); + + test('forTrace() outside of capture() returns a chain wrapping the given ' + 'trace', () { + var trace; + var chain = Chain.capture(() { + try { + throw 'error'; + } catch (_, stackTrace) { + trace = stackTrace; + return new Chain.forTrace(stackTrace); + } + }); + + expect(chain.traces, hasLength(1)); + expect(chain.traces.first.toString(), + equals(new Trace.from(trace).toString())); + }); +} diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart new file mode 100644 index 000000000..1e19eeb3c --- /dev/null +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -0,0 +1,93 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.test.chain.utils; + +import 'dart:async'; + +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; + +/// Runs [callback] in a microtask callback. +void inMicrotask(callback()) => scheduleMicrotask(callback); + +/// Runs [callback] in a one-shot timer callback. +void inOneShotTimer(callback()) => Timer.run(callback); + +/// Runs [callback] once in a periodic timer callback. +void inPeriodicTimer(callback()) { + var count = 0; + new Timer.periodic(new Duration(milliseconds: 1), (timer) { + count++; + if (count != 5) return; + timer.cancel(); + callback(); + }); +} + +/// Runs [callback] within a long asynchronous Future chain. +void inFutureChain(callback()) { + new Future(() {}) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => new Future(() {})) + .then((_) => callback()) + .then((_) => new Future(() {})); +} + +void inNewFuture(callback()) { + new Future(callback); +} + +void inSyncFuture(callback()) { + new Future.sync(callback); +} + +/// Returns a Future that completes to an error using a completer. +/// +/// If [trace] is passed, it's used as the stack trace for the error. +Future completerErrorFuture([StackTrace trace]) { + var completer = new Completer(); + completer.completeError('error', trace); + return completer.future; +} + +/// Returns a Stream that emits an error using a controller. +/// +/// If [trace] is passed, it's used as the stack trace for the error. +Stream controllerErrorStream([StackTrace trace]) { + var controller = new StreamController(); + controller.addError('error', trace); + return controller.stream; +} + +/// Runs [callback] within [asyncFn], then converts any errors raised into a +/// [Chain] with [Chain.forTrace]. +Future chainForTrace(asyncFn(callback()), callback()) { + var completer = new Completer(); + asyncFn(() { + // We use `new Future.value().then(...)` here as opposed to [new Future] or + // [new Future.sync] because those methods don't pass the exception through + // the zone specification before propagating it, so there's no chance to + // attach a chain to its stack trace. See issue 15105. + new Future.value().then((_) => callback()) + .catchError(completer.completeError); + }); + return completer.future + .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); +} + +/// Runs [callback] in a [Chain.capture] zone and returns a Future that +/// completes to the stack chain for an error thrown by [callback]. +/// +/// [callback] is expected to throw the string `"error"`. +Future captureFuture(callback()) { + var completer = new Completer(); + Chain.capture(callback, onError: (error, chain) { + expect(error, equals('error')); + completer.complete(chain); + }); + return completer.future; +} diff --git a/pkgs/stack_trace/test/chain_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart similarity index 58% rename from pkgs/stack_trace/test/chain_test.dart rename to pkgs/stack_trace/test/chain/vm_test.dart index 65d6790f9..70635b754 100644 --- a/pkgs/stack_trace/test/chain_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -1,16 +1,17 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file // 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. -// dart2js currently doesn't support chain-capturing. See sdk#15171. -@TestOn('vm') +// VM chain tests can rely on stronger guarantees about the contents of the +// stack traces than dart2js. +@TestOn('dart-vm') import 'dart:async'; -import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; +import '../utils.dart'; import 'utils.dart'; void main() { @@ -477,356 +478,4 @@ void main() { expect(chain.traces.first.toString(), equals(new Trace.from(trace).toString())); }); - - group('Chain.parse()', () { - test('parses a real Chain', () { - return captureFuture(() => inMicrotask(() => throw 'error')) - .then((chain) { - expect(new Chain.parse(chain.toString()).toString(), - equals(chain.toString())); - }); - }); - - test('parses an empty string', () { - var chain = new Chain.parse(''); - expect(chain.traces, isEmpty); - }); - - test('parses a chain containing empty traces', () { - var chain = new Chain.parse( - '===== asynchronous gap ===========================\n' - '===== asynchronous gap ===========================\n'); - expect(chain.traces, hasLength(3)); - expect(chain.traces[0].frames, isEmpty); - expect(chain.traces[1].frames, isEmpty); - expect(chain.traces[2].frames, isEmpty); - }); - }); - - test("toString() ensures that all traces are aligned", () { - var chain = new Chain([ - new Trace.parse('short 10:11 Foo.bar\n'), - new Trace.parse('loooooooooooong 10:11 Zop.zoop') - ]); - - expect(chain.toString(), equals( - 'short 10:11 Foo.bar\n' - '===== asynchronous gap ===========================\n' - 'loooooooooooong 10:11 Zop.zoop\n')); - }); - - var userSlashCode = p.join('user', 'code.dart'); - group('Chain.terse', () { - test('makes each trace terse', () { - var chain = new Chain([ - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz\n' - 'user/code.dart 10:11 Bang.qux\n' - 'dart:core 10:11 Zip.zap\n' - 'dart:core 10:11 Zop.zoop'), - new Trace.parse( - 'user/code.dart 10:11 Bang.qux\n' - 'dart:core 10:11 Foo.bar\n' - 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' - 'dart:core 10:11 Zip.zap\n' - 'user/code.dart 10:11 Zop.zoop') - ]); - - expect(chain.terse.toString(), equals( - 'dart:core Bar.baz\n' - '$userSlashCode 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Bang.qux\n' - 'dart:core Zip.zap\n' - '$userSlashCode 10:11 Zop.zoop\n')); - }); - - test('eliminates internal-only traces', () { - var chain = new Chain([ - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz'), - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' - 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' - 'dart:core 10:11 Zip.zap'), - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz') - ]); - - expect(chain.terse.toString(), equals( - '$userSlashCode 10:11 Foo.bar\n' - '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Foo.bar\n')); - }); - - test("doesn't return an empty chain", () { - var chain = new Chain([ - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' - 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' - 'dart:core 10:11 Zip.zap'), - new Trace.parse( - 'dart:core 10:11 A.b\n' - 'package:stack_trace/stack_trace.dart 10:11 C.d\n' - 'dart:core 10:11 E.f') - ]); - - expect(chain.terse.toString(), equals('dart:core E.f\n')); - }); - }); - - group('Chain.foldFrames', () { - test('folds each trace', () { - var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'a.dart 10:11 Bar.baz\n' - 'b.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zip.zap\n' - 'a.dart 10:11 Zop.zoop'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'a.dart 10:11 Bar.baz\n' - 'a.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop') - ]); - - var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); - expect(folded.toString(), equals( - 'a.dart 10:11 Bar.baz\n' - 'b.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zop.zoop\n' - '===== asynchronous gap ===========================\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); - }); - - test('with terse: true, folds core frames as well', () { - var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'dart:async-patch/future.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Bang.qux\n' - 'dart:core 10:11 Bar.baz\n' - 'a.dart 10:11 Zop.zoop'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'a.dart 10:11 Bar.baz\n' - 'a.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop') - ]); - - var folded = chain.foldFrames((frame) => frame.library == 'a.dart', - terse: true); - expect(folded.toString(), equals( - 'dart:async Zip.zap\n' - 'b.dart 10:11 Bang.qux\n' - 'a.dart Zop.zoop\n' - '===== asynchronous gap ===========================\n' - 'a.dart Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); - }); - - test('eliminates completely-folded traces', () { - var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'b.dart 10:11 Bang.qux'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'a.dart 10:11 Bang.qux'), - new Trace.parse( - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop') - ]); - - var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); - expect(folded.toString(), equals( - 'a.dart 10:11 Foo.bar\n' - 'b.dart 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); - }); - - test("doesn't return an empty trace", () { - var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' - 'a.dart 10:11 Bang.qux') - ]); - - var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); - expect(folded.toString(), equals('a.dart 10:11 Bang.qux\n')); - }); - }); - - test('Chain.toTrace eliminates asynchronous gaps', () { - var trace = new Chain([ - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz'), - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz') - ]).toTrace(); - - expect(trace.toString(), equals( - '$userSlashCode 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz\n' - '$userSlashCode 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz\n')); - }); - - group('Chain.track(Future)', () { - test('forwards the future value within Chain.capture()', () { - Chain.capture(() { - expect(Chain.track(new Future.value('value')), - completion(equals('value'))); - - var trace = new Trace.current(); - expect(Chain.track(new Future.error('error', trace)) - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - test('forwards the future value outside of Chain.capture()', () { - expect(Chain.track(new Future.value('value')), - completion(equals('value'))); - - var trace = new Trace.current(); - expect(Chain.track(new Future.error('error', trace)) - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - group('Chain.track(Stream)', () { - test('forwards stream values within Chain.capture()', () { - Chain.capture(() { - var controller = new StreamController() - ..add(1)..add(2)..add(3)..close(); - expect(Chain.track(controller.stream).toList(), - completion(equals([1, 2, 3]))); - - var trace = new Trace.current(); - controller = new StreamController()..addError('error', trace); - expect(Chain.track(controller.stream).toList() - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - test('forwards stream values outside of Chain.capture()', () { - Chain.capture(() { - var controller = new StreamController() - ..add(1)..add(2)..add(3)..close(); - expect(Chain.track(controller.stream).toList(), - completion(equals([1, 2, 3]))); - - var trace = new Trace.current(); - controller = new StreamController()..addError('error', trace); - expect(Chain.track(controller.stream).toList() - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - }); -} - -/// Runs [callback] in a microtask callback. -void inMicrotask(callback()) => scheduleMicrotask(callback); - -/// Runs [callback] in a one-shot timer callback. -void inOneShotTimer(callback()) => Timer.run(callback); - -/// Runs [callback] once in a periodic timer callback. -void inPeriodicTimer(callback()) { - var count = 0; - new Timer.periodic(new Duration(milliseconds: 1), (timer) { - count++; - if (count != 5) return; - timer.cancel(); - callback(); - }); -} - -/// Runs [callback] within a long asynchronous Future chain. -void inFutureChain(callback()) { - new Future(() {}) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) - .then((_) => callback()) - .then((_) => new Future(() {})); -} - -void inNewFuture(callback()) { - new Future(callback); -} - -void inSyncFuture(callback()) { - new Future.sync(callback); -} - -/// Returns a Future that completes to an error using a completer. -/// -/// If [trace] is passed, it's used as the stack trace for the error. -Future completerErrorFuture([StackTrace trace]) { - var completer = new Completer(); - completer.completeError('error', trace); - return completer.future; -} - -/// Returns a Stream that emits an error using a controller. -/// -/// If [trace] is passed, it's used as the stack trace for the error. -Stream controllerErrorStream([StackTrace trace]) { - var controller = new StreamController(); - controller.addError('error', trace); - return controller.stream; -} - -/// Runs [callback] within [asyncFn], then converts any errors raised into a -/// [Chain] with [Chain.forTrace]. -Future chainForTrace(asyncFn(callback()), callback()) { - var completer = new Completer(); - asyncFn(() { - // We use `new Future.value().then(...)` here as opposed to [new Future] or - // [new Future.sync] because those methods don't pass the exception through - // the zone specification before propagating it, so there's no chance to - // attach a chain to its stack trace. See issue 15105. - new Future.value().then((_) => callback()) - .catchError(completer.completeError); - }); - return completer.future - .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); -} - -/// Runs [callback] in a [Chain.capture] zone and returns a Future that -/// completes to the stack chain for an error thrown by [callback]. -/// -/// [callback] is expected to throw the string `"error"`. -Future captureFuture(callback()) { - var completer = new Completer(); - Chain.capture(callback, onError: (error, chain) { - expect(error, equals('error')); - completer.complete(chain); - }); - return completer.future; } From 39c1bee4aa3faf2877b2500110b968faa47e3626 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 7 Jul 2015 14:52:23 -0700 Subject: [PATCH 0205/1215] Use the test runner on the bots. R=kevmoo@google.com Review URL: https://codereview.chromium.org//1221303016. --- pkgs/stack_trace/.test_config | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pkgs/stack_trace/.test_config diff --git a/pkgs/stack_trace/.test_config b/pkgs/stack_trace/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/stack_trace/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file From 38659eed6e605179faaaae6a263f408c3fdda3c1 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 13 Jul 2015 13:14:30 -0700 Subject: [PATCH 0206/1215] Properly shorten library names on Windows. The library getter may be URL- or path-formatted, so to make Windows work we need to split on both kinds of separator. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1234733002 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 1 - pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 3fdf46eda..c660d8248 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.5 + +* Properly shorten library names for pathnames of folded frames on Windows. + ## 1.3.4 * No longer say that stack chains aren't supported on dart2js now that diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 9043d2baa..476b39c88 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -4,7 +4,6 @@ library frame; - import 'package:path/path.dart' as path; import 'trace.dart'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 4415161cb..a1691ed18 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -13,7 +13,7 @@ import 'lazy_trace.dart'; import 'utils.dart'; import 'vm_trace.dart'; -final _terseRegExp = new RegExp(r"(-patch)?(/.*)?$"); +final _terseRegExp = new RegExp(r"(-patch)?([/\\].*)?$"); /// A RegExp to match V8's stack traces. /// diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 93b081746..5a6117585 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.4 +version: 1.3.5 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 2f43e83906900d652604b4d77d1a7a65e9f91177 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Jul 2015 13:43:51 -0700 Subject: [PATCH 0207/1215] Upgrade to the new test runner. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1228353010 . --- pkgs/string_scanner/.gitignore | 1 + pkgs/string_scanner/.status | 3 --- pkgs/string_scanner/.test_config | 3 +++ pkgs/string_scanner/pubspec.yaml | 4 ++-- pkgs/string_scanner/test/error_test.dart | 2 +- pkgs/string_scanner/test/line_scanner_test.dart | 2 +- pkgs/string_scanner/test/span_scanner_test.dart | 2 +- pkgs/string_scanner/test/string_scanner_test.dart | 2 +- pkgs/string_scanner/test/utils.dart | 2 +- 9 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 pkgs/string_scanner/.status create mode 100644 pkgs/string_scanner/.test_config diff --git a/pkgs/string_scanner/.gitignore b/pkgs/string_scanner/.gitignore index 388eff0ba..7dbf0350d 100644 --- a/pkgs/string_scanner/.gitignore +++ b/pkgs/string_scanner/.gitignore @@ -3,6 +3,7 @@ .pub/ build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/string_scanner/.status b/pkgs/string_scanner/.status deleted file mode 100644 index e9f2b0049..000000000 --- a/pkgs/string_scanner/.status +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -# 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. diff --git a/pkgs/string_scanner/.test_config b/pkgs/string_scanner/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/string_scanner/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index ffd4ccc2a..16477beeb 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.3+1 +version: 0.1.4-dev author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > @@ -8,6 +8,6 @@ dependencies: path: ">=1.2.0 <2.0.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: - unittest: ">=0.10.0 <0.12.0" + test: ">=0.12.0 <0.13.0" environment: sdk: ">=1.2.0 <2.0.0" diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index d7b81e812..9c485e559 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -5,7 +5,7 @@ library string_scanner.error_test; import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 8cc79a65c..83222d6ce 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -5,7 +5,7 @@ library string_scanner.line_scanner_test; import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; void main() { var scanner; diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 796df2968..a6249b719 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -5,7 +5,7 @@ library string_scanner.span_scanner_test; import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; void main() { var scanner; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 7b00796ce..c8e43a5aa 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -5,7 +5,7 @@ library string_scanner.string_scanner_test; import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; void main() { group('with an empty string', () { diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index 3de601cf1..8df4b510f 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -5,7 +5,7 @@ library string_scanner.test.utils; import 'package:string_scanner/string_scanner.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; /// Returns a matcher that asserts that a closure throws a [FormatException] /// with the given [message]. From d976b9cfedcadcdb32de359bbac6bcf4b1e7f581 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Jul 2015 13:45:18 -0700 Subject: [PATCH 0208/1215] Use the new test runner on the bots. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1228353011 . --- pkgs/watcher/.gitignore | 1 + pkgs/watcher/.status | 30 ------------------------------ pkgs/watcher/.test_config | 5 +++++ 3 files changed, 6 insertions(+), 30 deletions(-) delete mode 100644 pkgs/watcher/.status create mode 100644 pkgs/watcher/.test_config diff --git a/pkgs/watcher/.gitignore b/pkgs/watcher/.gitignore index 388eff0ba..7dbf0350d 100644 --- a/pkgs/watcher/.gitignore +++ b/pkgs/watcher/.gitignore @@ -3,6 +3,7 @@ .pub/ build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/watcher/.status b/pkgs/watcher/.status deleted file mode 100644 index e79b8e04a..000000000 --- a/pkgs/watcher/.status +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -# 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. - -# Skip non-test files ending with "_test". -packages/*: Skip -*/packages/*: Skip -*/*/packages/*: Skip -*/*/*/packages/*: Skip -*/*/*/*packages/*: Skip -*/*/*/*/*packages/*: Skip - -# Only run tests from the build directory, since we don't care about the -# difference between transformed an untransformed code. -test/*: Skip - -[ $browser ] -*: Fail, OK # Uses dart:io. - -[ $arch == simarm && $checked ] -build/test/directory_watcher/linux_test: Skip # Issue 16118 - -[ $runtime == vm && ($system == windows || $system == macos) ] -build/test/*: Skip - -[ $runtime == vm && ($system == windows || $system == linux) ] -build/test/*: Skip - -[ $runtime == vm && ($system == macos || $system == linux) ] -build/test/*: Skip diff --git a/pkgs/watcher/.test_config b/pkgs/watcher/.test_config new file mode 100644 index 000000000..531426abb --- /dev/null +++ b/pkgs/watcher/.test_config @@ -0,0 +1,5 @@ +{ + "test_package": { + "platforms": ["vm"] + } +} \ No newline at end of file From 517a7f2f7c3dc66741b119d07d6053ced9f23aae Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 16 Jul 2015 16:24:57 -0700 Subject: [PATCH 0209/1215] Fix a race condition in file watcher. It was possible for events to be added to the events controller after it had been closed if the call to close() came in while a method was waiting on an asynchronous callback. R=cbracken@google.com Review URL: https://codereview.chromium.org//1228703007 . --- pkgs/watcher/CHANGELOG.md | 5 +++++ pkgs/watcher/lib/src/file_watcher/native.dart | 15 +++++++++++---- pkgs/watcher/lib/src/file_watcher/polling.dart | 12 +++++++++--- pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/file_watcher/shared.dart | 17 +++++++++++++++++ 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 4ff6cfaf6..30762a034 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7 + +* Fix a bug in `FileWatcher` where events could be added after watchers were + closed. + # 0.9.6 * Add a `Watcher` interface that encompasses watching both files and diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index f5699bbb4..1862e7b05 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -60,10 +60,17 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { } _onDone() async { - // If the file exists now, it was probably removed and quickly replaced; - // this can happen for example when another file is moved on top of it. - // Re-subscribe and report a modify event. - if (await new File(path).exists()) { + var fileExists = await new File(path).exists(); + + // Check for this after checking whether the file exists because it's + // possible that [close] was called between [File.exists] being called and + // it completing. + if (_eventsController.isClosed) return; + + if (fileExists) { + // If the file exists now, it was probably removed and quickly replaced; + // this can happen for example when another file is moved on top of it. + // Re-subscribe and report a modify event. _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); _listen(); } else { diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index a44f80cdb..3480ae29e 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -51,7 +51,10 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { // We don't mark the file as removed if this is the first poll (indicated by // [_lastModified] being null). Instead, below we forward the dart:io error // that comes from trying to read the mtime below. - if (_lastModified != null && !await new File(path).exists()) { + var pathExists = await new File(path).exists(); + if (_eventsController.isClosed) return; + + if (_lastModified != null && !pathExists) { _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); close(); return; @@ -59,14 +62,17 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { var modified; try { - modified = await getModificationTime(path); + try { + modified = await getModificationTime(path); + } finally { + if (_eventsController.isClosed) return; + } } on FileSystemException catch (error, stackTrace) { _eventsController.addError(error, stackTrace); close(); return; } - if (_eventsController.isClosed) return; if (_lastModified == modified) return; if (_lastModified == null) { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index f62248da2..2e033f153 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.6 +version: 0.9.7 author: Dart Team homepage: http://github.com/dart-lang/watcher description: > diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 2931d8022..9a4965ccc 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -2,6 +2,8 @@ // 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. +import 'dart:async'; + import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/utils.dart'; @@ -55,4 +57,19 @@ void sharedTests() { renameFile("old.txt", "file.txt"); expectModifyEvent("file.txt"); }); + + // Regression test for a race condition. + test("closes the watcher immediately after deleting the file", () { + writeFile("old.txt"); + var watcher = createWatcher(path: "file.txt", waitForReady: false); + var sub = schedule(() => watcher.events.listen(null)); + + deleteFile("file.txt"); + schedule(() async { + // Reproducing the race condition will always be flaky, but this sleep + // helped it reproduce more consistently on my machine. + await new Future.delayed(new Duration(milliseconds: 10)); + (await sub).cancel(); + }); + }); } From cfd76b571697ea98fef6b3a63ba937d0415d77cc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 11 Aug 2015 17:31:56 -0700 Subject: [PATCH 0210/1215] Properly parse native-code V8 frames. Fixes dart-lang/testdart-lang/stack_trace#316. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1288573002 . --- pkgs/stack_trace/.gitignore | 1 + pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 7 ++++++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 9 +++++++++ 5 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.gitignore b/pkgs/stack_trace/.gitignore index 388eff0ba..7dbf0350d 100644 --- a/pkgs/stack_trace/.gitignore +++ b/pkgs/stack_trace/.gitignore @@ -3,6 +3,7 @@ .pub/ build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index c660d8248..1d4eaae1d 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.6 + +* Properly parse native-code V8 frames. + ## 1.3.5 * Properly shorten library names for pathnames of folded frames on Windows. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 476b39c88..a5fd6ae2d 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -13,6 +13,7 @@ import 'trace.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart) final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); +// at Object.stringify (native) // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) // at VW.call$0 (eval as fn // (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) @@ -21,7 +22,7 @@ final _v8Frame = new RegExp( r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // http://pub.dartlang.org/stuff.dart.js:560:28 -final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)$'); +final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28 // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) @@ -166,6 +167,10 @@ class Frame { evalMatch = _v8EvalLocation.firstMatch(location); } + if (location == 'native') { + return new Frame(Uri.parse('native'), null, null, member); + } + var urlMatch = _v8UrlLocation.firstMatch(location); if (urlMatch == null) { throw new FormatException( diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 5a6117585..6e233cdd6 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.5 +version: 1.3.6-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 01177f0d7..809822a6d 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -149,6 +149,15 @@ void main() { expect(frame.member, equals('')); }); + test('parses a native stack frame correctly', () { + var frame = new Frame.parseV8( + " at Object.stringify (native)"); + expect(frame.uri, Uri.parse('native')); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('Object.stringify')); + }); + test('parses a stack frame with [as ...] correctly', () { // Ignore "[as ...]", since other stack trace formats don't support a // similar construct. From bf3e1262546cf82d224403d28c7c62c93e3a88ea Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 12 Aug 2015 13:38:48 -0700 Subject: [PATCH 0211/1215] Don't throw for unparseable frames. If the stack trace parser throws when it encounters a frame it doesn't understand, that tends to obscure other errors and generally make life difficult for users. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1283113002 . --- pkgs/stack_trace/CHANGELOG.md | 7 +- pkgs/stack_trace/lib/src/frame.dart | 47 +++++----- pkgs/stack_trace/lib/src/trace.dart | 8 +- pkgs/stack_trace/lib/src/unparsed_frame.dart | 26 ++++++ pkgs/stack_trace/lib/stack_trace.dart | 5 +- pkgs/stack_trace/test/frame_test.dart | 85 +++++++++--------- pkgs/stack_trace/test/trace_test.dart | 90 +++++++++++--------- 7 files changed, 160 insertions(+), 108 deletions(-) create mode 100644 pkgs/stack_trace/lib/src/unparsed_frame.dart diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 1d4eaae1d..ed1a6c7e2 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,9 @@ -## 1.3.6 +## 1.4.0 + +* `new Trace.parse()` and related constructors will no longer throw an exception + if they encounter an unparseable stack frame. Instead, they will generate an + `UnparsedFrame`, which exposes no metadata but preserves the frame's original + text. * Properly parse native-code V8 frames. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index a5fd6ae2d..072983a1b 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -7,6 +7,7 @@ library frame; import 'package:path/path.dart' as path; import 'trace.dart'; +import 'unparsed_frame.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42) @@ -126,7 +127,7 @@ class Frame { } /// Parses a string representation of a Dart VM stack frame. - factory Frame.parseVM(String frame) { + factory Frame.parseVM(String frame) => _catchFormatException(frame, () { // The VM sometimes folds multiple stack frames together and replaces them // with "...". if (frame == '...') { @@ -134,9 +135,7 @@ class Frame { } var match = _vmFrame.firstMatch(frame); - if (match == null) { - throw new FormatException("Couldn't parse VM stack trace line '$frame'."); - } + if (match == null) return new UnparsedFrame(frame); // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. @@ -149,14 +148,12 @@ class Frame { var line = lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; return new Frame(uri, line, column, member); - } + }); /// Parses a string representation of a Chrome/V8 stack frame. - factory Frame.parseV8(String frame) { + factory Frame.parseV8(String frame) => _catchFormatException(frame, () { var match = _v8Frame.firstMatch(frame); - if (match == null) { - throw new FormatException("Couldn't parse V8 stack trace line '$frame'."); - } + if (match == null) return new UnparsedFrame(frame); // v8 location strings can be arbitrarily-nested, since it adds a layer of // nesting for each eval performed on that line. @@ -172,10 +169,7 @@ class Frame { } var urlMatch = _v8UrlLocation.firstMatch(location); - if (urlMatch == null) { - throw new FormatException( - "Couldn't parse V8 stack trace line '$frame'."); - } + if (urlMatch == null) return new UnparsedFrame(frame); return new Frame( _uriOrPathToUri(urlMatch[1]), @@ -197,7 +191,7 @@ class Frame { // functions. return parseLocation(match[3], ""); } - } + }); /// Parses a string representation of a JavaScriptCore stack trace. factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame); @@ -209,12 +203,9 @@ class Frame { factory Frame.parseIE(String frame) => new Frame.parseV8(frame); /// Parses a string representation of a Firefox stack frame. - factory Frame.parseFirefox(String frame) { + factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { var match = _firefoxSafariFrame.firstMatch(frame); - if (match == null) { - throw new FormatException( - "Couldn't parse Firefox/Safari stack trace line '$frame'."); - } + if (match == null) return new UnparsedFrame(frame); // Normally this is a URI, but in a jsshell trace it can be a path. var uri = _uriOrPathToUri(match[3]); @@ -237,7 +228,7 @@ class Frame { var column = match[5] == null || match[5] == '' ? null : int.parse(match[5]); return new Frame(uri, line, column, member); - } + }); /// Parses a string representation of a Safari 6.0 stack frame. @Deprecated("Use Frame.parseSafari instead.") @@ -251,7 +242,7 @@ class Frame { factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); /// Parses this package's string representation of a stack frame. - factory Frame.parseFriendly(String frame) { + factory Frame.parseFriendly(String frame) => _catchFormatException(frame, () { var match = _friendlyFrame.firstMatch(frame); if (match == null) { throw new FormatException( @@ -268,7 +259,7 @@ class Frame { var line = match[2] == null ? null : int.parse(match[2]); var column = match[3] == null ? null : int.parse(match[3]); return new Frame(uri, line, column, match[4]); - } + }); /// A regular expression matching an absolute URI. static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); @@ -294,6 +285,18 @@ class Frame { return Uri.parse(uriOrPath); } + /// Runs [body] and returns its result. + /// + /// If [body] throws a [FormatException], returns an [UnparsedFrame] with + /// [text] instead. + static Frame _catchFormatException(String text, Frame body()) { + try { + return body(); + } on FormatException catch (_) { + return new UnparsedFrame(text); + } + } + Frame(this.uri, this.line, this.column, this.member); String toString() => '$location in $member'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index a1691ed18..f615cd26a 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -10,6 +10,7 @@ import 'dart:math' as math; import 'chain.dart'; import 'frame.dart'; import 'lazy_trace.dart'; +import 'unparsed_frame.dart'; import 'utils.dart'; import 'vm_trace.dart'; @@ -115,7 +116,7 @@ class Trace implements StackTrace { try { if (trace.isEmpty) return new Trace([]); if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); - if (trace.startsWith("\tat ")) return new Trace.parseJSCore(trace); + if (trace.contains("\tat ")) return new Trace.parseJSCore(trace); if (trace.contains(_firefoxSafariTrace)) { return new Trace.parseFirefox(trace); } @@ -262,7 +263,7 @@ class Trace implements StackTrace { var newFrames = []; for (var frame in frames.reversed) { - if (!predicate(frame)) { + if (frame is UnparsedFrame || !predicate(frame)) { newFrames.add(frame); } else if (newFrames.isEmpty || !predicate(newFrames.last)) { newFrames.add(new Frame( @@ -272,7 +273,7 @@ class Trace implements StackTrace { if (terse) { newFrames = newFrames.map((frame) { - if (!predicate(frame)) return frame; + if (frame is UnparsedFrame || !predicate(frame)) return frame; var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); }).toList(); @@ -290,6 +291,7 @@ class Trace implements StackTrace { // Print out the stack trace nicely formatted. return frames.map((frame) { + if (frame is UnparsedFrame) return "$frame\n"; return '${padRight(frame.location, longest)} ${frame.member}\n'; }).join(); } diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart new file mode 100644 index 000000000..19d09c65f --- /dev/null +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library stack_trace.unparsed_frame; + +import 'frame.dart'; + +/// A frame that failed to parse. +/// +/// The [member] property contains the original frame's contents. +class UnparsedFrame implements Frame { + final Uri uri = new Uri(path: "unparsed"); + final int line = null; + final int column = null; + final bool isCore = false; + final String library = "unparsed"; + final String package = null; + final String location = "unparsed"; + + final String member; + + UnparsedFrame(this.member); + + String toString() => _original; +} \ No newline at end of file diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index ac875a910..6bba6350f 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -23,6 +23,7 @@ */ library stack_trace; -export 'src/trace.dart'; -export 'src/frame.dart'; export 'src/chain.dart'; +export 'src/frame.dart'; +export 'src/trace.dart'; +export 'src/unparsed_frame.dart'; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 809822a6d..1233cbf85 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -71,14 +71,14 @@ void main() { expect(frame.column, isNull); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseVM(''), throwsFormatException); - expect(() => new Frame.parseVM('#1'), throwsFormatException); - expect(() => new Frame.parseVM('#1 Foo'), throwsFormatException); - expect(() => new Frame.parseVM('#1 (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseVM('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); + test('returns an UnparsedFrame for malformed frames', () { + expectIsUnparsed((text) => new Frame.parseV8(text), ''); + expectIsUnparsed((text) => new Frame.parseV8(text), '#1'); + expectIsUnparsed((text) => new Frame.parseV8(text), '#1 Foo'); + expectIsUnparsed((text) => new Frame.parseV8(text), + '#1 (dart:async/future.dart:10:15)'); + expectIsUnparsed((text) => new Frame.parseV8(text), + 'Foo (dart:async/future.dart:10:15)'); }); }); @@ -219,24 +219,22 @@ void main() { equals('..bar')); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseV8(''), throwsFormatException); - expect(() => new Frame.parseV8(' at'), throwsFormatException); - expect(() => new Frame.parseV8(' at Foo'), throwsFormatException); - expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at Foo (dart:async/future.dart:10)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseV8('Foo (dart:async/future.dart:10:15)'), - throwsFormatException); - expect(() => new Frame.parseV8(' at dart:async/future.dart'), - throwsFormatException); - expect(() => new Frame.parseV8(' at dart:async/future.dart:10'), - throwsFormatException); - expect(() => new Frame.parseV8('dart:async/future.dart:10:15'), - throwsFormatException); + test('returns an UnparsedFrame for malformed frames', () { + expectIsUnparsed((text) => new Frame.parseV8(text), ''); + expectIsUnparsed((text) => new Frame.parseV8(text), ' at'); + expectIsUnparsed((text) => new Frame.parseV8(text), ' at Foo'); + expectIsUnparsed((text) => new Frame.parseV8(text), + ' at Foo (dart:async/future.dart)'); + expectIsUnparsed((text) => new Frame.parseV8(text), + ' at (dart:async/future.dart:10:15)'); + expectIsUnparsed((text) => new Frame.parseV8(text), + 'Foo (dart:async/future.dart:10:15)'); + expectIsUnparsed((text) => new Frame.parseV8(text), + ' at dart:async/future.dart'); + expectIsUnparsed((text) => new Frame.parseV8(text), + ' at dart:async/future.dart:10'); + expectIsUnparsed((text) => new Frame.parseV8(text), + 'dart:async/future.dart:10:15'); }); }); @@ -376,15 +374,15 @@ void main() { expect(frame.member, equals("convertDartClosureToJS..")); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseFirefox(''), throwsFormatException); - expect(() => new Frame.parseFirefox('.foo'), throwsFormatException); - expect(() => new Frame.parseFirefox('.foo@dart:async/future.dart'), - throwsFormatException); - expect(() => new Frame.parseFirefox('.foo(@dart:async/future.dart:10'), - throwsFormatException); - expect(() => new Frame.parseFirefox('@dart:async/future.dart'), - throwsFormatException); + test('returns an UnparsedFrame for malformed frames', () { + expectIsUnparsed((text) => new Frame.parseFirefox(text), ''); + expectIsUnparsed((text) => new Frame.parseFirefox(text), '.foo'); + expectIsUnparsed((text) => new Frame.parseFirefox(text), + '.foo@dart:async/future.dart'); + expectIsUnparsed((text) => new Frame.parseFirefox(text), + '.foo(@dart:async/future.dart:10'); + expectIsUnparsed((text) => new Frame.parseFirefox(text), + '@dart:async/future.dart'); }); test('parses a simple stack frame correctly', () { @@ -470,12 +468,11 @@ void main() { expect(frame.member, equals('Foo..bar')); }); - test('throws a FormatException for malformed frames', () { - expect(() => new Frame.parseFriendly(''), throwsFormatException); - expect(() => new Frame.parseFriendly('foo/bar.dart'), - throwsFormatException); - expect(() => new Frame.parseFriendly('foo/bar.dart 10:11'), - throwsFormatException); + test('returns an UnparsedFrame for malformed frames', () { + expectIsUnparsed((text) => new Frame.parseFriendly(text), ''); + expectIsUnparsed((text) => new Frame.parseFriendly(text), 'foo/bar.dart'); + expectIsUnparsed((text) => new Frame.parseFriendly(text), + 'foo/bar.dart 10:11'); }); }); @@ -562,3 +559,9 @@ void main() { }); }); } + +void expectIsUnparsed(Frame constructor(String text), String text) { + var frame = constructor(text); + expect(frame, new isInstanceOf()); + expect(frame.toString(), equals(text)); +} diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 14e1e2bd1..1cc32f7cc 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -293,8 +293,9 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap '#3 baz (dart:async:15:0)\n')); }); - test('.terse folds core frames together bottom-up', () { - var trace = new Trace.parse(''' + group("folding", () { + test('.terse folds core frames together bottom-up', () { + var trace = new Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) #0 notCore (foo.dart:42:21) @@ -303,30 +304,30 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap #5 alsoNotCore (bar.dart:10:20) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:core bottom foo.dart 42:21 notCore dart:async bottom bar.dart 10:20 alsoNotCore ''')); - }); + }); - test('.terse folds empty async frames', () { - var trace = new Trace.parse(''' + test('.terse folds empty async frames', () { + var trace = new Trace.parse(''' #0 top (dart:async/future.dart:0:2) #1 empty.<_async_body> (bar.dart) #2 bottom (dart:async-patch/future.dart:9:11) #3 notCore (foo.dart:42:21) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:async bottom foo.dart 42:21 notCore ''')); - }); + }); - test('.terse removes the bottom-most async frame', () { - var trace = new Trace.parse(''' + test('.terse removes the bottom-most async frame', () { + var trace = new Trace.parse(''' #0 notCore (foo.dart:42:21) #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) @@ -334,32 +335,28 @@ foo.dart 42:21 notCore #4 bottom (dart:async-patch/future.dart:9:11) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' foo.dart 42:21 notCore ''')); - }); + }); - test(".terse won't make a trace empty", () { - var trace = new Trace.parse(''' + test(".terse won't make a trace empty", () { + var trace = new Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:core bottom ''')); - }); - - test(".terse won't panic on an empty trace", () { - var trace = new Trace.parse(''' -'''); + }); - expect(trace.terse.toString(), equals(''' -''')); - }); + test(".terse won't panic on an empty trace", () { + expect(Trace.parse("").terse.toString(), equals("")); + }); - test('.foldFrames folds frames together bottom-up', () { - var trace = new Trace.parse(''' + test('.foldFrames folds frames together bottom-up', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (foo.dart:1:100) @@ -368,17 +365,17 @@ dart:core bottom #5 fooBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo foo.dart 1:100 fooBottom bar.dart 10:20 alsoNotFoo dart:async-patch/future.dart 9:11 fooBottom ''')); - }); + }); - test('.foldFrames with terse: true folds core frames as well', () { - var trace = new Trace.parse(''' + test('.foldFrames with terse: true folds core frames as well', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 coreBottom (dart:async/future.dart:0:2) @@ -387,17 +384,17 @@ dart:async-patch/future.dart 9:11 fooBottom #5 coreBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), - terse: true); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo dart:async coreBottom bar.dart 10:20 alsoNotFoo ''')); - }); + }); - test('.foldFrames with terse: true shortens folded frames', () { - var trace = new Trace.parse(''' + test('.foldFrames with terse: true shortens folded frames', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (package:foo/bar.dart:0:2) @@ -406,13 +403,28 @@ bar.dart 10:20 alsoNotFoo #5 fooBottom (foo/bar.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), - terse: true); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo package:foo fooBottom bar.dart 10:20 alsoNotFoo foo fooBottom ''')); + }); + + test('.foldFrames will never fold unparsed frames', () { + var trace = new Trace.parse(r''' +.g"cs$#:b";a#>sw{*{ul$"$xqwr`p +%+j-?uppx<([j@#nu{{>*+$%x-={`{ +!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ +'''); + + expect(trace.foldFrames((frame) => true).toString(), equals(r''' +.g"cs$#:b";a#>sw{*{ul$"$xqwr`p +%+j-?uppx<([j@#nu{{>*+$%x-={`{ +!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ +''')); + }); }); } From 0a7e64eb5ae9b365c0e2a92679497e31fdfb7075 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 12 Aug 2015 13:41:04 -0700 Subject: [PATCH 0212/1215] Fix the pubspec version. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 6e233cdd6..95c26320c 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.3.6-dev +version: 1.4.0 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From a5c05af481981fa50f0762456b1e33b9fbdf8eaf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 12 Aug 2015 14:11:20 -0700 Subject: [PATCH 0213/1215] Fix a couple bugs introduced in the last CL. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1291633004 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/unparsed_frame.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/trace_test.dart | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ed1a6c7e2..defe09309 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.1 + +* Fix a crashing bug in `UnparsedFrame.toString()`. + ## 1.4.0 * `new Trace.parse()` and related constructors will no longer throw an exception diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index 19d09c65f..f037c8a5a 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -22,5 +22,5 @@ class UnparsedFrame implements Frame { UnparsedFrame(this.member); - String toString() => _original; + String toString() => member; } \ No newline at end of file diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 95c26320c..7274bcc7e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.4.0 +version: 1.4.1 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 1cc32f7cc..d12bc71f1 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -352,7 +352,7 @@ dart:core bottom }); test(".terse won't panic on an empty trace", () { - expect(Trace.parse("").terse.toString(), equals("")); + expect(new Trace.parse("").terse.toString(), equals("")); }); test('.foldFrames folds frames together bottom-up', () { From 8712d0807d6ba0f807a0c503ff7005a401529904 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 1 Sep 2015 17:11:08 -0700 Subject: [PATCH 0214/1215] Properly handle CR LF in LineScanner. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1327713003 . --- pkgs/string_scanner/CHANGELOG.md | 5 +++ pkgs/string_scanner/lib/src/line_scanner.dart | 32 +++++++++++--- pkgs/string_scanner/pubspec.yaml | 3 +- .../test/line_scanner_test.dart | 44 ++++++++++++++++--- 4 files changed, 69 insertions(+), 15 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index ce1e01212..ddfd54016 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.3+2 + +* Fix `LineScanner`'s handling of carriage returns to match that of + `SpanScanner`. + ## 0.1.3+1 * Fixed the homepage URL. diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 54ecf7bf9..6a2880b5e 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -4,8 +4,13 @@ library string_scanner.line_scanner; +import 'package:charcode/ascii.dart'; + import 'string_scanner.dart'; +/// A regular expression matching newlines across platforms. +final _newlineRegExp = new RegExp(r"\r\n?|\n"); + /// A subclass of [StringScanner] that tracks line and column information. class LineScanner extends StringScanner { /// The scanner's current (zero-based) line number. @@ -24,6 +29,10 @@ class LineScanner extends StringScanner { LineScannerState get state => new LineScannerState._(this, position, line, column); + /// Whether the current position is between a CR character and an LF + /// charactet. + bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; + set state(LineScannerState state) { if (!identical(state._scanner, this)) { throw new ArgumentError("The given LineScannerState was not returned by " @@ -40,8 +49,7 @@ class LineScanner extends StringScanner { super.position = newPosition; if (newPosition > oldPosition) { - var newlines = - "\n".allMatches(string.substring(oldPosition, newPosition)).toList(); + var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); _line += newlines.length; if (newlines.isEmpty) { _column += newPosition - oldPosition; @@ -49,13 +57,15 @@ class LineScanner extends StringScanner { _column = newPosition - newlines.last.end; } } else { - var newlines = - "\n".allMatches(string.substring(newPosition, oldPosition)).toList(); + var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + if (_betweenCRLF) newlines.removeLast(); + _line -= newlines.length; if (newlines.isEmpty) { _column -= oldPosition - newPosition; } else { - _column = newPosition - string.lastIndexOf("\n", newPosition) - 1; + _column = newPosition - + string.lastIndexOf(_newlineRegExp, newPosition) - 1; } } } @@ -65,7 +75,7 @@ class LineScanner extends StringScanner { int readChar() { var char = super.readChar(); - if (char == 0xA) { + if (char == $lf || (char == $cr && peekChar() != $lf)) { _line += 1; _column = 0; } else { @@ -77,7 +87,7 @@ class LineScanner extends StringScanner { bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - var newlines = "\n".allMatches(lastMatch[0]).toList(); + var newlines = _newlinesIn(lastMatch[0]); _line += newlines.length; if (newlines.isEmpty) { _column += lastMatch[0].length; @@ -87,6 +97,14 @@ class LineScanner extends StringScanner { return true; } + + /// Returns a list of [Match]es describing all the newlines in [text], which + /// is assumed to end at [position]. + List _newlinesIn(String text) { + var newlines = _newlineRegExp.allMatches(text).toList(); + if (_betweenCRLF) newlines.removeLast(); + return newlines; + } } /// A class representing the state of a [LineScanner]. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 16477beeb..efc7b0a36 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,10 +1,11 @@ name: string_scanner -version: 0.1.4-dev +version: 0.1.3+2 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > A class for parsing strings using a sequence of patterns. dependencies: + charcode: "^1.1.0" path: ">=1.2.0 <2.0.0" source_span: ">=1.0.0 <2.0.0" dev_dependencies: diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 83222d6ce..68e5c3814 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -10,7 +10,7 @@ import 'package:test/test.dart'; void main() { var scanner; setUp(() { - scanner = new LineScanner('foo\nbar\nbaz'); + scanner = new LineScanner('foo\nbar\r\nbaz'); }); test('begins with line and column 0', () { @@ -33,7 +33,17 @@ void main() { test("consuming multiple newlines resets the column and increases the line", () { - scanner.expect('foo\nbar\nb'); + scanner.expect('foo\nbar\r\nb'); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test("consuming halfway through a CR LF doesn't count as a line", () { + scanner.expect('foo\nbar\r'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + + scanner.expect('\nb'); expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); @@ -56,11 +66,25 @@ void main() { expect(scanner.line, equals(1)); expect(scanner.column, equals(0)); }); + + test("consuming halfway through a CR LF doesn't count as a line", () { + scanner.expect('foo\nbar'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(3)); + + scanner.readChar(); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + + scanner.readChar(); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); }); group("position=", () { test("forward through newlines sets the line and column", () { - scanner.position = 9; // "foo\nbar\nb" + scanner.position = 10; // "foo\nbar\r\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); @@ -72,18 +96,24 @@ void main() { }); test("backward through newlines sets the line and column", () { - scanner.scan("foo\nbar\nbaz"); + scanner.scan("foo\nbar\r\nbaz"); scanner.position = 2; // "fo" expect(scanner.line, equals(0)); expect(scanner.column, equals(2)); }); test("backward through no newlines sets the column", () { - scanner.scan("foo\nbar\nbaz"); - scanner.position = 9; // "foo\nbar\nb" + scanner.scan("foo\nbar\r\nbaz"); + scanner.position = 10; // "foo\nbar\r\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); + + test("forward halfway through a CR LF doesn't count as a line", () { + scanner.position = 8; // "foo\nbar\r" + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + }); }); test("state= restores the line, column, and position", () { @@ -92,7 +122,7 @@ void main() { scanner.scan('ar\nba'); scanner.state = state; - expect(scanner.rest, equals('ar\nbaz')); + expect(scanner.rest, equals('ar\r\nbaz')); expect(scanner.line, equals(1)); expect(scanner.column, equals(1)); }); From ab2cd25c257f8d32776f7f2d558aa978d1e7e535 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 1 Sep 2015 17:29:19 -0700 Subject: [PATCH 0215/1215] Increase the SDK constraint to allow ^ constraints. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1325943002 . --- pkgs/string_scanner/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index efc7b0a36..3e71eb732 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -6,9 +6,9 @@ description: > A class for parsing strings using a sequence of patterns. dependencies: charcode: "^1.1.0" - path: ">=1.2.0 <2.0.0" - source_span: ">=1.0.0 <2.0.0" + path: "^1.2.0" + source_span: "^1.0.0" dev_dependencies: test: ">=0.12.0 <0.13.0" environment: - sdk: ">=1.2.0 <2.0.0" + sdk: ">=1.8.0 <2.0.0" From 5d9076bb8fe9abf76c0e24d4be157f919474a1ca Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Sep 2015 11:45:35 -0700 Subject: [PATCH 0216/1215] Add new SpanScanner.eager(). This is more efficient for uses like the YAML parser, which uses the current line and especially column information frequently while parsing a file. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1318603008 . --- pkgs/string_scanner/CHANGELOG.md | 5 + .../lib/src/eager_span_scanner.dart | 115 ++++++++++++++++++ pkgs/string_scanner/lib/src/line_scanner.dart | 2 + pkgs/string_scanner/lib/src/span_scanner.dart | 15 +++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/span_scanner_test.dart | 84 +++++++------ 6 files changed, 185 insertions(+), 38 deletions(-) create mode 100644 pkgs/string_scanner/lib/src/eager_span_scanner.dart diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index ddfd54016..23f911c29 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.4 + +* Add `new SpanScanner.eager()` for creating a `SpanScanner` that eagerly + computes its current line and column numbers. + ## 0.1.3+2 * Fix `LineScanner`'s handling of carriage returns to match that of diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart new file mode 100644 index 000000000..3fae5cca7 --- /dev/null +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -0,0 +1,115 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +library string_scanner.eager_span_scanner; + +import 'package:charcode/ascii.dart'; + +import 'line_scanner.dart'; +import 'span_scanner.dart'; + +// TODO(nweiz): Currently this duplicates code in line_scanner.dart. Once +// sdk#23770 is fully complete, we should move the shared code into a mixin. + +/// A regular expression matching newlines across platforms. +final _newlineRegExp = new RegExp(r"\r\n?|\n"); + +/// A [SpanScanner] that tracks the line and column eagerly, like [LineScanner]. +class EagerSpanScanner extends SpanScanner { + int get line => _line; + int _line = 0; + + int get column => _column; + int _column = 0; + + LineScannerState get state => + new _EagerSpanScannerState(this, position, line, column); + + bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; + + set state(LineScannerState state) { + if (state is! _EagerSpanScannerState || + !identical((state as _EagerSpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + super.position = state.position; + _line = state.line; + _column = state.column; + } + + set position(int newPosition) { + var oldPosition = position; + super.position = newPosition; + + if (newPosition > oldPosition) { + var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + _line += newlines.length; + if (newlines.isEmpty) { + _column += newPosition - oldPosition; + } else { + _column = newPosition - newlines.last.end; + } + } else { + var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + if (_betweenCRLF) newlines.removeLast(); + + _line -= newlines.length; + if (newlines.isEmpty) { + _column -= oldPosition - newPosition; + } else { + _column = newPosition - + string.lastIndexOf(_newlineRegExp, newPosition) - 1; + } + } + } + + EagerSpanScanner(String string, {sourceUrl, int position}) + : super(string, sourceUrl: sourceUrl, position: position); + + int readChar() { + var char = super.readChar(); + if (char == $lf || (char == $cr && peekChar() != $lf)) { + _line += 1; + _column = 0; + } else { + _column += 1; + } + return char; + } + + bool scan(Pattern pattern) { + if (!super.scan(pattern)) return false; + + var newlines = _newlinesIn(lastMatch[0]); + _line += newlines.length; + if (newlines.isEmpty) { + _column += lastMatch[0].length; + } else { + _column = lastMatch[0].length - newlines.last.end; + } + + return true; + } + + /// Returns a list of [Match]es describing all the newlines in [text], which + /// is assumed to end at [position]. + List _newlinesIn(String text) { + var newlines = _newlineRegExp.allMatches(text).toList(); + if (_betweenCRLF) newlines.removeLast(); + return newlines; + } +} + +/// A class representing the state of an [EagerSpanScanner]. +class _EagerSpanScannerState implements LineScannerState { + final EagerSpanScanner _scanner; + final int position; + final int line; + final int column; + + _EagerSpanScannerState(this._scanner, this.position, this.line, this.column); +} + diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 6a2880b5e..66d7575b2 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -8,6 +8,8 @@ import 'package:charcode/ascii.dart'; import 'string_scanner.dart'; +// Note that much of this code is duplicated in eager_span_scanner.dart. + /// A regular expression matching newlines across platforms. final _newlineRegExp = new RegExp(r"\r\n?|\n"); diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 2a78b5bc0..ebe230d8a 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -6,6 +6,7 @@ library string_scanner.span_scanner; import 'package:source_span/source_span.dart'; +import 'eager_span_scanner.dart'; import 'exception.dart'; import 'line_scanner.dart'; import 'string_scanner.dart'; @@ -56,6 +57,20 @@ class SpanScanner extends StringScanner implements LineScanner { : _sourceFile = new SourceFile(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); + /// Creates a new [SpanScanner] that eagerly computes line and column numbers. + /// + /// In general [new SpanScanner] will be more efficient, since it avoids extra + /// computation on every scan. However, eager scanning can be useful for + /// situations where the normal course of parsing frequently involves + /// accessing the current line and column numbers. + /// + /// Note that *only* the `line` and `column` fields on the `SpanScanner` + /// itself and its `LineScannerState` are eagerly computed. To limit their + /// memory footprint, returned spans and locations will still lazily compute + /// their line and column numbers. + factory SpanScanner.eager(String string, {sourceUrl, int position}) = + EagerSpanScanner; + /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 3e71eb732..35b3fe01d 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.3+2 +version: 0.1.4 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index a6249b719..114bff726 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -8,53 +8,63 @@ import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; void main() { - var scanner; - setUp(() { - scanner = new SpanScanner('foo\nbar\nbaz', sourceUrl: 'source'); + testForImplementation("lazy", () { + return new SpanScanner('foo\nbar\nbaz', sourceUrl: 'source'); }); - test("tracks the span for the last match", () { - scanner.scan('fo'); - scanner.scan('o\nba'); + testForImplementation("eager", () { + return new SpanScanner.eager('foo\nbar\nbaz', sourceUrl: 'source'); + }); +} - var span = scanner.lastSpan; - expect(span.start.offset, equals(2)); - expect(span.start.line, equals(0)); - expect(span.start.column, equals(2)); - expect(span.start.sourceUrl, equals(Uri.parse('source'))); +void testForImplementation(String name, SpanScanner create()) { + group("for a $name scanner", () { + var scanner; + setUp(() => scanner = create()); - expect(span.end.offset, equals(6)); - expect(span.end.line, equals(1)); - expect(span.end.column, equals(2)); - expect(span.start.sourceUrl, equals(Uri.parse('source'))); + test("tracks the span for the last match", () { + scanner.scan('fo'); + scanner.scan('o\nba'); - expect(span.text, equals('o\nba')); - }); + var span = scanner.lastSpan; + expect(span.start.offset, equals(2)); + expect(span.start.line, equals(0)); + expect(span.start.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); - test(".spanFrom() returns a span from a previous state", () { - scanner.scan('fo'); - var state = scanner.state; - scanner.scan('o\nba'); - scanner.scan('r\nba'); + expect(span.end.offset, equals(6)); + expect(span.end.line, equals(1)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); - var span = scanner.spanFrom(state); - expect(span.text, equals('o\nbar\nba')); - }); + expect(span.text, equals('o\nba')); + }); + + test(".spanFrom() returns a span from a previous state", () { + scanner.scan('fo'); + var state = scanner.state; + scanner.scan('o\nba'); + scanner.scan('r\nba'); + + var span = scanner.spanFrom(state); + expect(span.text, equals('o\nbar\nba')); + }); - test(".emptySpan returns an empty span at the current location", () { - scanner.scan('foo\nba'); + test(".emptySpan returns an empty span at the current location", () { + scanner.scan('foo\nba'); - var span = scanner.emptySpan; - expect(span.start.offset, equals(6)); - expect(span.start.line, equals(1)); - expect(span.start.column, equals(2)); - expect(span.start.sourceUrl, equals(Uri.parse('source'))); + var span = scanner.emptySpan; + expect(span.start.offset, equals(6)); + expect(span.start.line, equals(1)); + expect(span.start.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); - expect(span.end.offset, equals(6)); - expect(span.end.line, equals(1)); - expect(span.end.column, equals(2)); - expect(span.start.sourceUrl, equals(Uri.parse('source'))); + expect(span.end.offset, equals(6)); + expect(span.end.line, equals(1)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); - expect(span.text, equals('')); + expect(span.text, equals('')); + }); }); } From 23fc2becb50e7f78ae63d2ffe5a1d5bb3a7a0edf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Sep 2015 15:53:00 -0700 Subject: [PATCH 0217/1215] Improve the display of data: URIs in stack traces. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1320393003 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 7 +++++-- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 6 ++++++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index defe09309..dae0db602 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.2 + +* Improve the display of `data:` URIs in stack traces. + ## 1.4.1 * Fix a crashing bug in `UnparsedFrame.toString()`. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 072983a1b..4077c7cba 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -95,8 +95,11 @@ class Frame { /// comes from. /// /// This will usually be the string form of [uri], but a relative URI will be - /// used if possible. - String get library => path.prettyUri(uri); + /// used if possible. Data URIs will be truncated. + String get library { + if (uri.scheme == 'data') return "data:..."; + return path.prettyUri(uri); + } /// Returns the name of the package this stack frame comes from, or `null` if /// this stack frame doesn't come from a `package:` URL. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 7274bcc7e..5c8b720db 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.4.1 +version: 1.4.2 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 1233cbf85..63035e0e6 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -503,6 +503,12 @@ void main() { expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, equals(path.join('foo', 'bar.dart'))); }); + + test('truncates data: URIs', () { + var frame = new Frame.parseVM( + '#0 Foo (data:application/dart;charset=utf-8,blah:0:0)'); + expect(frame.library, equals('data:...')); + }); }); group('.location', () { From f0f34c3afa049f0ffe9bc72e30aaf7257a1c1e37 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 3 Nov 2015 13:42:20 -0800 Subject: [PATCH 0218/1215] Make Chain.parse and Trace.parse more similar. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1410683011 . --- pkgs/stack_trace/CHANGELOG.md | 9 +++++++++ pkgs/stack_trace/lib/src/chain.dart | 14 +++++++------- pkgs/stack_trace/lib/src/trace.dart | 4 +++- pkgs/stack_trace/lib/src/utils.dart | 4 ++++ pkgs/stack_trace/pubspec.yaml | 2 +- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index dae0db602..624a9346e 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,12 @@ +## 1.5.0 + +* `new Chain.parse()` now parses all the stack trace formats supported by `new + Trace.parse()`. Formats other than that emitted by `Chain.toString()` will + produce single-element chains. + +* `new Trace.parse()` now parses the output of `Chain.toString()`. It produces + the same result as `Chain.parse().toTrace()`. + ## 1.4.2 * Improve the display of `data:` URIs in stack traces. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index acd17e9d5..2e07d4bb9 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -16,10 +16,6 @@ import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. typedef void ChainHandler(error, Chain chain); -/// The line used in the string representation of stack chains to represent -/// the gap between traces. -const _gap = '===== asynchronous gap ===========================\n'; - /// A chain of stack traces. /// /// A stack chain is a collection of one or more stack traces that collectively @@ -119,11 +115,15 @@ class Chain implements StackTrace { /// Parses a string representation of a stack chain. /// - /// Specifically, this parses the output of [Chain.toString]. + /// If [chain] is the output of a call to [Chain.toString], it will be parsed + /// as a full stack chain. Otherwise, it will be parsed as in [Trace.parse] + /// and returned as a single-trace chain. factory Chain.parse(String chain) { if (chain.isEmpty) return new Chain([]); + if (!chain.contains(chainGap)) return new Chain([new Trace.parse(chain)]); + return new Chain( - chain.split(_gap).map((trace) => new Trace.parseFriendly(trace))); + chain.split(chainGap).map((trace) => new Trace.parseFriendly(trace))); } /// Returns a new [Chain] comprised of [traces]. @@ -191,6 +191,6 @@ class Chain implements StackTrace { return trace.frames.map((frame) { return '${padRight(frame.location, longest)} ${frame.member}\n'; }).join(); - }).join(_gap); + }).join(chainGap); } } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index f615cd26a..7f2c662b5 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -111,7 +111,8 @@ class Trace implements StackTrace { /// Parses a string representation of a stack trace. /// /// [trace] should be formatted in the same way as a Dart VM or browser stack - /// trace. + /// trace. If it's formatted as a stack chain, this will return the equivalent + /// of [Chain.toTrace]. factory Trace.parse(String trace) { try { if (trace.isEmpty) return new Trace([]); @@ -120,6 +121,7 @@ class Trace implements StackTrace { if (trace.contains(_firefoxSafariTrace)) { return new Trace.parseFirefox(trace); } + if (trace.contains(chainGap)) return new Chain.parse(trace).toTrace(); if (trace.contains(_friendlyTrace)) { return new Trace.parseFriendly(trace); } diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 62a282085..1d09443c1 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -4,6 +4,10 @@ library stack_trace.src.utils; +/// The line used in the string representation of stack chains to represent +/// the gap between traces. +const chainGap = '===== asynchronous gap ===========================\n'; + /// Returns [string] with enough spaces added to the end to make it [length] /// characters long. String padRight(String string, int length) { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 5c8b720db..932f6488d 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.4.2 +version: 1.5.0 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 956b762dd596331b95e936bfce7eb1f1b0a36c4f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 11 Jan 2016 14:24:21 -0800 Subject: [PATCH 0219/1215] Fix a crash in Chain.terse and Chain.foldFrames. These methods didn't gracefully handle a chain with an empty frame, which comes up occasionally in practice. Closes dart-lang/stack_trace#9 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1492323004 . --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 624a9346e..dace263ea 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.5.1 + +* Fix a crash in `Chain.foldFrames()` and `Chain.terse` when one of the chain's + traces has no frames. + ## 1.5.0 * `new Chain.parse()` now parses all the stack trace formats supported by `new diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 2e07d4bb9..2e63ef02c 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -37,7 +37,6 @@ typedef void ChainHandler(error, Chain chain); /// "$stackChain"); /// }); class Chain implements StackTrace { - /// The stack traces that make up this chain. /// /// Like the frames in a stack trace, the traces are ordered from most local @@ -155,6 +154,7 @@ class Chain implements StackTrace { var nonEmptyTraces = foldedTraces.where((trace) { // Ignore traces that contain only folded frames. if (trace.frames.length > 1) return true; + if (trace.frames.isEmpty) return false; // In terse mode, the trace may have removed an outer folded frame, // leaving a single non-folded frame. We can detect a folded frame because diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 932f6488d..16b2a1f41 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.5.0 +version: 1.5.1 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 0eb3f0087..cddb4a623 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -109,6 +109,20 @@ void main() { expect(chain.terse.toString(), equals('dart:core E.f\n')); }); + + // Regression test for #9 + test("doesn't crash on empty traces", () { + var chain = new Chain([ + new Trace.parse('user/code.dart 10:11 Bang.qux'), + new Trace([]), + new Trace.parse('user/code.dart 10:11 Bang.qux') + ]); + + expect(chain.terse.toString(), equals( + '$userSlashCode 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Bang.qux\n')); + }); }); group('Chain.foldFrames', () { From 4cdc9e02c22e9302f2000dff7f64b36cf8c2c005 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 11 Jan 2016 15:48:00 -0800 Subject: [PATCH 0220/1215] Update the example in the README. The package now does include line numbers for core libraries outside of terse mode. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1573373002 . --- pkgs/stack_trace/README.md | 20 ++++++++++---------- pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index fe85adbae..4fb3c50a3 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -28,20 +28,20 @@ Here's an example native stack trace from debugging this library: and its human-readable representation: - dart:core-patch Object.noSuchMethod + dart:core-patch 1884:25 Object.noSuchMethod pkg/stack_trace/lib/src/trace.dart 47:21 Trace.terse. - dart:collection IterableMixinWorkaround.reduce - dart:core-patch List.reduce + dart:collection 29:29 IterableMixinWorkaround.reduce + dart:core-patch 1247:42 List.reduce pkg/stack_trace/lib/src/trace.dart 40:35 Trace.terse pkg/stack_trace/lib/stack_trace.dart 24:28 format test.dart 21:29 main. - dart:async _CatchErrorFuture._sendError - dart:async _FutureImpl._setErrorWithoutAsyncTrace - dart:async _FutureImpl._setError - dart:async _ThenFuture._sendValue - dart:async _FutureImpl._handleValue. - dart:async Timer.run. - dart:async-patch Timer.Timer. + dart:async 525:24 _CatchErrorFuture._sendError + dart:async 393:26 _FutureImpl._setErrorWithoutAsyncTrace + dart:async 378:31 _FutureImpl._setError + dart:async 490:16 _ThenFuture._sendValue + dart:async 349:28 _FutureImpl._handleValue. + dart:async 2402:21 Timer.run. + dart:async-patch 15:15 Timer.Timer. You can further clean up the stack trace using `Trace.terse`. This folds together multiple stack frames from the Dart core libraries, so that only the diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 16b2a1f41..242d305f9 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.5.1 +version: 1.5.2-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 9334d8f05885d9ed00059bd4d10d00b2b8b166a2 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 12 Jan 2016 11:38:57 -0800 Subject: [PATCH 0221/1215] Deprecate the ChainHandler typedef. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1576853003 . --- pkgs/stack_trace/CHANGELOG.md | 6 ++++++ pkgs/stack_trace/lib/src/chain.dart | 3 ++- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 5 ++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index dace263ea..c99f532cd 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.5.2 + +* Deprecate the `ChainHandler` typedef. This didn't provide any value over + directly annotating the function argument, and it made the documentation less + clear. + ## 1.5.1 * Fix a crash in `Chain.foldFrames()` and `Chain.terse` when one of the chain's diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 2e63ef02c..4baec216c 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -14,6 +14,7 @@ import 'trace.dart'; import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. +@Deprecated("Will be removed in stack_trace 2.0.0.") typedef void ChainHandler(error, Chain chain); /// A chain of stack traces. @@ -63,7 +64,7 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static capture(callback(), {ChainHandler onError}) { + static capture(callback(), {void onError(error, Chain chain)}) { var spec = new StackZoneSpecification(onError); return runZoned(() { try { diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 25d964271..6de43fae8 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -9,6 +9,9 @@ import 'dart:async'; import 'trace.dart'; import 'chain.dart'; +/// A function that handles errors in the zone wrapped by [Chain.capture]. +typedef void _ChainHandler(error, Chain chain); + /// A class encapsulating the zone specification for a [Chain.capture] zone. /// /// Until they're materialized and exposed to the user, stack chains are tracked @@ -43,7 +46,7 @@ class StackZoneSpecification { /// /// If this is null, that indicates that any unhandled errors should be passed /// to the parent zone. - final ChainHandler _onError; + final _ChainHandler _onError; /// The most recent node of the current stack chain. _Node _currentNode; From 18f110874a22e1de99c5288d9f401b2e5cfdad7d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 12 Jan 2016 15:47:44 -0800 Subject: [PATCH 0222/1215] Add a "when" parameter to Chain.capture(). This makes it easy for users to switch capturing on and off based on whether they're in a debug or development mode. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1583483003 . --- pkgs/stack_trace/CHANGELOG.md | 6 +++++- pkgs/stack_trace/lib/src/chain.dart | 24 ++++++++++++++++++--- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 16 ++++++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index c99f532cd..fb699c677 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,8 @@ -## 1.5.2 +## 1.6.0 + +* Add a `when` parameter to `Chain.capture()`. This allows capturing to be + easily enabled and disabled based on whether the application is running in + debug/development mode or not. * Deprecate the `ChainHandler` typedef. This didn't provide any value over directly annotating the function argument, and it made the documentation less diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 4baec216c..3f35c1601 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -49,8 +49,14 @@ class Chain implements StackTrace { static StackZoneSpecification get _currentSpec => Zone.current[#stack_trace.stack_zone.spec]; - /// Runs [callback] in a [Zone] in which the current stack chain is tracked - /// and automatically associated with (most) errors. + /// If [when] is `true`, runs [callback] in a [Zone] in which the current + /// stack chain is tracked and automatically associated with (most) errors. + /// + /// If [when] is `false`, this does not track stack chains. Instead, it's + /// identical to [runZoned], except that it wraps any errors in [new + /// Chain.forTrace]—which will only wrap the trace unless there's a different + /// [Chain.capture] active. This makes it easy for the caller to only capture + /// stack chains in debug mode or during development. /// /// If [onError] is passed, any error in the zone that would otherwise go /// unhandled is passed to it, along with the [Chain] associated with that @@ -64,7 +70,19 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static capture(callback(), {void onError(error, Chain chain)}) { + static capture(callback(), {void onError(error, Chain chain), + bool when: true}) { + if (!when) { + var newOnError; + if (onError != null) { + newOnError = (error, stackTrace) { + onError(error, new Chain.forTrace(stackTrace)); + }; + } + + return runZoned(callback, onError: newOnError); + } + var spec = new StackZoneSpecification(onError); return runZoned(() { try { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 242d305f9..1c805c33d 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.5.2-dev +version: 1.6.0 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index cddb4a623..40b06d552 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -36,6 +36,22 @@ void main() { }); }); + group("Chain.capture() with when: false", () { + test("with no onError doesn't block errors", () { + expect(Chain.capture(() => new Future.error("oh no"), when: false), + throwsA("oh no")); + }); + + test("with onError blocks errors", () { + Chain.capture(() { + return new Future.error("oh no"); + }, onError: expectAsync((error, chain) { + expect(error, equals("oh no")); + expect(chain, new isInstanceOf()); + }), when: false); + }); + }); + test("toString() ensures that all traces are aligned", () { var chain = new Chain([ new Trace.parse('short 10:11 Foo.bar\n'), From d9848699ec6cd067023224fcf63eb0986c5aaa81 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 12 Jan 2016 17:23:18 -0800 Subject: [PATCH 0223/1215] Get rid of all the library tags. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1580083003 . --- pkgs/stack_trace/lib/src/chain.dart | 2 -- pkgs/stack_trace/lib/src/frame.dart | 2 -- pkgs/stack_trace/lib/src/lazy_trace.dart | 2 -- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 -- pkgs/stack_trace/lib/src/trace.dart | 2 -- pkgs/stack_trace/lib/src/unparsed_frame.dart | 2 -- pkgs/stack_trace/lib/src/utils.dart | 2 -- pkgs/stack_trace/lib/src/vm_trace.dart | 2 -- pkgs/stack_trace/lib/stack_trace.dart | 2 -- pkgs/stack_trace/test/chain/utils.dart | 2 -- pkgs/stack_trace/test/frame_test.dart | 2 -- pkgs/stack_trace/test/trace_test.dart | 2 -- pkgs/stack_trace/test/utils.dart | 2 -- 13 files changed, 26 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 3f35c1601..c282387b8 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.chain; - import 'dart:async'; import 'dart:collection'; import 'dart:math' as math; diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 4077c7cba..efb221612 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -2,8 +2,6 @@ // 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. -library frame; - import 'package:path/path.dart' as path; import 'trace.dart'; diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 6bfe51c73..618f00794 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -2,8 +2,6 @@ // 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. -library lazy_trace; - import 'frame.dart'; import 'trace.dart'; diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 6de43fae8..3a9bf48e9 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.stack_zone_specification; - import 'dart:async'; import 'trace.dart'; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 7f2c662b5..6d9823b08 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -2,8 +2,6 @@ // 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. -library trace; - import 'dart:collection'; import 'dart:math' as math; diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index f037c8a5a..7ba9a6391 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.unparsed_frame; - import 'frame.dart'; /// A frame that failed to parse. diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 1d09443c1..5781d5f0a 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.src.utils; - /// The line used in the string representation of stack chains to represent /// the gap between traces. const chainGap = '===== asynchronous gap ===========================\n'; diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 79911602a..84fcb10bb 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -2,8 +2,6 @@ // 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. -library vm_trace; - import 'frame.dart'; import 'utils.dart'; diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index 6bba6350f..1e6f0b01e 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -21,8 +21,6 @@ * [pub]: http://pub.dartlang.org * [pkg]: http://pub.dartlang.org/packages/stack_trace */ -library stack_trace; - export 'src/chain.dart'; export 'src/frame.dart'; export 'src/trace.dart'; diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 1e19eeb3c..366502cbb 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.test.chain.utils; - import 'dart:async'; import 'package:stack_trace/stack_trace.dart'; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 63035e0e6..43bce9cb5 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -2,8 +2,6 @@ // 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. -library frame_test; - import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index d12bc71f1..edb29fd8a 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -2,8 +2,6 @@ // 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. -library trace_test; - import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index 912f8f4ed..afa384c47 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -2,8 +2,6 @@ // 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. -library stack_trace.test.utils; - import 'package:test/test.dart'; /// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. From 9e8e6a46739815393bb3fcf73d1033bec47ffb3c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 12 Jan 2016 17:23:49 -0800 Subject: [PATCH 0224/1215] Get rid of all the library tags. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1580653005 . --- pkgs/string_scanner/lib/src/eager_span_scanner.dart | 2 -- pkgs/string_scanner/lib/src/exception.dart | 2 -- pkgs/string_scanner/lib/src/line_scanner.dart | 2 -- pkgs/string_scanner/lib/src/span_scanner.dart | 2 -- pkgs/string_scanner/lib/src/string_scanner.dart | 2 -- pkgs/string_scanner/lib/src/utils.dart | 2 -- pkgs/string_scanner/lib/string_scanner.dart | 2 -- pkgs/string_scanner/test/error_test.dart | 2 -- pkgs/string_scanner/test/line_scanner_test.dart | 2 -- pkgs/string_scanner/test/span_scanner_test.dart | 2 -- pkgs/string_scanner/test/string_scanner_test.dart | 2 -- pkgs/string_scanner/test/utils.dart | 2 -- 12 files changed, 24 deletions(-) diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 3fae5cca7..c537b0cd6 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.eager_span_scanner; - import 'package:charcode/ascii.dart'; import 'line_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 50177d657..84bf5e861 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.exception; - import 'package:source_span/source_span.dart'; /// An exception thrown by a [StringScanner] that failed to parse a string. diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 66d7575b2..b4391934d 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.line_scanner; - import 'package:charcode/ascii.dart'; import 'string_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index ebe230d8a..dd16e47cf 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.span_scanner; - import 'package:source_span/source_span.dart'; import 'eager_span_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index d9c1c2fd3..775dd5e1c 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.string_scanner; - import 'package:source_span/source_span.dart'; import 'exception.dart'; diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index 107c4c52e..aa3e95736 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.utils; - /// Validates the arguments passed to [StringScanner.error]. void validateErrorArgs(String string, Match match, int position, int length) { if (match != null && (position != null || length != null)) { diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart index be294f4f6..7f36eef83 100644 --- a/pkgs/string_scanner/lib/string_scanner.dart +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -3,8 +3,6 @@ // BSD-style license that can be found in the LICENSE file. /// A library for parsing strings using a sequence of patterns. -library string_scanner; - export 'src/exception.dart'; export 'src/line_scanner.dart'; export 'src/span_scanner.dart'; diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index 9c485e559..ff451940e 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.error_test; - import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 68e5c3814..9874cb309 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.line_scanner_test; - import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 114bff726..b078f6e1a 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.span_scanner_test; - import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index c8e43a5aa..10e622a82 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.string_scanner_test; - import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index 8df4b510f..471b4c823 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -2,8 +2,6 @@ // 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. -library string_scanner.test.utils; - import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; From aadec1ad0401036056533506ea730b5f7b683eaf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 14 Jan 2016 16:29:22 -0800 Subject: [PATCH 0225/1215] Remove the dependency on "path". We never imported this, so it's not clear why the dependency was even added. Closes dart-lang/string_scanner#2 R=rnystrom@google.com Review URL: https://codereview.chromium.org//1589013004 . --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/pubspec.yaml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 23f911c29..a5650cc99 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+1 + +* Remove the dependency on `path`, since we don't actually import it. + ## 0.1.4 * Add `new SpanScanner.eager()` for creating a `SpanScanner` that eagerly diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 35b3fe01d..b249240c8 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,11 @@ name: string_scanner -version: 0.1.4 +version: 0.1.4+1 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > A class for parsing strings using a sequence of patterns. dependencies: charcode: "^1.1.0" - path: "^1.2.0" source_span: "^1.0.0" dev_dependencies: test: ">=0.12.0 <0.13.0" From d56a057cd1a4039ad70949238f4f500d069709f8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 16:41:33 -0800 Subject: [PATCH 0226/1215] Initial commit. --- pkgs/stream_channel/.gitignore | 9 ++++++++ pkgs/stream_channel/.test_config | 3 +++ pkgs/stream_channel/AUTHORS | 6 ++++++ pkgs/stream_channel/CHANGELOG.md | 3 +++ pkgs/stream_channel/CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++ pkgs/stream_channel/LICENSE | 26 +++++++++++++++++++++++ pkgs/stream_channel/README.md | 16 ++++++++++++++ pkgs/stream_channel/pubspec.yaml | 9 ++++++++ 8 files changed, 105 insertions(+) create mode 100644 pkgs/stream_channel/.gitignore create mode 100644 pkgs/stream_channel/.test_config create mode 100644 pkgs/stream_channel/AUTHORS create mode 100644 pkgs/stream_channel/CHANGELOG.md create mode 100644 pkgs/stream_channel/CONTRIBUTING.md create mode 100644 pkgs/stream_channel/LICENSE create mode 100644 pkgs/stream_channel/README.md create mode 100644 pkgs/stream_channel/pubspec.yaml diff --git a/pkgs/stream_channel/.gitignore b/pkgs/stream_channel/.gitignore new file mode 100644 index 000000000..25a1df332 --- /dev/null +++ b/pkgs/stream_channel/.gitignore @@ -0,0 +1,9 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +.packages +pubspec.lock diff --git a/pkgs/stream_channel/.test_config b/pkgs/stream_channel/.test_config new file mode 100644 index 000000000..352d2feee --- /dev/null +++ b/pkgs/stream_channel/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} diff --git a/pkgs/stream_channel/AUTHORS b/pkgs/stream_channel/AUTHORS new file mode 100644 index 000000000..e8063a8cd --- /dev/null +++ b/pkgs/stream_channel/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md new file mode 100644 index 000000000..847d60daa --- /dev/null +++ b/pkgs/stream_channel/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* Initial version diff --git a/pkgs/stream_channel/CONTRIBUTING.md b/pkgs/stream_channel/CONTRIBUTING.md new file mode 100644 index 000000000..6f5e0ea67 --- /dev/null +++ b/pkgs/stream_channel/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/stream_channel/LICENSE b/pkgs/stream_channel/LICENSE new file mode 100644 index 000000000..de31e1a0a --- /dev/null +++ b/pkgs/stream_channel/LICENSE @@ -0,0 +1,26 @@ +Copyright 2015, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md new file mode 100644 index 000000000..5d6a2b4e0 --- /dev/null +++ b/pkgs/stream_channel/README.md @@ -0,0 +1,16 @@ +This package exposes the `StreamChannel` interface, which represents a two-way +communication channel. Each `StreamChannel` exposes a `Stream` for receiving +data and a `StreamSink` for sending it. + +`StreamChannel` helps abstract communication logic away from the underlying +protocol. For example, the [`test`][test] package re-uses its test suite +communication protocol for both WebSocket connections to browser suites and +Isolate connections to VM tests. + +[test]: https://pub.dartlang.org/packages/test + +This package also contains utilities for dealing with `StreamChannel`s and with +two-way communications in general. For documentation of these utilities, see +[the API docs][api]. + +[api]: https://www.dartdocs.org/documentation/stream_channel/latest diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml new file mode 100644 index 000000000..76f22b7da --- /dev/null +++ b/pkgs/stream_channel/pubspec.yaml @@ -0,0 +1,9 @@ +name: stream_channel +version: 1.0.0-dev +description: An abstraction for two-way communication channels. +author: Dart Team +homepage: https://github.com/dart-lang/stream_channel +environment: + sdk: '>=1.0.0 <2.0.0' +dev_dependencies: + test: '^0.12.0' From d0b0d2d1150f7de04e3d4bfac27a238358197611 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 19 Jan 2016 16:50:25 -0800 Subject: [PATCH 0227/1215] Add codereview.settings. --- pkgs/stream_channel/codereview.settings | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 pkgs/stream_channel/codereview.settings diff --git a/pkgs/stream_channel/codereview.settings b/pkgs/stream_channel/codereview.settings new file mode 100644 index 000000000..7b0a9edc6 --- /dev/null +++ b/pkgs/stream_channel/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: https://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/stream_channel/commit/ +CC_LIST: reviews@dartlang.org \ No newline at end of file From 3ee20be6a7e5baa85fd75c270faa2c3af528734d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 20 Jan 2016 17:02:20 -0800 Subject: [PATCH 0228/1215] Add StreamChannel and MultiChannel. These are exact copies of the classes and tests from the test package. R=rnystrom@google.com, kevmoo@google.com Review URL: https://codereview.chromium.org//1610443002 . --- .../stream_channel/lib/src/multi_channel.dart | 244 ++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 50 +++ .../test/multi_channel_test.dart | 310 ++++++++++++++++++ pkgs/stream_channel/test/utils.dart | 20 ++ 4 files changed, 624 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/multi_channel.dart create mode 100644 pkgs/stream_channel/lib/stream_channel.dart create mode 100644 pkgs/stream_channel/test/multi_channel_test.dart create mode 100644 pkgs/stream_channel/test/utils.dart diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart new file mode 100644 index 000000000..e87deb33b --- /dev/null +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -0,0 +1,244 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import '../stream_channel.dart'; + +/// A class that multiplexes multiple virtual channels across a single +/// underlying transport layer. +/// +/// This should be connected to another [MultiChannel] on the other end of the +/// underlying channel. It starts with a single default virtual channel, +/// accessible via [stream] and [sink]. Additional virtual channels can be +/// created with [virtualChannel]. +/// +/// When a virtual channel is created by one endpoint, the other must connect to +/// it before messages may be sent through it. The first endpoint passes its +/// [VirtualChannel.id] to the second, which then creates a channel from that id +/// also using [virtualChannel]. For example: +/// +/// ```dart +/// // First endpoint +/// var virtual = multiChannel.virtualChannel(); +/// multiChannel.sink.add({ +/// "channel": virtual.id +/// }); +/// +/// // Second endpoint +/// multiChannel.stream.listen((message) { +/// var virtual = multiChannel.virtualChannel(message["channel"]); +/// // ... +/// }); +/// ``` +/// +/// Sending errors across a [MultiChannel] is not supported. Any errors from the +/// underlying stream will be reported only via the default +/// [MultiChannel.stream]. +/// +/// Each virtual channel may be closed individually. When all of them are +/// closed, the underlying [StreamSink] is closed automatically. +abstract class MultiChannel implements StreamChannel { + /// The default input stream. + /// + /// This connects to the remote [sink]. + Stream get stream; + + /// The default output stream. + /// + /// This connects to the remote [stream]. If this is closed, the remote + /// [stream] will close, but other virtual channels will remain open and new + /// virtual channels may be opened. + StreamSink get sink; + + /// Creates a new [MultiChannel] that sends messages over [innerStream] and + /// [innerSink]. + /// + /// The inner streams must take JSON-like objects. + factory MultiChannel(Stream innerStream, StreamSink innerSink) => + new _MultiChannel(innerStream, innerSink); + + /// Creates a new virtual channel. + /// + /// If [id] is not passed, this creates a virtual channel from scratch. Before + /// it's used, its [VirtualChannel.id] must be sent to the remote endpoint + /// where [virtualChannel] should be called with that id. + /// + /// If [id] is passed, this creates a virtual channel corresponding to the + /// channel with that id on the remote channel. + /// + /// Throws an [ArgumentError] if a virtual channel already exists for [id]. + /// Throws a [StateError] if the underlying channel is closed. + VirtualChannel virtualChannel([id]); +} + +/// The implementation of [MultiChannel]. +/// +/// This is private so that [VirtualChannel] can inherit from [MultiChannel] +/// without having to implement all the private members. +class _MultiChannel extends StreamChannelMixin implements MultiChannel { + /// The inner stream over which all communication is received. + /// + /// This will be `null` if the underlying communication channel is closed. + Stream _innerStream; + + /// The inner sink over which all communication is sent. + /// + /// This will be `null` if the underlying communication channel is closed. + StreamSink _innerSink; + + /// The subscription to [_innerStream]. + StreamSubscription _innerStreamSubscription; + + Stream get stream => _streamController.stream; + final _streamController = new StreamController(sync: true); + + StreamSink get sink => _sinkController.sink; + final _sinkController = new StreamController(sync: true); + + /// A map from virtual channel ids to [StreamController]s that should be used + /// to write messages received from those channels. + final _streamControllers = new Map(); + + /// A map from virtual channel ids to [StreamControllers]s that are used + /// to receive messages to write to those channels. + /// + /// Note that this uses the same keys as [_streamControllers]. + final _sinkControllers = new Map(); + + /// The next id to use for a local virtual channel. + /// + /// Ids are used to identify virtual channels. Each message is tagged with an + /// id; the receiving [MultiChannel] uses this id to look up which + /// [VirtualChannel] the message should be dispatched to. + /// + /// The id scheme for virtual channels is somewhat complicated. This is + /// necessary to ensure that there are no conflicts even when both endpoints + /// have virtual channels with the same id; since both endpoints can send and + /// receive messages across each virtual channel, a naïve scheme would make it + /// impossible to tell whether a message was from a channel that originated in + /// the remote endpoint or a reply on a channel that originated in the local + /// endpoint. + /// + /// The trick is that each endpoint only uses odd ids for its own channels. + /// When sending a message over a channel that was created by the remote + /// endpoint, the channel's id plus one is used. This way each [MultiChannel] + /// knows that if an incoming message has an odd id, it's using the local id + /// scheme, but if it has an even id, it's using the remote id scheme. + var _nextId = 1; + + _MultiChannel(this._innerStream, this._innerSink) { + // The default connection is a special case which has id 0 on both ends. + // This allows it to begin connected without having to send over an id. + _streamControllers[0] = _streamController; + _sinkControllers[0] = _sinkController; + _sinkController.stream.listen( + (message) => _innerSink.add([0, message]), + onDone: () => _closeChannel(0, 0)); + + _innerStreamSubscription = _innerStream.listen((message) { + var id = message[0]; + var sink = _streamControllers[id]; + + // A sink might not exist if the channel was closed before an incoming + // message was processed. + if (sink == null) return; + if (message.length > 1) { + sink.add(message[1]); + return; + } + + // A message without data indicates that the channel has been closed. + _sinkControllers[id].close(); + }, onDone: _closeInnerChannel, + onError: _streamController.addError); + } + + VirtualChannel virtualChannel([id]) { + if (_innerStream == null) { + throw new StateError("The underlying channel is closed."); + } + + var inputId; + var outputId; + if (id != null) { + // Since the user is passing in an id, we're connected to a remote + // VirtualChannel. This means messages they send over this channel will + // have the original odd id, but our replies will have an even id. + inputId = id; + outputId = (id as int) + 1; + } else { + // Since we're generating an id, we originated this VirtualChannel. This + // means messages we send over this channel will have the original odd id, + // but the remote channel's replies will have an even id. + inputId = _nextId + 1; + outputId = _nextId; + _nextId += 2; + } + + if (_streamControllers.containsKey(inputId)) { + throw new ArgumentError("A virtual channel with id $id already exists."); + } + + var streamController = new StreamController(sync: true); + var sinkController = new StreamController(sync: true); + _streamControllers[inputId] = streamController; + _sinkControllers[inputId] = sinkController; + sinkController.stream.listen( + (message) => _innerSink.add([outputId, message]), + onDone: () => _closeChannel(inputId, outputId)); + + return new VirtualChannel._( + this, outputId, streamController.stream, sinkController.sink); + } + + /// Closes the virtual channel for which incoming messages have [inputId] and + /// outgoing messages have [outputId]. + void _closeChannel(int inputId, int outputId) { + _streamControllers.remove(inputId).close(); + _sinkControllers.remove(inputId).close(); + + if (_innerSink == null) return; + + // A message without data indicates that the virtual channel has been + // closed. + _innerSink.add([outputId]); + if (_streamControllers.isEmpty) _closeInnerChannel(); + } + + /// Closes the underlying communication channel. + void _closeInnerChannel() { + _innerSink.close(); + _innerStreamSubscription.cancel(); + _innerStream = null; + _innerSink = null; + for (var controller in _sinkControllers.values.toList()) { + controller.close(); + } + } +} + +/// A virtual channel created by [MultiChannel]. +/// +/// This implements [MultiChannel] for convenience. +/// [VirtualChannel.virtualChannel] is semantically identical to the parent's +/// [MultiChannel.virtualChannel]. +class VirtualChannel extends StreamChannelMixin implements MultiChannel { + /// The [MultiChannel] that created this. + final MultiChannel _parent; + + /// The identifier for this channel. + /// + /// This can be sent across the [MultiChannel] to provide the remote endpoint + /// a means to connect to this channel. Nothing about this is guaranteed + /// except that it will be JSON-serializable. + final id; + + final Stream stream; + final StreamSink sink; + + VirtualChannel._(this._parent, this.id, this.stream, this.sink); + + VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart new file mode 100644 index 000000000..c4e28a0e3 --- /dev/null +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +export 'src/multi_channel.dart'; + +/// An abstract class representing a two-way communication channel. +/// +/// Subclasses are strongly encouraged to mix in or extend [StreamChannelMixin] +/// to get default implementations of the various instance methods. Adding new +/// methods to this interface will not be considered a breaking change if +/// implementations are also added to [StreamChannelMixin]. +abstract class StreamChannel { + /// The stream that emits values from the other endpoint. + Stream get stream; + + /// The sink for sending values to the other endpoint. + StreamSink get sink; + + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + factory StreamChannel(Stream stream, StreamSink sink) => + new _StreamChannel(stream, sink); + + /// Connects [this] to [other], so that any values emitted by either are sent + /// directly to the other. + void pipe(StreamChannel other); +} + +/// An implementation of [StreamChannel] that simply takes a stream and a sink +/// as parameters. +/// +/// This is distinct from [StreamChannel] so that it can use +/// [StreamChannelMixin]. +class _StreamChannel extends StreamChannelMixin { + final Stream stream; + final StreamSink sink; + + _StreamChannel(this.stream, this.sink); +} + +/// A mixin that implements the instance methods of [StreamChannel] in terms of +/// [stream] and [sink]. +abstract class StreamChannelMixin implements StreamChannel { + void pipe(StreamChannel other) { + stream.pipe(other.sink); + other.stream.pipe(sink); + } +} diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart new file mode 100644 index 000000000..e4594128a --- /dev/null +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -0,0 +1,310 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var oneToTwo; + var twoToOne; + var channel1; + var channel2; + setUp(() { + oneToTwo = new StreamController(); + twoToOne = new StreamController(); + channel1 = new MultiChannel(twoToOne.stream, oneToTwo.sink); + channel2 = new MultiChannel(oneToTwo.stream, twoToOne.sink); + }); + + group("the default virtual channel", () { + test("begins connected", () { + var first = true; + channel2.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + channel1.sink.add("hello"); + channel1.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(channel2.stream.toList(), completion(isEmpty)); + expect(channel2.sink.done, completes); + + channel1.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(channel1.stream.toList(), completion(isEmpty)); + expect(channel1.sink.done, completes); + + channel1.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + channel1.sink.done.then(expectAsync((_) {}, count: 0)); + + channel1.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () { + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + channel1.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + // Establish another virtual connection which should keep the underlying + // connection open. + channel2.virtualChannel(channel1.virtualChannel().id); + channel1.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + }); + + group("a locally-created virtual channel", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("sends messages only to the other virtual channel", () { + var first = true; + virtual2.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + // No other virtual channels should receive the message. + for (var i = 0; i < 10; i++) { + var virtual = channel2.virtualChannel(channel1.virtualChannel().id); + virtual.stream.listen(expectAsync((_) {}, count: 0)); + } + channel2.stream.listen(expectAsync((_) {}, count: 0)); + + virtual1.sink.add("hello"); + virtual1.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + virtual1.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + + virtual1.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + virtual1.sink.done.then(expectAsync((_) {}, count: 0)); + virtual1.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () async { + // First close the default channel so we can test the new channel as the + // last living virtual channel. + channel1.sink.close(); + + await channel2.stream.toList(); + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + virtual1.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + virtual1.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + + test("doesn't conflict with a remote virtual channel", () { + var virtual3 = channel2.virtualChannel(); + var virtual4 = channel1.virtualChannel(virtual3.id); + + // This is an implementation detail, but we assert it here to make sure + // we're properly testing two channels with the same id. + expect(virtual1.id, equals(virtual3.id)); + + virtual2.stream.listen( + expectAsync((message) => expect(message, equals("hello")))); + virtual4.stream.listen( + expectAsync((message) => expect(message, equals("goodbye")))); + + virtual1.sink.add("hello"); + virtual3.sink.add("goodbye"); + }); + }); + + group("a remotely-created virtual channel", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("sends messages only to the other virtual channel", () { + var first = true; + virtual1.stream.listen(expectAsync((message) { + if (first) { + expect(message, equals("hello")); + first = false; + } else { + expect(message, equals("world")); + } + }, count: 2)); + + // No other virtual channels should receive the message. + for (var i = 0; i < 10; i++) { + var virtual = channel2.virtualChannel(channel1.virtualChannel().id); + virtual.stream.listen(expectAsync((_) {}, count: 0)); + } + channel1.stream.listen(expectAsync((_) {}, count: 0)); + + virtual2.sink.add("hello"); + virtual2.sink.add("world"); + }); + + test("closes the remote virtual channel when it closes", () { + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + + virtual2.sink.close(); + }); + + test("closes the local virtual channel when it closes", () { + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + virtual2.sink.close(); + }); + + test("doesn't closes the local virtual channel when the stream " + "subscription is canceled", () { + virtual2.sink.done.then(expectAsync((_) {}, count: 0)); + virtual2.stream.listen((_) {}).cancel(); + + // Ensure that there's enough time for the channel to close if it's going + // to. + return pumpEventQueue(); + }); + + test("closes the underlying channel when it closes without any other " + "virtual channels", () async { + // First close the default channel so we can test the new channel as the + // last living virtual channel. + channel2.sink.close(); + + await channel1.stream.toList(); + expect(oneToTwo.done, completes); + expect(twoToOne.done, completes); + + virtual2.sink.close(); + }); + + test("doesn't close the underlying channel when it closes with other " + "virtual channels", () { + oneToTwo.done.then(expectAsync((_) {}, count: 0)); + twoToOne.done.then(expectAsync((_) {}, count: 0)); + + virtual2.sink.close(); + + // Ensure that there's enough time for the underlying channel to complete + // if it's going to. + return pumpEventQueue(); + }); + + test("doesn't allow another virtual channel with the same id", () { + expect(() => channel2.virtualChannel(virtual1.id), + throwsArgumentError); + }); + }); + + group("when the underlying stream", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("closes, all virtual channels close", () { + expect(channel1.stream.toList(), completion(isEmpty)); + expect(channel1.sink.done, completes); + expect(channel2.stream.toList(), completion(isEmpty)); + expect(channel2.sink.done, completes); + expect(virtual1.stream.toList(), completion(isEmpty)); + expect(virtual1.sink.done, completes); + expect(virtual2.stream.toList(), completion(isEmpty)); + expect(virtual2.sink.done, completes); + + oneToTwo.close(); + }); + + test("closes, no more virtual channels may be created", () { + expect(channel1.sink.done.then((_) => channel1.virtualChannel()), + throwsStateError); + expect(channel2.sink.done.then((_) => channel2.virtualChannel()), + throwsStateError); + + oneToTwo.close(); + }); + + test("emits an error, the error is sent only to the default channel", () { + channel1.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((error) => expect(error, equals("oh no")))); + virtual1.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((_) {}, count: 0)); + + twoToOne.addError("oh no"); + }); + }); +} diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart new file mode 100644 index 000000000..130a3e12b --- /dev/null +++ b/pkgs/stream_channel/test/utils.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Returns a [Future] that completes after pumping the event queue [times] +/// times. +/// +/// By default, this should pump the event queue enough times to allow any code +/// to run, as long as it's not waiting on some external event. +Future pumpEventQueue([int times=20]) { + if (times == 0) return new Future.value(); + // Use [new Future] future to allow microtask events to finish. The [new + // Future.value] constructor uses scheduleMicrotask itself and would therefore + // not wait for microtask callbacks that are scheduled after invoking this + // method. + return new Future(() => pumpEventQueue(times - 1)); +} + From 31deacaede3144d32b836a16f8a778f93f461356 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 21 Jan 2016 15:19:27 -0800 Subject: [PATCH 0229/1215] Add a DelegatingStreamChannel class. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1617483003 . --- .../lib/src/delegating_stream_channel.dart | 17 +++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + 2 files changed, 18 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/delegating_stream_channel.dart diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart new file mode 100644 index 000000000..9d6ad90fd --- /dev/null +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +/// A simple delegating wrapper around [StreamChannel]. +/// +/// Subclasses can override individual methods, or use this to expose only +/// [StreamChannel] methods. +class StreamChannelView extends StreamChannelMixin { + /// The inner channel to which methods are forwarded. + final StreamChannel _inner; + + Stream get stream => _inner.stream; + StreamSink get sink => _inner.sink; + + StreamChannelView(this._inner); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index c4e28a0e3..a8c9a0903 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -4,6 +4,7 @@ import 'dart:async'; +export 'src/delegating_stream_channel.dart'; export 'src/multi_channel.dart'; /// An abstract class representing a two-way communication channel. From 9eea7761575466adb45a7c1300a3d8d9be558cbc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 21 Jan 2016 15:29:15 -0800 Subject: [PATCH 0230/1215] Add clearer rules for implementations. This helps implementations know how to handle corner cases, and helps users know what behavior they can rely on. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1604903006 . --- pkgs/stream_channel/lib/stream_channel.dart | 47 ++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index a8c9a0903..fd7b09327 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -9,18 +9,55 @@ export 'src/multi_channel.dart'; /// An abstract class representing a two-way communication channel. /// -/// Subclasses are strongly encouraged to mix in or extend [StreamChannelMixin] -/// to get default implementations of the various instance methods. Adding new -/// methods to this interface will not be considered a breaking change if -/// implementations are also added to [StreamChannelMixin]. +/// Users should consider the [stream] emitting a "done" event to be the +/// canonical indicator that the channel has closed. If they wish to close the +/// channel, they should close the [sink]—canceling the stream subscription is +/// not sufficient. Protocol errors may be emitted through the stream or through +/// [Sink.done], depending on their underlying cause. Note that the sink may +/// silently drop events if the channel closes before [Sink.close] is called. +/// +/// Implementations are strongly encouraged to mix in or extend +/// [StreamChannelMixin] to get default implementations of the various instance +/// methods. Adding new methods to this interface will not be considered a +/// breaking change if implementations are also added to [StreamChannelMixin]. +/// +/// Implementations must provide the following guarantees: +/// +/// * The stream is single-subscription, and must follow all the guarantees of +/// single-subscription streams. +/// +/// * Closing the sink causes the stream to close before it emits any more +/// events. +/// +/// * After the stream closes, the sink is automatically closed. If this +/// happens, sink methods should silently drop their arguments until +/// [Sink.close] is called. +/// +/// * If the stream closes before it has a listener, the sink should silently +/// drop events if possible. +/// +/// * Canceling the stream's subscription has no effect on the sink. The channel +/// must still be able to respond to the other endpoint closing the channel +/// even after the subscription has been canceled. +/// +/// * The sink *either* forwards errors to the other endpoint *or* closes as +/// soon as an error is added and forwards that error to the [Sink.done] +/// future. +/// +/// These guarantees allow users to interact uniformly with all implementations, +/// and ensure that either endpoint closing the stream produces consistent +/// behavior. abstract class StreamChannel { - /// The stream that emits values from the other endpoint. + /// The single-subscription stream that emits values from the other endpoint. Stream get stream; /// The sink for sending values to the other endpoint. StreamSink get sink; /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// Note that this stream/sink pair must provide the guarantees listed in the + /// [StreamChannel] documentation. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); From 58ce9f4560f9141a401b4b4f77fe97cb6d63f0b6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 25 Jan 2016 15:09:57 -0800 Subject: [PATCH 0231/1215] Fix DelegatingStreamChannel. I apparently forgot to add imports and named it the wrong thing. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1615043004 . --- .../stream_channel/lib/src/delegating_stream_channel.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart index 9d6ad90fd..4434cf62a 100644 --- a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -2,16 +2,20 @@ // 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. +import 'dart:async'; + +import '../stream_channel.dart'; + /// A simple delegating wrapper around [StreamChannel]. /// /// Subclasses can override individual methods, or use this to expose only /// [StreamChannel] methods. -class StreamChannelView extends StreamChannelMixin { +class DelegatingStreamChannel extends StreamChannelMixin { /// The inner channel to which methods are forwarded. final StreamChannel _inner; Stream get stream => _inner.stream; StreamSink get sink => _inner.sink; - StreamChannelView(this._inner); + DelegatingStreamChannel(this._inner); } From 8c8923d24a14f1cb4103b07d96271cca957874f9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:25:07 -0800 Subject: [PATCH 0232/1215] Add a StreamChannelCompleter class. This is by analogy with StreamCompleter and StreamSinkCompleter in the async package, and is in fact implemented using them. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1631103002 . --- .../lib/src/stream_channel_completer.dart | 77 +++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 + .../test/stream_channel_completer_test.dart | 124 ++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/stream_channel_completer.dart create mode 100644 pkgs/stream_channel/test/stream_channel_completer_test.dart diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart new file mode 100644 index 000000000..d15adcf94 --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -0,0 +1,77 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [channel] where the source and destination are provided later. +/// +/// The [channel] is a normal channel that can be listened to and that events +/// can be added to immediately, but until [setChannel] is called it won't emit +/// any events and all events added to it will be buffered. +class StreamChannelCompleter { + /// The completer for this channel's stream. + final _streamCompleter = new StreamCompleter(); + + /// The completer for this channel's sink. + final _sinkCompleter = new StreamSinkCompleter(); + + /// The channel for this completer. + StreamChannel get channel => _channel; + StreamChannel _channel; + + /// Whether [setChannel] has been called. + bool _set = false; + + /// Convert a `Future` to a `StreamChannel`. + /// + /// This creates a channel using a channel completer, and sets the source + /// channel to the result of the future when the future completes. + /// + /// If the future completes with an error, the returned channel's stream will + /// instead contain just that error. The sink will silently discard all + /// events. + static StreamChannel fromFuture(Future channelFuture) { + var completer = new StreamChannelCompleter(); + channelFuture.then(completer.setChannel, onError: completer.setError); + return completer.channel; + } + + StreamChannelCompleter() { + _channel = new StreamChannel( + _streamCompleter.stream, _sinkCompleter.sink); + } + + /// Set a channel as the source and destination for [channel]. + /// + /// A channel may be set at most once. + /// + /// Either [setChannel] or [setError] may be called at most once. Trying to + /// call either of them again will fail. + void setChannel(StreamChannel channel) { + if (_set) throw new StateError("The channel has already been set."); + _set = true; + + _streamCompleter.setSourceStream(channel.stream); + _sinkCompleter.setDestinationSink(channel.sink); + } + + /// Indicates that there was an error connecting the channel. + /// + /// This makes the stream emit [error] and close. It makes the sink discard + /// all its events. + /// + /// Either [setChannel] or [setError] may be called at most once. Trying to + /// call either of them again will fail. + void setError(error, [StackTrace stackTrace]) { + if (_set) throw new StateError("The channel has already been set."); + _set = true; + + _streamCompleter.setError(error, stackTrace); + _sinkCompleter.setDestinationSink(new NullStreamSink()); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index fd7b09327..4b3c659ae 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,6 +6,7 @@ import 'dart:async'; export 'src/delegating_stream_channel.dart'; export 'src/multi_channel.dart'; +export 'src/stream_channel_completer.dart'; /// An abstract class representing a two-way communication channel. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 76f22b7da..a0d8d2200 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -5,5 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.0.0 <2.0.0' +dependencies: + async: '^1.8.0' dev_dependencies: test: '^0.12.0' diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart new file mode 100644 index 000000000..1ee40a5ca --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -0,0 +1,124 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var completer; + var streamController; + var sinkController; + var innerChannel; + setUp(() { + completer = new StreamChannelCompleter(); + streamController = new StreamController(); + sinkController = new StreamController(); + innerChannel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + group("when a channel is set before accessing", () { + test("forwards events through the stream", () { + completer.setChannel(innerChannel); + expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + }); + + test("forwards events through the sink", () { + completer.setChannel(innerChannel); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + + completer.channel.sink.add(1); + completer.channel.sink.add(2); + completer.channel.sink.add(3); + completer.channel.sink.close(); + }); + + test("forwards an error through the stream", () { + completer.setError("oh no"); + expect(completer.channel.stream.first, throwsA("oh no")); + }); + + test("drops sink events", () { + completer.setError("oh no"); + expect(completer.channel.sink.done, completes); + completer.channel.sink.add(1); + completer.channel.sink.addError("oh no"); + }); + }); + + group("when a channel is set after accessing", () { + test("forwards events through the stream", () async { + expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); + await pumpEventQueue(); + + completer.setChannel(innerChannel); + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + }); + + test("forwards events through the sink", () async { + completer.channel.sink.add(1); + completer.channel.sink.add(2); + completer.channel.sink.add(3); + completer.channel.sink.close(); + await pumpEventQueue(); + + completer.setChannel(innerChannel); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards an error through the stream", () async { + expect(completer.channel.stream.first, throwsA("oh no")); + await pumpEventQueue(); + + completer.setError("oh no"); + }); + + test("drops sink events", () async { + expect(completer.channel.sink.done, completes); + completer.channel.sink.add(1); + completer.channel.sink.addError("oh no"); + await pumpEventQueue(); + + completer.setError("oh no"); + }); + }); + + group("forFuture", () { + test("forwards a StreamChannel", () { + var channel = StreamChannelCompleter.fromFuture( + new Future.value(innerChannel)); + channel.sink.add(1); + channel.sink.close(); + streamController.sink.add(2); + streamController.sink.close(); + + expect(sinkController.stream.toList(), completion(equals([1]))); + expect(channel.stream.toList(), completion(equals([2]))); + }); + + test("forwards an error", () { + var channel = StreamChannelCompleter.fromFuture( + new Future.error("oh no")); + expect(channel.stream.toList(), throwsA("oh no")); + }); + }); + + test("doesn't allow the channel to be set multiple times", () { + completer.setChannel(innerChannel); + expect(() => completer.setChannel(innerChannel), throwsStateError); + expect(() => completer.setChannel(innerChannel), throwsStateError); + }); +} From 6c2fd24f90e5556c78207390ef5bb1f5289d36c8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:26:25 -0800 Subject: [PATCH 0233/1215] Add an IsolateChannel class. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1635873002 . --- .../lib/src/isolate_channel.dart | 146 ++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 +- .../test/isolate_channel_test.dart | 126 +++++++++++++++ 4 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/lib/src/isolate_channel.dart create mode 100644 pkgs/stream_channel/test/isolate_channel_test.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart new file mode 100644 index 000000000..c6645438d --- /dev/null +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -0,0 +1,146 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:isolate'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, +/// presumably with another isolate. +/// +/// The remote endpoint doesn't necessarily need to be running an +/// [IsolateChannel]. This can be used with any two ports, although the +/// [StreamChannel] semantics mean that this class will treat them as being +/// paired (for example, closing the [sink] will cause the [stream] to stop +/// emitting events). +/// +/// The underlying isolate ports have no notion of closing connections. This +/// means that [stream] won't close unless [sink] is closed, and that closing +/// [sink] won't cause the remote endpoint to close. Users should take care to +/// ensure that they always close the [sink] of every [IsolateChannel] they use +/// to avoid leaving dangling [ReceivePort]s. +class IsolateChannel extends StreamChannelMixin { + /// The port that produces incoming messages. + /// + /// This is wrapped in a [StreamView] to produce [stream]. + final ReceivePort _receivePort; + + /// The port that sends outgoing messages. + final SendPort _sendPort; + + Stream get stream => _stream; + final Stream _stream; + + StreamSink get sink => _sink; + _SendPortSink _sink; + + /// Creates a stream channel that receives messages from [receivePort] and + /// sends them over [sendPort]. + IsolateChannel(ReceivePort receivePort, this._sendPort) + : _receivePort = receivePort, + _stream = new StreamView(receivePort) { + _sink = new _SendPortSink(this); + } +} + +/// The sink for [IsolateChannel]. +/// +/// [SendPort] doesn't natively implement any sink API, so this adds that API as +/// a wrapper. Closing this just closes the [ReceivePort]. +class _SendPortSink implements StreamSink { + /// The channel that this sink is for. + final IsolateChannel _channel; + + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); + + /// Whether [done] has been completed. + /// + /// This is distinct from [_closed] because [done] can complete with an error + /// without the user explicitly calling [close]. + bool get _isDone => _doneCompleter.isCompleted; + + /// Whether the user has called [close]. + bool _closed = false; + + /// Whether we're currently adding a stream with [addStream]. + bool _inAddStream = false; + + _SendPortSink(this._channel); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDone) return; + + _add(data); + } + + /// A helper for [add] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. + void _add(T data) { + _channel._sendPort.send(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + + _close(error, stackTrace); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _close(); + } + + /// A helper for [close] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. It + /// also forwards [error] and [stackTrace] to [done] if they're passed. + Future _close([error, StackTrace stackTrace]) { + if (_isDone) return done; + + _channel._receivePort.close(); + + if (error != null) { + _doneCompleter.completeError(error, stackTrace); + } else { + _doneCompleter.complete(); + } + + return done; + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDone) return; + + _inAddStream = true; + var completer = new Completer.sync(); + stream.listen(_add, + onError: (error, stackTrace) { + _close(error, stackTrace); + completer.complete(); + }, + onDone: completer.complete, + cancelOnError: true); + return completer.future.then((_) { + _inAddStream = false; + }); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 4b3c659ae..ff36ec78b 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -5,6 +5,7 @@ import 'dart:async'; export 'src/delegating_stream_channel.dart'; +export 'src/isolate_channel.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index a0d8d2200..97057abe0 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -4,7 +4,7 @@ description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' dependencies: async: '^1.8.0' dev_dependencies: diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart new file mode 100644 index 000000000..9e4fddc95 --- /dev/null +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -0,0 +1,126 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:isolate'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var receivePort; + var sendPort; + var channel; + setUp(() { + receivePort = new ReceivePort(); + var receivePortForSend = new ReceivePort(); + sendPort = receivePortForSend.sendPort; + channel = new IsolateChannel(receivePortForSend, receivePort.sendPort); + }); + + tearDown(() { + receivePort.close(); + channel.sink.close(); + }); + + test("the channel can send messages", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + + expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("the channel can receive messages", () { + sendPort.send(1); + sendPort.send(2); + sendPort.send(3); + + expect(channel.stream.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("events can't be added to an explicitly-closed sink", () { + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + + group("stream channel rules", () { + test("closing the sink causes the stream to close before it emits any more " + "events", () { + sendPort.send(1); + sendPort.send(2); + sendPort.send(3); + sendPort.send(4); + sendPort.send(5); + + channel.stream.listen(expectAsync((message) { + expect(message, equals(1)); + channel.sink.close(); + }, count: 1)); + }); + + test("cancelling the stream's subscription has no effect on the sink", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); + }); + + test("the sink closes as soon as an error is added", () async { + channel.sink.addError("oh no"); + channel.sink.add(1); + expect(channel.sink.done, throwsA("oh no")); + + // Since the sink is closed, the stream should also be closed. + expect(channel.stream.isEmpty, completion(isTrue)); + + // The other end shouldn't receive the next event, since the sink was + // closed. Pump the event queue to give it a chance to. + receivePort.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("the sink closes as soon as an error is added via addStream", + () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + + // This future shouldn't get the error, because it's sent to [Sink.done]. + expect(channel.sink.addStream(controller.stream), completes); + + controller.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + await pumpEventQueue(); + expect(canceled, isTrue); + + // Even though the sink is closed, this shouldn't throw an error because + // the user didn't explicitly close it. + channel.sink.add(1); + }); + }); +} From 1a2eb425eba28db3bd20e191c6eb7a1769550bd8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 26 Jan 2016 15:28:31 -0800 Subject: [PATCH 0234/1215] Add StreamChannel.transform(). R=rnystrom@google.com Review URL: https://codereview.chromium.org//1639643002 . --- pkgs/stream_channel/lib/stream_channel.dart | 18 ++++++ .../test/stream_channel_test.dart | 58 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 pkgs/stream_channel/test/stream_channel_test.dart diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ff36ec78b..2885e2d23 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -3,6 +3,9 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'dart:convert'; + +import 'package:async/async.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; @@ -66,6 +69,13 @@ abstract class StreamChannel { /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); + + /// Transforms [this] using [codec]. + /// + /// This returns a stream channel that encodes all input using [Codec.encoder] + /// before passing it to this channel's [sink], and decodes all output from + /// this channel's [stream] using [Codec.decoder]. + StreamChannel transform(Codec codec); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -87,4 +97,12 @@ abstract class StreamChannelMixin implements StreamChannel { stream.pipe(other.sink); other.stream.pipe(sink); } + + StreamChannel transform(Codec codec) { + var sinkTransformer = + new StreamSinkTransformer.fromStreamTransformer(codec.encoder); + return new _StreamChannel( + stream.transform(codec.decoder), + sinkTransformer.bind(sink)); + } } diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart new file mode 100644 index 000000000..30a7db4fa --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:isolate'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + test("pipe() pipes data from each channel's stream into the other's sink", + () { + var otherStreamController = new StreamController(); + var otherSinkController = new StreamController(); + var otherChannel = new StreamChannel( + otherStreamController.stream, otherSinkController.sink); + channel.pipe(otherChannel); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + expect(otherSinkController.stream.toList(), completion(equals([1, 2, 3]))); + + otherStreamController.add(4); + otherStreamController.add(5); + otherStreamController.add(6); + otherStreamController.close(); + expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); + }); + + test("transform() transforms the channel", () { + var transformed = channel.transform(UTF8); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), completion(equals(["foobar"]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals([[102, 98, 108, 116, 104, 112]]))); + }); +} From 8a594ea113d24950f2d6723b8f8034cb3bd81779 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 27 Jan 2016 15:24:46 -0800 Subject: [PATCH 0235/1215] Add StreamChannelTransformer. This makes StreamChannel.transform() take a StreamChannelTransformer rather than a codec. This is better, since a codec is explicitly intended to convert chunked data, while transformers are more general. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1632903004 . --- .../lib/src/isolate_channel.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 52 +++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 21 +++----- .../test/stream_channel_test.dart | 3 +- 4 files changed, 62 insertions(+), 16 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/stream_channel_transformer.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c6645438d..46375c986 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -128,7 +128,7 @@ class _SendPortSink implements StreamSink { if (_inAddStream) { throw new StateError("Cannot add stream while adding stream."); } - if (_isDone) return; + if (_isDone) return new Future.value(); _inAddStream = true; var completer = new Completer.sync(); diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart new file mode 100644 index 000000000..be032c60d --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -0,0 +1,52 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannelTransformer] transforms the events being passed to and +/// emitted by a [StreamChannel]. +/// +/// This works on the same principle as [StreamTransformer] and +/// [StreamSinkTransformer]. Each transformer defines a [bind] method that takes +/// in the original [StreamChannel] and returns the transformed version. +/// +/// Transformers must be able to have `bind` called multiple times. +class StreamChannelTransformer { + /// The transformer to use on the channel's stream. + final StreamTransformer _streamTransformer; + + /// The transformer to use on the channel's sink. + final StreamSinkTransformer _sinkTransformer; + + /// Creates a [StreamChannelTransformer] from existing stream and sink + /// transformers. + const StreamChannelTransformer( + this._streamTransformer, this._sinkTransformer); + + /// Creates a [StreamChannelTransformer] from a codec's encoder and decoder. + /// + /// All input to the inner channel's sink is encoded using [Codec.encoder], + /// and all output from its stream is decoded using [Codec.decoder]. + StreamChannelTransformer.fromCodec(Codec codec) + : this( + codec.decoder, + new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + + /// Transforms the events sent to and emitted by [channel]. + /// + /// Creates a new channel. When events are passed to the returned channel's + /// sink, the transformer will transform them and pass the transformed + /// versions to `channel.sink`. When events are emitted from the + /// `channel.straem`, the transformer will transform them and pass the + /// transformed versions to the returned channel's stream. + StreamChannel bind(StreamChannel channel) => + new StreamChannel( + channel.stream.transform(_streamTransformer), + _sinkTransformer.bind(channel.sink)); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 2885e2d23..e7fb055aa 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -3,14 +3,14 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:convert'; -import 'package:async/async.dart'; +import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; +export 'src/stream_channel_transformer.dart'; /// An abstract class representing a two-way communication channel. /// @@ -70,12 +70,10 @@ abstract class StreamChannel { /// directly to the other. void pipe(StreamChannel other); - /// Transforms [this] using [codec]. + /// Transforms [this] using [transformer]. /// - /// This returns a stream channel that encodes all input using [Codec.encoder] - /// before passing it to this channel's [sink], and decodes all output from - /// this channel's [stream] using [Codec.decoder]. - StreamChannel transform(Codec codec); + /// This is identical to calling `transformer.bind(channel)`. + StreamChannel transform(StreamChannelTransformer transformer); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -98,11 +96,6 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(Codec codec) { - var sinkTransformer = - new StreamSinkTransformer.fromStreamTransformer(codec.encoder); - return new _StreamChannel( - stream.transform(codec.decoder), - sinkTransformer.bind(sink)); - } + StreamChannel transform(StreamChannelTransformer transformer) => + transformer.bind(this); } diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 30a7db4fa..5f006c39c 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -44,7 +44,8 @@ void main() { }); test("transform() transforms the channel", () { - var transformed = channel.transform(UTF8); + var transformed = channel.transform( + new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 83b986e85c009e5dfd42c11e64381ba062cf0bd4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 27 Jan 2016 15:28:46 -0800 Subject: [PATCH 0236/1215] Add IsolateChannel.connect* constructors. These constructors use a lightweight protocol to establish a two-way connection over a previously-one-way connection. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1638183002 . --- .../lib/src/isolate_channel.dart | 172 +++++++----------- .../src/isolate_channel/send_port_sink.dart | 111 +++++++++++ pkgs/stream_channel/pubspec.yaml | 1 + .../test/isolate_channel_test.dart | 35 ++++ 4 files changed, 208 insertions(+), 111 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 46375c986..a466d87f3 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -5,7 +5,11 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:async/async.dart'; +import 'package:stack_trace/stack_trace.dart'; + import '../stream_channel.dart'; +import 'isolate_channel/send_port_sink.dart'; /// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, /// presumably with another isolate. @@ -22,125 +26,71 @@ import '../stream_channel.dart'; /// ensure that they always close the [sink] of every [IsolateChannel] they use /// to avoid leaving dangling [ReceivePort]s. class IsolateChannel extends StreamChannelMixin { - /// The port that produces incoming messages. - /// - /// This is wrapped in a [StreamView] to produce [stream]. - final ReceivePort _receivePort; - - /// The port that sends outgoing messages. - final SendPort _sendPort; - - Stream get stream => _stream; - final Stream _stream; - - StreamSink get sink => _sink; - _SendPortSink _sink; + final Stream stream; + final StreamSink sink; - /// Creates a stream channel that receives messages from [receivePort] and - /// sends them over [sendPort]. - IsolateChannel(ReceivePort receivePort, this._sendPort) - : _receivePort = receivePort, - _stream = new StreamView(receivePort) { - _sink = new _SendPortSink(this); - } -} - -/// The sink for [IsolateChannel]. -/// -/// [SendPort] doesn't natively implement any sink API, so this adds that API as -/// a wrapper. Closing this just closes the [ReceivePort]. -class _SendPortSink implements StreamSink { - /// The channel that this sink is for. - final IsolateChannel _channel; - - Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); - - /// Whether [done] has been completed. + /// Connects to a remote channel that was created with + /// [IsolateChannel.connectSend]. /// - /// This is distinct from [_closed] because [done] can complete with an error - /// without the user explicitly calling [close]. - bool get _isDone => _doneCompleter.isCompleted; - - /// Whether the user has called [close]. - bool _closed = false; - - /// Whether we're currently adding a stream with [addStream]. - bool _inAddStream = false; - - _SendPortSink(this._channel); - - void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - if (_isDone) return; - - _add(data); - } - - /// A helper for [add] that doesn't check for [StateError]s. + /// These constructors establish a connection using only a single + /// [SendPort]/[ReceivePort] pair, as long as each side uses one of the + /// connect constructors. /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. - void _add(T data) { - _channel._sendPort.send(data); - } - - void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - - _close(error, stackTrace); - } - - Future close() { - if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); - } + /// The connection protocol is guaranteed to remain compatible across versions + /// at least until the next major version release. If the protocol is + /// violated, the resulting channel will emit a single value on its stream and + /// then close. + factory IsolateChannel.connectReceive(ReceivePort receivePort) { + // We can't use a [StreamChannelCompleter] here because we need the return + // value to be an [IsolateChannel]. + var streamCompleter = new StreamCompleter(); + var sinkCompleter = new StreamSinkCompleter(); + var channel = new IsolateChannel._( + streamCompleter.stream, sinkCompleter.sink); + + // The first message across the ReceivePort should be a SendPort pointing to + // the remote end. If it's not, we'll make the stream emit an error + // complaining. + var subscription; + subscription = receivePort.listen((message) { + if (message is SendPort) { + streamCompleter.setSourceStream( + new SubscriptionStream(subscription)); + sinkCompleter.setDestinationSink( + new SendPortSink(receivePort, message)); + return; + } + + streamCompleter.setError( + new StateError('Unexpected Isolate response "$message".'), + new Trace.current()); + sinkCompleter.setDestinationSink(new NullStreamSink()); + subscription.cancel(); + }); - _closed = true; - return _close(); + return channel; } - /// A helper for [close] that doesn't check for [StateError]s. + /// Connects to a remote channel that was created with + /// [IsolateChannel.connectReceive]. /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. It - /// also forwards [error] and [stackTrace] to [done] if they're passed. - Future _close([error, StackTrace stackTrace]) { - if (_isDone) return done; - - _channel._receivePort.close(); - - if (error != null) { - _doneCompleter.completeError(error, stackTrace); - } else { - _doneCompleter.complete(); - } - - return done; + /// These constructors establish a connection using only a single + /// [SendPort]/[ReceivePort] pair, as long as each side uses one of the + /// connect constructors. + /// + /// The connection protocol is guaranteed to remain compatible across versions + /// at least until the next major version release. + factory IsolateChannel.connectSend(SendPort sendPort) { + var receivePort = new ReceivePort(); + sendPort.send(receivePort.sendPort); + return new IsolateChannel(receivePort, sendPort); } - Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); - if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); - } - if (_isDone) return new Future.value(); + /// Creates a stream channel that receives messages from [receivePort] and + /// sends them over [sendPort]. + IsolateChannel(ReceivePort receivePort, SendPort sendPort) + : stream = new StreamView(receivePort), + sink = new SendPortSink(receivePort, sendPort); - _inAddStream = true; - var completer = new Completer.sync(); - stream.listen(_add, - onError: (error, stackTrace) { - _close(error, stackTrace); - completer.complete(); - }, - onDone: completer.complete, - cancelOnError: true); - return completer.future.then((_) { - _inAddStream = false; - }); - } + IsolateChannel._(this.stream, this.sink); } diff --git a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart new file mode 100644 index 000000000..d98f1da65 --- /dev/null +++ b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart @@ -0,0 +1,111 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:isolate'; + +/// The sink for [IsolateChannel]. +/// +/// [SendPort] doesn't natively implement any sink API, so this adds that API as +/// a wrapper. Closing this just closes the [ReceivePort]. +class SendPortSink implements StreamSink { + /// The port that produces incoming messages. + /// + /// This is wrapped in a [StreamView] to produce [stream]. + final ReceivePort _receivePort; + + /// The port that sends outgoing messages. + final SendPort _sendPort; + + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); + + /// Whether [done] has been completed. + /// + /// This is distinct from [_closed] because [done] can complete with an error + /// without the user explicitly calling [close]. + bool get _isDone => _doneCompleter.isCompleted; + + /// Whether the user has called [close]. + bool _closed = false; + + /// Whether we're currently adding a stream with [addStream]. + bool _inAddStream = false; + + SendPortSink(this._receivePort, this._sendPort); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDone) return; + + _add(data); + } + + /// A helper for [add] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. + void _add(T data) { + _sendPort.send(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + + _close(error, stackTrace); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _close(); + } + + /// A helper for [close] that doesn't check for [StateError]s. + /// + /// This is called from [addStream], so it shouldn't check [_inAddStream]. It + /// also forwards [error] and [stackTrace] to [done] if they're passed. + Future _close([error, StackTrace stackTrace]) { + if (_isDone) return done; + + _receivePort.close(); + + if (error != null) { + _doneCompleter.completeError(error, stackTrace); + } else { + _doneCompleter.complete(); + } + + return done; + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDone) return new Future.value(); + + _inAddStream = true; + var completer = new Completer.sync(); + stream.listen(_add, + onError: (error, stackTrace) { + _close(error, stackTrace); + completer.complete(); + }, + onDone: completer.complete, + cancelOnError: true); + return completer.future.then((_) { + _inAddStream = false; + }); + } +} diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 97057abe0..a8e26cd17 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,5 +7,6 @@ environment: sdk: '>=1.8.0 <2.0.0' dependencies: async: '^1.8.0' + stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.0' diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 9e4fddc95..fa4d8d532 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -123,4 +123,39 @@ void main() { channel.sink.add(1); }); }); + + group("connect constructors", () { + var connectPort; + setUp(() { + connectPort = new ReceivePort(); + }); + + tearDown(() { + connectPort.close(); + }); + + test("create a connected pair of channels", () { + var channel1 = new IsolateChannel.connectReceive(connectPort); + var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + expect(channel2.stream.take(3).toList(), completion(equals([1, 2, 3]))); + + channel2.sink.add(4); + channel2.sink.add(5); + channel2.sink.add(6); + expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); + }); + + test("the receiving channel produces an error if it gets the wrong message", + () { + var connectedChannel = new IsolateChannel.connectReceive(connectPort); + connectPort.sendPort.send("wrong value"); + + expect(connectedChannel.stream.toList(), throwsStateError); + expect(connectedChannel.sink.done, completes); + }); + }); } From 58a473046d65f1ca07349c933a071de2df8c11a6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 12:00:25 -0800 Subject: [PATCH 0237/1215] Add a document-by-document JSON transformer. This makes it easy to send JSON over WebSocket connections, for example. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1643843002 . --- .../lib/src/json_document_transformer.dart | 41 +++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + .../test/json_document_transformer_test.dart | 50 +++++++++++++++++++ 3 files changed, 92 insertions(+) create mode 100644 pkgs/stream_channel/lib/src/json_document_transformer.dart create mode 100644 pkgs/stream_channel/test/json_document_transformer_test.dart diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart new file mode 100644 index 000000000..8d8dcce23 --- /dev/null +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:convert'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; +import 'stream_channel_transformer.dart'; + +/// The canonical instance of [JsonDocumentTransformer]. +final jsonDocument = new JsonDocumentTransformer(); + +/// A [StreamChannelTransformer] that transforms JSON documents—strings that +/// contain individual objects encoded as JSON—into decoded Dart objects. +/// +/// This decodes JSON that's emitted by the transformed channel's stream, and +/// encodes objects so that JSON is passed to the transformed channel's sink. +class JsonDocumentTransformer + implements StreamChannelTransformer { + /// The underlying codec that implements the encoding and decoding logic. + final JsonCodec _codec; + + /// Creates a new transformer. + /// + /// The [reviver] and [toEncodable] arguments work the same way as the + /// corresponding arguments to [new JsonCodec]. + JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) + : _codec = new JsonCodec(reviver: reviver, toEncodable: toEncodable); + + JsonDocumentTransformer._(this._codec); + + StreamChannel bind(StreamChannel channel) { + var stream = channel.stream.map(_codec.decode); + var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { + sink.add(_codec.encode(data)); + }).bind(channel.sink); + return new StreamChannel(stream, sink); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index e7fb055aa..f914188e6 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -8,6 +8,7 @@ import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/isolate_channel.dart'; +export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; export 'src/stream_channel_transformer.dart'; diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart new file mode 100644 index 000000000..fec3d2ac1 --- /dev/null +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:convert'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel( + streamController.stream, sinkController.sink); + }); + + test("decodes JSON emitted by the channel", () { + var transformed = channel.transform(jsonDocument); + streamController.add('{"foo": "bar"}'); + expect(transformed.stream.first, completion(equals({"foo": "bar"}))); + }); + + test("encodes objects added to the channel", () { + var transformed = channel.transform(jsonDocument); + transformed.sink.add({"foo": "bar"}); + expect(sinkController.stream.first, + completion(equals(JSON.encode({"foo": "bar"})))); + }); + + test("supports the reviver function", () { + var transformed = channel.transform( + new JsonDocumentTransformer(reviver: (key, value) => "decoded")); + streamController.add('{"foo": "bar"}'); + expect(transformed.stream.first, completion(equals("decoded"))); + }); + + test("supports the toEncodable function", () { + var transformed = channel.transform( + new JsonDocumentTransformer(toEncodable: (object) => "encoded")); + transformed.sink.add(new Object()); + expect(sinkController.stream.first, completion(equals('"encoded"'))); + }); +} From 27f7f49ac0aa49d6934ce0d67aac7674b65909e9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 13:04:12 -0800 Subject: [PATCH 0238/1215] Release version 1.0.0. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1647983003 . --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 847d60daa..31490590d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,3 @@ -## 0.0.1 +## 1.0.0 * Initial version diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index a8e26cd17..5f1a73963 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.0-dev +version: 1.0.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From b2d21787d4dca41b75b03fd0c4ea68f8273b1cc9 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 28 Jan 2016 14:10:11 -0800 Subject: [PATCH 0239/1215] Fix the MultiChannel constructor. R=kevmoo@google.com, rnystrom@google.com Review URL: https://codereview.chromium.org//1644943004 . --- pkgs/stream_channel/CHANGELOG.md | 6 +++ .../stream_channel/lib/src/multi_channel.dart | 39 ++++++++----------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 6 ++- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 31490590d..c85bbe3c4 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.1 + +* Fix `MultiChannel`'s constructor to take a `StreamChannel`. This is + technically a breaking change, but since 1.0.0 was only released an hour ago, + we're treating it as a bug fix. + ## 1.0.0 * Initial version diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e87deb33b..cba592ab5 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -52,12 +52,11 @@ abstract class MultiChannel implements StreamChannel { /// virtual channels may be opened. StreamSink get sink; - /// Creates a new [MultiChannel] that sends messages over [innerStream] and - /// [innerSink]. + /// Creates a new [MultiChannel] that sends and receives messages over + /// [inner]. /// - /// The inner streams must take JSON-like objects. - factory MultiChannel(Stream innerStream, StreamSink innerSink) => - new _MultiChannel(innerStream, innerSink); + /// The inner channel must take JSON-like objects. + factory MultiChannel(StreamChannel inner) => new _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -78,17 +77,12 @@ abstract class MultiChannel implements StreamChannel { /// This is private so that [VirtualChannel] can inherit from [MultiChannel] /// without having to implement all the private members. class _MultiChannel extends StreamChannelMixin implements MultiChannel { - /// The inner stream over which all communication is received. + /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - Stream _innerStream; + StreamChannel _inner; - /// The inner sink over which all communication is sent. - /// - /// This will be `null` if the underlying communication channel is closed. - StreamSink _innerSink; - - /// The subscription to [_innerStream]. + /// The subscription to [_inner.stream]. StreamSubscription _innerStreamSubscription; Stream get stream => _streamController.stream; @@ -128,16 +122,16 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// scheme, but if it has an even id, it's using the remote id scheme. var _nextId = 1; - _MultiChannel(this._innerStream, this._innerSink) { + _MultiChannel(this._inner) { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. _streamControllers[0] = _streamController; _sinkControllers[0] = _sinkController; _sinkController.stream.listen( - (message) => _innerSink.add([0, message]), + (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _innerStream.listen((message) { + _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; var sink = _streamControllers[id]; @@ -156,7 +150,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { } VirtualChannel virtualChannel([id]) { - if (_innerStream == null) { + if (_inner == null) { throw new StateError("The underlying channel is closed."); } @@ -186,7 +180,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _streamControllers[inputId] = streamController; _sinkControllers[inputId] = sinkController; sinkController.stream.listen( - (message) => _innerSink.add([outputId, message]), + (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return new VirtualChannel._( @@ -199,20 +193,19 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _streamControllers.remove(inputId).close(); _sinkControllers.remove(inputId).close(); - if (_innerSink == null) return; + if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. - _innerSink.add([outputId]); + _inner.sink.add([outputId]); if (_streamControllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. void _closeInnerChannel() { - _innerSink.close(); + _inner.sink.close(); _innerStreamSubscription.cancel(); - _innerStream = null; - _innerSink = null; + _inner = null; for (var controller in _sinkControllers.values.toList()) { controller.close(); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5f1a73963..09df4a797 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.0 +version: 1.0.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index e4594128a..cc9ed1d26 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -17,8 +17,10 @@ void main() { setUp(() { oneToTwo = new StreamController(); twoToOne = new StreamController(); - channel1 = new MultiChannel(twoToOne.stream, oneToTwo.sink); - channel2 = new MultiChannel(oneToTwo.stream, twoToOne.sink); + channel1 = new MultiChannel( + new StreamChannel(twoToOne.stream, oneToTwo.sink)); + channel2 = new MultiChannel( + new StreamChannel(oneToTwo.stream, twoToOne.sink)); }); group("the default virtual channel", () { From fa624b0506e938821c05bdba91468b39fbeee9b0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 1 Feb 2016 14:20:16 -0800 Subject: [PATCH 0240/1215] Use StackTrace.current Closes https://github.com/dart-lang/stack_trace/issues/8 R=nweiz@google.com Review URL: https://codereview.chromium.org//1653603002 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/trace.dart | 8 ++------ pkgs/stack_trace/pubspec.yaml | 4 ++-- pkgs/stack_trace/test/trace_test.dart | 16 ---------------- pkgs/stack_trace/test/vm_test.dart | 20 ++------------------ 5 files changed, 10 insertions(+), 42 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index fb699c677..66c1108ca 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.1 + +* Use `StacktTrace.current` in Dart SDK 1.14 to get the current stack trace. + ## 1.6.0 * Add a `when` parameter to `Chain.capture()`. This allows capturing to be diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 6d9823b08..927a16784 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -81,12 +81,8 @@ class Trace implements StackTrace { "to 0."); } - try { - throw ''; - } catch (_, nativeTrace) { - var trace = new Trace.from(nativeTrace); - return new LazyTrace(() => new Trace(trace.frames.skip(level + 1))); - } + var trace = new Trace.from(StackTrace.current); + return new LazyTrace(() => new Trace(trace.frames.skip(level + 1))); } /// Returns a new stack trace containing the same data as [trace]. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1c805c33d..e0fdbb962 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.0 +version: 1.6.1 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > @@ -19,4 +19,4 @@ dependencies: dev_dependencies: test: "^0.12.0" environment: - sdk: ">=1.8.0 <2.0.0" + sdk: ">=1.14.0 <2.0.0" diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index edb29fd8a..077f1baed 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -6,22 +6,6 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -String getStackTraceString() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString(); - } -} - -StackTrace getStackTraceObject() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace; - } -} - Trace getCurrentTrace([int level]) => new Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 947f14bd7..f0967b510 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -12,22 +12,6 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -String getStackTraceString() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace.toString(); - } -} - -StackTrace getStackTraceObject() { - try { - throw ''; - } catch (_, stackTrace) { - return stackTrace; - } -} - Frame getCaller([int level]) { if (level == null) return new Frame.caller(); return new Frame.caller(level); @@ -42,7 +26,7 @@ Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { group('Trace', () { test('.parse parses a real stack trace correctly', () { - var string = getStackTraceString(); + var string = StackTrace.current.toString(); var trace = new Trace.parse(string); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); @@ -50,7 +34,7 @@ void main() { }); test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); + var trace = new Trace.from(StackTrace.current); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceObject')); From 3d3d041088e30403de76617863a214b0ff7f2794 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 1 Feb 2016 14:49:02 -0800 Subject: [PATCH 0241/1215] fix vm_test R=nweiz@google.com Review URL: https://codereview.chromium.org//1654063003 . --- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/vm_test.dart | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index e0fdbb962..1c180cfaa 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.1 +version: 1.6.2-dev author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index f0967b510..1b5345837 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -12,6 +12,12 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; +// The name of this (trivial) function is verified as part of the test +String getStackTraceString() => StackTrace.current.toString(); + +// The name of this (trivial) function is verified as part of the test +StackTrace getStackTraceObject() => StackTrace.current; + Frame getCaller([int level]) { if (level == null) return new Frame.caller(); return new Frame.caller(level); @@ -26,7 +32,7 @@ Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { group('Trace', () { test('.parse parses a real stack trace correctly', () { - var string = StackTrace.current.toString(); + var string = getStackTraceString(); var trace = new Trace.parse(string); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); @@ -34,7 +40,7 @@ void main() { }); test('converts from a native stack trace correctly', () { - var trace = new Trace.from(StackTrace.current); + var trace = new Trace.from(getStackTraceObject()); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceObject')); From 7c16f9368ea38930bc96099fa956cdd6d835d550 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 15:55:12 -0800 Subject: [PATCH 0242/1215] Be more explicit about JSON error handling. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1658833002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ .../lib/src/json_document_transformer.dart | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/json_document_transformer_test.dart | 12 ++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index c85bbe3c4..d101ea0d2 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2 + +* Be more explicit about `JsonDocumentTransformer`'s error-handling behavior. + ## 1.0.1 * Fix `MultiChannel`'s constructor to take a `StreamChannel`. This is diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 8d8dcce23..19b2e08f7 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -17,6 +17,10 @@ final jsonDocument = new JsonDocumentTransformer(); /// /// This decodes JSON that's emitted by the transformed channel's stream, and /// encodes objects so that JSON is passed to the transformed channel's sink. +/// +/// If the transformed channel emits invalid JSON, this emits a +/// [FormatException]. If an unencodable object is added to the sink, it +/// synchronously throws a [JsonUnsupportedObjectError]. class JsonDocumentTransformer implements StreamChannelTransformer { /// The underlying codec that implements the encoding and decoding logic. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 09df4a797..54e919873 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.1 +version: 1.0.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index fec3d2ac1..65a349724 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -47,4 +47,16 @@ void main() { transformed.sink.add(new Object()); expect(sinkController.stream.first, completion(equals('"encoded"'))); }); + + test("emits a stream error when incoming JSON is malformed", () { + var transformed = channel.transform(jsonDocument); + streamController.add("{invalid"); + expect(transformed.stream.first, throwsFormatException); + }); + + test("synchronously throws if an unencodable object is added", () { + var transformed = channel.transform(jsonDocument); + expect(() => transformed.sink.add(new Object()), + throwsA(new isInstanceOf())); + }); } From ad406409f2380deb69e76cca692eeac9d3140470 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 15:56:24 -0800 Subject: [PATCH 0243/1215] Add support for stream- and sink-specific changes. These are especially useful when doing stream-specific transformations like error handling. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1657943002 . --- pkgs/stream_channel/CHANGELOG.md | 6 +- pkgs/stream_channel/lib/stream_channel.dart | 28 +++++++++ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_test.dart | 59 +++++++++++++++++++ 4 files changed, 93 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index d101ea0d2..ab0807249 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,8 @@ -## 1.0.2 +## 1.1.0 + +* Add `StreamChannel.transformStream()`, `StreamChannel.transformSink()`, + `StreamChannel.changeStream()`, and `StreamChannel.changeSink()` to support + changing only the stream or only the sink of a channel. * Be more explicit about `JsonDocumentTransformer`'s error-handling behavior. diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index f914188e6..ff3104212 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -75,6 +77,20 @@ abstract class StreamChannel { /// /// This is identical to calling `transformer.bind(channel)`. StreamChannel transform(StreamChannelTransformer transformer); + + /// Transforms only the [stream] component of [this] using [transformer]. + StreamChannel transformStream(StreamTransformer transformer); + + /// Transforms only the [sink] component of [this] using [transformer]. + StreamChannel transformSink(StreamSinkTransformer transformer); + + /// Returns a copy of [this] with [stream] replaced by [change]'s return + /// value. + StreamChannel changeStream(Stream change(Stream stream)); + + /// Returns a copy of [this] with [sink] replaced by [change]'s return + /// value. + StreamChannel changeSink(StreamSink change(StreamSink sink)); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -99,4 +115,16 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); + + StreamChannel transformStream(StreamTransformer transformer) => + changeStream(transformer.bind); + + StreamChannel transformSink(StreamSinkTransformer transformer) => + changeSink(transformer.bind); + + StreamChannel changeStream(Stream change(Stream stream)) => + new StreamChannel(change(stream), sink); + + StreamChannel changeSink(StreamSink change(StreamSink sink)) => + new StreamChannel(stream, change(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 54e919873..7ef11010f 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.0.2 +version: 1.1.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 5f006c39c..f5251778d 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:isolate'; +import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -56,4 +57,62 @@ void main() { expect(sinkController.stream.toList(), completion(equals([[102, 98, 108, 116, 104, 112]]))); }); + + test("transformStream() transforms only the stream", () { + var transformed = channel.transformStream(UTF8.decoder); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), completion(equals(["foobar"]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals(["fblthp"]))); + }); + + test("transformSink() transforms only the sink", () { + var transformed = channel.transformSink( + new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); + + streamController.add([102, 111, 111, 98, 97, 114]); + streamController.close(); + expect(transformed.stream.toList(), + completion(equals([[102, 111, 111, 98, 97, 114]]))); + + transformed.sink.add("fblthp"); + transformed.sink.close(); + expect(sinkController.stream.toList(), + completion(equals([[102, 98, 108, 116, 104, 112]]))); + }); + + test("changeStream() changes the stream", () { + var newController = new StreamController(); + var changed = channel.changeStream((stream) { + expect(stream, equals(channel.stream)); + return newController.stream; + }); + + newController.add(10); + newController.close(); + + streamController.add(20); + streamController.close(); + + expect(changed.stream.toList(), completion(equals([10]))); + }); + + test("changeSink() changes the sink", () { + var newController = new StreamController(); + var changed = channel.changeSink((sink) { + expect(sink, equals(channel.sink)); + return newController.sink; + }); + + expect(newController.stream.toList(), completion(equals([10]))); + streamController.stream.listen(expectAsync((_) {}, count: 0)); + + changed.sink.add(10); + changed.sink.close(); + }); } From a251a33379742b54d2752003d37a079b457f06bd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 1 Feb 2016 17:29:51 -0800 Subject: [PATCH 0244/1215] Fix inverted generic parameters. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1658893002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/stream_channel.dart | 4 ++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ab0807249..813870874 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.1 + +* Fix the type annotation for `StreamChannel.transform()`'s parameter. + ## 1.1.0 * Add `StreamChannel.transformStream()`, `StreamChannel.transformSink()`, diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ff3104212..7fff6744c 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -76,7 +76,7 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform(StreamChannelTransformer transformer); + StreamChannel transform(StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -113,7 +113,7 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(StreamChannelTransformer transformer) => + StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7ef11010f..7d1c6a3e4 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.1.0 +version: 1.1.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From d0af7ea9dedf277718f7fb9272f712babcd3f73f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 3 Feb 2016 17:33:46 -0800 Subject: [PATCH 0245/1215] Add StreamChannel.withGuarantees and StreamChannelController. These APIs make it easier for users to create their own stream channels that follow the StreamChannel guarantees. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1662773003 . --- pkgs/stream_channel/CHANGELOG.md | 8 + .../lib/src/guarantee_channel.dart | 163 ++++++++++++++++++ .../lib/src/stream_channel_controller.dart | 58 +++++++ pkgs/stream_channel/lib/stream_channel.dart | 14 +- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_controller_test.dart | 86 +++++++++ .../test/with_guarantees_test.dart | 110 ++++++++++++ 7 files changed, 439 insertions(+), 2 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/guarantee_channel.dart create mode 100644 pkgs/stream_channel/lib/src/stream_channel_controller.dart create mode 100644 pkgs/stream_channel/test/stream_channel_controller_test.dart create mode 100644 pkgs/stream_channel/test/with_guarantees_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 813870874..0b61d81f8 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.2.0 + +* Add `new StreamChannel.withGuarantees()`, which creates a channel with extra + wrapping to ensure that it obeys the stream channel guarantees. + +* Add `StreamChannelController`, which can be used to create custom + `StreamChannel` objects. + ## 1.1.1 * Fix the type annotation for `StreamChannel.transform()`'s parameter. diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart new file mode 100644 index 000000000..849cc2ffe --- /dev/null +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -0,0 +1,163 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that enforces the stream channel guarantees. +/// +/// This is exposed via [new StreamChannel.withGuarantees]. +class GuaranteeChannel extends StreamChannelMixin { + Stream get stream => _streamController.stream; + + StreamSink get sink => _sink; + _GuaranteeSink _sink; + + /// The controller for [stream]. + /// + /// This intermediate controller allows us to continue listening for a done + /// event even after the user has canceled their subscription, and to send our + /// own done event when the sink is closed. + StreamController _streamController; + + /// The subscription to the inner stream. + StreamSubscription _subscription; + + /// Whether the sink has closed, causing the underlying channel to disconnect. + bool _disconnected = false; + + GuaranteeChannel(Stream innerStream, StreamSink innerSink) { + _sink = new _GuaranteeSink(innerSink, this); + + // Enforce the single-subscription guarantee by changing a broadcast stream + // to single-subscription. + if (innerStream.isBroadcast) { + innerStream = innerStream.transform( + const SingleSubscriptionTransformer()); + } + + _streamController = new StreamController(onListen: () { + // If the sink has disconnected, we've already called + // [_streamController.close]. + if (_disconnected) return; + + _subscription = innerStream.listen(_streamController.add, + onError: _streamController.addError, + onDone: () { + _sink._onStreamDisconnected(); + _streamController.close(); + }); + }, sync: true); + } + + /// Called by [_GuaranteeSink] when the user closes it. + /// + /// The sink closing indicates that the connection is closed, so the stream + /// should stop emitting events. + void _onSinkDisconnected() { + _disconnected = true; + if (_subscription != null) _subscription.cancel(); + _streamController.close(); + } +} + +/// The sink for [GuaranteeChannel]. +/// +/// This wraps the inner sink to ignore events and cancel any in-progress +/// [addStream] calls when the underlying channel closes. +class _GuaranteeSink implements StreamSink { + /// The inner sink being wrapped. + final StreamSink _inner; + + /// The [GuaranteeChannel] this belongs to. + final GuaranteeChannel _channel; + + Future get done => _inner.done; + + /// Whether the stream has emitted a done event, causing the underlying + /// channel to disconnect. + bool _disconnected = false; + + /// Whether the user has called [close]. + bool _closed = false; + + /// The subscription to the stream passed to [addStream], if a stream is + /// currently being added. + StreamSubscription _addStreamSubscription; + + /// The completer for the future returned by [addStream], if a stream is + /// currently being added. + Completer _addStreamCompleter; + + /// Whether we're currently adding a stream with [addStream]. + bool get _inAddStream => _addStreamSubscription != null; + + _GuaranteeSink(this._inner, this._channel); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_disconnected) return; + + _inner.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_disconnected) return; + + _inner.addError(error, stackTrace); + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_disconnected) return new Future.value(); + + _addStreamCompleter = new Completer.sync(); + _addStreamSubscription = stream.listen( + _inner.add, + onError: _inner.addError, + onDone: _addStreamCompleter.complete); + return _addStreamCompleter.future.then((_) { + _addStreamCompleter = null; + _addStreamSubscription = null; + }); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + if (_disconnected) return new Future.value(); + + _channel._onSinkDisconnected(); + return _inner.close(); + } + + /// Called by [GuaranteeChannel] when the stream emits a done event. + /// + /// The stream being done indicates that the connection is closed, so the + /// sink should stop forwarding events. + void _onStreamDisconnected() { + _disconnected = true; + if (!_inAddStream) return; + + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } +} diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart new file mode 100644 index 000000000..1812a0e3a --- /dev/null +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -0,0 +1,58 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import '../stream_channel.dart'; + +/// A controller for exposing a new [StreamChannel]. +/// +/// This exposes two connected [StreamChannel]s, [local] and [foreign]. The +/// user's code should use [local] to emit and receive events. Then [foreign] +/// can be returned for others to use. For example, here's a simplified version +/// of the implementation of [new IsolateChannel]: +/// +/// ```dart +/// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { +/// var controller = new StreamChannelController(); +/// +/// // Pipe all events from the receive port into the local sink... +/// receivePort.pipe(controller.local.sink); +/// +/// // ...and all events from the local stream into the send port. +/// controller.local.listen(sendPort.add, onDone: receivePort.close); +/// +/// // Then return the foreign controller for your users to use. +/// return controller.foreign; +/// } +/// ``` +class StreamChannelController { + /// The local channel. + /// + /// This channel should be used directly by the creator of this + /// [StreamChannelController] to send and receive events. + StreamChannel get local => _local; + StreamChannel _local; + + /// The foreign channel. + /// + /// This channel should be returned to external users so they can communicate + /// with [local]. + StreamChannel get foreign => _foreign; + StreamChannel _foreign; + + /// Creates a [StreamChannelController]. + /// + /// If [sync] is true, events added to either channel's sink are synchronously + /// dispatched to the other channel's stream. This should only be done if the + /// source of those events is already asynchronous. + StreamChannelController({bool sync: false}) { + var localToForeignController = new StreamController(sync: sync); + var foreignToLocalController = new StreamController(sync: sync); + _local = new StreamChannel.withGuarantees( + foreignToLocalController.stream, localToForeignController.sink); + _foreign = new StreamChannel.withGuarantees( + localToForeignController.stream, foreignToLocalController.sink); + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 7fff6744c..8c4fad520 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -13,6 +14,7 @@ export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; +export 'src/stream_channel_controller.dart'; export 'src/stream_channel_transformer.dart'; /// An abstract class representing a two-way communication channel. @@ -65,10 +67,20 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// /// Note that this stream/sink pair must provide the guarantees listed in the - /// [StreamChannel] documentation. + /// [StreamChannel] documentation. If they don't do so natively, [new + /// StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// Unlike [new StreamChannel], this enforces the guarantees listed in the + /// [StreamChannel] documentation. This makes it somewhat less efficient than + /// just wrapping a stream and a sink directly, so [new StreamChannel] should + /// be used when the guarantees are provided natively. + factory StreamChannel.withGuarantees(Stream stream, StreamSink sink) => + new GuaranteeChannel(stream, sink); + /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7d1c6a3e4..f0b830ca1 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.1.1 +version: 1.2.0-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart new file mode 100644 index 000000000..e45f09062 --- /dev/null +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + group("asynchronously", () { + var controller; + setUp(() { + controller = new StreamChannelController(); + }); + + test("forwards events from the local sink to the foreign stream", () { + controller.local.sink..add(1)..add(2)..add(3)..close(); + expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards events from the foreign sink to the local stream", () { + controller.foreign.sink..add(1)..add(2)..add(3)..close(); + expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); + }); + }); + + group("synchronously", () { + var controller; + setUp(() { + controller = new StreamChannelController(sync: true); + }); + + test("synchronously forwards events from the local sink to the foreign " + "stream", () { + var receivedEvent = false; + var receivedError = false; + var receivedDone = false; + controller.foreign.stream.listen(expectAsync((event) { + expect(event, equals(1)); + receivedEvent = true; + }), onError: expectAsync((error) { + expect(error, equals("oh no")); + receivedError = true; + }), onDone: expectAsync(() { + receivedDone = true; + })); + + controller.local.sink.add(1); + expect(receivedEvent, isTrue); + + controller.local.sink.addError("oh no"); + expect(receivedError, isTrue); + + controller.local.sink.close(); + expect(receivedDone, isTrue); + }); + + test("synchronously forwards events from the foreign sink to the local " + "stream", () { + var receivedEvent = false; + var receivedError = false; + var receivedDone = false; + controller.local.stream.listen(expectAsync((event) { + expect(event, equals(1)); + receivedEvent = true; + }), onError: expectAsync((error) { + expect(error, equals("oh no")); + receivedError = true; + }), onDone: expectAsync(() { + receivedDone = true; + })); + + controller.foreign.sink.add(1); + expect(receivedEvent, isTrue); + + controller.foreign.sink.addError("oh no"); + expect(receivedError, isTrue); + + controller.foreign.sink.close(); + expect(receivedDone, isTrue); + }); + }); +} diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart new file mode 100644 index 000000000..0e95f9d88 --- /dev/null +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink); + }); + + group("with a broadcast stream", () { + setUp(() { + streamController = new StreamController.broadcast(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink); + }); + + test("buffers events", () async { + streamController.add(1); + streamController.add(2); + streamController.add(3); + await pumpEventQueue(); + + expect(channel.stream.toList(), completion(equals([1, 2, 3]))); + streamController.close(); + }); + + test("only allows a single subscription", () { + channel.stream.listen(null); + expect(() => channel.stream.listen(null), throwsStateError); + }); + }); + + test("closing the event sink causes the stream to close before it emits any " + "more events", () { + streamController.add(1); + streamController.add(2); + streamController.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)).asFuture(), completes); + }); + + test("after the stream closes, the sink ignores events", () async { + streamController.close(); + + // Wait for the done event to be delivered. + await channel.stream.toList(); + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + // None of our channel.sink additions should make it to the other endpoint. + sinkController.stream.listen( + expectAsync((_) {}, count: 0), + onDone: expectAsync(() {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + channel.stream.listen(null).cancel(); + await pumpEventQueue(); + + streamController.close(); + await pumpEventQueue(); + + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + // The sink should be ignoring events because the stream closed. + sinkController.stream.listen( + expectAsync((_) {}, count: 0), + onDone: expectAsync(() {}, count: 0)); + await pumpEventQueue(); + }); + + test("forwards errors to the other endpoint", () { + channel.sink.addError("error"); + expect(sinkController.stream.first, throwsA("error")); + }); +} From 8bd8af51f53b27dd99eeac67a8b8bfa2d0548bd4 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 4 Feb 2016 16:10:16 -0800 Subject: [PATCH 0246/1215] Provide more error-handling customization. This makes it easier to wrap underlying channels that don't support errors at all. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1669953002 . --- .../lib/src/guarantee_channel.dart | 52 +++++++++++++++---- .../lib/src/stream_channel_controller.dart | 10 +++- pkgs/stream_channel/lib/stream_channel.dart | 9 +++- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/stream_channel_controller_test.dart | 11 ++++ .../test/with_guarantees_test.dart | 40 ++++++++++++++ 6 files changed, 108 insertions(+), 16 deletions(-) diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 849cc2ffe..1047e14ff 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -30,8 +30,10 @@ class GuaranteeChannel extends StreamChannelMixin { /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; - GuaranteeChannel(Stream innerStream, StreamSink innerSink) { - _sink = new _GuaranteeSink(innerSink, this); + GuaranteeChannel(Stream innerStream, StreamSink innerSink, + {bool allowSinkErrors: true}) { + _sink = new _GuaranteeSink(innerSink, this, + allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. @@ -76,10 +78,13 @@ class _GuaranteeSink implements StreamSink { /// The [GuaranteeChannel] this belongs to. final GuaranteeChannel _channel; - Future get done => _inner.done; + Future get done => _doneCompleter.future; + final _doneCompleter = new Completer(); - /// Whether the stream has emitted a done event, causing the underlying - /// channel to disconnect. + /// Whether connection is disconnected. + /// + /// This can happen because the stream has emitted a done event, or because + /// the user added an error when [_allowErrors] is `false`. bool _disconnected = false; /// Whether the user has called [close]. @@ -96,7 +101,14 @@ class _GuaranteeSink implements StreamSink { /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; - _GuaranteeSink(this._inner, this._channel); + /// Whether errors are passed on to the underlying sink. + /// + /// If this is `false`, any error passed to the sink is piped to [done] and + /// the underlying sink is closed. + final bool _allowErrors; + + _GuaranteeSink(this._inner, this._channel, {bool allowErrors: true}) + : _allowErrors = allowErrors; void add(T data) { if (_closed) throw new StateError("Cannot add event after closing."); @@ -115,7 +127,20 @@ class _GuaranteeSink implements StreamSink { } if (_disconnected) return; - _inner.addError(error, stackTrace); + if (_allowErrors) { + _inner.addError(error, stackTrace); + return; + } + + _doneCompleter.completeError(error, stackTrace); + + // Treat an error like both the stream and sink disconnecting. + _onStreamDisconnected(); + _channel._onSinkDisconnected(); + + // Ignore errors from the inner sink. We're already surfacing one error, and + // if the user handles it we don't want them to have another top-level. + _inner.close().catchError((_) {}); } Future addStream(Stream stream) { @@ -141,11 +166,15 @@ class _GuaranteeSink implements StreamSink { throw new StateError("Cannot close sink while adding stream."); } + if (_closed) return done; _closed = true; - if (_disconnected) return new Future.value(); - _channel._onSinkDisconnected(); - return _inner.close(); + if (!_disconnected) { + _channel._onSinkDisconnected(); + _doneCompleter.complete(_inner.close()); + } + + return done; } /// Called by [GuaranteeChannel] when the stream emits a done event. @@ -154,8 +183,9 @@ class _GuaranteeSink implements StreamSink { /// sink should stop forwarding events. void _onStreamDisconnected() { _disconnected = true; - if (!_inAddStream) return; + if (!_doneCompleter.isCompleted) _doneCompleter.complete(); + if (!_inAddStream) return; _addStreamCompleter.complete(_addStreamSubscription.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 1812a0e3a..ad78323ef 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -47,12 +47,18 @@ class StreamChannelController { /// If [sync] is true, events added to either channel's sink are synchronously /// dispatched to the other channel's stream. This should only be done if the /// source of those events is already asynchronous. - StreamChannelController({bool sync: false}) { + /// + /// If [allowForeignErrors] is `false`, errors are not allowed to be passed to + /// the foreign channel's sink. If any are, the connection will close and the + /// error will be forwarded to the foreign channel's [Sink.done] future. This + /// guarantees that the local stream will never emit errors. + StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { var localToForeignController = new StreamController(sync: sync); var foreignToLocalController = new StreamController(sync: sync); _local = new StreamChannel.withGuarantees( foreignToLocalController.stream, localToForeignController.sink); _foreign = new StreamChannel.withGuarantees( - localToForeignController.stream, foreignToLocalController.sink); + localToForeignController.stream, foreignToLocalController.sink, + allowSinkErrors: allowForeignErrors); } } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 8c4fad520..992f7026a 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -78,8 +78,13 @@ abstract class StreamChannel { /// [StreamChannel] documentation. This makes it somewhat less efficient than /// just wrapping a stream and a sink directly, so [new StreamChannel] should /// be used when the guarantees are provided natively. - factory StreamChannel.withGuarantees(Stream stream, StreamSink sink) => - new GuaranteeChannel(stream, sink); + /// + /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to + /// [sink]. If any are, the connection will close and the error will be + /// forwarded to [Sink.done]. + factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, + {bool allowSinkErrors: true}) => + new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index f0b830ca1..52ee52171 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.2.0-dev +version: 1.2.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index e45f09062..cf8a31b36 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -25,6 +25,17 @@ void main() { controller.foreign.sink..add(1)..add(2)..add(3)..close(); expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); }); + + test("with allowForeignErrors: false, shuts down the connection if an " + "error is added to the foreign channel", () { + controller = new StreamChannelController(allowForeignErrors: false); + + controller.foreign.sink.addError("oh no"); + expect(controller.foreign.sink.done, throwsA("oh no")); + expect(controller.foreign.stream.toList(), completion(isEmpty)); + expect(controller.local.sink.done, completes); + expect(controller.local.stream.toList(), completion(isEmpty)); + }); }); group("synchronously", () { diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 0e95f9d88..38afefac0 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -107,4 +107,44 @@ void main() { channel.sink.addError("error"); expect(sinkController.stream.first, throwsA("error")); }); + + test("Sink.done completes once the stream is done", () { + channel.stream.listen(null); + expect(channel.sink.done, completes); + streamController.close(); + }); + + group("with allowSinkErrors: false", () { + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink, allowSinkErrors: false); + }); + + test("forwards errors to Sink.done but not the stream", () { + channel.sink.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + sinkController.stream.listen(null, + onError: expectAsync((_) {}, count: 0)); + }); + + test("adding an error causes the stream to emit a done event", () { + expect(channel.sink.done, throwsA("oh no")); + + streamController.add(1); + streamController.add(2); + streamController.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.addError("oh no"); + }, count: 2)).asFuture(), completes); + }); + + test("adding an error closes the inner sink", () { + channel.sink.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + expect(sinkController.stream.toList(), completion(isEmpty)); + }); + }); } From f5810280eba19d7de62256fc35170c3e345d9dcc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 8 Feb 2016 16:11:18 -0800 Subject: [PATCH 0247/1215] Make IsolateChannel use StreamChannelCompleter. This exposed some lingering bugs in GuaranteeChannel as well. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1671763002 . --- .../lib/src/guarantee_channel.dart | 10 +- .../lib/src/isolate_channel.dart | 22 ++-- .../src/isolate_channel/send_port_sink.dart | 111 ------------------ .../lib/src/stream_channel_controller.dart | 4 +- .../test/with_guarantees_test.dart | 43 +++++++ 5 files changed, 68 insertions(+), 122 deletions(-) delete mode 100644 pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 1047e14ff..a874799c1 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -127,6 +127,14 @@ class _GuaranteeSink implements StreamSink { } if (_disconnected) return; + _addError(error, stackTrace); + } + + /// Like [addError], but doesn't check to ensure that an error can be added. + /// + /// This is called from [addStream], so it shouldn't fail if a stream is being + /// added. + void _addError(error, [StackTrace stackTrace]) { if (_allowErrors) { _inner.addError(error, stackTrace); return; @@ -153,7 +161,7 @@ class _GuaranteeSink implements StreamSink { _addStreamCompleter = new Completer.sync(); _addStreamSubscription = stream.listen( _inner.add, - onError: _inner.addError, + onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index a466d87f3..3466d19dd 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -9,7 +9,6 @@ import 'package:async/async.dart'; import 'package:stack_trace/stack_trace.dart'; import '../stream_channel.dart'; -import 'isolate_channel/send_port_sink.dart'; /// A [StreamChannel] that communicates over a [ReceivePort]/[SendPort] pair, /// presumably with another isolate. @@ -54,10 +53,13 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - streamCompleter.setSourceStream( - new SubscriptionStream(subscription)); - sinkCompleter.setDestinationSink( - new SendPortSink(receivePort, message)); + var controller = new StreamChannelController(allowForeignErrors: false); + new SubscriptionStream(subscription).pipe(controller.local.sink); + controller.local.stream.listen(message.send, + onDone: receivePort.close); + + streamCompleter.setSourceStream(controller.foreign.stream); + sinkCompleter.setDestinationSink(controller.foreign.sink); return; } @@ -88,9 +90,13 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. - IsolateChannel(ReceivePort receivePort, SendPort sendPort) - : stream = new StreamView(receivePort), - sink = new SendPortSink(receivePort, sendPort); + factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { + var controller = new StreamChannelController(allowForeignErrors: false); + receivePort.pipe(controller.local.sink); + controller.local.stream.listen(sendPort.send, onDone: receivePort.close); + return new IsolateChannel._( + controller.foreign.stream, controller.foreign.sink); + } IsolateChannel._(this.stream, this.sink); } diff --git a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart b/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart deleted file mode 100644 index d98f1da65..000000000 --- a/pkgs/stream_channel/lib/src/isolate_channel/send_port_sink.dart +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; -import 'dart:isolate'; - -/// The sink for [IsolateChannel]. -/// -/// [SendPort] doesn't natively implement any sink API, so this adds that API as -/// a wrapper. Closing this just closes the [ReceivePort]. -class SendPortSink implements StreamSink { - /// The port that produces incoming messages. - /// - /// This is wrapped in a [StreamView] to produce [stream]. - final ReceivePort _receivePort; - - /// The port that sends outgoing messages. - final SendPort _sendPort; - - Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); - - /// Whether [done] has been completed. - /// - /// This is distinct from [_closed] because [done] can complete with an error - /// without the user explicitly calling [close]. - bool get _isDone => _doneCompleter.isCompleted; - - /// Whether the user has called [close]. - bool _closed = false; - - /// Whether we're currently adding a stream with [addStream]. - bool _inAddStream = false; - - SendPortSink(this._receivePort, this._sendPort); - - void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - if (_isDone) return; - - _add(data); - } - - /// A helper for [add] that doesn't check for [StateError]s. - /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. - void _add(T data) { - _sendPort.send(data); - } - - void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); - if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); - } - - _close(error, stackTrace); - } - - Future close() { - if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); - } - - _closed = true; - return _close(); - } - - /// A helper for [close] that doesn't check for [StateError]s. - /// - /// This is called from [addStream], so it shouldn't check [_inAddStream]. It - /// also forwards [error] and [stackTrace] to [done] if they're passed. - Future _close([error, StackTrace stackTrace]) { - if (_isDone) return done; - - _receivePort.close(); - - if (error != null) { - _doneCompleter.completeError(error, stackTrace); - } else { - _doneCompleter.complete(); - } - - return done; - } - - Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); - if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); - } - if (_isDone) return new Future.value(); - - _inAddStream = true; - var completer = new Completer.sync(); - stream.listen(_add, - onError: (error, stackTrace) { - _close(error, stackTrace); - completer.complete(); - }, - onDone: completer.complete, - cancelOnError: true); - return completer.future.then((_) { - _inAddStream = false; - }); - } -} diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index ad78323ef..45b2865ed 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -15,13 +15,13 @@ import '../stream_channel.dart'; /// /// ```dart /// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { -/// var controller = new StreamChannelController(); +/// var controller = new StreamChannelController(allowForeignErrors: false); /// /// // Pipe all events from the receive port into the local sink... /// receivePort.pipe(controller.local.sink); /// /// // ...and all events from the local stream into the send port. -/// controller.local.listen(sendPort.add, onDone: receivePort.close); +/// controller.local.stream.listen(sendPort.send, onDone: receivePort.close); /// /// // Then return the foreign controller for your users to use. /// return controller.foreign; diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 38afefac0..409b28fdd 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -114,6 +114,29 @@ void main() { streamController.close(); }); + test("events can't be added to an explicitly-closed sink", () { + sinkController.stream.listen(null); // Work around sdk#19095. + + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + group("with allowSinkErrors: false", () { setUp(() { streamController = new StreamController(); @@ -146,5 +169,25 @@ void main() { expect(channel.sink.done, throwsA("oh no")); expect(sinkController.stream.toList(), completion(isEmpty)); }); + + test("adding an error via via addStream causes the stream to emit a done " + "event", () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + + // This future shouldn't get the error, because it's sent to [Sink.done]. + expect(channel.sink.addStream(controller.stream), completes); + + controller.addError("oh no"); + expect(channel.sink.done, throwsA("oh no")); + await pumpEventQueue(); + expect(canceled, isTrue); + + // Even though the sink is closed, this shouldn't throw an error because + // the user didn't explicitly close it. + channel.sink.add(1); + }); }); } From ed797d0f08bcf0c9368b2d21771adbeb8548079d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Feb 2016 11:11:06 -0800 Subject: [PATCH 0248/1215] Add a Disconnector class. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1679193002 . --- pkgs/stream_channel/CHANGELOG.md | 5 + pkgs/stream_channel/lib/src/disconnector.dart | 139 ++++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 + pkgs/stream_channel/pubspec.yaml | 2 +- .../test/disconnector_test.dart | 113 ++++++++++++++ 5 files changed, 259 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/lib/src/disconnector.dart create mode 100644 pkgs/stream_channel/test/disconnector_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0b61d81f8..dd749369e 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.3.0 + +* Add `Disconnector`, a transformer that allows the caller to disconnect the + transformed channel. + ## 1.2.0 * Add `new StreamChannel.withGuarantees()`, which creates a channel with extra diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart new file mode 100644 index 000000000..35ecd1cc4 --- /dev/null +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -0,0 +1,139 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import '../stream_channel.dart'; + +/// Allows the caller to force a channel to disconnect. +/// +/// When [disconnect] is called, the channel (or channels) transformed by this +/// transformer will act as though the remote end had disconnected—the stream +/// will emit a done event, and the sink will ignore future inputs. The inner +/// sink will also be closed to notify the remote end of the disconnection. +/// +/// If a channel is transformed after the [disconnect] has been called, it will +/// be disconnected immediately. +class Disconnector implements StreamChannelTransformer { + /// Whether [disconnect] has been called. + bool get isDisconnected => _isDisconnected; + var _isDisconnected = false; + + /// The sinks for transformed channels. + /// + /// Note that we assume that transformed channels provide the stream channel + /// guarantees. This allows us to only track sinks, because we know closing + /// the underlying sink will cause the stream to emit a done event. + final _sinks = <_DisconnectorSink>[]; + + /// Disconnects all channels that have been transformed. + void disconnect() { + _isDisconnected = true; + for (var sink in _sinks) { + sink._disconnect(); + } + _sinks.clear(); + } + + StreamChannel bind(StreamChannel channel) { + return channel.changeSink((innerSink) { + var sink = new _DisconnectorSink(innerSink); + + if (_isDisconnected) { + sink._disconnect(); + } else { + _sinks.add(sink); + } + + return sink; + }); + } +} + +/// A sink wrapper that can force a disconnection. +class _DisconnectorSink implements StreamSink { + /// The inner sink. + final StreamSink _inner; + + Future get done => _inner.done; + + /// Whether [Disconnector.disconnect] has been called. + var _isDisconnected = false; + + /// Whether the user has called [close]. + var _closed = false; + + /// The subscription to the stream passed to [addStream], if a stream is + /// currently being added. + StreamSubscription _addStreamSubscription; + + /// The completer for the future returned by [addStream], if a stream is + /// currently being added. + Completer _addStreamCompleter; + + /// Whether we're currently adding a stream with [addStream]. + bool get _inAddStream => _addStreamSubscription != null; + + _DisconnectorSink(this._inner); + + void add(T data) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDisconnected) return; + + _inner.add(data); + } + + void addError(error, [StackTrace stackTrace]) { + if (_closed) throw new StateError("Cannot add event after closing."); + if (_inAddStream) { + throw new StateError("Cannot add event while adding stream."); + } + if (_isDisconnected) return; + + _inner.addError(error, stackTrace); + } + + Future addStream(Stream stream) { + if (_closed) throw new StateError("Cannot add stream after closing."); + if (_inAddStream) { + throw new StateError("Cannot add stream while adding stream."); + } + if (_isDisconnected) return new Future.value(); + + _addStreamCompleter = new Completer.sync(); + _addStreamSubscription = stream.listen( + _inner.add, + onError: _inner.addError, + onDone: _addStreamCompleter.complete); + return _addStreamCompleter.future.then((_) { + _addStreamCompleter = null; + _addStreamSubscription = null; + }); + } + + Future close() { + if (_inAddStream) { + throw new StateError("Cannot close sink while adding stream."); + } + + _closed = true; + return _inner.close(); + } + + /// Disconnects this sink. + /// + /// This closes the underlying sink and stops forwarding events. + void _disconnect() { + _isDisconnected = true; + _inner.close(); + + if (!_inAddStream) return; + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 992f7026a..b89845d05 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -10,6 +10,7 @@ import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; +export 'src/disconnector.dart'; export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 52ee52171..c787b95ea 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.2.0 +version: 1.3.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart new file mode 100644 index 000000000..09cdddc57 --- /dev/null +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -0,0 +1,113 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:isolate'; + +import 'package:async/async.dart'; +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + var streamController; + var sinkController; + var disconnector; + var channel; + setUp(() { + streamController = new StreamController(); + sinkController = new StreamController(); + disconnector = new Disconnector(); + channel = new StreamChannel.withGuarantees( + streamController.stream, sinkController.sink) + .transform(disconnector); + }); + + group("before disconnection", () { + test("forwards events from the sink as normal", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("forwards events to the stream as normal", () { + streamController.add(1); + streamController.add(2); + streamController.add(3); + streamController.close(); + + expect(channel.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("events can't be added when the sink is explicitly closed", () { + sinkController.stream.listen(null); // Work around sdk#19095. + + expect(channel.sink.close(), completes); + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + }); + + test("events can't be added while a stream is being added", () { + var controller = new StreamController(); + channel.sink.addStream(controller.stream); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addStream(new Stream.fromIterable([])), + throwsStateError); + expect(() => channel.sink.close(), throwsStateError); + + controller.close(); + }); + }); + + test("cancels addStream when disconnected", () async { + var canceled = false; + var controller = new StreamController(onCancel: () { + canceled = true; + }); + expect(channel.sink.addStream(controller.stream), completes); + disconnector.disconnect(); + + await pumpEventQueue(); + expect(canceled, isTrue); + }); + + group("after disconnection", () { + setUp(() => disconnector.disconnect()); + + test("closes the inner sink and ignores events to the outer sink", () { + channel.sink.add(1); + channel.sink.add(2); + channel.sink.add(3); + channel.sink.close(); + + expect(sinkController.stream.toList(), completion(isEmpty)); + }); + + test("closes the stream", () { + expect(channel.stream.toList(), completion(isEmpty)); + }); + + test("completes done", () { + sinkController.stream.listen(null); // Work around sdk#19095. + expect(channel.sink.done, completes); + }); + + test("still emits state errors after explicit close", () { + sinkController.stream.listen(null); // Work around sdk#19095. + expect(channel.sink.close(), completes); + + expect(() => channel.sink.add(1), throwsStateError); + expect(() => channel.sink.addError("oh no"), throwsStateError); + }); + }); +} \ No newline at end of file From 0f4b74769c54889b9eaa430c4cb48d2ecacb6e5a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Feb 2016 13:08:55 -0800 Subject: [PATCH 0249/1215] Make IsolateChannel's controllers synchronous. This is slightly more efficient, and also make it easier for other packages to work around dart-lang/sdkdart-lang/stream_channel#25745. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1690473002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 6 ++++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index dd749369e..05a83e074 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1 + +* Make `IsolateChannel` slightly more efficient. + ## 1.3.0 * Add `Disconnector`, a transformer that allows the caller to disconnect the diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 3466d19dd..dcb52cbf3 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -53,7 +53,8 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController(allowForeignErrors: false); + var controller = new StreamChannelController( + allowForeignErrors: false, sync: true); new SubscriptionStream(subscription).pipe(controller.local.sink); controller.local.stream.listen(message.send, onDone: receivePort.close); @@ -91,7 +92,8 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController(allowForeignErrors: false); + var controller = new StreamChannelController( + allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); controller.local.stream.listen(sendPort.send, onDone: receivePort.close); return new IsolateChannel._( diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c787b95ea..930f74431 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.0 +version: 1.3.1-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 2ff097b8b67a2ba5dfceeb1ed5e6ec92a4e09de8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Feb 2016 14:26:24 -0800 Subject: [PATCH 0250/1215] Make MultiChannel follow the stream channel rules. It was written before the rules were fully fleshed-out, and I forgot to update it to comply. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1686263002 . --- pkgs/stream_channel/CHANGELOG.md | 2 + .../stream_channel/lib/src/multi_channel.dart | 86 ++++---- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 187 +++++++++++++++--- 4 files changed, 207 insertions(+), 70 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 05a83e074..b1b735072 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -2,6 +2,8 @@ * Make `IsolateChannel` slightly more efficient. +* Make `MultiChannel` follow the stream channel rules. + ## 1.3.0 * Add `Disconnector`, a transformer that allows the caller to disconnect the diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index cba592ab5..112997e57 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import '../stream_channel.dart'; /// A class that multiplexes multiple virtual channels across a single @@ -85,21 +87,15 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The subscription to [_inner.stream]. StreamSubscription _innerStreamSubscription; - Stream get stream => _streamController.stream; - final _streamController = new StreamController(sync: true); - - StreamSink get sink => _sinkController.sink; - final _sinkController = new StreamController(sync: true); + Stream get stream => _mainController.foreign.stream; + StreamSink get sink => _mainController.foreign.sink; - /// A map from virtual channel ids to [StreamController]s that should be used - /// to write messages received from those channels. - final _streamControllers = new Map(); + /// The controller for this channel. + final _mainController = new StreamChannelController(sync: true); - /// A map from virtual channel ids to [StreamControllers]s that are used - /// to receive messages to write to those channels. - /// - /// Note that this uses the same keys as [_streamControllers]. - final _sinkControllers = new Map(); + /// A map from virtual channel ids to [StreamChannelController]s that should + /// be used to communicate over those channels. + final _controllers = {}; /// The next id to use for a local virtual channel. /// @@ -125,35 +121,34 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _MultiChannel(this._inner) { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. - _streamControllers[0] = _streamController; - _sinkControllers[0] = _sinkController; - _sinkController.stream.listen( + _controllers[0] = _mainController; + _mainController.local.stream.listen( (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; - var sink = _streamControllers[id]; + var controller = _controllers[id]; - // A sink might not exist if the channel was closed before an incoming - // message was processed. - if (sink == null) return; + // A controller might not exist if the channel was closed before an + // incoming message was processed. + if (controller == null) return; if (message.length > 1) { - sink.add(message[1]); + controller.local.sink.add(message[1]); return; } - // A message without data indicates that the channel has been closed. - _sinkControllers[id].close(); - }, onDone: _closeInnerChannel, - onError: _streamController.addError); + // A message without data indicates that the channel has been closed. We + // can only close the sink here without doing any more cleanup, because + // the sink closing will cause the stream to emit a done event which will + // trigger more cleanup. + controller.local.sink.close(); + }, + onDone: _closeInnerChannel, + onError: _mainController.local.sink.addError); } VirtualChannel virtualChannel([id]) { - if (_inner == null) { - throw new StateError("The underlying channel is closed."); - } - var inputId; var outputId; if (id != null) { @@ -171,34 +166,39 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _nextId += 2; } - if (_streamControllers.containsKey(inputId)) { + // If the inner channel has already closed, create new virtual channels in a + // closed state. + if (_inner == null) { + return new VirtualChannel._( + this, inputId, new Stream.empty(), new NullStreamSink()); + } + + if (_controllers.containsKey(inputId)) { throw new ArgumentError("A virtual channel with id $id already exists."); } - var streamController = new StreamController(sync: true); - var sinkController = new StreamController(sync: true); - _streamControllers[inputId] = streamController; - _sinkControllers[inputId] = sinkController; - sinkController.stream.listen( + var controller = new StreamChannelController(sync: true); + _controllers[inputId] = controller; + controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return new VirtualChannel._( - this, outputId, streamController.stream, sinkController.sink); + this, outputId, controller.foreign.stream, controller.foreign.sink); } /// Closes the virtual channel for which incoming messages have [inputId] and /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { - _streamControllers.remove(inputId).close(); - _sinkControllers.remove(inputId).close(); + var controller = _controllers.remove(inputId); + controller.local.sink.close(); if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. _inner.sink.add([outputId]); - if (_streamControllers.isEmpty) _closeInnerChannel(); + if (_controllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. @@ -206,9 +206,13 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _inner.sink.close(); _innerStreamSubscription.cancel(); _inner = null; - for (var controller in _sinkControllers.values.toList()) { - controller.close(); + + // Convert this to a list because the close is dispatched synchronously, and + // that could conceivably remove a controller from [_controllers]. + for (var controller in new List.from(_controllers.values)) { + controller.local.sink.close(); } + _controllers.clear(); } } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 930f74431..c38c167f3 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.1-dev +version: 1.3.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index cc9ed1d26..5be250535 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -10,17 +10,13 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - var oneToTwo; - var twoToOne; + var controller; var channel1; var channel2; setUp(() { - oneToTwo = new StreamController(); - twoToOne = new StreamController(); - channel1 = new MultiChannel( - new StreamChannel(twoToOne.stream, oneToTwo.sink)); - channel2 = new MultiChannel( - new StreamChannel(oneToTwo.stream, twoToOne.sink)); + controller = new StreamChannelController(); + channel1 = new MultiChannel(controller.local); + channel2 = new MultiChannel(controller.foreign); }); group("the default virtual channel", () { @@ -66,16 +62,16 @@ void main() { test("closes the underlying channel when it closes without any other " "virtual channels", () { - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); channel1.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); // Establish another virtual connection which should keep the underlying // connection open. @@ -149,16 +145,16 @@ void main() { channel1.sink.close(); await channel2.stream.toList(); - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); virtual1.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); virtual1.sink.close(); @@ -246,16 +242,16 @@ void main() { channel2.sink.close(); await channel1.stream.toList(); - expect(oneToTwo.done, completes); - expect(twoToOne.done, completes); + expect(controller.local.sink.done, completes); + expect(controller.foreign.sink.done, completes); virtual2.sink.close(); }); test("doesn't close the underlying channel when it closes with other " "virtual channels", () { - oneToTwo.done.then(expectAsync((_) {}, count: 0)); - twoToOne.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); virtual2.sink.close(); @@ -288,16 +284,24 @@ void main() { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); - oneToTwo.close(); + controller.local.sink.close(); }); - test("closes, no more virtual channels may be created", () { - expect(channel1.sink.done.then((_) => channel1.virtualChannel()), - throwsStateError); - expect(channel2.sink.done.then((_) => channel2.virtualChannel()), - throwsStateError); + test("closes, more virtual channels are created closed", () async { + channel2.sink.close(); + virtual2.sink.close(); + + // Wait for the existing channels to emit done events. + await channel1.stream.toList(); + await virtual1.stream.toList(); + + var virtual = channel1.virtualChannel(); + expect(virtual.stream.toList(), completion(isEmpty)); + expect(virtual.sink.done, completes); - oneToTwo.close(); + virtual = channel1.virtualChannel(); + expect(virtual.stream.toList(), completion(isEmpty)); + expect(virtual.sink.done, completes); }); test("emits an error, the error is sent only to the default channel", () { @@ -306,7 +310,134 @@ void main() { virtual1.stream.listen(expectAsync((_) {}, count: 0), onError: expectAsync((_) {}, count: 0)); - twoToOne.addError("oh no"); + controller.foreign.sink.addError("oh no"); + }); + }); + + group("stream channel rules", () { + group("for the main stream:", () { + test("closing the sink causes the stream to close before it emits any more " + "events", () { + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + + channel2.stream.listen(expectAsync((message) { + expect(message, equals(1)); + channel2.sink.close(); + }, count: 1)); + }); + + test("after the stream closes, the sink ignores events", () async { + channel1.sink.close(); + + // Wait for the done event to be delivered. + await channel2.stream.toList(); + channel2.sink.add(1); + channel2.sink.add(2); + channel2.sink.add(3); + channel2.sink.close(); + + // None of our channel.sink additions should make it to the other endpoint. + channel1.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + channel1.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + channel1.sink.close(); + expect(channel2.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + channel1.stream.listen(null).cancel(); + await pumpEventQueue(); + + channel2.sink.close(); + await pumpEventQueue(); + + channel1.sink.add(1); + channel1.sink.add(2); + channel1.sink.add(3); + channel1.sink.close(); + + // The sink should be ignoring events because the channel closed. + channel2.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + }); + + group("for a virtual channel:", () { + var virtual1; + var virtual2; + setUp(() { + virtual1 = channel1.virtualChannel(); + virtual2 = channel2.virtualChannel(virtual1.id); + }); + + test("closing the sink causes the stream to close before it emits any more " + "events", () { + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + + virtual2.stream.listen(expectAsync((message) { + expect(message, equals(1)); + virtual2.sink.close(); + }, count: 1)); + }); + + test("after the stream closes, the sink ignores events", () async { + virtual1.sink.close(); + + // Wait for the done event to be delivered. + await virtual2.stream.toList(); + virtual2.sink.add(1); + virtual2.sink.add(2); + virtual2.sink.add(3); + virtual2.sink.close(); + + // None of our virtual.sink additions should make it to the other endpoint. + virtual1.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); + + test("canceling the stream's subscription has no effect on the sink", + () async { + virtual1.stream.listen(null).cancel(); + await pumpEventQueue(); + + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + virtual1.sink.close(); + expect(virtual2.stream.toList(), completion(equals([1, 2, 3]))); + }); + + test("canceling the stream's subscription doesn't stop a done event", + () async { + virtual1.stream.listen(null).cancel(); + await pumpEventQueue(); + + virtual2.sink.close(); + await pumpEventQueue(); + + virtual1.sink.add(1); + virtual1.sink.add(2); + virtual1.sink.add(3); + virtual1.sink.close(); + + // The sink should be ignoring events because the stream closed. + virtual2.stream.listen(expectAsync((_) {}, count: 0)); + await pumpEventQueue(); + }); }); }); } From 05da8f92b2e7ec573bbcc55974d1c6c58f863a79 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 8 Mar 2016 17:09:46 -0800 Subject: [PATCH 0251/1215] Fix unused imports --- pkgs/stream_channel/test/disconnector_test.dart | 5 +---- pkgs/stream_channel/test/json_document_transformer_test.dart | 2 -- pkgs/stream_channel/test/multi_channel_test.dart | 2 -- pkgs/stream_channel/test/stream_channel_controller_test.dart | 4 ---- pkgs/stream_channel/test/stream_channel_test.dart | 3 --- 5 files changed, 1 insertion(+), 15 deletions(-) diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 09cdddc57..d7fa885cd 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -3,10 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:convert'; -import 'dart:isolate'; -import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -110,4 +107,4 @@ void main() { expect(() => channel.sink.addError("oh no"), throwsStateError); }); }); -} \ No newline at end of file +} diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 65a349724..4dd5ea7fb 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -8,8 +8,6 @@ import 'dart:convert'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 5be250535..0e58d382e 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -2,8 +2,6 @@ // 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. -import 'dart:async'; - import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index cf8a31b36..7503387d5 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -2,13 +2,9 @@ // 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. -import 'dart:async'; - import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { group("asynchronously", () { var controller; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index f5251778d..2a6566ac7 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -4,14 +4,11 @@ import 'dart:async'; import 'dart:convert'; -import 'dart:isolate'; import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; From f16f39f1a1e2cb1990709e47a3b62c11946610c3 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 23 Mar 2016 17:32:37 -0700 Subject: [PATCH 0252/1215] Fix all strong mode warnings. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1830053002 . --- pkgs/stack_trace/.analysis_options | 2 ++ pkgs/stack_trace/CHANGELOG.md | 6 +++++- pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/lib/src/utils.dart | 17 ----------------- pkgs/stack_trace/pubspec.yaml | 2 +- 6 files changed, 10 insertions(+), 21 deletions(-) create mode 100644 pkgs/stack_trace/.analysis_options diff --git a/pkgs/stack_trace/.analysis_options b/pkgs/stack_trace/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/stack_trace/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 66c1108ca..8ed506025 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,6 +1,10 @@ +## 1.6.2 + +* Fix all strong mode warnings. + ## 1.6.1 -* Use `StacktTrace.current` in Dart SDK 1.14 to get the current stack trace. +* Use `StackTrace.current` in Dart SDK 1.14 to get the current stack trace. ## 1.6.0 diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index c282387b8..b6f36d20e 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -193,7 +193,7 @@ class Chain implements StackTrace { /// /// The trace version of a chain is just the concatenation of all the traces /// in the chain. - Trace toTrace() => new Trace(flatten(traces.map((trace) => trace.frames))); + Trace toTrace() => new Trace(traces.expand((trace) => trace.frames)); String toString() { // Figure out the longest path so we know how much to pad. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 927a16784..0a7f320b6 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -257,7 +257,7 @@ class Trace implements StackTrace { }; } - var newFrames = []; + var newFrames = []; for (var frame in frames.reversed) { if (frame is UnparsedFrame || !predicate(frame)) { newFrames.add(frame); diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 5781d5f0a..710abdc04 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -19,20 +19,3 @@ String padRight(String string, int length) { return result.toString(); } - -/// Flattens nested lists inside an iterable into a single list containing only -/// non-list elements. -List flatten(Iterable nested) { - var result = []; - helper(list) { - for (var element in list) { - if (element is List) { - helper(element); - } else { - result.add(element); - } - } - } - helper(nested); - return result; -} diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1c180cfaa..465011b21 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.2-dev +version: 1.6.2 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 7a680ff8f561ee50aa3dba87f37fb984aef03f72 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 28 Mar 2016 14:32:04 -0700 Subject: [PATCH 0253/1215] Make Chain.capture() generic. Closes dart-lang/stack_trace#10 R=rnystrom@google.com, jmesserly@google.com Review URL: https://codereview.chromium.org//1834283003 . --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/chain.dart | 4 ++-- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 8ed506025..a23eebde7 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.3 + +* Make `Chain.capture()` generic. Its signature is now `T Chain.capture(T + callback(), ...)`. + ## 1.6.2 * Fix all strong mode warnings. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index b6f36d20e..b43665129 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -68,8 +68,8 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static capture(callback(), {void onError(error, Chain chain), - bool when: true}) { + static /*=T*? capture/**/(/*=T*/ callback(), + {void onError(error, Chain chain), bool when: true}) { if (!when) { var newOnError; if (onError != null) { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 465011b21..ce1d39d5f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.2 +version: 1.6.3 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 8fdd817d5eb2552c5076f83c44b640bb6e5da3bf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 28 Mar 2016 14:45:35 -0700 Subject: [PATCH 0254/1215] Fix a syntax error. R=rnystrom@google.com Review URL: https://codereview.chromium.org//1834263004 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a23eebde7..75a311f30 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.4 + +* Fix a syntax error introduced in 1.6.3. + ## 1.6.3 * Make `Chain.capture()` generic. Its signature is now `T Chain.capture(T diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index b43665129..6de670f22 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -68,7 +68,7 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static /*=T*? capture/**/(/*=T*/ callback(), + static /*=T*/ capture/**/(/*=T*/ callback(), {void onError(error, Chain chain), bool when: true}) { if (!when) { var newOnError; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ce1d39d5f..654d13d34 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.3 +version: 1.6.4 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > From 5a2ea3e875dcd13800c32f00c0cc17d031f53e5c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 31 Mar 2016 17:22:08 -0700 Subject: [PATCH 0255/1215] Declare this package strong-mode clean. R=tjblasi@google.com Review URL: https://codereview.chromium.org//1840423003 . --- pkgs/string_scanner/.analysis_options | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 pkgs/string_scanner/.analysis_options diff --git a/pkgs/string_scanner/.analysis_options b/pkgs/string_scanner/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/string_scanner/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true From 10ca56bc9a09de6c975b73ea8e10be877516b39a Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Thu, 7 Apr 2016 17:25:41 -0700 Subject: [PATCH 0256/1215] Fix the remaining strong mode warnings. These ones require explicit casts to work around limitations in some SDK methods and expectAsync() in test. Ideally, we will change those APIs to be more soundly typed. Until then, this gets the package clean. R=nweiz@google.com Review URL: https://codereview.chromium.org//1871763002 . --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 6 ++++-- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 5 ++++- pkgs/stack_trace/test/chain/utils.dart | 5 ++++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 75a311f30..174754ccd 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.5 + +* Really fix strong mode warnings. + ## 1.6.4 * Fix a syntax error introduced in 1.6.3. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 6de670f22..a27e8a68d 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -78,7 +78,8 @@ class Chain implements StackTrace { }; } - return runZoned(callback, onError: newOnError); + // TODO(rnystrom): Remove this cast if runZoned() gets a generic type. + return runZoned(callback, onError: newOnError) as dynamic/*=T*/; } var spec = new StackZoneSpecification(onError); @@ -91,7 +92,8 @@ class Chain implements StackTrace { } }, zoneSpecification: spec.toSpec(), zoneValues: { #stack_trace.stack_zone.spec: spec - }); + }) as dynamic/*=T*/; + // TODO(rnystrom): Remove this cast if runZoned() gets a generic type. } /// Returns [futureOrStream] unmodified. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 654d13d34..e49783ed4 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.4 +version: 1.6.5 author: "Dart Team " homepage: http://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 40b06d552..0824f4f76 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -10,6 +10,8 @@ import 'package:test/test.dart'; import 'utils.dart'; +typedef void ChainErrorCallback(stack, Chain chain); + void main() { group('Chain.parse()', () { test('parses a real Chain', () { @@ -48,7 +50,8 @@ void main() { }, onError: expectAsync((error, chain) { expect(error, equals("oh no")); expect(chain, new isInstanceOf()); - }), when: false); + }) as ChainErrorCallback, when: false); + // TODO(rnystrom): Remove this cast if expectAsync() gets a better type. }); }); diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 366502cbb..f345fc007 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -73,8 +73,11 @@ Future chainForTrace(asyncFn(callback()), callback()) { new Future.value().then((_) => callback()) .catchError(completer.completeError); }); + + // TODO(rnystrom): Remove this cast if catchError() gets a better type. return completer.future - .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); + .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)) + as Future; } /// Runs [callback] in a [Chain.capture] zone and returns a Future that From 7baed2ff52ef3d076f21e65e52b3820cebaaae0d Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 20 Jul 2015 15:30:13 -0700 Subject: [PATCH 0257/1215] Backport fixes from master to 0.9.7+x. --- pkgs/watcher/benchmark/path_set.dart | 147 +++++++++ pkgs/watcher/lib/src/async_queue.dart | 2 - .../src/constructable_file_system_event.dart | 2 - pkgs/watcher/lib/src/directory_watcher.dart | 3 - .../lib/src/directory_watcher/linux.dart | 301 ++++++++---------- .../lib/src/directory_watcher/mac_os.dart | 24 +- .../lib/src/directory_watcher/polling.dart | 2 - .../lib/src/directory_watcher/windows.dart | 32 +- pkgs/watcher/lib/src/file_watcher.dart | 3 - pkgs/watcher/lib/src/file_watcher/native.dart | 2 - .../watcher/lib/src/file_watcher/polling.dart | 2 - pkgs/watcher/lib/src/path_set.dart | 144 +++++---- pkgs/watcher/lib/src/resubscribable.dart | 2 - pkgs/watcher/lib/src/stat.dart | 2 - pkgs/watcher/lib/src/utils.dart | 6 +- pkgs/watcher/lib/src/watch_event.dart | 2 - pkgs/watcher/lib/watcher.dart | 2 - pkgs/watcher/pubspec.yaml | 7 +- .../test/directory_watcher/shared.dart | 31 ++ .../test/file_watcher/native_test.dart | 1 - .../test/no_subscription/mac_os_test.dart | 1 + pkgs/watcher/test/path_set_test.dart | 24 +- pkgs/watcher/test/utils.dart | 14 +- 23 files changed, 432 insertions(+), 324 deletions(-) create mode 100644 pkgs/watcher/benchmark/path_set.dart diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart new file mode 100644 index 000000000..aba3ed750 --- /dev/null +++ b/pkgs/watcher/benchmark/path_set.dart @@ -0,0 +1,147 @@ +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file +// 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. + +/// Benchmarks for the PathSet class. +library watcher.benchmark.path_set; + +import 'dart:io'; +import 'dart:math' as math; + +import 'package:benchmark_harness/benchmark_harness.dart'; +import 'package:path/path.dart' as p; + +import 'package:watcher/src/path_set.dart'; + +final String root = Platform.isWindows ? r"C:\root" : "/root"; + +/// Base class for benchmarks on [PathSet]. +abstract class PathSetBenchmark extends BenchmarkBase { + PathSetBenchmark(String method) : super("PathSet.$method"); + + final PathSet pathSet = new PathSet(root); + + /// Use a fixed [Random] with a constant seed to ensure the tests are + /// deterministic. + final math.Random random = new math.Random(1234); + + /// Walks over a virtual directory [depth] levels deep invoking [callback] + /// for each "file". + /// + /// Each virtual directory contains ten entries: either subdirectories or + /// files. + void walkTree(int depth, callback(String path)) { + recurse(path, remainingDepth) { + for (var i = 0; i < 10; i++) { + var padded = i.toString().padLeft(2, '0'); + if (remainingDepth == 0) { + callback(p.join(path, "file_$padded.txt")); + } else { + var subdir = p.join(path, "subdirectory_$padded"); + recurse(subdir, remainingDepth - 1); + } + } + } + + recurse(root, depth); + } +} + +class AddBenchmark extends PathSetBenchmark { + AddBenchmark() : super("add()"); + + final List paths = []; + + void setup() { + // Make a bunch of paths in about the same order we expect to get them from + // Directory.list(). + walkTree(3, paths.add); + } + + void run() { + for (var path in paths) pathSet.add(path); + } +} + +class ContainsBenchmark extends PathSetBenchmark { + ContainsBenchmark() : super("contains()"); + + final List paths = []; + + void setup() { + // Add a bunch of paths to the set. + walkTree(3, (path) { + pathSet.add(path); + paths.add(path); + }); + + // Add some non-existent paths to test the false case. + for (var i = 0; i < 100; i++) { + paths.addAll([ + "/nope", + "/root/nope", + "/root/subdirectory_04/nope", + "/root/subdirectory_04/subdirectory_04/nope", + "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope", + "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope/file_04.txt", + ]); + } + } + + void run() { + var contained = 0; + for (var path in paths) { + if (pathSet.contains(path)) contained++; + } + + if (contained != 10000) throw "Wrong result: $contained"; + } +} + +class PathsBenchmark extends PathSetBenchmark { + PathsBenchmark() : super("toSet()"); + + void setup() { + walkTree(3, pathSet.add); + } + + void run() { + var count = 0; + for (var _ in pathSet.paths) { + count++; + } + + if (count != 10000) throw "Wrong result: $count"; + } +} + +class RemoveBenchmark extends PathSetBenchmark { + RemoveBenchmark() : super("remove()"); + + final List paths = []; + + void setup() { + // Make a bunch of paths. Do this here so that we don't spend benchmarked + // time synthesizing paths. + walkTree(3, (path) { + pathSet.add(path); + paths.add(path); + }); + + // Shuffle the paths so that we delete them in a random order that + // hopefully mimics real-world file system usage. Do the shuffling here so + // that we don't spend benchmarked time shuffling. + paths.shuffle(random); + } + + void run() { + for (var path in paths) pathSet.remove(path); + } +} + +main() { + new AddBenchmark().report(); + new ContainsBenchmark().report(); + new PathsBenchmark().report(); + new RemoveBenchmark().report(); +} diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index b83493d73..adf667101 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -2,8 +2,6 @@ // 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. -library watcher.async_queue; - import 'dart:async'; import 'dart:collection'; diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index d00a1dce7..63b51c192 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -2,8 +2,6 @@ // 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. -library watcher.constructable_file_system_event; - import 'dart:io'; abstract class _ConstructableFileSystemEvent implements FileSystemEvent { diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 82837855b..6beebd0a4 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -2,11 +2,8 @@ // 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. -library watcher.directory_watcher; - import 'dart:io'; -import 'watch_event.dart'; import '../watcher.dart'; import 'directory_watcher/linux.dart'; import 'directory_watcher/mac_os.dart'; diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index a747839d2..f327bb0d3 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -2,12 +2,13 @@ // 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. -library watcher.directory_watcher.linux; - import 'dart:async'; import 'dart:io'; +import 'package:async/async.dart'; + import '../directory_watcher.dart'; +import '../path_set.dart'; import '../resubscribable.dart'; import '../utils.dart'; import '../watch_event.dart'; @@ -32,8 +33,8 @@ class LinuxDirectoryWatcher extends ResubscribableWatcher class _LinuxDirectoryWatcher implements DirectoryWatcher, ManuallyClosedWatcher { - String get directory => path; - final String path; + String get directory => _files.root; + String get path => _files.root; Stream get events => _eventsController.stream; final _eventsController = new StreamController.broadcast(); @@ -43,15 +44,17 @@ class _LinuxDirectoryWatcher Future get ready => _readyCompleter.future; final _readyCompleter = new Completer(); - /// The last known state for each entry in this directory. - /// - /// The keys in this map are the paths to the directory entries; the values - /// are [_EntryState]s indicating whether the entries are files or - /// directories. - final _entries = new Map(); + /// A stream group for the [Directory.watch] events of [path] and all its + /// subdirectories. + var _nativeEvents = new StreamGroup(); - /// The watchers for subdirectories of [directory]. - final _subWatchers = new Map(); + /// All known files recursively within [path]. + final PathSet _files; + + /// [Directory.watch] streams for [path]'s subdirectories, indexed by name. + /// + /// A stream is in this map if and only if it's also in [_nativeEvents]. + final _subdirStreams = >{}; /// A set of all subscriptions that this watcher subscribes to. /// @@ -59,93 +62,51 @@ class _LinuxDirectoryWatcher /// watcher is closed. final _subscriptions = new Set(); - _LinuxDirectoryWatcher(this.path) { + _LinuxDirectoryWatcher(String path) + : _files = new PathSet(path) { + _nativeEvents.add(new Directory(path).watch().transform( + new StreamTransformer.fromHandlers(handleDone: (sink) { + // Once the root directory is deleted, no more new subdirectories will be + // watched. + _nativeEvents.close(); + sink.close(); + }))); + // Batch the inotify changes together so that we can dedup events. - var innerStream = new Directory(path).watch() + var innerStream = _nativeEvents.stream .transform(new BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError, onDone: _onDone); - _listen(new Directory(path).list(), (entity) { - _entries[entity.path] = new _EntryState(entity is Directory); - if (entity is! Directory) return; - _watchSubdir(entity.path); + _listen(new Directory(path).list(recursive: true), (entity) { + if (entity is Directory) { + _watchSubdir(entity.path); + } else { + _files.add(entity.path); + } }, onError: (error, stackTrace) { _eventsController.addError(error, stackTrace); close(); }, onDone: () { - _waitUntilReady().then((_) => _readyCompleter.complete()); + _readyCompleter.complete(); }, cancelOnError: true); } - /// Returns a [Future] that completes once all the subdirectory watchers are - /// fully initialized. - Future _waitUntilReady() { - return Future.wait(_subWatchers.values.map((watcher) => watcher.ready)) - .then((_) { - if (_subWatchers.values.every((watcher) => watcher.isReady)) return null; - return _waitUntilReady(); - }); - } - void close() { for (var subscription in _subscriptions) { subscription.cancel(); } - for (var watcher in _subWatchers.values) { - watcher.close(); - } - _subWatchers.clear(); _subscriptions.clear(); + _subdirStreams.clear(); + _files.clear(); + _nativeEvents.close(); _eventsController.close(); } - /// Returns all files (not directories) that this watcher knows of are - /// recursively in the watched directory. - Set get _allFiles { - var files = new Set(); - _getAllFiles(files); - return files; - } - - /// Helper function for [_allFiles]. - /// - /// Adds all files that this watcher knows of to [files]. - void _getAllFiles(Set files) { - files.addAll(_entries.keys - .where((path) => _entries[path] == _EntryState.FILE).toSet()); - for (var watcher in _subWatchers.values) { - watcher._getAllFiles(files); - } - } - /// Watch a subdirectory of [directory] for changes. - /// - /// If the subdirectory was added after [this] began emitting events, its - /// contents will be emitted as ADD events. void _watchSubdir(String path) { - if (_subWatchers.containsKey(path)) return; - var watcher = new _LinuxDirectoryWatcher(path); - _subWatchers[path] = watcher; - - // TODO(nweiz): Catch any errors here that indicate that the directory in - // question doesn't exist and silently stop watching it instead of - // propagating the errors. - _listen(watcher.events, (event) { - if (isReady) _eventsController.add(event); - }, onError: (error, stackTrace) { - _eventsController.addError(error, stackTrace); - close(); - }, onDone: () { - if (_subWatchers[path] == watcher) _subWatchers.remove(path); - - // It's possible that a directory was removed and recreated very quickly. - // If so, make sure we're still watching it. - if (new Directory(path).existsSync()) _watchSubdir(path); - }); - // TODO(nweiz): Right now it's possible for the watcher to emit an event for // a file before the directory list is complete. This could lead to the user // seeing a MODIFY or REMOVE event for a file before they see an ADD event, @@ -157,96 +118,110 @@ class _LinuxDirectoryWatcher // top-level clients such as barback as well, and could be implemented with // a wrapper similar to how listening/canceling works now. - // If a directory is added after we're finished with the initial scan, emit - // an event for each entry in it. This gives the user consistently gets an - // event for every new file. - watcher.ready.then((_) { - if (!isReady || _eventsController.isClosed) return; - _listen(new Directory(path).list(recursive: true), (entry) { - if (entry is Directory) return; - _eventsController.add(new WatchEvent(ChangeType.ADD, entry.path)); - }, onError: (error, stackTrace) { - // Ignore an exception caused by the dir not existing. It's fine if it - // was added and then quickly removed. - if (error is FileSystemException) return; - - _eventsController.addError(error, stackTrace); - close(); - }, cancelOnError: true); - }); + // TODO(nweiz): Catch any errors here that indicate that the directory in + // question doesn't exist and silently stop watching it instead of + // propagating the errors. + var stream = new Directory(path).watch(); + _subdirStreams[path] = stream; + _nativeEvents.add(stream); } /// The callback that's run when a batch of changes comes in. void _onBatch(List batch) { - var changedEntries = new Set(); - var oldEntries = new Map.from(_entries); + var files = new Set(); + var dirs = new Set(); + var changed = new Set(); // inotify event batches are ordered by occurrence, so we treat them as a - // log of what happened to a file. + // log of what happened to a file. We only emit events based on the + // difference between the state before the batch and the state after it, not + // the intermediate state. for (var event in batch) { // If the watched directory is deleted or moved, we'll get a deletion // event for it. Ignore it; we handle closing [this] when the underlying // stream is closed. if (event.path == path) continue; - changedEntries.add(event.path); + changed.add(event.path); if (event is FileSystemMoveEvent) { - changedEntries.add(event.destination); - _changeEntryState(event.path, ChangeType.REMOVE, event.isDirectory); - _changeEntryState(event.destination, ChangeType.ADD, event.isDirectory); + files.remove(event.path); + dirs.remove(event.path); + + changed.add(event.destination); + if (event.isDirectory) { + files.remove(event.destination); + dirs.add(event.destination); + } else { + files.add(event.destination); + dirs.remove(event.destination); + } + } else if (event is FileSystemDeleteEvent) { + files.remove(event.path); + dirs.remove(event.path); + } else if (event.isDirectory) { + files.remove(event.path); + dirs.add(event.path); } else { - _changeEntryState(event.path, _changeTypeFor(event), event.isDirectory); + files.add(event.path); + dirs.remove(event.path); } } - for (var path in changedEntries) { - emitEvent(ChangeType type) { - if (isReady) _eventsController.add(new WatchEvent(type, path)); - } - - var oldState = oldEntries[path]; - var newState = _entries[path]; + _applyChanges(files, dirs, changed); + } - if (oldState != _EntryState.FILE && newState == _EntryState.FILE) { - emitEvent(ChangeType.ADD); - } else if (oldState == _EntryState.FILE && newState == _EntryState.FILE) { - emitEvent(ChangeType.MODIFY); - } else if (oldState == _EntryState.FILE && newState != _EntryState.FILE) { - emitEvent(ChangeType.REMOVE); + /// Applies the net changes computed for a batch. + /// + /// The [files] and [dirs] sets contain the files and directories that now + /// exist, respectively. The [changed] set contains all files and directories + /// that have changed (including being removed), and so is a superset of + /// [files] and [dirs]. + void _applyChanges(Set files, Set dirs, Set changed) { + for (var path in changed) { + var stream = _subdirStreams.remove(path); + if (stream != null) _nativeEvents.add(stream); + + // Unless [path] was a file and still is, emit REMOVE events for it or its + // contents, + if (files.contains(path) && _files.contains(path)) continue; + for (var file in _files.remove(path)) { + _emit(ChangeType.REMOVE, file); } + } - if (oldState == _EntryState.DIRECTORY) { - var watcher = _subWatchers.remove(path); - if (watcher == null) continue; - for (var path in watcher._allFiles) { - _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); - } - watcher.close(); + for (var file in files) { + if (_files.contains(file)) { + _emit(ChangeType.MODIFY, file); + } else { + _emit(ChangeType.ADD, file); + _files.add(file); } - - if (newState == _EntryState.DIRECTORY) _watchSubdir(path); } - } - /// Changes the known state of the entry at [path] based on [change] and - /// [isDir]. - void _changeEntryState(String path, ChangeType change, bool isDir) { - if (change == ChangeType.ADD || change == ChangeType.MODIFY) { - _entries[path] = new _EntryState(isDir); - } else { - assert(change == ChangeType.REMOVE); - _entries.remove(path); + for (var dir in dirs) { + _watchSubdir(dir); + _addSubdir(dir); } } - /// Determines the [ChangeType] associated with [event]. - ChangeType _changeTypeFor(FileSystemEvent event) { - if (event is FileSystemDeleteEvent) return ChangeType.REMOVE; - if (event is FileSystemCreateEvent) return ChangeType.ADD; + /// Emits [ChangeType.ADD] events for the recursive contents of [path]. + void _addSubdir(String path) { + _listen(new Directory(path).list(recursive: true), (entity) { + if (entity is Directory) { + _watchSubdir(entity.path); + } else { + _files.add(entity.path); + _emit(ChangeType.ADD, entity.path); + } + }, onError: (error, stackTrace) { + // Ignore an exception caused by the dir not existing. It's fine if it + // was added and then quickly removed. + if (error is FileSystemException) return; - assert(event is FileSystemModifyEvent); - return ChangeType.MODIFY; + _eventsController.addError(error, stackTrace); + close(); + }, cancelOnError: true); } /// Handles the underlying event stream closing, indicating that the directory @@ -254,28 +229,23 @@ class _LinuxDirectoryWatcher void _onDone() { // Most of the time when a directory is removed, its contents will get // individual REMOVE events before the watch stream is closed -- in that - // case, [_entries] will be empty here. However, if the directory's removal - // is caused by a MOVE, we need to manually emit events. + // case, [_files] will be empty here. However, if the directory's removal is + // caused by a MOVE, we need to manually emit events. if (isReady) { - _entries.forEach((path, state) { - if (state == _EntryState.DIRECTORY) return; - _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); - }); + for (var file in _files.paths) { + _emit(ChangeType.REMOVE, file); + } } - // The parent directory often gets a close event before the subdirectories - // are done emitting events. We wait for them to finish before we close - // [events] so that we can be sure to emit a remove event for every file - // that used to exist. - Future.wait(_subWatchers.values.map((watcher) { - try { - return watcher.events.toList(); - } on StateError catch (_) { - // It's possible that [watcher.events] is closed but the onDone event - // hasn't reached us yet. It's fine if so. - return new Future.value(); - } - })).then((_) => close()); + close(); + } + + /// Emits a [WatchEvent] with [type] and [path] if this watcher is in a state + /// to emit events. + void _emit(ChangeType type, String path) { + if (!isReady) return; + if (_eventsController.isClosed) return; + _eventsController.add(new WatchEvent(type, path)); } /// Like [Stream.listen], but automatically adds the subscription to @@ -290,22 +260,3 @@ class _LinuxDirectoryWatcher _subscriptions.add(subscription); } } - -/// An enum for the possible states of entries in a watched directory. -class _EntryState { - final String _name; - - /// The entry is a file. - static const FILE = const _EntryState._("file"); - - /// The entry is a directory. - static const DIRECTORY = const _EntryState._("directory"); - - const _EntryState._(this._name); - - /// Returns [DIRECTORY] if [isDir] is true, and [FILE] otherwise. - factory _EntryState(bool isDir) => - isDir ? _EntryState.DIRECTORY : _EntryState.FILE; - - String toString() => _name; -} diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 487225eb4..8a17e2e79 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -2,8 +2,6 @@ // 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. -library watcher.directory_watcher.mac_os; - import 'dart:async'; import 'dart:io'; @@ -58,7 +56,7 @@ class _MacOSDirectoryWatcher /// /// This is separate from [_subscriptions] because this stream occasionally /// needs to be resubscribed in order to work around issue 14849. - StreamSubscription _watchSubscription; + StreamSubscription> _watchSubscription; /// The subscription to the [Directory.list] call for the initial listing of /// the directory to determine its initial state. @@ -116,9 +114,9 @@ class _MacOSDirectoryWatcher return; } - _sortEvents(batch).forEach((path, events) { - var canonicalEvent = _canonicalEvent(events); - events = canonicalEvent == null ? + _sortEvents(batch).forEach((path, eventSet) { + var canonicalEvent = _canonicalEvent(eventSet); + var events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; for (var event in events) { @@ -139,7 +137,7 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; - var subscription; + StreamSubscription subscription; subscription = new Directory(path).list(recursive: true) .listen((entity) { if (entity is Directory) return; @@ -175,7 +173,7 @@ class _MacOSDirectoryWatcher /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it /// contain any events relating to [path]. Map> _sortEvents(List batch) { - var eventsForPaths = {}; + var eventsForPaths = {}; // FSEvents can report past events, including events on the root directory // such as it being created. We want to ignore these. If the directory is @@ -187,8 +185,10 @@ class _MacOSDirectoryWatcher // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { if (!event.isDirectory) return new Set(); - if (event is! FileSystemMoveEvent) return new Set.from([event.path]); - return new Set.from([event.path, event.destination]); + if (event is FileSystemMoveEvent) { + return new Set.from([event.path, event.destination]); + } + return new Set.from([event.path]); })); isInModifiedDirectory(path) => @@ -294,7 +294,7 @@ class _MacOSDirectoryWatcher var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - var events = []; + var events = []; if (fileExisted) { if (fileExists) { events.add(new ConstructableFileSystemModifyEvent(path, false, false)); @@ -337,7 +337,7 @@ class _MacOSDirectoryWatcher // FSEvents can fail to report the contents of the directory being removed // when the directory itself is removed, so we need to manually mark the // files as removed. - for (var file in _files.toSet()) { + for (var file in _files.paths) { _emitEvent(ChangeType.REMOVE, file); } _files.clear(); diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 7f417d630..ebc170963 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -2,8 +2,6 @@ // 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. -library watcher.directory_watcher.polling; - import 'dart:async'; import 'dart:io'; diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 089951964..67a274198 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -3,8 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // TODO(rnystrom): Merge with mac_os version. -library watcher.directory_watcher.windows; - import 'dart:async'; import 'dart:collection'; import 'dart:io'; @@ -136,7 +134,7 @@ class _WindowsDirectoryWatcher event is FileSystemDeleteEvent || (FileSystemEntity.typeSync(path) == FileSystemEntityType.NOT_FOUND)) { - for (var path in _files.toSet()) { + for (var path in _files.paths) { _emitEvent(ChangeType.REMOVE, path); } _files.clear(); @@ -163,10 +161,10 @@ class _WindowsDirectoryWatcher /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { - _sortEvents(batch).forEach((path, events) { + _sortEvents(batch).forEach((path, eventSet) { - var canonicalEvent = _canonicalEvent(events); - events = canonicalEvent == null ? + var canonicalEvent = _canonicalEvent(eventSet); + var events = canonicalEvent == null ? _eventsBasedOnFileSystem(path) : [canonicalEvent]; for (var event in events) { @@ -182,20 +180,20 @@ class _WindowsDirectoryWatcher if (_files.containsDir(path)) continue; var stream = new Directory(path).list(recursive: true); - var sub; - sub = stream.listen((entity) { + StreamSubscription subscription; + subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); }, onDone: () { - _listSubscriptions.remove(sub); + _listSubscriptions.remove(subscription); }, onError: (e, stackTrace) { - _listSubscriptions.remove(sub); + _listSubscriptions.remove(subscription); _emitError(e, stackTrace); }, cancelOnError: true); - _listSubscriptions.add(sub); + _listSubscriptions.add(subscription); } else if (event is FileSystemModifyEvent) { if (!event.isDirectory) { _emitEvent(ChangeType.MODIFY, path); @@ -219,15 +217,17 @@ class _WindowsDirectoryWatcher /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it /// contain any events relating to [path]. Map> _sortEvents(List batch) { - var eventsForPaths = {}; + var eventsForPaths = {}; // Events within directories that already have events are superfluous; the // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { if (!event.isDirectory) return new Set(); - if (event is! FileSystemMoveEvent) return new Set.from([event.path]); - return new Set.from([event.path, event.destination]); + if (event is FileSystemMoveEvent) { + return new Set.from([event.path, event.destination]); + } + return new Set.from([event.path]); })); isInModifiedDirectory(path) => @@ -322,7 +322,7 @@ class _WindowsDirectoryWatcher var fileExists = new File(path).existsSync(); var dirExists = new Directory(path).existsSync(); - var events = []; + var events = []; if (fileExisted) { if (fileExists) { events.add(new ConstructableFileSystemModifyEvent(path, false, false)); @@ -357,7 +357,7 @@ class _WindowsDirectoryWatcher _watchSubscription = null; // Emit remove events for any remaining files. - for (var file in _files.toSet()) { + for (var file in _files.paths) { _emitEvent(ChangeType.REMOVE, file); } _files.clear(); diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index 9b315378d..17c5f2efb 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -2,11 +2,8 @@ // 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. -library watcher.file_watcher; - import 'dart:io'; -import 'watch_event.dart'; import '../watcher.dart'; import 'file_watcher/native.dart'; import 'file_watcher/polling.dart'; diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 1862e7b05..f413a72c4 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -2,8 +2,6 @@ // 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. -library watcher.file_watcher.native; - import 'dart:async'; import 'dart:io'; diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 3480ae29e..3f2e9f143 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -2,8 +2,6 @@ // 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. -library watcher.file_watcher.polling; - import 'dart:async'; import 'dart:io'; diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index e9f7d32d2..3726e1fd8 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -2,8 +2,6 @@ // 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. -library watcher.path_dart; - import 'dart:collection'; import 'package:path/path.dart' as p; @@ -21,32 +19,24 @@ class PathSet { /// The path set's directory hierarchy. /// - /// Each level of this hierarchy has the same structure: a map from strings to - /// other maps, which are further levels of the hierarchy. A map with no - /// elements indicates a path that was added to the set that has no paths - /// beneath it. Such a path should not be treated as a directory by - /// [containsDir]. - final _entries = new Map(); - - /// The set of paths that were explicitly added to this set. - /// - /// This is needed to disambiguate a directory that was explicitly added to - /// the set from a directory that was implicitly added by adding a path - /// beneath it. - final _paths = new Set(); + /// Each entry represents a directory or file. It may be a file or directory + /// that was explicitly added, or a parent directory that was implicitly + /// added in order to add a child. + final _Entry _entries = new _Entry(); PathSet(this.root); /// Adds [path] to the set. void add(String path) { path = _normalize(path); - _paths.add(path); - var parts = _split(path); - var dir = _entries; + var parts = p.split(path); + var entry = _entries; for (var part in parts) { - dir = dir.putIfAbsent(part, () => {}); + entry = entry.contents.putIfAbsent(part, () => new _Entry()); } + + entry.isExplicit = true; } /// Removes [path] and any paths beneath it from the set and returns the @@ -59,110 +49,140 @@ class PathSet { /// empty set. Set remove(String path) { path = _normalize(path); - var parts = new Queue.from(_split(path)); + var parts = new Queue.from(p.split(path)); // Remove the children of [dir], as well as [dir] itself if necessary. // // [partialPath] is the path to [dir], and a prefix of [path]; the remaining // components of [path] are in [parts]. - recurse(dir, partialPath) { + Set recurse(dir, partialPath) { if (parts.length > 1) { // If there's more than one component left in [path], recurse down to // the next level. var part = parts.removeFirst(); - var entry = dir[part]; - if (entry == null || entry.isEmpty) return new Set(); + var entry = dir.contents[part]; + if (entry == null || entry.contents.isEmpty) return new Set(); partialPath = p.join(partialPath, part); var paths = recurse(entry, partialPath); // After removing this entry's children, if it has no more children and // it's not in the set in its own right, remove it as well. - if (entry.isEmpty && !_paths.contains(partialPath)) dir.remove(part); + if (entry.contents.isEmpty && !entry.isExplicit) { + dir.contents.remove(part); + } return paths; } // If there's only one component left in [path], we should remove it. - var entry = dir.remove(parts.first); + var entry = dir.contents.remove(parts.first); if (entry == null) return new Set(); - if (entry.isEmpty) { - _paths.remove(path); - return new Set.from([path]); + if (entry.contents.isEmpty) { + return new Set.from([p.join(root, path)]); } - var set = _removePathsIn(entry, path); - if (_paths.contains(path)) { - _paths.remove(path); - set.add(path); + var set = _explicitPathsWithin(entry, path); + if (entry.isExplicit) { + set.add(p.join(root, path)); } + return set; } return recurse(_entries, root); } - /// Recursively removes and returns all paths in [dir]. + /// Recursively lists all of the explicit paths within [dir]. /// - /// [root] should be the path to [dir]. - Set _removePathsIn(Map dir, String root) { - var removedPaths = new Set(); + /// [dirPath] should be the path to [dir]. + Set _explicitPathsWithin(_Entry dir, String dirPath) { + var paths = new Set(); recurse(dir, path) { - dir.forEach((name, entry) { + dir.contents.forEach((name, entry) { var entryPath = p.join(path, name); - if (_paths.remove(entryPath)) removedPaths.add(entryPath); + if (entry.isExplicit) paths.add(p.join(root, entryPath)); + recurse(entry, entryPath); }); } - recurse(dir, root); - return removedPaths; + recurse(dir, dirPath); + return paths; } /// Returns whether [this] contains [path]. /// /// This only returns true for paths explicitly added to [this]. /// Implicitly-added directories can be inspected using [containsDir]. - bool contains(String path) => _paths.contains(_normalize(path)); + bool contains(String path) { + path = _normalize(path); + var entry = _entries; + + for (var part in p.split(path)) { + entry = entry.contents[part]; + if (entry == null) return false; + } + + return entry.isExplicit; + } /// Returns whether [this] contains paths beneath [path]. bool containsDir(String path) { path = _normalize(path); - var dir = _entries; + var entry = _entries; - for (var part in _split(path)) { - dir = dir[part]; - if (dir == null) return false; + for (var part in p.split(path)) { + entry = entry.contents[part]; + if (entry == null) return false; } - return !dir.isEmpty; + return !entry.contents.isEmpty; } - /// Returns a [Set] of all paths in [this]. - Set toSet() => _paths.toSet(); + /// All of the paths explicitly added to this set. + List get paths { + var result = []; + + recurse(dir, path) { + for (var name in dir.contents.keys) { + var entry = dir.contents[name]; + var entryPath = p.join(path, name); + if (entry.isExplicit) result.add(entryPath); + recurse(entry, entryPath); + } + } + + recurse(_entries, root); + return result; + } /// Removes all paths from [this]. void clear() { - _paths.clear(); - _entries.clear(); + _entries.contents.clear(); } - String toString() => _paths.toString(); - /// Returns a normalized version of [path]. /// /// This removes any extra ".." or "."s and ensure that the returned path /// begins with [root]. It's an error if [path] isn't within [root]. String _normalize(String path) { - var relative = p.relative(p.normalize(path), from: root); - var parts = p.split(relative); - // TODO(nweiz): replace this with [p.isWithin] when that exists (issue - // 14980). - if (!p.isRelative(relative) || parts.first == '..' || parts.first == '.') { - throw new ArgumentError('Path "$path" is not inside "$root".'); - } - return p.join(root, relative); + assert(p.isWithin(root, path)); + + return p.relative(p.normalize(path), from: root); } +} - /// Returns the segments of [path] beneath [root]. - List _split(String path) => p.split(p.relative(path, from: root)); +/// A virtual file system entity tracked by the [PathSet]. +/// +/// It may have child entries in [contents], which implies it's a directory. +class _Entry { + /// The child entries contained in this directory. + final Map contents = {}; + + /// If this entry was explicitly added as a leaf file system entity, this + /// will be true. + /// + /// Otherwise, it represents a parent directory that was implicitly added + /// when added some child of it. + bool isExplicit = false; } diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 2844c1e2c..aeefe9366 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -2,8 +2,6 @@ // 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. -library watcher.resubscribable; - import 'dart:async'; import '../watcher.dart'; diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index d36eff3bd..05ee9ba0a 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -2,8 +2,6 @@ // 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. -library watcher.stat; - import 'dart:async'; import 'dart:io'; diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 007c84c19..d263f2f7c 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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. -library watcher.utils; - import 'dart:async'; import 'dart:io'; import 'dart:collection'; @@ -33,7 +31,7 @@ Set unionAll(Iterable sets) => /// [broadcast] defaults to false. Stream futureStream(Future future, {bool broadcast: false}) { var subscription; - var controller; + StreamController controller; future = future.catchError((e, stackTrace) { // Since [controller] is synchronous, it's likely that emitting an error @@ -94,7 +92,7 @@ Future pumpEventQueue([int times = 20]) { /// microtasks. class BatchedStreamTransformer implements StreamTransformer> { Stream> bind(Stream input) { - var batch = new Queue(); + var batch = new Queue(); return new StreamTransformer>.fromHandlers( handleData: (event, sink) { batch.add(event); diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart index be6d70c92..54093a5d7 100644 --- a/pkgs/watcher/lib/src/watch_event.dart +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -2,8 +2,6 @@ // 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. -library watcher.watch_event; - /// An event describing a single change to the file system. class WatchEvent { /// The manner in which the file at [path] has changed. diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 79dcc0dae..b3cebe665 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -2,8 +2,6 @@ // 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. -library watcher; - import 'dart:async'; import 'dart:io'; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 2e033f153..c0152e032 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,14 +1,17 @@ name: watcher -version: 0.9.7 +version: 0.9.8-dev author: Dart Team -homepage: http://github.com/dart-lang/watcher +homepage: https://github.com/dart-lang/watcher description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: sdk: '>=1.9.0 <2.0.0' dependencies: + async: '^1.2.0' + collection: '^1.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: + benchmark_harness: '^1.0.4' scheduled_test: '^0.12.0' test: '^0.12.0' diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index ff48cb2aa..c95ee39f4 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -246,6 +246,37 @@ void sharedTests() { expectModifyEvent("new/file.txt"); }); + test('notifies when a file is replaced by a subdirectory', () { + writeFile("new"); + writeFile("old/file.txt"); + startWatcher(); + + deleteFile("new"); + renameDir("old", "new"); + inAnyOrder([ + isRemoveEvent("new"), + isRemoveEvent("old/file.txt"), + isAddEvent("new/file.txt") + ]); + }); + + test('notifies when a subdirectory is replaced by a file', () { + writeFile("old"); + writeFile("new/file.txt"); + startWatcher(); + + renameDir("new", "newer"); + renameFile("old", "new"); + inAnyOrder([ + isRemoveEvent("new/file.txt"), + isAddEvent("newer/file.txt"), + isRemoveEvent("old"), + isAddEvent("new") + ]); + }, onPlatform: { + "mac-os": new Skip("https://github.com/dart-lang/watcher/issues/21") + }); + test('emits events for many nested files added at once', () { withPermutations((i, j, k) => writeFile("sub/sub-$i/sub-$j/file-$k.txt")); diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart index 30d0eca42..cbf11b6cd 100644 --- a/pkgs/watcher/test/file_watcher/native_test.dart +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -6,7 +6,6 @@ import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/file_watcher/native.dart'; -import 'package:watcher/watcher.dart'; import 'shared.dart'; import '../utils.dart'; diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index d5b1c8e3f..499aff3ca 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('mac-os') +@Skip("Flaky due to sdk#23877") import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index 13e797c20..d3420d377 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -6,8 +6,6 @@ import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:watcher/src/path_set.dart'; -import 'utils.dart'; - Matcher containsPath(String path) => predicate((set) => set is PathSet && set.contains(path), 'set contains "$path"'); @@ -42,10 +40,6 @@ void main() { set.add(p.absolute("root/path/to/file")); expect(set, containsPath("root/path/to/file")); }); - - test("that's not beneath the root throws an error", () { - expect(() => set.add("path/to/file"), throwsArgumentError); - }); }); group("removing a path", () { @@ -78,7 +72,7 @@ void main() { expect(set, isNot(containsPath("root/path/to/two"))); expect(set, isNot(containsPath("root/path/to/sub/three"))); }); - + test("that's a directory in the set removes and returns it and all files " "beneath it", () { set.add("root/path"); @@ -110,10 +104,6 @@ void main() { expect(set.remove(p.absolute("root/path/to/file")), unorderedEquals([p.normalize("root/path/to/file")])); }); - - test("that's not beneath the root throws an error", () { - expect(() => set.remove("path/to/file"), throwsArgumentError); - }); }); group("containsPath()", () { @@ -143,10 +133,6 @@ void main() { set.add("root/path/to/file"); expect(set, containsPath(p.absolute("root/path/to/file"))); }); - - test("with a path that's not beneath the root throws an error", () { - expect(() => set.contains("path/to/file"), throwsArgumentError); - }); }); group("containsDir()", () { @@ -198,13 +184,13 @@ void main() { }); }); - group("toSet", () { + group("paths", () { test("returns paths added to the set", () { set.add("root/path"); set.add("root/path/to/one"); set.add("root/path/to/two"); - expect(set.toSet(), unorderedEquals([ + expect(set.paths, unorderedEquals([ "root/path", "root/path/to/one", "root/path/to/two", @@ -216,7 +202,7 @@ void main() { set.add("root/path/to/two"); set.remove("root/path/to/two"); - expect(set.toSet(), unorderedEquals([p.normalize("root/path/to/one")])); + expect(set.paths, unorderedEquals([p.normalize("root/path/to/one")])); }); }); @@ -227,7 +213,7 @@ void main() { set.add("root/path/to/two"); set.clear(); - expect(set.toSet(), isEmpty); + expect(set.paths, isEmpty); }); }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 7dd833231..e3c2a1b4d 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -2,8 +2,6 @@ // 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. -library watcher.test.utils; - import 'dart:io'; import 'package:path/path.dart' as p; @@ -13,9 +11,6 @@ import 'package:watcher/watcher.dart'; import 'package:watcher/src/stat.dart'; import 'package:watcher/src/utils.dart'; -// TODO(nweiz): remove this when issue 15042 is fixed. -import 'package:watcher/src/directory_watcher/mac_os.dart'; - /// The path to the temporary sandbox created for each test. All file /// operations are implicitly relative to this directory. String _sandboxDir; @@ -292,7 +287,7 @@ void writeFile(String path, {String contents, bool updateModified}) { // Make sure we always use the same separator on Windows. path = p.normalize(path); - var milliseconds = _mockFileModificationTimes.putIfAbsent(path, () => 0); + _mockFileModificationTimes.putIfAbsent(path, () => 0); _mockFileModificationTimes[path]++; } }, "write file $path"); @@ -316,7 +311,7 @@ void renameFile(String from, String to) { to = p.normalize(to); // Manually update the mock modification time for the file. - var milliseconds = _mockFileModificationTimes.putIfAbsent(to, () => 0); + _mockFileModificationTimes.putIfAbsent(to, () => 0); _mockFileModificationTimes[to]++; }, "rename file $from to $to"); } @@ -349,9 +344,10 @@ void deleteDir(String path) { /// Returns a set of all values returns by [callback]. /// /// [limit] defaults to 3. -Set withPermutations(callback(int i, int j, int k), {int limit}) { +Set/**/ withPermutations/**/(/*=S*/ callback(int i, int j, int k), + {int limit}) { if (limit == null) limit = 3; - var results = new Set(); + var results = new Set/**/(); for (var i = 0; i < limit; i++) { for (var j = 0; j < limit; j++) { for (var k = 0; k < limit; k++) { From f256c7d89b8f30026fd60a3dd3f40df590d56071 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 May 2016 14:48:23 -0700 Subject: [PATCH 0258/1215] Fix all strong-mode warnings. --- pkgs/watcher/.analysis_options | 2 ++ pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/lib/src/directory_watcher/linux.dart | 6 +++--- pkgs/watcher/lib/src/utils.dart | 11 +++++++---- pkgs/watcher/pubspec.yaml | 3 ++- 5 files changed, 18 insertions(+), 8 deletions(-) create mode 100644 pkgs/watcher/.analysis_options diff --git a/pkgs/watcher/.analysis_options b/pkgs/watcher/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/watcher/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 30762a034..dc0b45b91 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+1 + +* Fix all strong-mode warnings. + # 0.9.7 * Fix a bug in `FileWatcher` where events could be added after watchers were diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index f327bb0d3..f33a55476 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -128,9 +128,9 @@ class _LinuxDirectoryWatcher /// The callback that's run when a batch of changes comes in. void _onBatch(List batch) { - var files = new Set(); - var dirs = new Set(); - var changed = new Set(); + var files = new Set(); + var dirs = new Set(); + var changed = new Set(); // inotify event batches are ordered by occurrence, so we treat them as a // log of what happened to a file. We only emit events based on the diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index d263f2f7c..6f3ff0215 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -6,6 +6,8 @@ import 'dart:async'; import 'dart:io'; import 'dart:collection'; +import 'package:async/async.dart'; + /// Returns `true` if [error] is a [FileSystemException] for a missing /// directory. bool isDirectoryNotFoundException(error) { @@ -29,17 +31,18 @@ Set unionAll(Iterable sets) => /// If [broadcast] is true, a broadcast stream is returned. This assumes that /// the stream returned by [future] will be a broadcast stream as well. /// [broadcast] defaults to false. -Stream futureStream(Future future, {bool broadcast: false}) { +Stream/**/ futureStream/**/(Future*/> future, + {bool broadcast: false}) { var subscription; - StreamController controller; + StreamController/**/ controller; - future = future.catchError((e, stackTrace) { + future = DelegatingFuture.typed(future.catchError((e, stackTrace) { // Since [controller] is synchronous, it's likely that emitting an error // will cause it to be cancelled before we call close. if (controller != null) controller.addError(e, stackTrace); if (controller != null) controller.close(); controller = null; - }); + })); onListen() { future.then((stream) { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index c0152e032..ce644785a 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.8-dev +version: 0.9.7+1 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > @@ -12,6 +12,7 @@ dependencies: collection: '^1.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: + async: '^1.8.0' benchmark_harness: '^1.0.4' scheduled_test: '^0.12.0' test: '^0.12.0' From a60efc6d5afeaf9adcbf1b5183e3ac8d6382f272 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 2 May 2016 14:57:15 -0700 Subject: [PATCH 0259/1215] Remove async from dev_dependencies. --- pkgs/watcher/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index ce644785a..71a94dfad 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -8,11 +8,10 @@ description: > environment: sdk: '>=1.9.0 <2.0.0' dependencies: - async: '^1.2.0' + async: '^1.8.0' collection: '^1.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: - async: '^1.8.0' benchmark_harness: '^1.0.4' scheduled_test: '^0.12.0' test: '^0.12.0' From 530cbf8b91abc6c14d9f5122a3c09f8f0c55a238 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 2 May 2016 20:35:12 -0700 Subject: [PATCH 0260/1215] use List.unmodifiable when possible R=nweiz@google.com Review URL: https://codereview.chromium.org//1940453003 . --- pkgs/stack_trace/lib/src/chain.dart | 3 +-- pkgs/stack_trace/lib/src/trace.dart | 3 +-- pkgs/stack_trace/pubspec.yaml | 4 ++-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index a27e8a68d..fdb091702 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:collection'; import 'dart:math' as math; import 'frame.dart'; @@ -146,7 +145,7 @@ class Chain implements StackTrace { /// Returns a new [Chain] comprised of [traces]. Chain(Iterable traces) - : traces = new UnmodifiableListView(traces.toList()); + : traces = new List.unmodifiable(traces); /// Returns a terser version of [this]. /// diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 0a7f320b6..8537b6236 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:collection'; import 'dart:math' as math; import 'chain.dart'; @@ -205,7 +204,7 @@ class Trace implements StackTrace { /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames) - : frames = new UnmodifiableListView(frames.toList()); + : frames = new List.unmodifiable(frames); /// Returns a VM-style [StackTrace] object. /// diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index e49783ed4..ac3c3114a 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,9 +7,9 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.5 +version: 1.6.6-dev author: "Dart Team " -homepage: http://github.com/dart-lang/stack_trace +homepage: https://github.com/dart-lang/stack_trace description: > A package for manipulating stack traces and printing them readably. From 264b5d6194b4b6923d55e1d7346221a88bd08164 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 3 May 2016 14:53:01 -0700 Subject: [PATCH 0261/1215] Narrow the constraint on async. --- pkgs/watcher/CHANGELOG.md | 5 +++++ pkgs/watcher/pubspec.yaml | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index dc0b45b91..aa6752e45 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7+2 + +* Narrow the constraint on `async` to reflect the APIs this package is actually + using. + # 0.9.7+1 * Fix all strong-mode warnings. diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 71a94dfad..57e75e66c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+1 +version: 0.9.7+2 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > @@ -8,7 +8,7 @@ description: > environment: sdk: '>=1.9.0 <2.0.0' dependencies: - async: '^1.8.0' + async: '^1.10.0' collection: '^1.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: From d58d636733c810835851ace1aee70c23dd4f6ef5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 14:54:50 -0700 Subject: [PATCH 0262/1215] Fix all strong-mode errors and warnings. R=sigmund@google.com Review URL: https://codereview.chromium.org//1966893002 . --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/disconnector.dart | 2 +- pkgs/stream_channel/lib/src/isolate_channel.dart | 15 +++++++++------ .../lib/src/json_document_transformer.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 9 +++++---- pkgs/stream_channel/pubspec.yaml | 2 +- 6 files changed, 21 insertions(+), 13 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index b1b735072..a5a7e466b 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.2 + +* Fix all strong-mode errors and warnings. + ## 1.3.1 * Make `IsolateChannel` slightly more efficient. diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 35ecd1cc4..beff71dd0 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,7 +38,7 @@ class Disconnector implements StreamChannelTransformer { StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { - var sink = new _DisconnectorSink(innerSink); + var sink = new _DisconnectorSink(innerSink); if (_isDisconnected) { sink._disconnect(); diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index dcb52cbf3..c725fef8e 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -44,7 +44,7 @@ class IsolateChannel extends StreamChannelMixin { // value to be an [IsolateChannel]. var streamCompleter = new StreamCompleter(); var sinkCompleter = new StreamSinkCompleter(); - var channel = new IsolateChannel._( + var channel = new IsolateChannel._( streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to @@ -53,10 +53,11 @@ class IsolateChannel extends StreamChannelMixin { var subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController( + var controller = new StreamChannelController( allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription).pipe(controller.local.sink); - controller.local.stream.listen(message.send, + new SubscriptionStream(subscription).pipe(controller.local.sink); + controller.local.stream.listen( + (data) => message.send(data), onDone: receivePort.close); streamCompleter.setSourceStream(controller.foreign.stream); @@ -92,10 +93,12 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController( + var controller = new StreamChannelController( allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); - controller.local.stream.listen(sendPort.send, onDone: receivePort.close); + controller.local.stream.listen( + (data) => sendPort.send(data), + onDone: receivePort.close); return new IsolateChannel._( controller.foreign.stream, controller.foreign.sink); } diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 19b2e08f7..c62c597cb 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -22,7 +22,7 @@ final jsonDocument = new JsonDocumentTransformer(); /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. class JsonDocumentTransformer - implements StreamChannelTransformer { + implements StreamChannelTransformer { /// The underlying codec that implements the encoding and decoding logic. final JsonCodec _codec; diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index be032c60d..ac980859d 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -19,10 +19,10 @@ import '../stream_channel.dart'; /// Transformers must be able to have `bind` called multiple times. class StreamChannelTransformer { /// The transformer to use on the channel's stream. - final StreamTransformer _streamTransformer; + final StreamTransformer _streamTransformer; /// The transformer to use on the channel's sink. - final StreamSinkTransformer _sinkTransformer; + final StreamSinkTransformer _sinkTransformer; /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. @@ -35,8 +35,9 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this( - codec.decoder, - new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + typedStreamTransformer(codec.decoder), + StreamSinkTransformer.typed( + new StreamSinkTransformer.fromStreamTransformer(codec.encoder))); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c38c167f3..8410e05c3 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -6,7 +6,7 @@ homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.8.0 <2.0.0' dependencies: - async: '^1.8.0' + async: '^1.11.0' stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.0' From cafec58f341bd7b7cae073e9c6b7c20d3acd0ed5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 14:59:00 -0700 Subject: [PATCH 0263/1215] Bump the version to 1.3.2. This was supposed to happen in the last CL, but didn't instead. R=sigmund@google.com Review URL: https://codereview.chromium.org//1971573002 . --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 8410e05c3..3e87e2bba 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.1 +version: 1.3.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 0029c282a14810946eb2e686e0792912b0127322 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 10 May 2016 15:42:17 -0700 Subject: [PATCH 0264/1215] Add type-coercion functions. These match (and are based on) the coercion functions in dart-lang/async. R=sigmund@google.com Review URL: https://codereview.chromium.org//1966853003 . --- pkgs/stream_channel/.analysis_options | 2 ++ pkgs/stream_channel/CHANGELOG.md | 8 ++++++++ .../lib/src/stream_channel_transformer.dart | 16 ++++++++++++++++ .../lib/src/transformer/typed.dart | 17 +++++++++++++++++ pkgs/stream_channel/lib/stream_channel.dart | 10 ++++++++++ pkgs/stream_channel/pubspec.yaml | 2 +- 6 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_channel/.analysis_options create mode 100644 pkgs/stream_channel/lib/src/transformer/typed.dart diff --git a/pkgs/stream_channel/.analysis_options b/pkgs/stream_channel/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/stream_channel/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a5a7e466b..6d86e4886 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.0 + +* Add `StreamChannel.cast()`, which soundly coerces the generic type of a + channel. + +* Add `StreamChannelTransformer.typed()`, which soundly coerces the generic type + of a transformer. + ## 1.3.2 * Fix all strong-mode errors and warnings. diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index ac980859d..ca09ea16b 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -8,6 +8,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; +import 'transformer/typed.dart'; /// A [StreamChannelTransformer] transforms the events being passed to and /// emitted by a [StreamChannel]. @@ -24,6 +25,21 @@ class StreamChannelTransformer { /// The transformer to use on the channel's sink. final StreamSinkTransformer _sinkTransformer; + /// Creates a wrapper that coerces the type of [transformer]. + /// + /// This soundly converts a [StreamChannelTransformer] to a + /// `StreamChannelTransformer`, regardless of its original generic type, + /// by asserting that the events emitted by the transformed channel's stream + /// are instances of `T` whenever they're provided. If they're not, the stream + /// throws a [CastError]. This also means that calls to [StreamSink.add] on + /// the transformed channel's sink may throw a [CastError] if the argument + /// type doesn't match the reified type of the sink. + static StreamChannelTransformer/**/ typed/**/( + StreamChannelTransformer transformer) => + transformer is StreamChannelTransformer/**/ + ? transformer + : new TypeSafeStreamChannelTransformer(transformer); + /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. const StreamChannelTransformer( diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart new file mode 100644 index 000000000..f35e01c98 --- /dev/null +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import '../../stream_channel.dart'; + +/// A wrapper that coerces the generic type of the channel returned by an inner +/// transformer to `S`. +class TypeSafeStreamChannelTransformer + implements StreamChannelTransformer { + final StreamChannelTransformer _inner; + + TypeSafeStreamChannelTransformer(this._inner); + + StreamChannel bind(StreamChannel channel) => + _inner.bind(channel).cast(); +} diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index b89845d05..3615d2129 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -109,6 +109,13 @@ abstract class StreamChannel { /// Returns a copy of [this] with [sink] replaced by [change]'s return /// value. StreamChannel changeSink(StreamSink change(StreamSink sink)); + + /// Returns a copy of [this] with the generic type coerced to [S]. + /// + /// If any events emitted by [stream] aren't of type [S], they're converted + /// into [CastError] events. Similarly, if any events are added to [sync] that + /// aren't of type [S], a [CastError] is thrown. + StreamChannel/**/ cast/**/(); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -145,4 +152,7 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel changeSink(StreamSink change(StreamSink sink)) => new StreamChannel(stream, change(sink)); + + StreamChannel/**/ cast/**/() => new StreamChannel( + DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 3e87e2bba..1c1df3136 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.3.2 +version: 1.4.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 0ccf8a08e277a1889de14a0dadbfc20942f41d9f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:22:28 -0700 Subject: [PATCH 0265/1215] Add SpanScanner.within(). This is useful for doing more detailed parses of sub-sections of larger text. R=rnystrom@google.com Review URL: https://codereview.chromium.org//2039163002 . --- pkgs/string_scanner/CHANGELOG.md | 4 + .../lib/src/relative_span_scanner.dart | 112 ++++++++++++++++++ pkgs/string_scanner/lib/src/span_scanner.dart | 9 ++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/span_scanner_test.dart | 88 ++++++++++++++ 5 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 pkgs/string_scanner/lib/src/relative_span_scanner.dart diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index a5650cc99..ea1268c1e 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5 + +* Add `new SpanScanner.within()`, which scans within a existing `FileSpan`. + ## 0.1.4+1 * Remove the dependency on `path`, since we don't actually import it. diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart new file mode 100644 index 000000000..fdcd03fba --- /dev/null +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -0,0 +1,112 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:source_span/source_span.dart'; + +import 'exception.dart'; +import 'line_scanner.dart'; +import 'span_scanner.dart'; +import 'string_scanner.dart'; +import 'utils.dart'; + +/// A [SpanScanner] that scans within an existing [FileSpan]. +/// +/// This re-implements chunks of [SpanScanner] rather than using a dummy span or +/// inheritance because scanning is often a performance-critical operation, so +/// it's important to avoid adding extra overhead when relative scanning isn't +/// needed. +class RelativeSpanScanner extends StringScanner implements SpanScanner { + /// The source of the scanner. + /// + /// This caches line break information and is used to generate [Span]s. + final SourceFile _sourceFile; + + /// The start location of the span within which this scanner is scanning. + /// + /// This is used to convert between span-relative and file-relative fields. + final FileLocation _startLocation; + + int get line => _sourceFile.getLine(_startLocation.offset + position) - + _startLocation.line; + + int get column { + var line = _sourceFile.getLine(_startLocation.offset + position); + var column = _sourceFile.getColumn(_startLocation.offset + position, + line: line); + return line == _startLocation.line + ? column - _startLocation.column + : column; + } + + LineScannerState get state => new _SpanScannerState(this, position); + + set state(LineScannerState state) { + if (state is! _SpanScannerState || + !identical((state as _SpanScannerState)._scanner, this)) { + throw new ArgumentError("The given LineScannerState was not returned by " + "this LineScanner."); + } + + this.position = state.position; + } + + FileSpan get lastSpan => _lastSpan; + FileSpan _lastSpan; + + FileLocation get location => + _sourceFile.location(_startLocation.offset + position); + + FileSpan get emptySpan => location.pointSpan(); + + RelativeSpanScanner(FileSpan span) + : _sourceFile = span.file, + _startLocation = span.start, + super(span.text, sourceUrl: span.sourceUrl); + + FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + var endPosition = endState == null ? position : endState.position; + return _sourceFile.span( + _startLocation.offset + startState.position, + _startLocation.offset + endPosition); + } + + bool matches(Pattern pattern) { + if (!super.matches(pattern)) { + _lastSpan = null; + return false; + } + + _lastSpan = _sourceFile.span( + _startLocation.offset + position, + _startLocation.offset + lastMatch.end); + return true; + } + + void error(String message, {Match match, int position, int length}) { + validateErrorArgs(string, match, position, length); + + if (match == null && position == null && length == null) match = lastMatch; + if (position == null) { + position = match == null ? this.position : match.start; + } + if (length == null) length = match == null ? 1 : match.end - match.start; + + var span = _sourceFile.span( + _startLocation.offset + position, + _startLocation.offset + position + length); + throw new StringScannerException(message, span, string); + } +} + +/// A class representing the state of a [SpanScanner]. +class _SpanScannerState implements LineScannerState { + /// The [SpanScanner] that created this. + final RelativeSpanScanner _scanner; + + final int position; + int get line => _scanner._sourceFile.getLine(position); + int get column => _scanner._sourceFile.getColumn(position); + + _SpanScannerState(this._scanner, this.position); +} diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index dd16e47cf..dd7f0e4f2 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -7,6 +7,7 @@ import 'package:source_span/source_span.dart'; import 'eager_span_scanner.dart'; import 'exception.dart'; import 'line_scanner.dart'; +import 'relative_span_scanner.dart'; import 'string_scanner.dart'; import 'utils.dart'; @@ -69,6 +70,14 @@ class SpanScanner extends StringScanner implements LineScanner { factory SpanScanner.eager(String string, {sourceUrl, int position}) = EagerSpanScanner; + /// Creates a new [SpanScanner] that scans within [span]. + /// + /// This scans through [span.text], but emits new spans from [span.file] in + /// their appropriate relative positions. The [string] field contains only + /// [span.text], and [position], [line], and [column] are all relative to the + /// span. + factory SpanScanner.within(FileSpan span) = RelativeSpanScanner; + /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index b249240c8..24bd6bb12 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.4+1 +version: 0.1.5-dev author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index b078f6e1a..84d7b94ee 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -2,9 +2,12 @@ // 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. +import 'package:source_span/source_span.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; +import 'utils.dart'; + void main() { testForImplementation("lazy", () { return new SpanScanner('foo\nbar\nbaz', sourceUrl: 'source'); @@ -13,6 +16,91 @@ void main() { testForImplementation("eager", () { return new SpanScanner.eager('foo\nbar\nbaz', sourceUrl: 'source'); }); + + group("within", () { + var text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; + var startOffset = text.indexOf('foo'); + + var scanner; + setUp(() { + var file = new SourceFile(text, url: 'source'); + scanner = new SpanScanner.within( + file.span(startOffset, text.indexOf(' :after'))); + }); + + test("string only includes the span text", () { + expect(scanner.string, equals("foo\nbar\nbaz")); + }); + + test("line and column are span-relative", () { + expect(scanner.line, equals(0)); + expect(scanner.column, equals(0)); + + scanner.scan("foo"); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.scan("\n"); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test("tracks the span for the last match", () { + scanner.scan('fo'); + scanner.scan('o\nba'); + + var span = scanner.lastSpan; + expect(span.start.offset, equals(startOffset + 2)); + expect(span.start.line, equals(1)); + expect(span.start.column, equals(10)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); + + expect(span.end.offset, equals(startOffset + 6)); + expect(span.end.line, equals(2)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); + + expect(span.text, equals('o\nba')); + }); + + test(".spanFrom() returns a span from a previous state", () { + scanner.scan('fo'); + var state = scanner.state; + scanner.scan('o\nba'); + scanner.scan('r\nba'); + + var span = scanner.spanFrom(state); + expect(span.text, equals('o\nbar\nba')); + }); + + test(".emptySpan returns an empty span at the current location", () { + scanner.scan('foo\nba'); + + var span = scanner.emptySpan; + expect(span.start.offset, equals(startOffset + 6)); + expect(span.start.line, equals(2)); + expect(span.start.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); + + expect(span.end.offset, equals(startOffset + 6)); + expect(span.end.line, equals(2)); + expect(span.end.column, equals(2)); + expect(span.start.sourceUrl, equals(Uri.parse('source'))); + + expect(span.text, equals('')); + }); + + test(".error() uses an absolute span", () { + scanner.expect("foo"); + expect(() => scanner.error('oh no!'), + throwsStringScannerException("foo")); + }); + + test(".isDone returns true at the end of the span", () { + scanner.expect("foo\nbar\nbaz"); + expect(scanner.isDone, isTrue); + }); + }); } void testForImplementation(String name, SpanScanner create()) { From 29a1b0242ec1a713d2f2957049574cf26a7c0196 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:25:39 -0700 Subject: [PATCH 0266/1215] Add StreamChannel.withCloseGuarantee. This also properly enforces the close guarantee for transformers provided by this package. R=rnystrom@google.com Review URL: https://codereview.chromium.org//2041983003 . --- pkgs/stream_channel/CHANGELOG.md | 11 +++ .../lib/src/close_guarantee_channel.dart | 86 +++++++++++++++++++ .../lib/src/json_document_transformer.dart | 2 +- .../lib/src/stream_channel_transformer.dart | 11 ++- pkgs/stream_channel/lib/stream_channel.dart | 18 +++- .../test/with_close_guarantee_test.dart | 66 ++++++++++++++ 6 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 pkgs/stream_channel/lib/src/close_guarantee_channel.dart create mode 100644 pkgs/stream_channel/test/with_close_guarantee_test.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 6d86e4886..6e3a6ac94 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,14 @@ +## 1.5.0 + +* Add `new StreamChannel.withCloseGuarantee()` to provide the specific guarantee + that closing the sink causes the stream to close before it emits any more + events. This is the only guarantee that isn't automatically preserved when + transforming a channel. + +* `StreamChannelTransformer`s provided by the `stream_channel` package now + properly provide the guarantee that closing the sink causes the stream to + close before it emits any more events + ## 1.4.0 * Add `StreamChannel.cast()`, which soundly coerces the generic type of a diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart new file mode 100644 index 000000000..a2c69bcb8 --- /dev/null +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:async/async.dart'; + +import '../stream_channel.dart'; + +/// A [StreamChannel] that specifically enforces the stream channel guarantee +/// that closing the sink causes the stream to close before it emits any more +/// events +/// +/// This is exposed via [new StreamChannel.withCloseGuarantee]. +class CloseGuaranteeChannel extends StreamChannelMixin { + Stream get stream => _stream; + _CloseGuaranteeStream _stream; + + StreamSink get sink => _sink; + _CloseGuaranteeSink _sink; + + /// The subscription to the inner stream. + StreamSubscription _subscription; + + /// Whether the sink has closed, causing the underlying channel to disconnect. + bool _disconnected = false; + + CloseGuaranteeChannel(Stream innerStream, StreamSink innerSink) { + _sink = new _CloseGuaranteeSink(innerSink, this); + _stream = new _CloseGuaranteeStream(innerStream, this); + } +} + +/// The stream for [CloseGuaranteeChannel]. +/// +/// This wraps the inner stream to save the subscription on the channel when +/// [listen] is called. +class _CloseGuaranteeStream extends Stream { + /// The inner stream this is delegating to. + final Stream _inner; + + /// The [CloseGuaranteeChannel] this belongs to. + final CloseGuaranteeChannel _channel; + + _CloseGuaranteeStream(this._inner, this._channel); + + StreamSubscription listen(void onData(T event), + {Function onError, void onDone(), bool cancelOnError}) { + // If the channel is already disconnected, we shouldn't dispatch anything + // but a done event. + if (_channel._disconnected) { + onData = null; + onError = null; + } + + var subscription = _inner.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError); + if (!_channel._disconnected) { + _channel._subscription = subscription; + } + return subscription; + } +} + +/// The sink for [CloseGuaranteeChannel]. +/// +/// This wraps the inner sink to cancel the stream subscription when the sink is +/// canceled. +class _CloseGuaranteeSink extends DelegatingStreamSink { + /// The [CloseGuaranteeChannel] this belongs to. + final CloseGuaranteeChannel _channel; + + _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + + Future close() { + var done = super.close(); + _channel._disconnected = true; + if (_channel._subscription != null) { + // Don't dispatch anything but a done event. + _channel._subscription.onData(null); + _channel._subscription.onError(null); + } + return done; + } +} diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index c62c597cb..86b9ae71c 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -40,6 +40,6 @@ class JsonDocumentTransformer var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); - return new StreamChannel(stream, sink); + return new StreamChannel.withCloseGuarantee(stream, sink); } } diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index ca09ea16b..46232d74c 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -17,7 +17,14 @@ import 'transformer/typed.dart'; /// [StreamSinkTransformer]. Each transformer defines a [bind] method that takes /// in the original [StreamChannel] and returns the transformed version. /// -/// Transformers must be able to have `bind` called multiple times. +/// Transformers must be able to have [bind] called multiple times. If a +/// subclass implements [bind] explicitly, it should be sure that the returned +/// stream follows the second stream channel guarantee: closing the sink causes +/// the stream to close before it emits any more events. This guarantee is +/// invalidated when an asynchronous gap is added between the original stream's +/// event dispatch and the returned stream's, for example by transforming it +/// with a [StreamTransformer]. The guarantee can be easily preserved using [new +/// StreamChannel.withCloseGuarantee]. class StreamChannelTransformer { /// The transformer to use on the channel's stream. final StreamTransformer _streamTransformer; @@ -63,7 +70,7 @@ class StreamChannelTransformer { /// `channel.straem`, the transformer will transform them and pass the /// transformed versions to the returned channel's stream. StreamChannel bind(StreamChannel channel) => - new StreamChannel( + new StreamChannel.withCloseGuarantee( channel.stream.transform(_streamTransformer), _sinkTransformer.bind(channel.sink)); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 3615d2129..16323b169 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'package:async/async.dart'; import 'src/guarantee_channel.dart'; +import 'src/close_guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -87,6 +88,19 @@ abstract class StreamChannel { {bool allowSinkErrors: true}) => new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); + /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. + /// + /// This specifically enforces the second guarantee: closing the sink causes + /// the stream to close before it emits any more events. This guarantee is + /// invalidated when an asynchronous gap is added between the original + /// stream's event dispatch and the returned stream's, for example by + /// transforming it with a [StreamTransformer]. This is a lighter-weight way + /// of preserving that guarantee in particular than + /// [StreamChannel.withGuarantees]. + factory StreamChannel.withCloseGuarantee(Stream stream, + StreamSink sink) => + new CloseGuaranteeChannel(stream, sink); + /// Connects [this] to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); @@ -148,10 +162,10 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); StreamChannel changeStream(Stream change(Stream stream)) => - new StreamChannel(change(stream), sink); + new StreamChannel.withCloseGuarantee(change(stream), sink); StreamChannel changeSink(StreamSink change(StreamSink sink)) => - new StreamChannel(stream, change(sink)); + new StreamChannel.withCloseGuarantee(stream, change(sink)); StreamChannel/**/ cast/**/() => new StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart new file mode 100644 index 000000000..caf48cf1c --- /dev/null +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -0,0 +1,66 @@ +// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:async/async.dart'; +import 'package:stream_channel/stream_channel.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +final _delayTransformer = new StreamTransformer.fromHandlers( + handleData: (data, sink) => new Future.microtask(() => sink.add(data)), + handleDone: (sink) => new Future.microtask(() => sink.close())); + +final _delaySinkTransformer = + new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); + +void main() { + var controller; + var channel; + setUp(() { + controller = new StreamChannelController(); + + // Add a bunch of layers of asynchronous dispatch between the channel and + // the underlying controllers. + var stream = controller.foreign.stream; + var sink = controller.foreign.sink; + for (var i = 0; i < 10; i++) { + stream = stream.transform(_delayTransformer); + sink = _delaySinkTransformer.bind(sink); + } + + channel = new StreamChannel.withCloseGuarantee(stream, sink); + }); + + test("closing the event sink causes the stream to close before it emits any " + "more events", () async { + controller.local.sink.add(1); + controller.local.sink.add(2); + controller.local.sink.add(3); + + expect(channel.stream.listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)).asFuture(), completes); + + await pumpEventQueue(); + }); + + test("closing the event sink before events are emitted causes the stream to " + "close immediately", () async { + channel.sink.close(); + channel.stream.listen( + expectAsync((_) {}, count: 0), + onError: expectAsync((_, __) {}, count: 0), + onDone: expectAsync(() {})); + + controller.local.sink.add(1); + controller.local.sink.add(2); + controller.local.sink.add(3); + controller.local.sink.close(); + + await pumpEventQueue(); + }); +} From e39e092305561edffc588391472e4bdc94df9d76 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:35:00 -0700 Subject: [PATCH 0267/1215] Bump the pubspec version to 1.5.0. R=cbracken@google.com Review URL: https://codereview.chromium.org//2041813003 . --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 1c1df3136..3428dac28 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.4.0 +version: 1.5.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 1518a7a312dc0c63043ccef9767e38f1cf7e2e32 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:52:04 -0700 Subject: [PATCH 0268/1215] Add StringScanner.scanChar() and .expectChar(). R=jmesserly@google.com Review URL: https://codereview.chromium.org//2041813002 . --- pkgs/string_scanner/CHANGELOG.md | 2 + .../lib/src/eager_span_scanner.dart | 17 +++++-- pkgs/string_scanner/lib/src/line_scanner.dart | 17 +++++-- .../lib/src/string_scanner.dart | 33 +++++++++++++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/line_scanner_test.dart | 34 +++++++++++++ .../test/string_scanner_test.dart | 49 +++++++++++++++++++ 7 files changed, 147 insertions(+), 7 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index ea1268c1e..db7368619 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -2,6 +2,8 @@ * Add `new SpanScanner.within()`, which scans within a existing `FileSpan`. +* Add `StringScanner.scanChar()` and `StringScanner.expectChar()`. + ## 0.1.4+1 * Remove the dependency on `path`, since we don't actually import it. diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index c537b0cd6..f80dce5c3 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -67,15 +67,26 @@ class EagerSpanScanner extends SpanScanner { EagerSpanScanner(String string, {sourceUrl, int position}) : super(string, sourceUrl: sourceUrl, position: position); + bool scanChar(int character) { + if (!super.scanChar(character)) return false; + _adjustLineAndColumn(character); + return true; + } + int readChar() { - var char = super.readChar(); - if (char == $lf || (char == $cr && peekChar() != $lf)) { + var character = super.readChar(); + _adjustLineAndColumn(character); + return character; + } + + /// Adjusts [_line] and [_column] after having consumed [character]. + void _adjustLineAndColumn(int character) { + if (character == $lf || (character == $cr && peekChar() != $lf)) { _line += 1; _column = 0; } else { _column += 1; } - return char; } bool scan(Pattern pattern) { diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index b4391934d..fe6359212 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -73,15 +73,26 @@ class LineScanner extends StringScanner { LineScanner(String string, {sourceUrl, int position}) : super(string, sourceUrl: sourceUrl, position: position); + bool scanChar(int character) { + if (!super.scanChar(character)) return false; + _adjustLineAndColumn(character); + return true; + } + int readChar() { - var char = super.readChar(); - if (char == $lf || (char == $cr && peekChar() != $lf)) { + var character = super.readChar(); + _adjustLineAndColumn(character); + return character; + } + + /// Adjusts [_line] and [_column] after having consumed [character]. + void _adjustLineAndColumn(int character) { + if (character == $lf || (character == $cr && peekChar() != $lf)) { _line += 1; _column = 0; } else { _column += 1; } - return char; } bool scan(Pattern pattern) { diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 775dd5e1c..8334ccb3e 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.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. +import 'package:charcode/charcode.dart'; import 'package:source_span/source_span.dart'; import 'exception.dart'; @@ -79,6 +80,38 @@ class StringScanner { return string.codeUnitAt(index); } + /// If the next character in the string is [character], consumes it. + /// + /// Returns whether or not [character] was consumed. + bool scanChar(int character) { + if (isDone) return false; + if (string.codeUnitAt(_position) != character) return false; + _position++; + return true; + } + + /// If the next character in the string is [character], consumes it. + /// + /// If [character] could not be consumed, throws a [FormatException] + /// describing the position of the failure. [name] is used in this error as + /// the expected name of the character being matched; if it's `null`, the + /// character itself is used instead. + void expectChar(int character, {String name}) { + if (scanChar(character)) return; + + if (name == null) { + if (character == $backslash) { + name = r'"\"'; + } else if (character == $double_quote) { + name = r'"\""'; + } else { + name = '"${new String.fromCharCode(character)}"'; + } + } + + _fail('Expected $name.'); + } + /// If [pattern] matches at the current position of the string, scans forward /// until the end of the match. /// diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 24bd6bb12..7f7e33a30 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.5-dev +version: 0.1.5 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 9874cb309..ed04b371c 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.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. +import 'package:charcode/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; @@ -80,6 +81,39 @@ void main() { }); }); + group("scanChar()", () { + test("on a non-newline character increases the column but not the line", + () { + scanner.scanChar($f); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(1)); + }); + + test("consuming a newline resets the column and increases the line", () { + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.scanChar($lf); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test("consuming halfway through a CR LF doesn't count as a line", () { + scanner.expect('foo\nbar'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(3)); + + scanner.scanChar($cr); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + + scanner.scanChar($lf); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); + }); + group("position=", () { test("forward through newlines sets the line and column", () { scanner.position = 10; // "foo\nbar\r\nb" diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 10e622a82..0b4d4824f 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.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. +import 'package:charcode/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; @@ -41,6 +42,18 @@ void main() { expect(scanner.position, equals(0)); }); + test("scanChar returns false and doesn't change the state", () { + expect(scanner.scanChar($f), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test("expectChar fails and doesn't change the state", () { + expect(() => scanner.expectChar($f), throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("scan returns false and doesn't change the state", () { expect(scanner.scan(new RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); @@ -117,6 +130,30 @@ void main() { expect(scanner.position, equals(0)); }); + test("a matching scanChar returns true moves forward", () { + expect(scanner.scanChar($f), isTrue); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(1)); + }); + + test("a non-matching scanChar returns false and does nothing", () { + expect(scanner.scanChar($x), isFalse); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + + test("a matching expectChar moves forward", () { + scanner.expectChar($f); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(1)); + }); + + test("a non-matching expectChar fails", () { + expect(() => scanner.expectChar($x), throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("a matching scan returns true and changes the state", () { expect(scanner.scan(new RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); @@ -256,6 +293,18 @@ void main() { expect(scanner.position, equals(7)); }); + test("scanChar returns false and doesn't change the state", () { + expect(scanner.scanChar($f), isFalse); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + + test("expectChar fails and doesn't change the state", () { + expect(() => scanner.expectChar($f), throwsFormatException); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + test("scan returns false and sets lastMatch to null", () { expect(scanner.scan(new RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); From a35416e22a7b83ab32268f1122bc51dc148b79fa Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 6 Jun 2016 16:54:35 -0700 Subject: [PATCH 0269/1215] Fix transformer tests. These tests should never have passed, since they were closing a sink before its controller emitted events. R=cbracken@google.com Review URL: https://codereview.chromium.org//2048473002 . --- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/stream_channel_test.dart | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 3428dac28..bcdfe8e78 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.5.0 +version: 1.5.1-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 2a6566ac7..41f4c32ec 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,13 +41,13 @@ void main() { expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); }); - test("transform() transforms the channel", () { + test("transform() transforms the channel", () async { var transformed = channel.transform( new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), completion(equals(["foobar"]))); + expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); transformed.sink.close(); @@ -55,12 +55,12 @@ void main() { completion(equals([[102, 98, 108, 116, 104, 112]]))); }); - test("transformStream() transforms only the stream", () { + test("transformStream() transforms only the stream", () async { var transformed = channel.transformStream(UTF8.decoder); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), completion(equals(["foobar"]))); + expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); transformed.sink.close(); @@ -68,14 +68,14 @@ void main() { completion(equals(["fblthp"]))); }); - test("transformSink() transforms only the sink", () { + test("transformSink() transforms only the sink", () async { var transformed = channel.transformSink( new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(transformed.stream.toList(), - completion(equals([[102, 111, 111, 98, 97, 114]]))); + expect(await transformed.stream.toList(), + equals([[102, 111, 111, 98, 97, 114]])); transformed.sink.add("fblthp"); transformed.sink.close(); From 579891ad3abfa2f54797d83fcb5e855fdecc46a0 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 14 Jun 2016 16:21:23 -0700 Subject: [PATCH 0270/1215] Add breaking changes and release 1.0.0. This makes `.error()` default to empty spans rather than single-character ones. This better represents the semantics of failing at a particular position in the text. It also makes `lastMatch` reset whenever the scanner's position changes. This makes `.error()` behave more consistently when primarily doing character-based scanning, since it won't unexpectedly emit an error for stale match data. R=jmesserly@google.com Review URL: https://codereview.chromium.org//2056933002 . --- pkgs/string_scanner/CHANGELOG.md | 13 ++++++++ pkgs/string_scanner/lib/src/line_scanner.dart | 2 ++ pkgs/string_scanner/lib/src/span_scanner.dart | 7 ++-- .../lib/src/string_scanner.dart | 19 ++++++++--- pkgs/string_scanner/pubspec.yaml | 2 +- pkgs/string_scanner/test/error_test.dart | 4 +-- .../test/string_scanner_test.dart | 33 +++++++++++++++++++ 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index db7368619..910d30ebc 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,16 @@ +## 1.0.0 + +* **Breaking change**: `StringScanner.error()`'s `length` argument now defaults + to `0` rather than `1` when no match data is available. + +* **Breaking change**: `StringScanner.lastMatch` and related methods are now + reset when the scanner's position changes without producing a new match. + +**Note**: While the changes in `1.0.0` are user-visible, they're unlikely to +actually break any code in practice. Unless you know that your package is +incompatible with 0.1.x, consider using 0.1.5 as your lower bound rather +than 1.0.0. For example, `string_scanner: ">=0.1.5 <2.0.0"`. + ## 0.1.5 * Add `new SpanScanner.within()`, which scans within a existing `FileSpan`. diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index fe6359212..06f1cbc1e 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -26,6 +26,8 @@ class LineScanner extends StringScanner { /// This can be used to efficiently save and restore the state of the scanner /// when backtracking. A given [LineScannerState] is only valid for the /// [LineScanner] that created it. + /// + /// This does not include the scanner's match information. LineScannerState get state => new LineScannerState._(this, position, line, column); diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index dd7f0e4f2..043021b4d 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -38,7 +38,10 @@ class SpanScanner extends StringScanner implements LineScanner { /// /// This is the span for the entire match. There's no way to get spans for /// subgroups since [Match] exposes no information about their positions. - FileSpan get lastSpan => _lastSpan; + FileSpan get lastSpan { + if (lastMatch == null) _lastSpan = null; + return _lastSpan; + } FileSpan _lastSpan; /// The current location of the scanner. @@ -102,7 +105,7 @@ class SpanScanner extends StringScanner implements LineScanner { if (position == null) { position = match == null ? this.position : match.start; } - if (length == null) length = match == null ? 1 : match.end - match.start; + if (length == null) length = match == null ? 0 : match.end - match.start; var span = _sourceFile.span(position, position + length); throw new StringScannerException(message, span, string); diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 8334ccb3e..b9714ff68 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -32,14 +32,21 @@ class StringScanner { } _position = position; + _lastMatch = null; } int _position = 0; /// The data about the previous match made by the scanner. /// /// If the last match failed, this will be `null`. - Match get lastMatch => _lastMatch; + Match get lastMatch { + // Lazily unset [_lastMatch] so that we avoid extra assignments in + // character-by-character methods that are used in core loops. + if (_position != _lastMatchPosition) _lastMatch = null; + return _lastMatch; + } Match _lastMatch; + int _lastMatchPosition; /// The portion of the string that hasn't yet been scanned. String get rest => string.substring(position); @@ -118,7 +125,10 @@ class StringScanner { /// Returns whether or not [pattern] matched. bool scan(Pattern pattern) { var success = matches(pattern); - if (success) _position = _lastMatch.end; + if (success) { + _position = _lastMatch.end; + _lastMatchPosition = _position; + } return success; } @@ -159,6 +169,7 @@ class StringScanner { /// This doesn't move the scan pointer forward. bool matches(Pattern pattern) { _lastMatch = pattern.matchAsPrefix(string, position); + _lastMatchPosition = _position; return _lastMatch != null; } @@ -181,7 +192,7 @@ class StringScanner { /// /// If [position] and/or [length] are passed, they are used as the error span /// instead. If only [length] is passed, [position] defaults to the current - /// position; if only [position] is passed, [length] defaults to 1. + /// position; if only [position] is passed, [length] defaults to 0. /// /// It's an error to pass [match] at the same time as [position] or [length]. void error(String message, {Match match, int position, int length}) { @@ -191,7 +202,7 @@ class StringScanner { if (position == null) { position = match == null ? this.position : match.start; } - if (length == null) length = match == null ? 1 : match.end - match.start; + if (length == null) length = match == null ? 0 : match.end - match.start; var sourceFile = new SourceFile(string, url: sourceUrl); var span = sourceFile.span(position, position + length); diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 7f7e33a30..48ed59dbc 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 0.1.5 +version: 1.0.0 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index ff451940e..166077d5e 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -59,11 +59,11 @@ void main() { }); group("with position and/or length", () { - test('defaults to length 1', () { + test('defaults to length 0', () { var scanner = new StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1), - throwsStringScannerException('o')); + throwsStringScannerException('')); }); test('defaults to the current position', () { diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 0b4d4824f..55ffa0a9f 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -261,6 +261,32 @@ void main() { }); }); + group('after a scan', () { + var scanner; + setUp(() { + scanner = new StringScanner('foo bar'); + expect(scanner.scan('foo'), isTrue); + }); + + test('readChar returns the first character and unsets the last match', () { + expect(scanner.readChar(), equals($space)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(4)); + }); + + test('a matching scanChar returns true and unsets the last match', () { + expect(scanner.scanChar($space), isTrue); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(4)); + }); + + test('a matching expectChar returns true and unsets the last match', () { + scanner.expectChar($space); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(4)); + }); + }); + group('at the end of a string', () { var scanner; setUp(() { @@ -346,6 +372,13 @@ void main() { expect(scanner.rest, equals('bar')); }); + test('setting and resetting position clears lastMatch', () { + var oldPosition = scanner.position; + scanner.position = 1; + scanner.position = oldPosition; + expect(scanner.lastMatch, isNull); + }); + test('setting position beyond the string throws an ArgumentError', () { expect(() { scanner.position = 8; From b1e47f0da90352dcc5378855d0980970d792acaa Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 14 Jun 2016 16:23:18 -0700 Subject: [PATCH 0271/1215] Trace.current skips an extra frame in JS. JS traces include a frame for StackTrace.current while VM traces do not. R=rnystrom@google.com Review URL: https://codereview.chromium.org//2067063002 . --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/trace.dart | 6 +++++- pkgs/stack_trace/lib/src/utils.dart | 6 ++++++ pkgs/stack_trace/pubspec.yaml | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 174754ccd..21fd73454 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.6 + +* `new Trace.current()` and `new Chain.current()` now skip an extra frame when + run in a JS context. This makes their return values match the VM context. + ## 1.6.5 * Really fix strong mode warnings. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 8537b6236..20343ad5a 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -81,7 +81,11 @@ class Trace implements StackTrace { } var trace = new Trace.from(StackTrace.current); - return new LazyTrace(() => new Trace(trace.frames.skip(level + 1))); + return new LazyTrace(() { + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1))); + }); } /// Returns a new stack trace containing the same data as [trace]. diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 710abdc04..b06d462aa 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -2,10 +2,16 @@ // 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. +import 'package:path/path.dart' as p; + /// The line used in the string representation of stack chains to represent /// the gap between traces. const chainGap = '===== asynchronous gap ===========================\n'; +// TODO(nweiz): When cross-platform imports work, use them to set this. +/// Whether we're running in a JS context. +final bool inJS = p.style == p.Style.url; + /// Returns [string] with enough spaces added to the end to make it [length] /// characters long. String padRight(String string, int length) { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ac3c3114a..06c9d3c48 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.6-dev +version: 1.6.6 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From 0b1902052632bf68b8e619f2304aa7643ef5b703 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Aug 2016 17:59:00 -0700 Subject: [PATCH 0272/1215] Fix a crashing bug on Linux. When a directory was removed immediately after a subdirectory was created, the subdirectory event would be buffered. We'd then attempt to watch the subdirectory even though the stream group was already closed. Fixed b/30768513. --- pkgs/watcher/CHANGELOG.md | 4 ++++ .../lib/src/directory_watcher/linux.dart | 14 +++++++------- pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/directory_watcher/shared.dart | 17 +++++++++++++++++ 4 files changed, 29 insertions(+), 8 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index aa6752e45..c3acaf53e 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+3 + +* Fix a crashing bug on Linux. + # 0.9.7+2 * Narrow the constraint on `async` to reflect the APIs this package is actually diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index f33a55476..df1365c76 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -66,18 +66,18 @@ class _LinuxDirectoryWatcher : _files = new PathSet(path) { _nativeEvents.add(new Directory(path).watch().transform( new StreamTransformer.fromHandlers(handleDone: (sink) { - // Once the root directory is deleted, no more new subdirectories will be - // watched. - _nativeEvents.close(); - sink.close(); + // Handle the done event here rather than in the call to [_listen] because + // [innerStream] won't close until we close the [StreamGroup]. However, if + // we close the [StreamGroup] here, we run the risk of new-directory + // events being fired after the group is closed, since batching delays + // those events. See b/30768513. + _onDone(); }))); // Batch the inotify changes together so that we can dedup events. var innerStream = _nativeEvents.stream .transform(new BatchedStreamTransformer()); - _listen(innerStream, _onBatch, - onError: _eventsController.addError, - onDone: _onDone); + _listen(innerStream, _onBatch, onError: _eventsController.addError); _listen(new Directory(path).list(recursive: true), (entity) { if (entity is Directory) { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 57e75e66c..35b651745 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+2 +version: 0.9.8-dev author: Dart Team homepage: https://github.com/dart-lang/watcher description: > diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index c95ee39f4..148eee263 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -92,6 +92,23 @@ void sharedTests() { ]); }); + // Regression test for b/30768513. + test("doesn't crash when the directory is moved immediately after a subdir " + "is added", () { + writeFile("dir/a.txt"); + writeFile("dir/b.txt"); + + startWatcher(path: "dir"); + + createDir("dir/subdir"); + renameDir("dir", "moved_dir"); + createDir("dir"); + inAnyOrder([ + isRemoveEvent("dir/a.txt"), + isRemoveEvent("dir/b.txt") + ]); + }); + group("moves", () { test('notifies when a file is moved within the watched directory', () { writeFile("old.txt"); From 1f4c3612807614f9863f3d30aca0c5459c84ff92 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Aug 2016 12:02:03 -0700 Subject: [PATCH 0273/1215] Release 0.9.7+2. --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 35b651745..57e75e66c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.8-dev +version: 0.9.7+2 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > From dd8f02975b57908b70674617b4e5f8dbcd28d86c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Aug 2016 12:09:22 -0700 Subject: [PATCH 0274/1215] Oops, that was supposed to be 0.9.7+3. --- pkgs/watcher/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 57e75e66c..bee354602 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+2 +version: 0.9.7+3 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > From 0f1b3e35a43f54ef07cde3c077826f02a8381105 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Aug 2016 16:00:52 -0700 Subject: [PATCH 0275/1215] Convert all files to Unix newlines. --- .../lib/src/directory_watcher/windows.dart | 816 +++++++++--------- pkgs/watcher/pubspec.yaml | 2 +- .../test/directory_watcher/windows_test.dart | 50 +- 3 files changed, 434 insertions(+), 434 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 67a274198..ec119f75e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -1,408 +1,408 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// 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. -// TODO(rnystrom): Merge with mac_os version. - -import 'dart:async'; -import 'dart:collection'; -import 'dart:io'; - -import 'package:path/path.dart' as p; - -import '../constructable_file_system_event.dart'; -import '../directory_watcher.dart'; -import '../path_set.dart'; -import '../resubscribable.dart'; -import '../utils.dart'; -import '../watch_event.dart'; - -class WindowsDirectoryWatcher extends ResubscribableWatcher - implements DirectoryWatcher { - String get directory => path; - - WindowsDirectoryWatcher(String directory) - : super(directory, () => new _WindowsDirectoryWatcher(directory)); -} - -class _EventBatcher { - static const Duration _BATCH_DELAY = const Duration(milliseconds: 100); - final List events = []; - Timer timer; - - void addEvent(FileSystemEvent event, void callback()) { - events.add(event); - if (timer != null) { - timer.cancel(); - } - timer = new Timer(_BATCH_DELAY, callback); - } - - void cancelTimer() { - timer.cancel(); - } -} - -class _WindowsDirectoryWatcher - implements DirectoryWatcher, ManuallyClosedWatcher { - String get directory => path; - final String path; - - Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); - - bool get isReady => _readyCompleter.isCompleted; - - Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); - - final Map _eventBatchers = - new HashMap(); - - /// The set of files that are known to exist recursively within the watched - /// directory. - /// - /// The state of files on the filesystem is compared against this to determine - /// the real change that occurred. This is also used to emit REMOVE events - /// when subdirectories are moved out of the watched directory. - final PathSet _files; - - /// The subscription to the stream returned by [Directory.watch]. - StreamSubscription _watchSubscription; - - /// The subscription to the stream returned by [Directory.watch] of the - /// parent directory to [directory]. This is needed to detect changes to - /// [directory], as they are not included on Windows. - StreamSubscription _parentWatchSubscription; - - /// The subscription to the [Directory.list] call for the initial listing of - /// the directory to determine its initial state. - StreamSubscription _initialListSubscription; - - /// The subscriptions to the [Directory.list] calls for listing the contents - /// of subdirectories that were moved into the watched directory. - final Set> _listSubscriptions - = new HashSet>(); - - _WindowsDirectoryWatcher(String path) - : path = path, - _files = new PathSet(path) { - // Before we're ready to emit events, wait for [_listDir] to complete. - _listDir().then((_) { - _startWatch(); - _startParentWatcher(); - _readyCompleter.complete(); - }); - } - - void close() { - if (_watchSubscription != null) _watchSubscription.cancel(); - if (_parentWatchSubscription != null) _parentWatchSubscription.cancel(); - if (_initialListSubscription != null) _initialListSubscription.cancel(); - for (var sub in _listSubscriptions) { - sub.cancel(); - } - _listSubscriptions.clear(); - for (var batcher in _eventBatchers.values) { - batcher.cancelTimer(); - } - _eventBatchers.clear(); - _watchSubscription = null; - _parentWatchSubscription = null; - _initialListSubscription = null; - _eventsController.close(); - } - - /// On Windows, if [directory] is deleted, we will not receive any event. - /// - /// Instead, we add a watcher on the parent folder (if any), that can notify - /// us about [path]. This also includes events such as moves. - void _startParentWatcher() { - var absoluteDir = p.absolute(path); - var parent = p.dirname(absoluteDir); - // Check if [path] is already the root directory. - if (FileSystemEntity.identicalSync(parent, path)) return; - var parentStream = new Directory(parent).watch(recursive: false); - _parentWatchSubscription = parentStream.listen((event) { - // Only look at events for 'directory'. - if (p.basename(event.path) != p.basename(absoluteDir)) return; - // Test if the directory is removed. FileSystemEntity.typeSync will - // return NOT_FOUND if it's unable to decide upon the type, including - // access denied issues, which may happen when the directory is deleted. - // FileSystemMoveEvent and FileSystemDeleteEvent events will always mean - // the directory is now gone. - if (event is FileSystemMoveEvent || - event is FileSystemDeleteEvent || - (FileSystemEntity.typeSync(path) == - FileSystemEntityType.NOT_FOUND)) { - for (var path in _files.paths) { - _emitEvent(ChangeType.REMOVE, path); - } - _files.clear(); - close(); - } - }, onError: (error) { - // Ignore errors, simply close the stream. The user listens on - // [directory], and while it can fail to listen on the parent, we may - // still be able to listen on the path requested. - _parentWatchSubscription.cancel(); - _parentWatchSubscription = null; - }); - } - - void _onEvent(FileSystemEvent event) { - assert(isReady); - final batcher = _eventBatchers.putIfAbsent( - event.path, () => new _EventBatcher()); - batcher.addEvent(event, () { - _eventBatchers.remove(event.path); - _onBatch(batcher.events); - }); - } - - /// The callback that's run when [Directory.watch] emits a batch of events. - void _onBatch(List batch) { - _sortEvents(batch).forEach((path, eventSet) { - - var canonicalEvent = _canonicalEvent(eventSet); - var events = canonicalEvent == null ? - _eventsBasedOnFileSystem(path) : [canonicalEvent]; - - for (var event in events) { - if (event is FileSystemCreateEvent) { - if (!event.isDirectory) { - if (_files.contains(path)) continue; - - _emitEvent(ChangeType.ADD, path); - _files.add(path); - continue; - } - - if (_files.containsDir(path)) continue; - - var stream = new Directory(path).list(recursive: true); - StreamSubscription subscription; - subscription = stream.listen((entity) { - if (entity is Directory) return; - if (_files.contains(path)) return; - - _emitEvent(ChangeType.ADD, entity.path); - _files.add(entity.path); - }, onDone: () { - _listSubscriptions.remove(subscription); - }, onError: (e, stackTrace) { - _listSubscriptions.remove(subscription); - _emitError(e, stackTrace); - }, cancelOnError: true); - _listSubscriptions.add(subscription); - } else if (event is FileSystemModifyEvent) { - if (!event.isDirectory) { - _emitEvent(ChangeType.MODIFY, path); - } - } else { - assert(event is FileSystemDeleteEvent); - for (var removedPath in _files.remove(path)) { - _emitEvent(ChangeType.REMOVE, removedPath); - } - } - } - }); - } - - /// Sort all the events in a batch into sets based on their path. - /// - /// A single input event may result in multiple events in the returned map; - /// for example, a MOVE event becomes a DELETE event for the source and a - /// CREATE event for the destination. - /// - /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it - /// contain any events relating to [path]. - Map> _sortEvents(List batch) { - var eventsForPaths = {}; - - // Events within directories that already have events are superfluous; the - // directory's full contents will be examined anyway, so we ignore such - // events. Emitting them could cause useless or out-of-order events. - var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return new Set(); - if (event is FileSystemMoveEvent) { - return new Set.from([event.path, event.destination]); - } - return new Set.from([event.path]); - })); - - isInModifiedDirectory(path) => - directories.any((dir) => path != dir && path.startsWith(dir)); - - addEvent(path, event) { - if (isInModifiedDirectory(path)) return; - var set = eventsForPaths.putIfAbsent(path, () => new Set()); - set.add(event); - } - - for (var event in batch) { - if (event is FileSystemMoveEvent) { - addEvent(event.destination, event); - } - addEvent(event.path, event); - } - - return eventsForPaths; - } - - /// Returns the canonical event from a batch of events on the same path, if - /// one exists. - /// - /// If [batch] doesn't contain any contradictory events (e.g. DELETE and - /// CREATE, or events with different values for [isDirectory]), this returns a - /// single event that describes what happened to the path in question. - /// - /// If [batch] does contain contradictory events, this returns `null` to - /// indicate that the state of the path on the filesystem should be checked to - /// determine what occurred. - FileSystemEvent _canonicalEvent(Set batch) { - // An empty batch indicates that we've learned earlier that the batch is - // contradictory (e.g. because of a move). - if (batch.isEmpty) return null; - - var type = batch.first.type; - var isDir = batch.first.isDirectory; - - for (var event in batch.skip(1)) { - // If one event reports that the file is a directory and another event - // doesn't, that's a contradiction. - if (isDir != event.isDirectory) return null; - - // Modify events don't contradict either CREATE or REMOVE events. We can - // safely assume the file was modified after a CREATE or before the - // REMOVE; otherwise there will also be a REMOVE or CREATE event - // (respectively) that will be contradictory. - if (event is FileSystemModifyEvent) continue; - assert(event is FileSystemCreateEvent || - event is FileSystemDeleteEvent || - event is FileSystemMoveEvent); - - // If we previously thought this was a MODIFY, we now consider it to be a - // CREATE or REMOVE event. This is safe for the same reason as above. - if (type == FileSystemEvent.MODIFY) { - type = event.type; - continue; - } - - // A CREATE event contradicts a REMOVE event and vice versa. - assert(type == FileSystemEvent.CREATE || - type == FileSystemEvent.DELETE || - type == FileSystemEvent.MOVE); - if (type != event.type) return null; - } - - switch (type) { - case FileSystemEvent.CREATE: - return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); - case FileSystemEvent.DELETE: - return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); - case FileSystemEvent.MODIFY: - return new ConstructableFileSystemModifyEvent( - batch.first.path, isDir, false); - case FileSystemEvent.MOVE: - return null; - default: throw 'unreachable'; - } - } - - /// Returns one or more events that describe the change between the last known - /// state of [path] and its current state on the filesystem. - /// - /// This returns a list whose order should be reflected in the events emitted - /// to the user, unlike the batched events from [Directory.watch]. The - /// returned list may be empty, indicating that no changes occurred to [path] - /// (probably indicating that it was created and then immediately deleted). - List _eventsBasedOnFileSystem(String path) { - var fileExisted = _files.contains(path); - var dirExisted = _files.containsDir(path); - var fileExists = new File(path).existsSync(); - var dirExists = new Directory(path).existsSync(); - - var events = []; - if (fileExisted) { - if (fileExists) { - events.add(new ConstructableFileSystemModifyEvent(path, false, false)); - } else { - events.add(new ConstructableFileSystemDeleteEvent(path, false)); - } - } else if (dirExisted) { - if (dirExists) { - // If we got contradictory events for a directory that used to exist and - // still exists, we need to rescan the whole thing in case it was - // replaced with a different directory. - events.add(new ConstructableFileSystemDeleteEvent(path, true)); - events.add(new ConstructableFileSystemCreateEvent(path, true)); - } else { - events.add(new ConstructableFileSystemDeleteEvent(path, true)); - } - } - - if (!fileExisted && fileExists) { - events.add(new ConstructableFileSystemCreateEvent(path, false)); - } else if (!dirExisted && dirExists) { - events.add(new ConstructableFileSystemCreateEvent(path, true)); - } - - return events; - } - - /// The callback that's run when the [Directory.watch] stream is closed. - /// Note that this is unlikely to happen on Windows, unless the system itself - /// closes the handle. - void _onDone() { - _watchSubscription = null; - - // Emit remove events for any remaining files. - for (var file in _files.paths) { - _emitEvent(ChangeType.REMOVE, file); - } - _files.clear(); - close(); - } - - /// Start or restart the underlying [Directory.watch] stream. - void _startWatch() { - // Batch the events together so that we can dedup events. - var innerStream = new Directory(path).watch(recursive: true); - _watchSubscription = innerStream.listen(_onEvent, - onError: _eventsController.addError, - onDone: _onDone); - } - - /// Starts or restarts listing the watched directory to get an initial picture - /// of its state. - Future _listDir() { - assert(!isReady); - if (_initialListSubscription != null) _initialListSubscription.cancel(); - - _files.clear(); - var completer = new Completer(); - var stream = new Directory(path).list(recursive: true); - void handleEntity(entity) { - if (entity is! Directory) _files.add(entity.path); - } - _initialListSubscription = stream.listen( - handleEntity, - onError: _emitError, - onDone: completer.complete, - cancelOnError: true); - return completer.future; - } - - /// Emit an event with the given [type] and [path]. - void _emitEvent(ChangeType type, String path) { - if (!isReady) return; - - _eventsController.add(new WatchEvent(type, path)); - } - - /// Emit an error, then close the watcher. - void _emitError(error, StackTrace stackTrace) { - _eventsController.addError(error, stackTrace); - close(); - } -} +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. +// TODO(rnystrom): Merge with mac_os version. + +import 'dart:async'; +import 'dart:collection'; +import 'dart:io'; + +import 'package:path/path.dart' as p; + +import '../constructable_file_system_event.dart'; +import '../directory_watcher.dart'; +import '../path_set.dart'; +import '../resubscribable.dart'; +import '../utils.dart'; +import '../watch_event.dart'; + +class WindowsDirectoryWatcher extends ResubscribableWatcher + implements DirectoryWatcher { + String get directory => path; + + WindowsDirectoryWatcher(String directory) + : super(directory, () => new _WindowsDirectoryWatcher(directory)); +} + +class _EventBatcher { + static const Duration _BATCH_DELAY = const Duration(milliseconds: 100); + final List events = []; + Timer timer; + + void addEvent(FileSystemEvent event, void callback()) { + events.add(event); + if (timer != null) { + timer.cancel(); + } + timer = new Timer(_BATCH_DELAY, callback); + } + + void cancelTimer() { + timer.cancel(); + } +} + +class _WindowsDirectoryWatcher + implements DirectoryWatcher, ManuallyClosedWatcher { + String get directory => path; + final String path; + + Stream get events => _eventsController.stream; + final _eventsController = new StreamController.broadcast(); + + bool get isReady => _readyCompleter.isCompleted; + + Future get ready => _readyCompleter.future; + final _readyCompleter = new Completer(); + + final Map _eventBatchers = + new HashMap(); + + /// The set of files that are known to exist recursively within the watched + /// directory. + /// + /// The state of files on the filesystem is compared against this to determine + /// the real change that occurred. This is also used to emit REMOVE events + /// when subdirectories are moved out of the watched directory. + final PathSet _files; + + /// The subscription to the stream returned by [Directory.watch]. + StreamSubscription _watchSubscription; + + /// The subscription to the stream returned by [Directory.watch] of the + /// parent directory to [directory]. This is needed to detect changes to + /// [directory], as they are not included on Windows. + StreamSubscription _parentWatchSubscription; + + /// The subscription to the [Directory.list] call for the initial listing of + /// the directory to determine its initial state. + StreamSubscription _initialListSubscription; + + /// The subscriptions to the [Directory.list] calls for listing the contents + /// of subdirectories that were moved into the watched directory. + final Set> _listSubscriptions + = new HashSet>(); + + _WindowsDirectoryWatcher(String path) + : path = path, + _files = new PathSet(path) { + // Before we're ready to emit events, wait for [_listDir] to complete. + _listDir().then((_) { + _startWatch(); + _startParentWatcher(); + _readyCompleter.complete(); + }); + } + + void close() { + if (_watchSubscription != null) _watchSubscription.cancel(); + if (_parentWatchSubscription != null) _parentWatchSubscription.cancel(); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + for (var sub in _listSubscriptions) { + sub.cancel(); + } + _listSubscriptions.clear(); + for (var batcher in _eventBatchers.values) { + batcher.cancelTimer(); + } + _eventBatchers.clear(); + _watchSubscription = null; + _parentWatchSubscription = null; + _initialListSubscription = null; + _eventsController.close(); + } + + /// On Windows, if [directory] is deleted, we will not receive any event. + /// + /// Instead, we add a watcher on the parent folder (if any), that can notify + /// us about [path]. This also includes events such as moves. + void _startParentWatcher() { + var absoluteDir = p.absolute(path); + var parent = p.dirname(absoluteDir); + // Check if [path] is already the root directory. + if (FileSystemEntity.identicalSync(parent, path)) return; + var parentStream = new Directory(parent).watch(recursive: false); + _parentWatchSubscription = parentStream.listen((event) { + // Only look at events for 'directory'. + if (p.basename(event.path) != p.basename(absoluteDir)) return; + // Test if the directory is removed. FileSystemEntity.typeSync will + // return NOT_FOUND if it's unable to decide upon the type, including + // access denied issues, which may happen when the directory is deleted. + // FileSystemMoveEvent and FileSystemDeleteEvent events will always mean + // the directory is now gone. + if (event is FileSystemMoveEvent || + event is FileSystemDeleteEvent || + (FileSystemEntity.typeSync(path) == + FileSystemEntityType.NOT_FOUND)) { + for (var path in _files.paths) { + _emitEvent(ChangeType.REMOVE, path); + } + _files.clear(); + close(); + } + }, onError: (error) { + // Ignore errors, simply close the stream. The user listens on + // [directory], and while it can fail to listen on the parent, we may + // still be able to listen on the path requested. + _parentWatchSubscription.cancel(); + _parentWatchSubscription = null; + }); + } + + void _onEvent(FileSystemEvent event) { + assert(isReady); + final batcher = _eventBatchers.putIfAbsent( + event.path, () => new _EventBatcher()); + batcher.addEvent(event, () { + _eventBatchers.remove(event.path); + _onBatch(batcher.events); + }); + } + + /// The callback that's run when [Directory.watch] emits a batch of events. + void _onBatch(List batch) { + _sortEvents(batch).forEach((path, eventSet) { + + var canonicalEvent = _canonicalEvent(eventSet); + var events = canonicalEvent == null ? + _eventsBasedOnFileSystem(path) : [canonicalEvent]; + + for (var event in events) { + if (event is FileSystemCreateEvent) { + if (!event.isDirectory) { + if (_files.contains(path)) continue; + + _emitEvent(ChangeType.ADD, path); + _files.add(path); + continue; + } + + if (_files.containsDir(path)) continue; + + var stream = new Directory(path).list(recursive: true); + StreamSubscription subscription; + subscription = stream.listen((entity) { + if (entity is Directory) return; + if (_files.contains(path)) return; + + _emitEvent(ChangeType.ADD, entity.path); + _files.add(entity.path); + }, onDone: () { + _listSubscriptions.remove(subscription); + }, onError: (e, stackTrace) { + _listSubscriptions.remove(subscription); + _emitError(e, stackTrace); + }, cancelOnError: true); + _listSubscriptions.add(subscription); + } else if (event is FileSystemModifyEvent) { + if (!event.isDirectory) { + _emitEvent(ChangeType.MODIFY, path); + } + } else { + assert(event is FileSystemDeleteEvent); + for (var removedPath in _files.remove(path)) { + _emitEvent(ChangeType.REMOVE, removedPath); + } + } + } + }); + } + + /// Sort all the events in a batch into sets based on their path. + /// + /// A single input event may result in multiple events in the returned map; + /// for example, a MOVE event becomes a DELETE event for the source and a + /// CREATE event for the destination. + /// + /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it + /// contain any events relating to [path]. + Map> _sortEvents(List batch) { + var eventsForPaths = {}; + + // Events within directories that already have events are superfluous; the + // directory's full contents will be examined anyway, so we ignore such + // events. Emitting them could cause useless or out-of-order events. + var directories = unionAll(batch.map((event) { + if (!event.isDirectory) return new Set(); + if (event is FileSystemMoveEvent) { + return new Set.from([event.path, event.destination]); + } + return new Set.from([event.path]); + })); + + isInModifiedDirectory(path) => + directories.any((dir) => path != dir && path.startsWith(dir)); + + addEvent(path, event) { + if (isInModifiedDirectory(path)) return; + var set = eventsForPaths.putIfAbsent(path, () => new Set()); + set.add(event); + } + + for (var event in batch) { + if (event is FileSystemMoveEvent) { + addEvent(event.destination, event); + } + addEvent(event.path, event); + } + + return eventsForPaths; + } + + /// Returns the canonical event from a batch of events on the same path, if + /// one exists. + /// + /// If [batch] doesn't contain any contradictory events (e.g. DELETE and + /// CREATE, or events with different values for [isDirectory]), this returns a + /// single event that describes what happened to the path in question. + /// + /// If [batch] does contain contradictory events, this returns `null` to + /// indicate that the state of the path on the filesystem should be checked to + /// determine what occurred. + FileSystemEvent _canonicalEvent(Set batch) { + // An empty batch indicates that we've learned earlier that the batch is + // contradictory (e.g. because of a move). + if (batch.isEmpty) return null; + + var type = batch.first.type; + var isDir = batch.first.isDirectory; + + for (var event in batch.skip(1)) { + // If one event reports that the file is a directory and another event + // doesn't, that's a contradiction. + if (isDir != event.isDirectory) return null; + + // Modify events don't contradict either CREATE or REMOVE events. We can + // safely assume the file was modified after a CREATE or before the + // REMOVE; otherwise there will also be a REMOVE or CREATE event + // (respectively) that will be contradictory. + if (event is FileSystemModifyEvent) continue; + assert(event is FileSystemCreateEvent || + event is FileSystemDeleteEvent || + event is FileSystemMoveEvent); + + // If we previously thought this was a MODIFY, we now consider it to be a + // CREATE or REMOVE event. This is safe for the same reason as above. + if (type == FileSystemEvent.MODIFY) { + type = event.type; + continue; + } + + // A CREATE event contradicts a REMOVE event and vice versa. + assert(type == FileSystemEvent.CREATE || + type == FileSystemEvent.DELETE || + type == FileSystemEvent.MOVE); + if (type != event.type) return null; + } + + switch (type) { + case FileSystemEvent.CREATE: + return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); + case FileSystemEvent.DELETE: + return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + case FileSystemEvent.MODIFY: + return new ConstructableFileSystemModifyEvent( + batch.first.path, isDir, false); + case FileSystemEvent.MOVE: + return null; + default: throw 'unreachable'; + } + } + + /// Returns one or more events that describe the change between the last known + /// state of [path] and its current state on the filesystem. + /// + /// This returns a list whose order should be reflected in the events emitted + /// to the user, unlike the batched events from [Directory.watch]. The + /// returned list may be empty, indicating that no changes occurred to [path] + /// (probably indicating that it was created and then immediately deleted). + List _eventsBasedOnFileSystem(String path) { + var fileExisted = _files.contains(path); + var dirExisted = _files.containsDir(path); + var fileExists = new File(path).existsSync(); + var dirExists = new Directory(path).existsSync(); + + var events = []; + if (fileExisted) { + if (fileExists) { + events.add(new ConstructableFileSystemModifyEvent(path, false, false)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, false)); + } + } else if (dirExisted) { + if (dirExists) { + // If we got contradictory events for a directory that used to exist and + // still exists, we need to rescan the whole thing in case it was + // replaced with a different directory. + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } else { + events.add(new ConstructableFileSystemDeleteEvent(path, true)); + } + } + + if (!fileExisted && fileExists) { + events.add(new ConstructableFileSystemCreateEvent(path, false)); + } else if (!dirExisted && dirExists) { + events.add(new ConstructableFileSystemCreateEvent(path, true)); + } + + return events; + } + + /// The callback that's run when the [Directory.watch] stream is closed. + /// Note that this is unlikely to happen on Windows, unless the system itself + /// closes the handle. + void _onDone() { + _watchSubscription = null; + + // Emit remove events for any remaining files. + for (var file in _files.paths) { + _emitEvent(ChangeType.REMOVE, file); + } + _files.clear(); + close(); + } + + /// Start or restart the underlying [Directory.watch] stream. + void _startWatch() { + // Batch the events together so that we can dedup events. + var innerStream = new Directory(path).watch(recursive: true); + _watchSubscription = innerStream.listen(_onEvent, + onError: _eventsController.addError, + onDone: _onDone); + } + + /// Starts or restarts listing the watched directory to get an initial picture + /// of its state. + Future _listDir() { + assert(!isReady); + if (_initialListSubscription != null) _initialListSubscription.cancel(); + + _files.clear(); + var completer = new Completer(); + var stream = new Directory(path).list(recursive: true); + void handleEntity(entity) { + if (entity is! Directory) _files.add(entity.path); + } + _initialListSubscription = stream.listen( + handleEntity, + onError: _emitError, + onDone: completer.complete, + cancelOnError: true); + return completer.future; + } + + /// Emit an event with the given [type] and [path]. + void _emitEvent(ChangeType type, String path) { + if (!isReady) return; + + _eventsController.add(new WatchEvent(type, path)); + } + + /// Emit an error, then close the watcher. + void _emitError(error, StackTrace stackTrace) { + _eventsController.addError(error, stackTrace); + close(); + } +} diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index bee354602..35b651745 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+3 +version: 0.9.8-dev author: Dart Team homepage: https://github.com/dart-lang/watcher description: > diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 4c77ced50..55e40a937 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -1,25 +1,25 @@ -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -// 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. - -@TestOn('windows') - -import 'package:scheduled_test/scheduled_test.dart'; -import 'package:watcher/src/directory_watcher/windows.dart'; -import 'package:watcher/watcher.dart'; - -import 'shared.dart'; -import '../utils.dart'; - -void main() { - watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); - - setUp(createSandbox); - - sharedTests(); - - test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { - expect(new DirectoryWatcher('.'), - new isInstanceOf()); - }); -} +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('windows') + +import 'package:scheduled_test/scheduled_test.dart'; +import 'package:watcher/src/directory_watcher/windows.dart'; +import 'package:watcher/watcher.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +void main() { + watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); + + setUp(createSandbox); + + sharedTests(); + + test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { + expect(new DirectoryWatcher('.'), + new isInstanceOf()); + }); +} From dd4154e1f42f9094956d93fcc3b7c3ba9bcd3e12 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 10 Aug 2016 16:02:13 -0700 Subject: [PATCH 0276/1215] Remove an unused dependency on collection. --- pkgs/watcher/pubspec.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index bee354602..90f96f5a7 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+3 +version: 0.9.8-dev author: Dart Team homepage: https://github.com/dart-lang/watcher description: > @@ -9,7 +9,6 @@ environment: sdk: '>=1.9.0 <2.0.0' dependencies: async: '^1.10.0' - collection: '^1.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: benchmark_harness: '^1.0.4' From 9e5d9a8f572d7f6eeb4cd1cf019738fdc08a5a34 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Wed, 31 Aug 2016 12:55:57 -0700 Subject: [PATCH 0277/1215] Update with implementation from 'analyzer'. R=brianwilkerson@google.com BUG= Review URL: https://codereview.chromium.org/2300503003 . --- pkgs/test_reflective_loader/CHANGELOG.md | 4 + .../codereview.settings | 4 + .../lib/test_reflective_loader.dart | 111 +++++++++++++++--- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 4 files changed, 103 insertions(+), 18 deletions(-) create mode 100644 pkgs/test_reflective_loader/codereview.settings diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 2a2d63cf8..da6f2f79d 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.0.4 + +- Added @failingTest, @assertFailingTest and @soloTest annotations. + ## 0.0.1 - Initial version diff --git a/pkgs/test_reflective_loader/codereview.settings b/pkgs/test_reflective_loader/codereview.settings new file mode 100644 index 000000000..3ba713c75 --- /dev/null +++ b/pkgs/test_reflective_loader/codereview.settings @@ -0,0 +1,4 @@ +# This file is used by gcl to get repository specific information. +CODE_REVIEW_SERVER: http://codereview.chromium.org +VIEW_VC: https://github.com/dart-lang/test_reflective_loader/commit/ +CC_LIST: reviews@dartlang.org diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index f8387e34c..6e3c945a2 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -4,14 +4,50 @@ library test_reflective_loader; +import 'dart:async'; @MirrorsUsed(metaTargets: 'ReflectiveTest') import 'dart:mirrors'; -import 'dart:async'; import 'package:unittest/unittest.dart'; /** - * Define tests using methods existing in the given [type]. + * A marker annotation used to annotate overridden test methods (so we cannot + * rename them to `fail_`) which are expected to fail at `assert` in the + * checked mode. + */ +const _AssertFailingTest assertFailingTest = const _AssertFailingTest(); + +/** + * A marker annotation used to annotate overridden test methods (so we cannot + * rename them to `fail_`) which are expected to fail. + */ +const _FailingTest failingTest = const _FailingTest(); + +/** + * A marker annotation used to instruct dart2js to keep reflection information + * for the annotated classes. + */ +const ReflectiveTest reflectiveTest = const ReflectiveTest(); + +/** + * Test classes annotated with this annotation are run using [solo_group]. + */ +const _SoloTest soloTest = const _SoloTest(); + +/** + * Is `true` the application is running in the checked mode. + */ +final bool _isCheckedMode = () { + try { + assert(false); + return false; + } catch (_) { + return true; + } +}(); + +/** + * Runs test methods existing in the given [type]. * * Methods with names starting with `test` are run using [test] function. * Methods with names starting with `solo_test` are run using [solo_test] function. @@ -23,20 +59,20 @@ import 'package:unittest/unittest.dart'; * method invocation. * * If [type] declares method `tearDown`, it will be invoked after any test - * method invocation. If method returns [Future] to test some asyncronous + * method invocation. If method returns [Future] to test some asynchronous * behavior, then `tearDown` will be invoked in `Future.complete`. */ void defineReflectiveTests(Type type) { ClassMirror classMirror = reflectClass(type); if (!classMirror.metadata.any((InstanceMirror annotation) => - annotation.type.reflectedType == ReflectiveTest)) { + annotation.type.reflectedType == ReflectiveTest)) { String name = MirrorSystem.getName(classMirror.qualifiedName); throw new Exception('Class $name must have annotation "@reflectiveTest" ' 'in order to be run by runReflectiveTests.'); } - String className = MirrorSystem.getName(classMirror.simpleName); - group(className, () { - classMirror.instanceMembers.forEach((symbol, memberMirror) { + void runMembers() { + classMirror.instanceMembers + .forEach((Symbol symbol, MethodMirror memberMirror) { // we need only methods if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) { return; @@ -45,7 +81,12 @@ void defineReflectiveTests(Type type) { // test_ if (memberName.startsWith('test_')) { test(memberName, () { - return _runTest(classMirror, symbol); + if (_hasFailingTestAnnotation(memberMirror) || + _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { + return _runFailingTest(classMirror, symbol); + } else { + return _runTest(classMirror, symbol); + } }); return; } @@ -68,19 +109,36 @@ void defineReflectiveTests(Type type) { }); } }); - }); + } + String className = MirrorSystem.getName(classMirror.simpleName); + if (_hasAnnotationInstance(classMirror, soloTest)) { + solo_group(className, runMembers); + } else { + group(className, runMembers); + } } +bool _hasAnnotationInstance(DeclarationMirror declaration, instance) => + declaration.metadata.any((InstanceMirror annotation) => + identical(annotation.reflectee, instance)); + +bool _hasAssertFailingTestAnnotation(MethodMirror method) => + _hasAnnotationInstance(method, assertFailingTest); + +bool _hasFailingTestAnnotation(MethodMirror method) => + _hasAnnotationInstance(method, failingTest); + Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { var invocationResult = null; + InstanceMirror closure; try { - invocationResult = instanceMirror.invoke(symbol, []).reflectee; + closure = instanceMirror.getField(symbol); } on NoSuchMethodError {} - if (invocationResult is Future) { - return invocationResult; - } else { - return new Future.value(invocationResult); + + if (closure is ClosureMirror) { + invocationResult = closure.apply([]).reflectee; } + return new Future.value(invocationResult); } /** @@ -115,7 +173,26 @@ class ReflectiveTest { } /** - * A marker annotation used to instruct dart2js to keep reflection information - * for the annotated classes. + * A marker annotation used to annotate overridden test methods (so we cannot + * rename them to `fail_`) which are expected to fail at `assert` in the + * checked mode. */ -const ReflectiveTest reflectiveTest = const ReflectiveTest(); +class _AssertFailingTest { + const _AssertFailingTest(); +} + +/** + * A marker annotation used to annotate overridden test methods (so we cannot + * rename them to `fail_`) which are expected to fail. + */ +class _FailingTest { + const _FailingTest(); +} + +/** + * A marker annotation used to annotate a test class to run it using + * [solo_group]. + */ +class _SoloTest { + const _SoloTest(); +} diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 60d4ec8d0..8b93c1eaf 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.0.3 +version: 0.0.4 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From 4e43b6af71c194f214ea7bb68e36fff512b02285 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 29 Sep 2016 12:49:28 -0700 Subject: [PATCH 0278/1215] Don't treat Dartium as a JS context. (dart-lang/stack_trace#12) --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/utils.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 21fd73454..70b514764 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.7 + +* Fix a bug where `new Frame.caller()` returned the wrong depth of frame on + Dartium. + ## 1.6.6 * `new Trace.current()` and `new Chain.current()` now skip an extra frame when diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index b06d462aa..6d23728c0 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -10,7 +10,7 @@ const chainGap = '===== asynchronous gap ===========================\n'; // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. -final bool inJS = p.style == p.Style.url; +final bool inJS = 0.0 is int; /// Returns [string] with enough spaces added to the end to make it [length] /// characters long. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 06c9d3c48..e23c6d6be 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.6 +version: 1.6.7 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From 1cb057a61e89f0fb5361722182be8cae99c5a1f6 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 3 Oct 2016 17:07:35 -0700 Subject: [PATCH 0279/1215] Fix analysis hints. (dart-lang/stack_trace#13) Also get rid of an outdated util method. --- pkgs/stack_trace/lib/src/chain.dart | 5 ++--- pkgs/stack_trace/lib/src/trace.dart | 2 +- pkgs/stack_trace/lib/src/utils.dart | 16 ---------------- pkgs/stack_trace/lib/src/vm_trace.dart | 3 +-- pkgs/stack_trace/pubspec.yaml | 2 +- 5 files changed, 5 insertions(+), 23 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index fdb091702..656846463 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -77,8 +77,7 @@ class Chain implements StackTrace { }; } - // TODO(rnystrom): Remove this cast if runZoned() gets a generic type. - return runZoned(callback, onError: newOnError) as dynamic/*=T*/; + return runZoned(callback, onError: newOnError); } var spec = new StackZoneSpecification(onError); @@ -207,7 +206,7 @@ class Chain implements StackTrace { // padding is consistent across all traces. return traces.map((trace) { return trace.frames.map((frame) { - return '${padRight(frame.location, longest)} ${frame.member}\n'; + return '${frame.location.padRight(longest)} ${frame.member}\n'; }).join(); }).join(chainGap); } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 20343ad5a..1a53071fe 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -291,7 +291,7 @@ class Trace implements StackTrace { // Print out the stack trace nicely formatted. return frames.map((frame) { if (frame is UnparsedFrame) return "$frame\n"; - return '${padRight(frame.location, longest)} ${frame.member}\n'; + return '${frame.location.padRight(longest)} ${frame.member}\n'; }).join(); } } diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 6d23728c0..51897602f 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -2,8 +2,6 @@ // 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. -import 'package:path/path.dart' as p; - /// The line used in the string representation of stack chains to represent /// the gap between traces. const chainGap = '===== asynchronous gap ===========================\n'; @@ -11,17 +9,3 @@ const chainGap = '===== asynchronous gap ===========================\n'; // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. final bool inJS = 0.0 is int; - -/// Returns [string] with enough spaces added to the end to make it [length] -/// characters long. -String padRight(String string, int length) { - if (string.length >= length) return string; - - var result = new StringBuffer(); - result.write(string); - for (var i = 0; i < length - string.length; i++) { - result.write(' '); - } - - return result.toString(); -} diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 84fcb10bb..7086df700 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'frame.dart'; -import 'utils.dart'; /// An implementation of [StackTrace] that emulates the behavior of the VM's /// implementation. @@ -19,7 +18,7 @@ class VMTrace implements StackTrace { String toString() { var i = 1; return frames.map((frame) { - var number = padRight("#${i++}", 8); + var number = "#${i++}".padRight(8); var member = frame.member .replaceAllMapped(new RegExp(r"[^.]+\."), (match) => "${match[1]}.<${match[1]}_async_body>") diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index e23c6d6be..d46689cfe 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.7 +version: 1.6.8-dev author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From 7cbedea9e7d1fa4e1b6092cb2fca6d5dbb162856 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 4 Oct 2016 12:48:15 -0700 Subject: [PATCH 0280/1215] Switch to 'test', add different support for 'solo'. R=brianwilkerson@google.com, paulberry@google.com BUG= Review URL: https://codereview.chromium.org/2388073004 . --- pkgs/test_reflective_loader/CHANGELOG.md | 7 + .../lib/test_reflective_loader.dart | 204 +++++++++++++----- pkgs/test_reflective_loader/pubspec.yaml | 4 +- 3 files changed, 164 insertions(+), 51 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index da6f2f79d..49931bb3b 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## 0.1.0 + +- Switched from 'package:unittest' to 'package:test'. +- Since 'package:test' does not define 'solo_test', in order to keep + this functionality, `defineReflectiveSuite` must be used to wrap + all `defineReflectiveTests` invocations. + ## 0.0.4 - Added @failingTest, @assertFailingTest and @soloTest annotations. diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 6e3c945a2..375f5843c 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -8,7 +8,7 @@ import 'dart:async'; @MirrorsUsed(metaTargets: 'ReflectiveTest') import 'dart:mirrors'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart' as test_package; /** * A marker annotation used to annotate overridden test methods (so we cannot @@ -30,10 +30,14 @@ const _FailingTest failingTest = const _FailingTest(); const ReflectiveTest reflectiveTest = const ReflectiveTest(); /** - * Test classes annotated with this annotation are run using [solo_group]. + * A marker annotation used to annotate "solo" groups and tests. */ const _SoloTest soloTest = const _SoloTest(); +final List<_Group> _currentGroups = <_Group>[]; +int _currentSuiteLevel = 0; +String _currentSuiteName = null; + /** * Is `true` the application is running in the checked mode. */ @@ -46,11 +50,34 @@ final bool _isCheckedMode = () { } }(); +/** + * Run the [define] function parameter that calls [defineReflectiveTests] to + * add normal and "solo" tests, and also calls [defineReflectiveSuite] to + * create embedded suites. If the current suite is the top-level one, perform + * check for "solo" groups and tests, and run all or only "solo" items. + */ +void defineReflectiveSuite(void define(), {String name}) { + String groupName = _currentSuiteName; + _currentSuiteLevel++; + try { + _currentSuiteName = _combineNames(_currentSuiteName, name); + define(); + } finally { + _currentSuiteName = groupName; + _currentSuiteLevel--; + } + _addTestsIfTopLevelSuite(); +} + /** * Runs test methods existing in the given [type]. * - * Methods with names starting with `test` are run using [test] function. - * Methods with names starting with `solo_test` are run using [solo_test] function. + * If there is a "solo" test method in the top-level suite, only "solo" methods + * are run. + * + * If there is a "solo" test type, only its test methods are run. + * + * Otherwise all tests methods of all test types are run. * * Each method is run with a new instance of [type]. * So, [type] should have a default constructor. @@ -65,56 +92,105 @@ final bool _isCheckedMode = () { void defineReflectiveTests(Type type) { ClassMirror classMirror = reflectClass(type); if (!classMirror.metadata.any((InstanceMirror annotation) => - annotation.type.reflectedType == ReflectiveTest)) { + annotation.type.reflectedType == ReflectiveTest)) { String name = MirrorSystem.getName(classMirror.qualifiedName); throw new Exception('Class $name must have annotation "@reflectiveTest" ' 'in order to be run by runReflectiveTests.'); } - void runMembers() { - classMirror.instanceMembers - .forEach((Symbol symbol, MethodMirror memberMirror) { - // we need only methods - if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) { - return; - } - String memberName = MirrorSystem.getName(symbol); - // test_ - if (memberName.startsWith('test_')) { - test(memberName, () { - if (_hasFailingTestAnnotation(memberMirror) || - _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { - return _runFailingTest(classMirror, symbol); - } else { - return _runTest(classMirror, symbol); - } - }); - return; - } - // solo_test_ - if (memberName.startsWith('solo_test_')) { - solo_test(memberName, () { - return _runTest(classMirror, symbol); - }); - } - // fail_test_ - if (memberName.startsWith('fail_')) { - test(memberName, () { - return _runFailingTest(classMirror, symbol); - }); - } - // solo_fail_test_ - if (memberName.startsWith('solo_fail_')) { - solo_test(memberName, () { + + _Group group; + { + bool isSolo = _hasAnnotationInstance(classMirror, soloTest); + String className = MirrorSystem.getName(classMirror.simpleName); + group = new _Group(isSolo, _combineNames(_currentSuiteName, className)); + _currentGroups.add(group); + } + + classMirror.instanceMembers + .forEach((Symbol symbol, MethodMirror memberMirror) { + // we need only methods + if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) { + return; + } + // prepare information about the method + String memberName = MirrorSystem.getName(symbol); + bool isSolo = memberName.startsWith('solo_') || + _hasAnnotationInstance(memberMirror, soloTest); + // test_ + if (memberName.startsWith('test_')) { + group.addTest(isSolo, memberName, () { + if (_hasFailingTestAnnotation(memberMirror) || + _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { return _runFailingTest(classMirror, symbol); - }); + } else { + return _runTest(classMirror, symbol); + } + }); + return; + } + // solo_test_ + if (memberName.startsWith('solo_test_')) { + group.addTest(true, memberName, () { + return _runTest(classMirror, symbol); + }); + } + // fail_test_ + if (memberName.startsWith('fail_')) { + group.addTest(isSolo, memberName, () { + return _runFailingTest(classMirror, symbol); + }); + } + // solo_fail_test_ + if (memberName.startsWith('solo_fail_')) { + group.addTest(true, memberName, () { + return _runFailingTest(classMirror, symbol); + }); + } + }); + + // Support for the case of missing enclosing [defineReflectiveSuite]. + _addTestsIfTopLevelSuite(); +} + +/** + * If the current suite is the top-level one, add tests to the `test` package. + */ +void _addTestsIfTopLevelSuite() { + if (_currentSuiteLevel == 0) { + void runTests({bool allGroups, bool allTests}) { + for (_Group group in _currentGroups) { + if (allGroups || group.isSolo) { + for (_Test test in group.tests) { + if (allTests || test.isSolo) { + test_package.test(test.name, test.function); + } + } + } } - }); + } + + if (_currentGroups.any((g) => g.hasSoloTest)) { + runTests(allGroups: true, allTests: false); + } else if (_currentGroups.any((g) => g.isSolo)) { + runTests(allGroups: false, allTests: true); + } else { + runTests(allGroups: true, allTests: true); + } + _currentGroups.clear(); } - String className = MirrorSystem.getName(classMirror.simpleName); - if (_hasAnnotationInstance(classMirror, soloTest)) { - solo_group(className, runMembers); +} + +/** + * Return the combination of the [base] and [addition] names. + * If any other two is `null`, then the other one is returned. + */ +String _combineNames(String base, String addition) { + if (base == null) { + return addition; + } else if (addition == null) { + return base; } else { - group(className, runMembers); + return '$base | $addition'; } } @@ -153,7 +229,7 @@ Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { */ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { return new Future(() => _runTest(classMirror, symbol)).then((_) { - fail('Test passed - expected to fail.'); + test_package.fail('Test passed - expected to fail.'); }, onError: (_) {}); } @@ -164,6 +240,8 @@ _runTest(ClassMirror classMirror, Symbol symbol) { .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); } +typedef _TestFunction(); + /** * A marker annotation used to instruct dart2js to keep reflection information * for the annotated classes. @@ -190,9 +268,37 @@ class _FailingTest { } /** - * A marker annotation used to annotate a test class to run it using - * [solo_group]. + * Information about a type based test group. + */ +class _Group { + final bool isSolo; + final String name; + final List<_Test> tests = <_Test>[]; + + _Group(this.isSolo, this.name); + + bool get hasSoloTest => tests.any((test) => test.isSolo); + + void addTest(bool isSolo, String name, _TestFunction function) { + String fullName = _combineNames(this.name, name); + tests.add(new _Test(isSolo, fullName, function)); + } +} + +/** + * A marker annotation used to annotate "solo" groups and tests. */ class _SoloTest { const _SoloTest(); } + +/** + * Information about a test. + */ +class _Test { + final bool isSolo; + final String name; + final _TestFunction function; + + _Test(this.isSolo, this.name, this.function); +} diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 8b93c1eaf..9373aec3b 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.0.4 +version: 0.1.0 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader @@ -8,4 +8,4 @@ environment: sdk: '>=1.0.0 <2.0.0' dev_dependencies: - unittest: '>=0.9.0 <0.12.0' + test: ^0.12.0 From 010aefee859c2c82922a2d91d489089c73456b0f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 10 Oct 2016 14:37:21 -0700 Subject: [PATCH 0281/1215] Document that terse doesn't work with JS traces. (dart-lang/stack_trace#15) Closes dart-lang/stack_trace#14 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 7 +++++++ pkgs/stack_trace/lib/src/trace.dart | 7 +++++++ pkgs/stack_trace/pubspec.yaml | 2 +- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 70b514764..7182baff6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.8 + +* Add a note to the documentation of `Chain.terse` and `Trace.terse`. + ## 1.6.7 * Fix a bug where `new Frame.caller()` returned the wrong depth of frame on diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 656846463..3d1e1fc01 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -150,6 +150,13 @@ class Chain implements StackTrace { /// /// This calls [Trace.terse] on every trace in [traces], and discards any /// trace that contain only internal frames. + /// + /// This won't do anything with a raw JavaScript trace, since there's no way + /// to determine which frames come from which Dart libraries. However, the + /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to + /// convert JavaScript traces into Dart-style traces. + /// + /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace Chain get terse => foldFrames((_) => false, terse: true); /// Returns a new [Chain] based on [this] where multiple stack frames matching diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 1a53071fe..ad55fc79b 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -225,6 +225,13 @@ class Trace implements StackTrace { /// removed. If the outermost frame of the stack trace is a core library /// frame, it's removed entirely. /// + /// This won't do anything with a raw JavaScript trace, since there's no way + /// to determine which frames come from which Dart libraries. However, the + /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to + /// convert JavaScript traces into Dart-style traces. + /// + /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace + /// /// For custom folding, see [foldFrames]. Trace get terse => foldFrames((_) => false, terse: true); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index d46689cfe..ff5a3c112 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.8-dev +version: 1.6.8 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From 553513c30fac4d98e1e1c4619d5902e4eaeb498a Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 Nov 2016 15:11:53 -0700 Subject: [PATCH 0282/1215] Fix the expectChar() error text. (dart-lang/string_scanner#3) --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/lib/src/string_scanner.dart | 2 +- pkgs/string_scanner/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 910d30ebc..fa4cb6e43 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Fix the error text emitted by `StringScanner.expectChar()`. + ## 1.0.0 * **Breaking change**: `StringScanner.error()`'s `length` argument now defaults diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index b9714ff68..5817d562f 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -116,7 +116,7 @@ class StringScanner { } } - _fail('Expected $name.'); + _fail(name); } /// If [pattern] matches at the current position of the string, scans forward diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 48ed59dbc..ac893e26d 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.0.0 +version: 1.0.1 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > From 51614446c2bdc1ee0199a1eefe123b6fb08d9828 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 15 Nov 2016 16:33:14 -0800 Subject: [PATCH 0283/1215] Add the ability to disable chain-tracking. (dart-lang/stack_trace#17) --- pkgs/stack_trace/CHANGELOG.md | 7 + pkgs/stack_trace/lib/src/chain.dart | 30 +++- .../lib/src/stack_zone_specification.dart | 79 ++++------ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 141 ++++++++++-------- pkgs/stack_trace/test/chain/dart2js_test.dart | 7 +- pkgs/stack_trace/test/chain/vm_test.dart | 7 +- 7 files changed, 146 insertions(+), 127 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 7182baff6..5d25eac43 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.7.0 + +* Add a `Chain.disable()` function that disables stack-chain tracking. + +* Fix a bug where `Chain.capture(..., when: false)` would throw if an error was + emitted without a stack trace. + ## 1.6.8 * Add a note to the documentation of `Chain.terse` and `Trace.terse`. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 3d1e1fc01..7045e194c 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -14,6 +14,9 @@ import 'utils.dart'; @Deprecated("Will be removed in stack_trace 2.0.0.") typedef void ChainHandler(error, Chain chain); +/// An opaque key used to track the current [StackZoneSpecification]. +final _specKey = new Object(); + /// A chain of stack traces. /// /// A stack chain is a collection of one or more stack traces that collectively @@ -43,8 +46,7 @@ class Chain implements StackTrace { final List traces; /// The [StackZoneSpecification] for the current zone. - static StackZoneSpecification get _currentSpec => - Zone.current[#stack_trace.stack_zone.spec]; + static StackZoneSpecification get _currentSpec => Zone.current[_specKey]; /// If [when] is `true`, runs [callback] in a [Zone] in which the current /// stack chain is tracked and automatically associated with (most) errors. @@ -73,7 +75,11 @@ class Chain implements StackTrace { var newOnError; if (onError != null) { newOnError = (error, stackTrace) { - onError(error, new Chain.forTrace(stackTrace)); + onError( + error, + stackTrace == null + ? new Chain.current() + : new Chain.forTrace(stackTrace)); }; } @@ -89,11 +95,27 @@ class Chain implements StackTrace { return Zone.current.handleUncaughtError(error, stackTrace); } }, zoneSpecification: spec.toSpec(), zoneValues: { - #stack_trace.stack_zone.spec: spec + _specKey: spec, + StackZoneSpecification.disableKey: false }) as dynamic/*=T*/; // TODO(rnystrom): Remove this cast if runZoned() gets a generic type. } + /// If [when] is `true` and this is called within a [Chain.capture] zone, runs + /// [callback] in a [Zone] in which chain capturing is disabled. + /// + /// If [callback] returns a value, it will be returned by [disable] as well. + static /*=T*/ disable/**/(/*=T*/ callback(), {bool when: true}) { + var zoneValues = when + ? { + _specKey: null, + StackZoneSpecification.disableKey: true + } + : null; + + return runZoned(callback, zoneValues: zoneValues); + } + /// Returns [futureOrStream] unmodified. /// /// Prior to Dart 1.7, this was necessary to ensure that stack traces for diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 3a9bf48e9..712524929 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -30,6 +30,15 @@ typedef void _ChainHandler(error, Chain chain); /// Since [ZoneSpecification] can't be extended or even implemented, in order to /// get a real [ZoneSpecification] instance it's necessary to call [toSpec]. class StackZoneSpecification { + /// An opaque object used as a zone value to disable chain tracking in a given + /// zone. + /// + /// If `Zone.current[disableKey]` is `true`, no stack chains will be tracked. + static final disableKey = new Object(); + + /// Whether chain-tracking is disabled in the current zone. + bool get _disabled => Zone.current[disableKey] == true; + /// The expando that associates stack chains with [StackTrace]s. /// /// The chains are associated with stack traces rather than errors themselves @@ -54,11 +63,11 @@ class StackZoneSpecification { /// Converts [this] to a real [ZoneSpecification]. ZoneSpecification toSpec() { return new ZoneSpecification( - handleUncaughtError: handleUncaughtError, - registerCallback: registerCallback, - registerUnaryCallback: registerUnaryCallback, - registerBinaryCallback: registerBinaryCallback, - errorCallback: errorCallback); + handleUncaughtError: _handleUncaughtError, + registerCallback: _registerCallback, + registerUnaryCallback: _registerUnaryCallback, + registerBinaryCallback: _registerBinaryCallback, + errorCallback: _errorCallback); } /// Returns the current stack chain. @@ -79,57 +88,20 @@ class StackZoneSpecification { return new _Node(trace, previous).toChain(); } - /// Ensures that an error emitted by [future] has the correct stack - /// information associated with it. - /// - /// By default, the first frame of the first trace will be the line where - /// [trackFuture] is called. If [level] is passed, the first trace will start - /// that many frames up instead. - Future trackFuture(Future future, [int level=0]) { - var completer = new Completer.sync(); - var node = _createNode(level + 1); - future.then(completer.complete).catchError((e, stackTrace) { - if (stackTrace == null) stackTrace = new Trace.current(); - if (stackTrace is! Chain && _chains[stackTrace] == null) { - _chains[stackTrace] = node; - } - completer.completeError(e, stackTrace); - }); - return completer.future; - } - - /// Ensures that any errors emitted by [stream] have the correct stack - /// information associated with them. - /// - /// By default, the first frame of the first trace will be the line where - /// [trackStream] is called. If [level] is passed, the first trace will start - /// that many frames up instead. - Stream trackStream(Stream stream, [int level=0]) { - var node = _createNode(level + 1); - return stream.transform(new StreamTransformer.fromHandlers( - handleError: (error, stackTrace, sink) { - if (stackTrace == null) stackTrace = new Trace.current(); - if (stackTrace is! Chain && _chains[stackTrace] == null) { - _chains[stackTrace] = node; - } - sink.addError(error, stackTrace); - })); - } - /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneCallback registerCallback(Zone self, ZoneDelegate parent, Zone zone, + ZoneCallback _registerCallback(Zone self, ZoneDelegate parent, Zone zone, Function f) { - if (f == null) return parent.registerCallback(zone, null); + if (f == null || _disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); } /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneUnaryCallback registerUnaryCallback(Zone self, ZoneDelegate parent, + ZoneUnaryCallback _registerUnaryCallback(Zone self, ZoneDelegate parent, Zone zone, Function f) { - if (f == null) return parent.registerUnaryCallback(zone, null); + if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { return _run(() => f(arg), node); @@ -138,9 +110,10 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneBinaryCallback registerBinaryCallback(Zone self, ZoneDelegate parent, + ZoneBinaryCallback _registerBinaryCallback(Zone self, ZoneDelegate parent, Zone zone, Function f) { - if (f == null) return parent.registerBinaryCallback(zone, null); + if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); + var node = _createNode(1); return parent.registerBinaryCallback(zone, (arg1, arg2) { return _run(() => f(arg1, arg2), node); @@ -149,8 +122,12 @@ class StackZoneSpecification { /// Looks up the chain associated with [stackTrace] and passes it either to /// [_onError] or [parent]'s error handler. - handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error, + _handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { + if (_disabled) { + return parent.handleUncaughtError(zone, error, stackTrace); + } + var stackChain = chainFor(stackTrace); if (_onError == null) { return parent.handleUncaughtError(zone, error, stackChain); @@ -171,8 +148,10 @@ class StackZoneSpecification { /// Attaches the current stack chain to [stackTrace], replacing it if /// necessary. - AsyncError errorCallback(Zone self, ZoneDelegate parent, Zone zone, + AsyncError _errorCallback(Zone self, ZoneDelegate parent, Zone zone, Object error, StackTrace stackTrace) { + if (_disabled) return parent.errorCallback(zone, error, stackTrace); + // Go up two levels to get through [_CustomZone.errorCallback]. if (stackTrace == null) { stackTrace = _createNode(2).toChain(); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index ff5a3c112..6984445a3 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.6.8 +version: 1.7.0 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 0824f4f76..301f338b2 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -8,6 +8,7 @@ import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; +import '../utils.dart'; import 'utils.dart'; typedef void ChainErrorCallback(stack, Chain chain); @@ -53,6 +54,82 @@ void main() { }) as ChainErrorCallback, when: false); // TODO(rnystrom): Remove this cast if expectAsync() gets a better type. }); + + test("doesn't enable chain-tracking", () { + return Chain.disable(() { + return Chain.capture(() { + var completer = new Completer(); + inMicrotask(() { + completer.complete(new Chain.current()); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(1)); + }); + }, when: false); + }); + }); + }); + + group("Chain.disable()", () { + test("disables chain-tracking", () { + return Chain.disable(() { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(1)); + }); + }); + }); + + test("Chain.capture() re-enables chain-tracking", () { + return Chain.disable(() { + return Chain.capture(() { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + }); + }); + }); + }); + + test("preserves parent zones of the capture zone", () { + // The outer disable call turns off the test package's chain-tracking. + return Chain.disable(() { + return runZoned(() { + return Chain.capture(() { + expect(Chain.disable(() => Zone.current[#enabled]), isTrue); + }); + }, zoneValues: {#enabled: true}); + }); + }); + + test("preserves child zones of the capture zone", () { + // The outer disable call turns off the test package's chain-tracking. + return Chain.disable(() { + return Chain.capture(() { + return runZoned(() { + expect(Chain.disable(() => Zone.current[#enabled]), isTrue); + }, zoneValues: {#enabled: true}); + }); + }); + }); + + test("with when: false doesn't disable", () { + return Chain.capture(() { + return Chain.disable(() { + var completer = new Completer(); + inMicrotask(() => completer.complete(new Chain.current())); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(2)); + }); + }, when: false); + }); + }); }); test("toString() ensures that all traces are aligned", () { @@ -248,68 +325,4 @@ void main() { '$userSlashCode 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n')); }); - - group('Chain.track(Future)', () { - test('forwards the future value within Chain.capture()', () { - Chain.capture(() { - expect(Chain.track(new Future.value('value')), - completion(equals('value'))); - - var trace = new Trace.current(); - expect(Chain.track(new Future.error('error', trace)) - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - test('forwards the future value outside of Chain.capture()', () { - expect(Chain.track(new Future.value('value')), - completion(equals('value'))); - - var trace = new Trace.current(); - expect(Chain.track(new Future.error('error', trace)) - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - group('Chain.track(Stream)', () { - test('forwards stream values within Chain.capture()', () { - Chain.capture(() { - var controller = new StreamController() - ..add(1)..add(2)..add(3)..close(); - expect(Chain.track(controller.stream).toList(), - completion(equals([1, 2, 3]))); - - var trace = new Trace.current(); - controller = new StreamController()..addError('error', trace); - expect(Chain.track(controller.stream).toList() - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - - test('forwards stream values outside of Chain.capture()', () { - Chain.capture(() { - var controller = new StreamController() - ..add(1)..add(2)..add(3)..close(); - expect(Chain.track(controller.stream).toList(), - completion(equals([1, 2, 3]))); - - var trace = new Trace.current(); - controller = new StreamController()..addError('error', trace); - expect(Chain.track(controller.stream).toList() - .catchError((e, stackTrace) { - expect(e, equals('error')); - expect(stackTrace.toString(), equals(trace.toString())); - }), completes); - }); - }); - }); } \ No newline at end of file diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index afb27fa04..b8d3a825d 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -240,9 +240,8 @@ void main() { test('current() outside of capture() returns a chain wrapping the current ' 'trace', () { - // The test runner runs all tests with chains enabled, so to test without we - // have to do some zone munging. - return runZoned(() async { + // The test runner runs all tests with chains enabled. + return Chain.disable(() async { var completer = new Completer(); inMicrotask(() => completer.complete(new Chain.current())); @@ -251,7 +250,7 @@ void main() { // chain isn't available and it just returns the current stack when // called. expect(chain.traces, hasLength(1)); - }, zoneValues: {#stack_trace.stack_zone.spec: null}); + }); }); group('forTrace() within capture()', () { diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 70635b754..716b146bc 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -351,9 +351,8 @@ void main() { test('current() outside of capture() returns a chain wrapping the current ' 'trace', () { - // The test runner runs all tests with chains enabled, so to test without we - // have to do some zone munging. - return runZoned(() { + // The test runner runs all tests with chains enabled. + return Chain.disable(() { var completer = new Completer(); inMicrotask(() => completer.complete(new Chain.current())); @@ -365,7 +364,7 @@ void main() { expect(chain.traces.first.frames.first, frameMember(startsWith('main'))); }); - }, zoneValues: {#stack_trace.stack_zone.spec: null}); + }); }); group('forTrace() within capture()', () { From 4df2eb1aae2bff2114e2403ab7850f512e279152 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 4 Jan 2017 14:47:49 -0800 Subject: [PATCH 0284/1215] Template files. --- pkgs/term_glyph/.gitignore | 9 +++++++++ pkgs/term_glyph/AUTHORS | 6 ++++++ pkgs/term_glyph/CHANGELOG.md | 3 +++ pkgs/term_glyph/CONTRIBUTING.md | 33 +++++++++++++++++++++++++++++++++ pkgs/term_glyph/LICENSE | 26 ++++++++++++++++++++++++++ pkgs/term_glyph/README.md | 3 +++ pkgs/term_glyph/pubspec.yaml | 8 ++++++++ 7 files changed, 88 insertions(+) create mode 100644 pkgs/term_glyph/.gitignore create mode 100644 pkgs/term_glyph/AUTHORS create mode 100644 pkgs/term_glyph/CHANGELOG.md create mode 100644 pkgs/term_glyph/CONTRIBUTING.md create mode 100644 pkgs/term_glyph/LICENSE create mode 100644 pkgs/term_glyph/README.md create mode 100644 pkgs/term_glyph/pubspec.yaml diff --git a/pkgs/term_glyph/.gitignore b/pkgs/term_glyph/.gitignore new file mode 100644 index 000000000..25a1df332 --- /dev/null +++ b/pkgs/term_glyph/.gitignore @@ -0,0 +1,9 @@ +.buildlog +.DS_Store +.idea +.pub/ +.settings/ +build/ +packages +.packages +pubspec.lock diff --git a/pkgs/term_glyph/AUTHORS b/pkgs/term_glyph/AUTHORS new file mode 100644 index 000000000..e8063a8cd --- /dev/null +++ b/pkgs/term_glyph/AUTHORS @@ -0,0 +1,6 @@ +# Below is a list of people and organizations that have contributed +# to the project. Names should be added to the list like so: +# +# Name/Organization + +Google Inc. diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md new file mode 100644 index 000000000..5b26ad30f --- /dev/null +++ b/pkgs/term_glyph/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +* Initial version. diff --git a/pkgs/term_glyph/CONTRIBUTING.md b/pkgs/term_glyph/CONTRIBUTING.md new file mode 100644 index 000000000..6f5e0ea67 --- /dev/null +++ b/pkgs/term_glyph/CONTRIBUTING.md @@ -0,0 +1,33 @@ +Want to contribute? Great! First, read this page (including the small print at +the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. + +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. + +### File headers +All files in the project must start with the following header. + + // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file + // 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. + +### The small print +Contributions made by corporations are covered by a different agreement than the +one above, the +[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/term_glyph/LICENSE b/pkgs/term_glyph/LICENSE new file mode 100644 index 000000000..389ce9856 --- /dev/null +++ b/pkgs/term_glyph/LICENSE @@ -0,0 +1,26 @@ +Copyright 2017, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md new file mode 100644 index 000000000..44458b06b --- /dev/null +++ b/pkgs/term_glyph/README.md @@ -0,0 +1,3 @@ +This library contains getters for useful semantic symbols. Because `cmd.exe` on +Windows can't display Unicode, it also provides a mode where the symbols are +replaced with plain-ASCII equivalents. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml new file mode 100644 index 000000000..275c2bfd8 --- /dev/null +++ b/pkgs/term_glyph/pubspec.yaml @@ -0,0 +1,8 @@ +name: symbol +version: 1.0.0-dev +description: Useful symbols and Windows-safe equivalents. +author: Dart Team +homepage: https://github.com/dart-lang/symbol + +environment: + sdk: '>=1.8.0 <2.0.0' From b38ee12b1689837dd72fbf867529dae06c865e07 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 5 Jan 2017 16:31:50 -0800 Subject: [PATCH 0285/1215] Add the package's contents. (dart-lang/term_glyph#1) --- pkgs/term_glyph/README.md | 45 +- pkgs/term_glyph/data.csv | 85 ++++ pkgs/term_glyph/lib/src/generated.dart | 564 +++++++++++++++++++++++++ pkgs/term_glyph/lib/term_glyph.dart | 12 + pkgs/term_glyph/pubspec.yaml | 13 +- pkgs/term_glyph/test/symbol_test.dart | 41 ++ pkgs/term_glyph/tool/generate.dart | 67 +++ 7 files changed, 820 insertions(+), 7 deletions(-) create mode 100644 pkgs/term_glyph/data.csv create mode 100644 pkgs/term_glyph/lib/src/generated.dart create mode 100644 pkgs/term_glyph/lib/term_glyph.dart create mode 100644 pkgs/term_glyph/test/symbol_test.dart create mode 100644 pkgs/term_glyph/tool/generate.dart diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md index 44458b06b..5459994ad 100644 --- a/pkgs/term_glyph/README.md +++ b/pkgs/term_glyph/README.md @@ -1,3 +1,42 @@ -This library contains getters for useful semantic symbols. Because `cmd.exe` on -Windows can't display Unicode, it also provides a mode where the symbols are -replaced with plain-ASCII equivalents. +This library contains getters for useful Unicode glyphs as well as plain ASCII +alternatives. It's intended to be used in command-line applications that may run +on Windows and libraries that may be used by those applications. + +We recommend that you import this library with the prefix "glyph". For example: + +```dart +import 'package:term_glyph/term_glyph.dart' as glyph; + +/// Formats [items] into a bulleted list, with one item per line. +String bulletedList(List items) => + items.map((item) => "${glyph.bullet} $item").join("\n"); +``` + +## ASCII Mode + +The default Windows `cmd.exe` shell is unable to display Unicode characters, so +this package is able to transparently switch its glyphs to ASCII alternatives by +setting [the `ascii` attribute][ascii]. When this attribute is `true`, all +glyphs use ASCII characters instead. It currently defaults to `false`, although +in the future it may default to `true` for applications running on the Dart VM +on Windows. For example: + +[ascii]: https://www.dartdocs.org/documentation/term_glyph/latest/term_glyph/ascii.html + +```dart +import 'dart:io'; + +import 'package:term_glyph/term_glyph.dart' as glyph; + +void main() { + glyph.ascii = Platform.isWindows; + + // Prints "Unicode => ASCII" on Windows, "Unicode ━▶ ASCII" everywhere else. + print("Unicode ${glyph.rightArrow} ASCII"); +} +``` + +All ASCII glyphs are guaranteed to be the same number of characters as the +corresponding Unicode glyphs, so that they line up properly when printed on a +terminal. The specific ASCII text for a given Unicode glyph may change over +time; this is not considered a breaking change. diff --git a/pkgs/term_glyph/data.csv b/pkgs/term_glyph/data.csv new file mode 100644 index 000000000..92a72f7bc --- /dev/null +++ b/pkgs/term_glyph/data.csv @@ -0,0 +1,85 @@ +# Miscellaneous +bullet,•,*,A bullet point. + +# Arrows +leftArrow,←,<,"A left-pointing arrow. + +Note that the Unicode arrow glyphs may overlap with adjacent characters in some +terminal fonts, and should generally be surrounding by spaces." +rightArrow,→,>,"A right-pointing arrow. + +Note that the Unicode arrow glyphs may overlap with adjacent characters in some +terminal fonts, and should generally be surrounding by spaces." +upArrow,↑,^,An upwards-pointing arrow. +downArrow,↓,v,A downwards-pointing arrow. +longLeftArrow,◀━,<=,A two-character left-pointing arrow. +longRightArrow,━▶,=>,A two-character right-pointing arrow. + +# Box drawing characters + +## Normal +horizontalLine,─,-,A horizontal line that can be used to draw a box. +verticalLine,│,|,A vertical line that can be used to draw a box. +topLeftCorner,┌,",",The upper left-hand corner of a box. +topRightCorner,┐,",",The upper right-hand corner of a box. +bottomLeftCorner,└,',The lower left-hand corner of a box. +bottomRightCorner,┘,',The lower right-hand corner of a box. +cross,┼,+,An intersection of vertical and horizontal box lines. +teeUp,┴,+,A horizontal box line with a vertical line going up from the middle. +teeDown,┬,+,A horizontal box line with a vertical line going down from the middle. +teeLeft,┤,+,A vertical box line with a horizontal line going left from the middle. +teeRight,├,+,A vertical box line with a horizontal line going right from the middle. +upEnd,╵,',The top half of a vertical box line. +downEnd,╷,",",The bottom half of a vertical box line. +leftEnd,╴,-,The left half of a horizontal box line. +rightEnd,╶,-,The right half of a horizontal box line. + +## Bold +horizontalLineBold,━,=,A bold horizontal line that can be used to draw a box. +verticalLineBold,┃,|,A bold vertical line that can be used to draw a box. +topLeftCornerBold,┏,",",The bold upper left-hand corner of a box. +topRightCornerBold,┓,",",The bold upper right-hand corner of a box. +bottomLeftCornerBold,┗,',The bold lower left-hand corner of a box. +bottomRightCornerBold,┛,',The bold lower right-hand corner of a box. +crossBold,╋,+,An intersection of bold vertical and horizontal box lines. +teeUpBold,┻,+,A bold horizontal box line with a vertical line going up from the middle. +teeDownBold,┳,+,A bold horizontal box line with a vertical line going down from the middle. +teeLeftBold,┫,+,A bold vertical box line with a horizontal line going left from the middle. +teeRightBold,┣,+,A bold vertical box line with a horizontal line going right from the middle. +upEndBold,╹,',The top half of a bold vertical box line. +downEndBold,╻,",",The bottom half of a bold vertical box line. +leftEndBold,╸,-,The left half of a bold horizontal box line. +rightEndBold,╺,-,The right half of a bold horizontal box line. + +## Double +horizontalLineDouble,═,=,A double horizontal line that can be used to draw a box. +verticalLineDouble,║,|,A double vertical line that can be used to draw a box. +topLeftCornerDouble,╔,",",The double upper left-hand corner of a box. +topRightCornerDouble,╗,",",The double upper right-hand corner of a box. +bottomLeftCornerDouble,╚,"""",The double lower left-hand corner of a box. +bottomRightCornerDouble,╝,"""",The double lower right-hand corner of a box. +crossDouble,╬,+,An intersection of double vertical and horizontal box lines. +teeUpDouble,╩,+,A double horizontal box line with a vertical line going up from the middle. +teeDownDouble,╦,+,A double horizontal box line with a vertical line going down from the middle. +teeLeftDouble,╣,+,A double vertical box line with a horizontal line going left from the middle. +teeRightDouble,╠,+,A double vertical box line with a horizontal line going right from the middle. + +## Dashed + +### Double +horizontalLineDoubleDash,╌,-,A dashed horizontal line that can be used to draw a box. +horizontalLineDoubleDashBold,╍,-,A bold dashed horizontal line that can be used to draw a box. +verticalLineDoubleDash,╎,|,A dashed vertical line that can be used to draw a box. +verticalLineDoubleDashBold,╏,|,A bold dashed vertical line that can be used to draw a box. + +### Triple +horizontalLineTripleDash,┄,-,A dashed horizontal line that can be used to draw a box. +horizontalLineTripleDashBold,┅,-,A bold dashed horizontal line that can be used to draw a box. +verticalLineTripleDash,┆,|,A dashed vertical line that can be used to draw a box. +verticalLineTripleDashBold,┇,|,A bold dashed vertical line that can be used to draw a box. + +### Quadruple +horizontalLineQuadrupleDash,┈,-,A dashed horizontal line that can be used to draw a box. +horizontalLineQuadrupleDashBold,┉,-,A bold dashed horizontal line that can be used to draw a box. +verticalLineQuadrupleDash,┊,|,A dashed vertical line that can be used to draw a box. +verticalLineQuadrupleDashBold,┋,|,A bold dashed vertical line that can be used to draw a box. diff --git a/pkgs/term_glyph/lib/src/generated.dart b/pkgs/term_glyph/lib/src/generated.dart new file mode 100644 index 000000000..e1b83d196 --- /dev/null +++ b/pkgs/term_glyph/lib/src/generated.dart @@ -0,0 +1,564 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +// Don't modify this file by hand! It's generated by tool/generate.dart. + +/// Whether the glyph getters return plain ASCII, as opposed to Unicode +/// characters or sequences. +/// +/// Defaults to `false`. +bool get ascii => _ascii; +var _ascii = false; +set ascii(bool value) { + _ascii = value; + if (value) { + _bullet = "*"; + _leftArrow = "<"; + _rightArrow = ">"; + _upArrow = "^"; + _downArrow = "v"; + _longLeftArrow = "<="; + _longRightArrow = "=>"; + _horizontalLine = "-"; + _verticalLine = "|"; + _topLeftCorner = ","; + _topRightCorner = ","; + _bottomLeftCorner = "'"; + _bottomRightCorner = "'"; + _cross = "+"; + _teeUp = "+"; + _teeDown = "+"; + _teeLeft = "+"; + _teeRight = "+"; + _upEnd = "'"; + _downEnd = ","; + _leftEnd = "-"; + _rightEnd = "-"; + _horizontalLineBold = "="; + _verticalLineBold = "|"; + _topLeftCornerBold = ","; + _topRightCornerBold = ","; + _bottomLeftCornerBold = "'"; + _bottomRightCornerBold = "'"; + _crossBold = "+"; + _teeUpBold = "+"; + _teeDownBold = "+"; + _teeLeftBold = "+"; + _teeRightBold = "+"; + _upEndBold = "'"; + _downEndBold = ","; + _leftEndBold = "-"; + _rightEndBold = "-"; + _horizontalLineDouble = "="; + _verticalLineDouble = "|"; + _topLeftCornerDouble = ","; + _topRightCornerDouble = ","; + _bottomLeftCornerDouble = '"'; + _bottomRightCornerDouble = '"'; + _crossDouble = "+"; + _teeUpDouble = "+"; + _teeDownDouble = "+"; + _teeLeftDouble = "+"; + _teeRightDouble = "+"; + _horizontalLineDoubleDash = "-"; + _horizontalLineDoubleDashBold = "-"; + _verticalLineDoubleDash = "|"; + _verticalLineDoubleDashBold = "|"; + _horizontalLineTripleDash = "-"; + _horizontalLineTripleDashBold = "-"; + _verticalLineTripleDash = "|"; + _verticalLineTripleDashBold = "|"; + _horizontalLineQuadrupleDash = "-"; + _horizontalLineQuadrupleDashBold = "-"; + _verticalLineQuadrupleDash = "|"; + _verticalLineQuadrupleDashBold = "|"; + } else { + _bullet = "•"; + _leftArrow = "←"; + _rightArrow = "→"; + _upArrow = "↑"; + _downArrow = "↓"; + _longLeftArrow = "◀━"; + _longRightArrow = "━▶"; + _horizontalLine = "─"; + _verticalLine = "│"; + _topLeftCorner = "┌"; + _topRightCorner = "┐"; + _bottomLeftCorner = "└"; + _bottomRightCorner = "┘"; + _cross = "┼"; + _teeUp = "┴"; + _teeDown = "┬"; + _teeLeft = "┤"; + _teeRight = "├"; + _upEnd = "╵"; + _downEnd = "╷"; + _leftEnd = "╴"; + _rightEnd = "╶"; + _horizontalLineBold = "━"; + _verticalLineBold = "┃"; + _topLeftCornerBold = "┏"; + _topRightCornerBold = "┓"; + _bottomLeftCornerBold = "┗"; + _bottomRightCornerBold = "┛"; + _crossBold = "╋"; + _teeUpBold = "┻"; + _teeDownBold = "┳"; + _teeLeftBold = "┫"; + _teeRightBold = "┣"; + _upEndBold = "╹"; + _downEndBold = "╻"; + _leftEndBold = "╸"; + _rightEndBold = "╺"; + _horizontalLineDouble = "═"; + _verticalLineDouble = "║"; + _topLeftCornerDouble = "╔"; + _topRightCornerDouble = "╗"; + _bottomLeftCornerDouble = "╚"; + _bottomRightCornerDouble = "╝"; + _crossDouble = "╬"; + _teeUpDouble = "╩"; + _teeDownDouble = "╦"; + _teeLeftDouble = "╣"; + _teeRightDouble = "╠"; + _horizontalLineDoubleDash = "╌"; + _horizontalLineDoubleDashBold = "╍"; + _verticalLineDoubleDash = "╎"; + _verticalLineDoubleDashBold = "╏"; + _horizontalLineTripleDash = "┄"; + _horizontalLineTripleDashBold = "┅"; + _verticalLineTripleDash = "┆"; + _verticalLineTripleDashBold = "┇"; + _horizontalLineQuadrupleDash = "┈"; + _horizontalLineQuadrupleDashBold = "┉"; + _verticalLineQuadrupleDash = "┊"; + _verticalLineQuadrupleDashBold = "┋"; + } +} + +/// A bullet point. +/// +/// If [ascii] is `false`, this is "•". If it's `true`, this is +/// "*" instead. +String get bullet => _bullet; +var _bullet = "•"; + +/// A left-pointing arrow. +/// +/// Note that the Unicode arrow glyphs may overlap with adjacent characters in some +/// terminal fonts, and should generally be surrounding by spaces. +/// +/// If [ascii] is `false`, this is "←". If it's `true`, this is +/// "<" instead. +String get leftArrow => _leftArrow; +var _leftArrow = "←"; + +/// A right-pointing arrow. +/// +/// Note that the Unicode arrow glyphs may overlap with adjacent characters in some +/// terminal fonts, and should generally be surrounding by spaces. +/// +/// If [ascii] is `false`, this is "→". If it's `true`, this is +/// ">" instead. +String get rightArrow => _rightArrow; +var _rightArrow = "→"; + +/// An upwards-pointing arrow. +/// +/// If [ascii] is `false`, this is "↑". If it's `true`, this is +/// "^" instead. +String get upArrow => _upArrow; +var _upArrow = "↑"; + +/// A downwards-pointing arrow. +/// +/// If [ascii] is `false`, this is "↓". If it's `true`, this is +/// "v" instead. +String get downArrow => _downArrow; +var _downArrow = "↓"; + +/// A two-character left-pointing arrow. +/// +/// If [ascii] is `false`, this is "◀━". If it's `true`, this is +/// "<=" instead. +String get longLeftArrow => _longLeftArrow; +var _longLeftArrow = "◀━"; + +/// A two-character right-pointing arrow. +/// +/// If [ascii] is `false`, this is "━▶". If it's `true`, this is +/// "=>" instead. +String get longRightArrow => _longRightArrow; +var _longRightArrow = "━▶"; + +/// A horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "─". If it's `true`, this is +/// "-" instead. +String get horizontalLine => _horizontalLine; +var _horizontalLine = "─"; + +/// A vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "│". If it's `true`, this is +/// "|" instead. +String get verticalLine => _verticalLine; +var _verticalLine = "│"; + +/// The upper left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┌". If it's `true`, this is +/// "," instead. +String get topLeftCorner => _topLeftCorner; +var _topLeftCorner = "┌"; + +/// The upper right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┐". If it's `true`, this is +/// "," instead. +String get topRightCorner => _topRightCorner; +var _topRightCorner = "┐"; + +/// The lower left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "└". If it's `true`, this is +/// "'" instead. +String get bottomLeftCorner => _bottomLeftCorner; +var _bottomLeftCorner = "└"; + +/// The lower right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┘". If it's `true`, this is +/// "'" instead. +String get bottomRightCorner => _bottomRightCorner; +var _bottomRightCorner = "┘"; + +/// An intersection of vertical and horizontal box lines. +/// +/// If [ascii] is `false`, this is "┼". If it's `true`, this is +/// "+" instead. +String get cross => _cross; +var _cross = "┼"; + +/// A horizontal box line with a vertical line going up from the middle. +/// +/// If [ascii] is `false`, this is "┴". If it's `true`, this is +/// "+" instead. +String get teeUp => _teeUp; +var _teeUp = "┴"; + +/// A horizontal box line with a vertical line going down from the middle. +/// +/// If [ascii] is `false`, this is "┬". If it's `true`, this is +/// "+" instead. +String get teeDown => _teeDown; +var _teeDown = "┬"; + +/// A vertical box line with a horizontal line going left from the middle. +/// +/// If [ascii] is `false`, this is "┤". If it's `true`, this is +/// "+" instead. +String get teeLeft => _teeLeft; +var _teeLeft = "┤"; + +/// A vertical box line with a horizontal line going right from the middle. +/// +/// If [ascii] is `false`, this is "├". If it's `true`, this is +/// "+" instead. +String get teeRight => _teeRight; +var _teeRight = "├"; + +/// The top half of a vertical box line. +/// +/// If [ascii] is `false`, this is "╵". If it's `true`, this is +/// "'" instead. +String get upEnd => _upEnd; +var _upEnd = "╵"; + +/// The bottom half of a vertical box line. +/// +/// If [ascii] is `false`, this is "╷". If it's `true`, this is +/// "," instead. +String get downEnd => _downEnd; +var _downEnd = "╷"; + +/// The left half of a horizontal box line. +/// +/// If [ascii] is `false`, this is "╴". If it's `true`, this is +/// "-" instead. +String get leftEnd => _leftEnd; +var _leftEnd = "╴"; + +/// The right half of a horizontal box line. +/// +/// If [ascii] is `false`, this is "╶". If it's `true`, this is +/// "-" instead. +String get rightEnd => _rightEnd; +var _rightEnd = "╶"; + +/// A bold horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "━". If it's `true`, this is +/// "=" instead. +String get horizontalLineBold => _horizontalLineBold; +var _horizontalLineBold = "━"; + +/// A bold vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┃". If it's `true`, this is +/// "|" instead. +String get verticalLineBold => _verticalLineBold; +var _verticalLineBold = "┃"; + +/// The bold upper left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┏". If it's `true`, this is +/// "," instead. +String get topLeftCornerBold => _topLeftCornerBold; +var _topLeftCornerBold = "┏"; + +/// The bold upper right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┓". If it's `true`, this is +/// "," instead. +String get topRightCornerBold => _topRightCornerBold; +var _topRightCornerBold = "┓"; + +/// The bold lower left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┗". If it's `true`, this is +/// "'" instead. +String get bottomLeftCornerBold => _bottomLeftCornerBold; +var _bottomLeftCornerBold = "┗"; + +/// The bold lower right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "┛". If it's `true`, this is +/// "'" instead. +String get bottomRightCornerBold => _bottomRightCornerBold; +var _bottomRightCornerBold = "┛"; + +/// An intersection of bold vertical and horizontal box lines. +/// +/// If [ascii] is `false`, this is "╋". If it's `true`, this is +/// "+" instead. +String get crossBold => _crossBold; +var _crossBold = "╋"; + +/// A bold horizontal box line with a vertical line going up from the middle. +/// +/// If [ascii] is `false`, this is "┻". If it's `true`, this is +/// "+" instead. +String get teeUpBold => _teeUpBold; +var _teeUpBold = "┻"; + +/// A bold horizontal box line with a vertical line going down from the middle. +/// +/// If [ascii] is `false`, this is "┳". If it's `true`, this is +/// "+" instead. +String get teeDownBold => _teeDownBold; +var _teeDownBold = "┳"; + +/// A bold vertical box line with a horizontal line going left from the middle. +/// +/// If [ascii] is `false`, this is "┫". If it's `true`, this is +/// "+" instead. +String get teeLeftBold => _teeLeftBold; +var _teeLeftBold = "┫"; + +/// A bold vertical box line with a horizontal line going right from the middle. +/// +/// If [ascii] is `false`, this is "┣". If it's `true`, this is +/// "+" instead. +String get teeRightBold => _teeRightBold; +var _teeRightBold = "┣"; + +/// The top half of a bold vertical box line. +/// +/// If [ascii] is `false`, this is "╹". If it's `true`, this is +/// "'" instead. +String get upEndBold => _upEndBold; +var _upEndBold = "╹"; + +/// The bottom half of a bold vertical box line. +/// +/// If [ascii] is `false`, this is "╻". If it's `true`, this is +/// "," instead. +String get downEndBold => _downEndBold; +var _downEndBold = "╻"; + +/// The left half of a bold horizontal box line. +/// +/// If [ascii] is `false`, this is "╸". If it's `true`, this is +/// "-" instead. +String get leftEndBold => _leftEndBold; +var _leftEndBold = "╸"; + +/// The right half of a bold horizontal box line. +/// +/// If [ascii] is `false`, this is "╺". If it's `true`, this is +/// "-" instead. +String get rightEndBold => _rightEndBold; +var _rightEndBold = "╺"; + +/// A double horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "═". If it's `true`, this is +/// "=" instead. +String get horizontalLineDouble => _horizontalLineDouble; +var _horizontalLineDouble = "═"; + +/// A double vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "║". If it's `true`, this is +/// "|" instead. +String get verticalLineDouble => _verticalLineDouble; +var _verticalLineDouble = "║"; + +/// The double upper left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "╔". If it's `true`, this is +/// "," instead. +String get topLeftCornerDouble => _topLeftCornerDouble; +var _topLeftCornerDouble = "╔"; + +/// The double upper right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "╗". If it's `true`, this is +/// "," instead. +String get topRightCornerDouble => _topRightCornerDouble; +var _topRightCornerDouble = "╗"; + +/// The double lower left-hand corner of a box. +/// +/// If [ascii] is `false`, this is "╚". If it's `true`, this is +/// """ instead. +String get bottomLeftCornerDouble => _bottomLeftCornerDouble; +var _bottomLeftCornerDouble = "╚"; + +/// The double lower right-hand corner of a box. +/// +/// If [ascii] is `false`, this is "╝". If it's `true`, this is +/// """ instead. +String get bottomRightCornerDouble => _bottomRightCornerDouble; +var _bottomRightCornerDouble = "╝"; + +/// An intersection of double vertical and horizontal box lines. +/// +/// If [ascii] is `false`, this is "╬". If it's `true`, this is +/// "+" instead. +String get crossDouble => _crossDouble; +var _crossDouble = "╬"; + +/// A double horizontal box line with a vertical line going up from the middle. +/// +/// If [ascii] is `false`, this is "╩". If it's `true`, this is +/// "+" instead. +String get teeUpDouble => _teeUpDouble; +var _teeUpDouble = "╩"; + +/// A double horizontal box line with a vertical line going down from the middle. +/// +/// If [ascii] is `false`, this is "╦". If it's `true`, this is +/// "+" instead. +String get teeDownDouble => _teeDownDouble; +var _teeDownDouble = "╦"; + +/// A double vertical box line with a horizontal line going left from the middle. +/// +/// If [ascii] is `false`, this is "╣". If it's `true`, this is +/// "+" instead. +String get teeLeftDouble => _teeLeftDouble; +var _teeLeftDouble = "╣"; + +/// A double vertical box line with a horizontal line going right from the middle. +/// +/// If [ascii] is `false`, this is "╠". If it's `true`, this is +/// "+" instead. +String get teeRightDouble => _teeRightDouble; +var _teeRightDouble = "╠"; + +/// A dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "╌". If it's `true`, this is +/// "-" instead. +String get horizontalLineDoubleDash => _horizontalLineDoubleDash; +var _horizontalLineDoubleDash = "╌"; + +/// A bold dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "╍". If it's `true`, this is +/// "-" instead. +String get horizontalLineDoubleDashBold => _horizontalLineDoubleDashBold; +var _horizontalLineDoubleDashBold = "╍"; + +/// A dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "╎". If it's `true`, this is +/// "|" instead. +String get verticalLineDoubleDash => _verticalLineDoubleDash; +var _verticalLineDoubleDash = "╎"; + +/// A bold dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "╏". If it's `true`, this is +/// "|" instead. +String get verticalLineDoubleDashBold => _verticalLineDoubleDashBold; +var _verticalLineDoubleDashBold = "╏"; + +/// A dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┄". If it's `true`, this is +/// "-" instead. +String get horizontalLineTripleDash => _horizontalLineTripleDash; +var _horizontalLineTripleDash = "┄"; + +/// A bold dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┅". If it's `true`, this is +/// "-" instead. +String get horizontalLineTripleDashBold => _horizontalLineTripleDashBold; +var _horizontalLineTripleDashBold = "┅"; + +/// A dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┆". If it's `true`, this is +/// "|" instead. +String get verticalLineTripleDash => _verticalLineTripleDash; +var _verticalLineTripleDash = "┆"; + +/// A bold dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┇". If it's `true`, this is +/// "|" instead. +String get verticalLineTripleDashBold => _verticalLineTripleDashBold; +var _verticalLineTripleDashBold = "┇"; + +/// A dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┈". If it's `true`, this is +/// "-" instead. +String get horizontalLineQuadrupleDash => _horizontalLineQuadrupleDash; +var _horizontalLineQuadrupleDash = "┈"; + +/// A bold dashed horizontal line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┉". If it's `true`, this is +/// "-" instead. +String get horizontalLineQuadrupleDashBold => _horizontalLineQuadrupleDashBold; +var _horizontalLineQuadrupleDashBold = "┉"; + +/// A dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┊". If it's `true`, this is +/// "|" instead. +String get verticalLineQuadrupleDash => _verticalLineQuadrupleDash; +var _verticalLineQuadrupleDash = "┊"; + +/// A bold dashed vertical line that can be used to draw a box. +/// +/// If [ascii] is `false`, this is "┋". If it's `true`, this is +/// "|" instead. +String get verticalLineQuadrupleDashBold => _verticalLineQuadrupleDashBold; +var _verticalLineQuadrupleDashBold = "┋"; diff --git a/pkgs/term_glyph/lib/term_glyph.dart b/pkgs/term_glyph/lib/term_glyph.dart new file mode 100644 index 000000000..8582175ed --- /dev/null +++ b/pkgs/term_glyph/lib/term_glyph.dart @@ -0,0 +1,12 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +export 'src/generated.dart'; + +import 'src/generated.dart'; + +/// Returns [glyph] if Unicode glyph are allowed, and [alternative] if they +/// aren't. +String glyphOrAscii(String glyph, String alternative) => + ascii ? alternative : glyph; diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 275c2bfd8..4ba1efbe6 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,8 +1,13 @@ -name: symbol -version: 1.0.0-dev -description: Useful symbols and Windows-safe equivalents. +name: term_glyph +version: 1.0.0 +description: Useful glyphs and Windows-safe equivalents. author: Dart Team -homepage: https://github.com/dart-lang/symbol +homepage: https://github.com/dart-lang/term_glyph environment: sdk: '>=1.8.0 <2.0.0' + +dev_dependencies: + csv: '^3.0.0' + dart_style: '^0.2.0' + test: '^0.12.0' diff --git a/pkgs/term_glyph/test/symbol_test.dart b/pkgs/term_glyph/test/symbol_test.dart new file mode 100644 index 000000000..e3f94e575 --- /dev/null +++ b/pkgs/term_glyph/test/symbol_test.dart @@ -0,0 +1,41 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:test/test.dart'; + +import 'package:term_glyph/term_glyph.dart' as glyph; + +void main() { + group("with ascii = false", () { + setUpAll(() { + glyph.ascii = false; + }); + + test("glyphs return Unicode versions", () { + expect(glyph.topLeftCorner, equals("┌")); + expect(glyph.teeUpBold, equals("┻")); + expect(glyph.longLeftArrow, equals("◀━")); + }); + + test("glyphOrAscii returns the first argument", () { + expect(glyph.glyphOrAscii("A", "B"), equals("A")); + }); + }); + + group("with ascii = true", () { + setUpAll(() { + glyph.ascii = true; + }); + + test("glyphs return ASCII versions", () { + expect(glyph.topLeftCorner, equals(",")); + expect(glyph.teeUpBold, equals("+")); + expect(glyph.longLeftArrow, equals("<=")); + }); + + test("glyphOrAscii returns the second argument", () { + expect(glyph.glyphOrAscii("A", "B"), equals("B")); + }); + }); +} diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart new file mode 100644 index 000000000..2e94b4ca1 --- /dev/null +++ b/pkgs/term_glyph/tool/generate.dart @@ -0,0 +1,67 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:io'; + +import 'package:csv/csv.dart'; + +void main() { + var csv = new CsvCodec(eol: "\n"); + var data = csv.decode(new File("data.csv").readAsStringSync()); + + // Remove comments and empty lines. + data.removeWhere((row) => row.length < 3); + + var file = new File("lib/src/generated.dart").openSync(mode: FileMode.WRITE); + file.writeStringSync(""" + // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file + // 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. + + // Don't modify this file by hand! It's generated by tool/generate.dart. + + /// Whether the glyph getters return plain ASCII, as opposed to Unicode + /// characters or sequences. + /// + /// Defaults to `false`. + bool get ascii => _ascii; + var _ascii = false; + set ascii(bool value) { + _ascii = value; + if (value) { + """); + + for (var glyph in data) { + file.writeStringSync("_${glyph[0]} = ${_quote(glyph[2])};"); + } + + file.writeStringSync("} else {"); + + for (var glyph in data) { + file.writeStringSync("_${glyph[0]} = ${_quote(glyph[1])};"); + } + + file.writeStringSync("}}"); + + for (var glyph in data) { + for (var line in glyph[3].split("\n")) { + file.writeStringSync("/// $line\n"); + } + + file.writeStringSync(""" + /// + /// If [ascii] is `false`, this is "${glyph[1]}". If it's `true`, this is + /// "${glyph[2]}" instead. + String get ${glyph[0]} => _${glyph[0]}; + var _${glyph[0]} = ${_quote(glyph[1])}; + """); + } + + var result = Process.runSync( + "pub", ["run", "dart_style:format", "-w", "lib/src/generated.dart"]); + print(result.stderr); + exit(result.exitCode); +} + +String _quote(String input) => input.contains('"') ? "'$input'" : '"$input"'; From 6a99277c40fa77a3bc7dbcc6e003d5386b0b8143 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 19 Jan 2017 13:43:02 -0800 Subject: [PATCH 0286/1215] Return a future from Disconnector.disconnect(). (dart-lang/stream_channel#4) --- pkgs/stream_channel/CHANGELOG.md | 5 +++ pkgs/stream_channel/lib/src/disconnector.dart | 44 ++++++++++++------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/disconnector_test.dart | 44 ++++++++++++++++++- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 6e3a6ac94..a018418ef 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.0 + +* `Disconnector.disconnect()` now returns a future that completes when all the + inner `StreamSink.close()` futures have completed. + ## 1.5.0 * Add `new StreamChannel.withCloseGuarantee()` to provide the specific guarantee diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index beff71dd0..b23813e96 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + import '../stream_channel.dart'; /// Allows the caller to force a channel to disconnect. @@ -17,8 +19,7 @@ import '../stream_channel.dart'; /// be disconnected immediately. class Disconnector implements StreamChannelTransformer { /// Whether [disconnect] has been called. - bool get isDisconnected => _isDisconnected; - var _isDisconnected = false; + bool get isDisconnected => _disconnectMemo.hasRun; /// The sinks for transformed channels. /// @@ -28,20 +29,25 @@ class Disconnector implements StreamChannelTransformer { final _sinks = <_DisconnectorSink>[]; /// Disconnects all channels that have been transformed. - void disconnect() { - _isDisconnected = true; - for (var sink in _sinks) { - sink._disconnect(); - } + /// + /// Returns a future that completes when all inner sinks' [StreamSink.close] + /// futures have completed. Note that a [StreamController]'s sink won't close + /// until the corresponding stream has a listener. + Future disconnect() => _disconnectMemo.runOnce(() { + var futures = _sinks.map((sink) => sink._disconnect()).toList(); _sinks.clear(); - } + return Future.wait(futures, eagerError: true); + }); + final _disconnectMemo = new AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { var sink = new _DisconnectorSink(innerSink); - if (_isDisconnected) { - sink._disconnect(); + if (isDisconnected) { + // Ignore errors here, because otherwise there would be no way for the + // user to handle them gracefully. + sink._disconnect().catchError((_) {}); } else { _sinks.add(sink); } @@ -126,14 +132,18 @@ class _DisconnectorSink implements StreamSink { /// Disconnects this sink. /// - /// This closes the underlying sink and stops forwarding events. - void _disconnect() { + /// This closes the underlying sink and stops forwarding events. It returns + /// the [StreamSink.close] future for the underlying sink. + Future _disconnect() { _isDisconnected = true; - _inner.close(); + var future = _inner.close(); + + if (_inAddStream) { + _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter = null; + _addStreamSubscription = null; + } - if (!_inAddStream) return; - _addStreamCompleter.complete(_addStreamSubscription.cancel()); - _addStreamCompleter = null; - _addStreamSubscription = null; + return future; } } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bcdfe8e78..46d77617c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.5.1-dev +version: 1.6.0 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index d7fa885cd..311a41c9a 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -78,8 +79,35 @@ void main() { expect(canceled, isTrue); }); + test("disconnect() returns the close future from the inner sink", () async { + var streamController = new StreamController(); + var sinkController = new StreamController(); + var disconnector = new Disconnector(); + var sink = new _CloseCompleterSink(sinkController.sink); + var channel = new StreamChannel.withGuarantees( + streamController.stream, sink) + .transform(disconnector); + + var disconnectFutureFired = false; + expect(disconnector.disconnect().then((_) { + disconnectFutureFired = true; + }), completes); + + // Give the future time to fire early if it's going to. + await pumpEventQueue(); + expect(disconnectFutureFired, isFalse); + + // When the inner sink's close future completes, so should the + // disconnector's. + sink.completer.complete(); + await pumpEventQueue(); + expect(disconnectFutureFired, isTrue); + }); + group("after disconnection", () { - setUp(() => disconnector.disconnect()); + setUp(() { + disconnector.disconnect(); + }); test("closes the inner sink and ignores events to the outer sink", () { channel.sink.add(1); @@ -108,3 +136,17 @@ void main() { }); }); } + +/// A [StreamSink] wrapper that adds the ability to manually complete the Future +/// returned by [close] using [completer]. +class _CloseCompleterSink extends DelegatingStreamSink { + /// The completer for the future returned by [close]. + final completer = new Completer(); + + _CloseCompleterSink(StreamSink inner) : super(inner); + + Future close() { + super.close(); + return completer.future; + } +} From 963bab00ef228ba381f4fbfba1d62be09a00ff8f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 25 Jan 2017 15:01:46 -0800 Subject: [PATCH 0287/1215] Fix the type args for StreamChannel.transform(). (dart-lang/stream_channel#7) Closes dart-lang/stream_channel#6 --- pkgs/stream_channel/CHANGELOG.md | 6 ++++++ pkgs/stream_channel/lib/stream_channel.dart | 6 ++++-- pkgs/stream_channel/pubspec.yaml | 2 +- .../stream_channel/test/json_document_transformer_test.dart | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a018418ef..8d44b214a 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.1 + +* Fix the type of `StreamChannel.transform()`. This previously inverted the + generic parameters, so it only really worked with transformers where both + generic types were identical. + ## 1.6.0 * `Disconnector.disconnect()` now returns a future that completes when all the diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 16323b169..34be085ea 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -108,7 +108,8 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform(StreamChannelTransformer transformer); + StreamChannel/**/ transform/**/( + StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -152,7 +153,8 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform(StreamChannelTransformer transformer) => + StreamChannel/**/ transform/**/( + StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 46d77617c..7d395a3ea 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.0 +version: 1.6.1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 4dd5ea7fb..6f18e361f 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -11,11 +11,11 @@ import 'package:test/test.dart'; void main() { var streamController; var sinkController; - var channel; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( + channel = new StreamChannel( streamController.stream, sinkController.sink); }); From 28075ed34cf11ae627840208ed0fcea60f51b452 Mon Sep 17 00:00:00 2001 From: Yegor Date: Wed, 8 Feb 2017 12:17:49 -0800 Subject: [PATCH 0288/1215] fix friendly frame sample; tiny test code org fix (dart-lang/stack_trace#18) --- pkgs/stack_trace/lib/src/frame.dart | 4 ++-- pkgs/stack_trace/test/frame_test.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index efb221612..8dde788a7 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -51,8 +51,8 @@ final _firefoxSafariFrame = new RegExp( // empty in Safari if it's unknown. r'$'); -// foo/bar.dart 10:11 in Foo._bar -// http://dartlang.org/foo/bar.dart in Foo._bar +// foo/bar.dart 10:11 Foo._bar +// http://dartlang.org/foo/bar.dart Foo._bar final _friendlyFrame = new RegExp( r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$'); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 43bce9cb5..080c8b8ed 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -68,7 +68,9 @@ void main() { expect(frame.line, isNull); expect(frame.column, isNull); }); + }); + group('.parseV8', () { test('returns an UnparsedFrame for malformed frames', () { expectIsUnparsed((text) => new Frame.parseV8(text), ''); expectIsUnparsed((text) => new Frame.parseV8(text), '#1'); @@ -78,9 +80,7 @@ void main() { expectIsUnparsed((text) => new Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); }); - }); - group('.parseV8', () { test('parses a stack frame correctly', () { var frame = new Frame.parseV8(" at VW.call\$0 " "(http://pub.dartlang.org/stuff.dart.js:560:28)"); From 86b9d65efd5dcaf38aca8aa0c011fd451e0ec8af Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 15 Feb 2017 13:45:59 -0800 Subject: [PATCH 0289/1215] Support the VM's new causal async stack traces. (dart-lang/stack_trace#19) --- pkgs/stack_trace/CHANGELOG.md | 7 ++++ pkgs/stack_trace/lib/src/chain.dart | 19 +++++++++-- pkgs/stack_trace/lib/src/lazy_chain.dart | 33 +++++++++++++++++++ .../lib/src/stack_zone_specification.dart | 27 +++++++++++++-- pkgs/stack_trace/lib/src/trace.dart | 6 ++-- pkgs/stack_trace/lib/src/utils.dart | 4 +++ pkgs/stack_trace/pubspec.yaml | 2 +- 7 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 pkgs/stack_trace/lib/src/lazy_chain.dart diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 5d25eac43..293538f19 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.7.1 + +* Make `Trace.parse()`, `Chain.parse()`, treat the VM's new causal asynchronous + stack traces as chains. Outside of a `Chain.capture()` block, `new + Chain.current()` will return a stack chain constructed from the asynchronous + stack traces. + ## 1.7.0 * Add a `Chain.disable()` function that disables stack-chain tracking. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 7045e194c..4543eff41 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:math' as math; import 'frame.dart'; +import 'lazy_chain.dart'; import 'stack_zone_specification.dart'; import 'trace.dart'; import 'utils.dart'; @@ -134,7 +135,15 @@ class Chain implements StackTrace { /// single-trace chain. factory Chain.current([int level=0]) { if (_currentSpec != null) return _currentSpec.currentChain(level + 1); - return new Chain([new Trace.current(level + 1)]); + + var chain = new Chain.forTrace(StackTrace.current); + return new LazyChain(() { + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + var first = new Trace( + chain.traces.first.frames.skip(level + (inJS ? 2 : 1))); + return new Chain([first]..addAll(chain.traces.skip(1))); + }); } /// Returns the stack chain associated with [trace]. @@ -147,8 +156,8 @@ class Chain implements StackTrace { /// If [trace] is already a [Chain], it will be returned as-is. factory Chain.forTrace(StackTrace trace) { if (trace is Chain) return trace; - if (_currentSpec == null) return new Chain([new Trace.from(trace)]); - return _currentSpec.chainFor(trace); + if (_currentSpec != null) return _currentSpec.chainFor(trace); + return new LazyChain(() => new Chain.parse(trace.toString())); } /// Parses a string representation of a stack chain. @@ -158,6 +167,10 @@ class Chain implements StackTrace { /// and returned as a single-trace chain. factory Chain.parse(String chain) { if (chain.isEmpty) return new Chain([]); + if (chain.contains(vmChainGap)) { + return new Chain( + chain.split(vmChainGap).map((trace) => new Trace.parseVM(trace))); + } if (!chain.contains(chainGap)) return new Chain([new Trace.parse(chain)]); return new Chain( diff --git a/pkgs/stack_trace/lib/src/lazy_chain.dart b/pkgs/stack_trace/lib/src/lazy_chain.dart new file mode 100644 index 000000000..55b98974a --- /dev/null +++ b/pkgs/stack_trace/lib/src/lazy_chain.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'chain.dart'; +import 'frame.dart'; +import 'lazy_trace.dart'; +import 'trace.dart'; + +/// A thunk for lazily constructing a [Chain]. +typedef Chain ChainThunk(); + +/// A wrapper around a [ChainThunk]. This works around issue 9579 by avoiding +/// the conversion of native [StackTrace]s to strings until it's absolutely +/// necessary. +class LazyChain implements Chain { + final ChainThunk _thunk; + Chain _inner; + + LazyChain(this._thunk); + + Chain get _chain { + if (_inner == null) _inner = _thunk(); + return _inner; + } + + List get traces => _chain.traces; + Chain get terse => _chain.terse; + Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) => + new LazyChain(() => _chain.foldFrames(predicate, terse: terse)); + Trace toTrace() => new LazyTrace(() => _chain.toTrace()); + String toString() => _chain.toString(); +} diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 712524929..948ef309e 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -4,8 +4,10 @@ import 'dart:async'; -import 'trace.dart'; import 'chain.dart'; +import 'lazy_trace.dart'; +import 'trace.dart'; +import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. typedef void _ChainHandler(error, Chain chain); @@ -170,7 +172,7 @@ class StackZoneSpecification { /// [_createNode] is called. If [level] is passed, the first trace will start /// that many frames up instead. _Node _createNode([int level=0]) => - new _Node(new Trace.current(level + 1), _currentNode); + new _Node(_currentTrace(level + 1), _currentNode); // TODO(nweiz): use a more robust way of detecting and tracking errors when // issue 15105 is fixed. @@ -201,7 +203,7 @@ class _Node { final _Node previous; _Node(StackTrace trace, [this.previous]) - : trace = trace == null ? new Trace.current() : new Trace.from(trace); + : trace = trace == null ? _currentTrace() : new Trace.from(trace); /// Converts this to a [Chain]. Chain toChain() { @@ -214,3 +216,22 @@ class _Node { return new Chain(nodes); } } + +/// Like [new Trace.current], but if the current stack trace has VM chaining +/// enabled, this only returns the innermost sub-trace. +Trace _currentTrace([int level]) { + level ??= 0; + var stackTrace = StackTrace.current; + return new LazyTrace(() { + // Ignore the VM's stack chains when we generate our own. Otherwise we'll + // end up with duplicate frames all over the place. + var text = stackTrace.toString(); + var index = text.indexOf(vmChainGap); + if (index != -1) text = text.substring(0, index); + + var trace = new Trace.parse(text); + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1))); + }); +} diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index ad55fc79b..eb8ecd858 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -51,7 +51,7 @@ final _firefoxSafariTrace = new RegExp( r"$", multiLine: true); /// A RegExp to match this package's stack traces. -final _friendlyTrace = new RegExp(r"^[^\s]+( \d+(:\d+)?)?[ \t]+[^\s]+$", +final _friendlyTrace = new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); /// A stack trace, comprised of a list of stack frames. @@ -137,7 +137,9 @@ class Trace implements StackTrace { : this(_parseVM(trace)); static List _parseVM(String trace) { - var lines = trace.trim().split("\n"); + // Ignore [vmChainGap]. This matches the behavior of + // `Chain.parse().toTrace()`. + var lines = trace.trim().replaceAll(vmChainGap, '').split("\n"); var frames = lines.take(lines.length - 1) .map((line) => new Frame.parseVM(line)) .toList(); diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 51897602f..838a093b5 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -6,6 +6,10 @@ /// the gap between traces. const chainGap = '===== asynchronous gap ===========================\n'; +/// The line used in the string representation of VM stack chains to represent +/// the gap between traces. +const vmChainGap = '\n'; + // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. final bool inJS = 0.0 is int; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 6984445a3..4289a6e46 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.0 +version: 1.7.1 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From befaaffbcf81844ba455a483af12afdbd9d5c52f Mon Sep 17 00:00:00 2001 From: Jacob Richman Date: Tue, 7 Mar 2017 15:45:34 -0800 Subject: [PATCH 0290/1215] Fix friendly frame parsing bugs. Fix bug parsing a friendly frame with spaces in the member name. Fix bug parsing a friendly frame where the location is a data url. BUG= R=nweiz@google.com Review-Url: https://codereview.chromium.org//2739643004 . --- pkgs/stack_trace/CHANGELOG.md | 4 +++ pkgs/stack_trace/lib/src/frame.dart | 14 ++++++--- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 41 ++++++++++++++++++++++++++- pkgs/stack_trace/test/trace_test.dart | 17 +++++++++++ 5 files changed, 72 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 293538f19..53cdd378a 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.2 +* Fix bug parsing a friendly frame with spaces in the member name. +* Fix bug parsing a friendly frame where the location is a data url. + ## 1.7.1 * Make `Trace.parse()`, `Chain.parse()`, treat the VM's new causal asynchronous diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 8dde788a7..859924549 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -52,9 +52,11 @@ final _firefoxSafariFrame = new RegExp( r'$'); // foo/bar.dart 10:11 Foo._bar +// foo/bar.dart 10:11 (anonymous function).dart.fn // http://dartlang.org/foo/bar.dart Foo._bar +// data:... 10:11 Foo._bar final _friendlyFrame = new RegExp( - r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d]\S*)$'); + r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); /// A regular expression that matches asynchronous member names generated by the /// VM. @@ -186,7 +188,8 @@ class Frame { // as "Anonymous function". return parseLocation(match[2], match[1].replaceAll("", "") - .replaceAll("Anonymous function", "")); + .replaceAll("Anonymous function", "") + .replaceAll("(anonymous function)", "")); } else { // The second form looks like " at LOCATION", and is used for anonymous // functions. @@ -249,8 +252,11 @@ class Frame { throw new FormatException( "Couldn't parse package:stack_trace stack trace line '$frame'."); } - - var uri = Uri.parse(match[1]); + // Fake truncated data urls generated by the friendly stack trace format + // cause Uri.parse to throw an exception so we have to special case them. + var uri = match[1] == 'data:...' + ? new Uri.dataFromString('') + : Uri.parse(match[1]); // If there's no scheme, this is a relative URI. We should interpret it as // relative to the current working directory. if (uri.scheme == '') { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 4289a6e46..dd081eaee 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.1 +version: 1.7.2 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 080c8b8ed..a5f8b2344 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -448,7 +448,7 @@ void main() { expect(frame.member, equals('Foo..bar')); }); - test('parses a stack frame with no line correctly', () { + test('parses a stack frame with no column correctly', () { var frame = new Frame.parseFriendly( "http://dartlang.org/foo/bar.dart 10 Foo..bar"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); @@ -472,6 +472,45 @@ void main() { expectIsUnparsed((text) => new Frame.parseFriendly(text), 'foo/bar.dart 10:11'); }); + + test('parses a data url stack frame with no line or column correctly', () { + var frame = new Frame.parseFriendly( + "data:... main"); + expect(frame.uri.scheme, equals('data')); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('main')); + }); + + test('parses a data url stack frame correctly', () { + var frame = new Frame.parseFriendly( + "data:... 10:11 main"); + expect(frame.uri.scheme, equals('data')); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('main')); + }); + + test('parses a stack frame with spaces in the member name correctly', () { + var frame = new Frame.parseFriendly( + "foo/bar.dart 10:11 (anonymous function).dart.fn"); + expect(frame.uri, + equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); + expect(frame.line, equals(10)); + expect(frame.column, equals(11)); + expect(frame.member, equals('(anonymous function).dart.fn')); + }); + + test('parses a stack frame with spaces in the member name and no line or ' + 'column correctly', () { + var frame = new Frame.parseFriendly( + "http://dartlang.org/foo/bar.dart (anonymous function).dart.fn"); + expect( + frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.line, isNull); + expect(frame.column, isNull); + expect(frame.member, equals('(anonymous function).dart.fn')); + }); }); test('only considers dart URIs to be core', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 077f1baed..327eff065 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -72,6 +72,23 @@ void main() { equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + + trace = new Trace.parse( + 'Exception: foo\n' + ' bar\n' + ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at (anonymous function).zip.zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); + + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].member, equals("")); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + expect(trace.frames[2].member, equals(".zip.zap")); }); // JavaScriptCore traces are just like V8, except that it doesn't have a From 41f91c26f5190aeee18cc340e3b851308d1288cd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 7 Mar 2017 16:51:18 -0800 Subject: [PATCH 0291/1215] Remove the outermost folded frame in terse mode. (dart-lang/stack_trace#21) We always removed this frame if it was a core library frame, which (until recent SDK releases) it always was. Now that the boilerplate core library frames have been removed, we should remove *any* folded frame. This partially addresses dart-lang/testdart-lang/stack_trace#555 --- pkgs/stack_trace/CHANGELOG.md | 5 + pkgs/stack_trace/lib/src/trace.dart | 5 +- pkgs/stack_trace/test/chain/chain_test.dart | 3 +- pkgs/stack_trace/test/trace_test.dart | 109 ++++++++++++-------- 4 files changed, 76 insertions(+), 46 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 53cdd378a..db53c7398 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,5 +1,10 @@ ## 1.7.2 + +* `Trace.foldFrames()` and `Chain.foldFrames()` now remove the outermost folded + frame. This matches the behavior of `.terse` with core frames. + * Fix bug parsing a friendly frame with spaces in the member name. + * Fix bug parsing a friendly frame where the location is a data url. ## 1.7.1 diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index eb8ecd858..9edee6e07 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -285,7 +285,10 @@ class Trace implements StackTrace { var library = frame.library.replaceAll(_terseRegExp, ''); return new Frame(Uri.parse(library), null, null, frame.member); }).toList(); - if (newFrames.length > 1 && newFrames.first.isCore) newFrames.removeAt(0); + + if (newFrames.length > 1 && predicate(newFrames.first)) { + newFrames.removeAt(0); + } } return new Trace(newFrames.reversed); diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 301f338b2..60137c8fe 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -269,7 +269,6 @@ void main() { expect(folded.toString(), equals( 'dart:async Zip.zap\n' 'b.dart 10:11 Bang.qux\n' - 'a.dart Zop.zoop\n' '===== asynchronous gap ===========================\n' 'a.dart Zip.zap\n' 'b.dart 10:11 Zop.zoop\n')); @@ -325,4 +324,4 @@ void main() { '$userSlashCode 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n')); }); -} \ No newline at end of file +} diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 327eff065..1297932ee 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -293,8 +293,9 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap }); group("folding", () { - test('.terse folds core frames together bottom-up', () { - var trace = new Trace.parse(''' + group(".terse", () { + test('folds core frames together bottom-up', () { + var trace = new Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) #0 notCore (foo.dart:42:21) @@ -303,30 +304,30 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap #5 alsoNotCore (bar.dart:10:20) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:core bottom foo.dart 42:21 notCore dart:async bottom bar.dart 10:20 alsoNotCore ''')); - }); + }); - test('.terse folds empty async frames', () { - var trace = new Trace.parse(''' + test('folds empty async frames', () { + var trace = new Trace.parse(''' #0 top (dart:async/future.dart:0:2) #1 empty.<_async_body> (bar.dart) #2 bottom (dart:async-patch/future.dart:9:11) #3 notCore (foo.dart:42:21) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:async bottom foo.dart 42:21 notCore ''')); - }); + }); - test('.terse removes the bottom-most async frame', () { - var trace = new Trace.parse(''' + test('removes the bottom-most async frame', () { + var trace = new Trace.parse(''' #0 notCore (foo.dart:42:21) #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) @@ -337,25 +338,27 @@ foo.dart 42:21 notCore expect(trace.terse.toString(), equals(''' foo.dart 42:21 notCore ''')); - }); + }); - test(".terse won't make a trace empty", () { - var trace = new Trace.parse(''' + test("won't make a trace empty", () { + var trace = new Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' dart:core bottom ''')); - }); + }); - test(".terse won't panic on an empty trace", () { - expect(new Trace.parse("").terse.toString(), equals("")); + test("won't panic on an empty trace", () { + expect(new Trace.parse("").terse.toString(), equals("")); + }); }); - test('.foldFrames folds frames together bottom-up', () { - var trace = new Trace.parse(''' + group(".foldFrames", () { + test('folds frames together bottom-up', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (foo.dart:1:100) @@ -364,17 +367,32 @@ dart:core bottom #5 fooBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo foo.dart 1:100 fooBottom bar.dart 10:20 alsoNotFoo dart:async-patch/future.dart 9:11 fooBottom ''')); - }); + }); - test('.foldFrames with terse: true folds core frames as well', () { - var trace = new Trace.parse(''' + test('will never fold unparsed frames', () { + var trace = new Trace.parse(r''' +.g"cs$#:b";a#>sw{*{ul$"$xqwr`p +%+j-?uppx<([j@#nu{{>*+$%x-={`{ +!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ +'''); + + expect(trace.foldFrames((frame) => true).toString(), equals(r''' +.g"cs$#:b";a#>sw{*{ul$"$xqwr`p +%+j-?uppx<([j@#nu{{>*+$%x-={`{ +!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ +''')); + }); + + group("with terse: true", () { + test('folds core frames as well', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 coreBottom (dart:async/future.dart:0:2) @@ -383,47 +401,52 @@ dart:async-patch/future.dart 9:11 fooBottom #5 coreBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), - terse: true); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo dart:async coreBottom bar.dart 10:20 alsoNotFoo ''')); - }); + }); - test('.foldFrames with terse: true shortens folded frames', () { - var trace = new Trace.parse(''' + test('shortens folded frames', () { + var trace = new Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (package:foo/bar.dart:0:2) #3 alsoNotFoo (bar.dart:10:20) #4 fooTop (foo.dart:9:11) #5 fooBottom (foo/bar.dart:9:11) +#6 againNotFoo (bar.dart:20:20) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), - terse: true); - expect(folded.toString(), equals(''' + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' foo.dart 42:21 notFoo package:foo fooBottom bar.dart 10:20 alsoNotFoo foo fooBottom +bar.dart 20:20 againNotFoo ''')); - }); + }); - test('.foldFrames will never fold unparsed frames', () { - var trace = new Trace.parse(r''' -.g"cs$#:b";a#>sw{*{ul$"$xqwr`p -%+j-?uppx<([j@#nu{{>*+$%x-={`{ -!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ + test('removes the bottom-most folded frame', () { + var trace = new Trace.parse(''' +#2 fooTop (package:foo/bar.dart:0:2) +#3 notFoo (bar.dart:10:20) +#5 fooBottom (foo/bar.dart:9:11) '''); - expect(trace.foldFrames((frame) => true).toString(), equals(r''' -.g"cs$#:b";a#>sw{*{ul$"$xqwr`p -%+j-?uppx<([j@#nu{{>*+$%x-={`{ -!e($b{nj)zs?cgr%!;bmw.+$j+pfj~ + var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + terse: true); + expect(folded.toString(), equals(''' +package:foo fooTop +bar.dart 10:20 notFoo ''')); + }); + }); }); }); } From a9edf52c128be2fc9c083c37d89b1922dba27b30 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 9 Mar 2017 18:22:27 -0800 Subject: [PATCH 0292/1215] Fix broken README links. (dart-lang/stack_trace#23) Closes dart-lang/stack_trace#22 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/README.md | 4 ++-- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index db53c7398..5e56d8d6f 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.3 + +* Fix broken links in the README. + ## 1.7.2 * `Trace.foldFrames()` and `Chain.foldFrames()` now remove the outermost folded diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 4fb3c50a3..3f0837424 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -7,7 +7,7 @@ the native [StackTrace] implementation. using `Trace.current`. Native [StackTrace]s can also be directly converted to human-readable strings using `Trace.format`. -[StackTrace]: http://api.dartlang.org/docs/releases/latest/dart_core/StackTrace.html +[StackTrace]: https://api.dartlang.org/stable/dart-core/StackTrace-class.html Here's an example native stack trace from debugging this library: @@ -202,4 +202,4 @@ this: That's a lot easier to understand! -[Zone]: https://api.dartlang.org/apidocs/channels/stable/#dart-async.Zone +[Zone]: https://api.dartlang.org/stable/dart-async/Zone-class.html diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index dd081eaee..850a701f8 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.2 +version: 1.7.3 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: > From d3fc100532067b74cfb72dda64030f84e1f2e47e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Apr 2017 21:13:00 -0700 Subject: [PATCH 0293/1215] fix analyzer warnings Including using latest pkg/test expectAsync2 method --- pkgs/stack_trace/pubspec.yaml | 8 +++----- pkgs/stack_trace/test/chain/chain_test.dart | 6 ++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 850a701f8..93f059eaa 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,16 +7,14 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.3 +version: 1.7.4-dev author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace -description: > - A package for manipulating stack traces and printing them readably. - +description: A package for manipulating stack traces and printing them readably. dependencies: path: "^1.2.0" dev_dependencies: - test: "^0.12.0" + test: '^0.12.17' environment: sdk: ">=1.14.0 <2.0.0" diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 60137c8fe..b974aa98a 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -8,7 +8,6 @@ import 'package:path/path.dart' as p; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -import '../utils.dart'; import 'utils.dart'; typedef void ChainErrorCallback(stack, Chain chain); @@ -48,11 +47,10 @@ void main() { test("with onError blocks errors", () { Chain.capture(() { return new Future.error("oh no"); - }, onError: expectAsync((error, chain) { + }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); expect(chain, new isInstanceOf()); - }) as ChainErrorCallback, when: false); - // TODO(rnystrom): Remove this cast if expectAsync() gets a better type. + }), when: false); }); test("doesn't enable chain-tracking", () { From 0904964870df876d433f8d49e1c250e65e1bedbe Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Apr 2017 21:13:26 -0700 Subject: [PATCH 0294/1215] dartfmt --- pkgs/stack_trace/lib/src/chain.dart | 28 +- pkgs/stack_trace/lib/src/frame.dart | 239 +++++++++--------- pkgs/stack_trace/lib/src/lazy_trace.dart | 2 +- .../lib/src/stack_zone_specification.dart | 22 +- pkgs/stack_trace/lib/src/trace.dart | 76 +++--- pkgs/stack_trace/lib/src/unparsed_frame.dart | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 155 ++++++------ pkgs/stack_trace/test/chain/dart2js_test.dart | 20 +- pkgs/stack_trace/test/chain/utils.dart | 3 +- pkgs/stack_trace/test/chain/vm_test.dart | 23 +- pkgs/stack_trace/test/frame_test.dart | 136 +++++----- pkgs/stack_trace/test/trace_test.dart | 93 ++++--- pkgs/stack_trace/test/utils.dart | 10 +- 13 files changed, 408 insertions(+), 401 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 4543eff41..04a153a75 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -70,7 +70,7 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static /*=T*/ capture/**/(/*=T*/ callback(), + static/*=T*/ capture/**/(/*=T*/ callback(), {void onError(error, Chain chain), bool when: true}) { if (!when) { var newOnError; @@ -106,13 +106,9 @@ class Chain implements StackTrace { /// [callback] in a [Zone] in which chain capturing is disabled. /// /// If [callback] returns a value, it will be returned by [disable] as well. - static /*=T*/ disable/**/(/*=T*/ callback(), {bool when: true}) { - var zoneValues = when - ? { - _specKey: null, - StackZoneSpecification.disableKey: true - } - : null; + static/*=T*/ disable/**/(/*=T*/ callback(), {bool when: true}) { + var zoneValues = + when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null; return runZoned(callback, zoneValues: zoneValues); } @@ -133,15 +129,15 @@ class Chain implements StackTrace { /// /// If this is called outside of a [capture] zone, it just returns a /// single-trace chain. - factory Chain.current([int level=0]) { + factory Chain.current([int level = 0]) { if (_currentSpec != null) return _currentSpec.currentChain(level + 1); var chain = new Chain.forTrace(StackTrace.current); return new LazyChain(() { // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - var first = new Trace( - chain.traces.first.frames.skip(level + (inJS ? 2 : 1))); + var first = + new Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1))); return new Chain([first]..addAll(chain.traces.skip(1))); }); } @@ -178,8 +174,7 @@ class Chain implements StackTrace { } /// Returns a new [Chain] comprised of [traces]. - Chain(Iterable traces) - : traces = new List.unmodifiable(traces); + Chain(Iterable traces) : traces = new List.unmodifiable(traces); /// Returns a terser version of [this]. /// @@ -208,8 +203,8 @@ class Chain implements StackTrace { /// library or from this package, and simplify core library frames as in /// [Trace.terse]. Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) { - var foldedTraces = traces.map( - (trace) => trace.foldFrames(predicate, terse: terse)); + var foldedTraces = + traces.map((trace) => trace.foldFrames(predicate, terse: terse)); var nonEmptyTraces = foldedTraces.where((trace) { // Ignore traces that contain only folded frames. if (trace.frames.length > 1) return true; @@ -240,7 +235,8 @@ class Chain implements StackTrace { String toString() { // Figure out the longest path so we know how much to pad. var longest = traces.map((trace) { - return trace.frames.map((frame) => frame.location.length) + return trace.frames + .map((frame) => frame.location.length) .fold(0, math.max); }).fold(0, math.max); diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 859924549..bbe5c79e6 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -17,8 +17,8 @@ final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // at VW.call$0 (eval as fn // (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 -final _v8Frame = new RegExp( - r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); +final _v8Frame = + new RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // http://pub.dartlang.org/stuff.dart.js:560:28 final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); @@ -27,36 +27,34 @@ final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) // eval as function (eval as otherFunction // (http://pub.dartlang.org/stuff.dart.js:560:28)) -final _v8EvalLocation = new RegExp( - r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); +final _v8EvalLocation = + new RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36 // http://pub.dartlang.org/stuff.dart.js:560 -final _firefoxSafariFrame = new RegExp( - r'^' +final _firefoxSafariFrame = new RegExp(r'^' r'(?:' // Member description. Not present in some Safari frames. - r'([^@(/]*)' // The actual name of the member. - r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. - r'((?:/[^/]*)*)' // Extra characters indicating a nested closure. - r'(?:\(.*\))?' // Arguments to the closure. - r'@' + r'([^@(/]*)' // The actual name of the member. + r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. + r'((?:/[^/]*)*)' // Extra characters indicating a nested closure. + r'(?:\(.*\))?' // Arguments to the closure. + r'@' r')?' r'(.*?)' // The frame's URL. r':' r'(\d*)' // The line number. Empty in Safari if it's unknown. r'(?::(\d*))?' // The column number. Not present in older browsers and - // empty in Safari if it's unknown. + // empty in Safari if it's unknown. r'$'); // foo/bar.dart 10:11 Foo._bar // foo/bar.dart 10:11 (anonymous function).dart.fn // http://dartlang.org/foo/bar.dart Foo._bar // data:... 10:11 Foo._bar -final _friendlyFrame = new RegExp( - r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); +final _friendlyFrame = new RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); /// A regular expression that matches asynchronous member names generated by the /// VM. @@ -120,7 +118,7 @@ class Frame { /// By default, this will return the frame above the current method. If /// [level] is `0`, it will return the current method's frame; if [level] is /// higher than `1`, it will return higher frames. - factory Frame.caller([int level=1]) { + factory Frame.caller([int level = 1]) { if (level < 0) { throw new ArgumentError("Argument [level] must be greater than or equal " "to 0."); @@ -131,71 +129,72 @@ class Frame { /// Parses a string representation of a Dart VM stack frame. factory Frame.parseVM(String frame) => _catchFormatException(frame, () { - // The VM sometimes folds multiple stack frames together and replaces them - // with "...". - if (frame == '...') { - return new Frame(new Uri(), null, null, '...'); - } - - var match = _vmFrame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); - - // Get the pieces out of the regexp match. Function, URI and line should - // always be found. The column is optional. - var member = match[1] - .replaceAll(_asyncBody, "") - .replaceAll("", ""); - var uri = Uri.parse(match[2]); - - var lineAndColumn = match[3].split(':'); - var line = lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; - var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; - return new Frame(uri, line, column, member); - }); + // The VM sometimes folds multiple stack frames together and replaces them + // with "...". + if (frame == '...') { + return new Frame(new Uri(), null, null, '...'); + } + + var match = _vmFrame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // Get the pieces out of the regexp match. Function, URI and line should + // always be found. The column is optional. + var member = match[1] + .replaceAll(_asyncBody, "") + .replaceAll("", ""); + var uri = Uri.parse(match[2]); + + var lineAndColumn = match[3].split(':'); + var line = + lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; + var column = + lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; + return new Frame(uri, line, column, member); + }); /// Parses a string representation of a Chrome/V8 stack frame. factory Frame.parseV8(String frame) => _catchFormatException(frame, () { - var match = _v8Frame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); - - // v8 location strings can be arbitrarily-nested, since it adds a layer of - // nesting for each eval performed on that line. - parseLocation(location, member) { - var evalMatch = _v8EvalLocation.firstMatch(location); - while (evalMatch != null) { - location = evalMatch[1]; - evalMatch = _v8EvalLocation.firstMatch(location); - } - - if (location == 'native') { - return new Frame(Uri.parse('native'), null, null, member); - } - - var urlMatch = _v8UrlLocation.firstMatch(location); - if (urlMatch == null) return new UnparsedFrame(frame); - - return new Frame( - _uriOrPathToUri(urlMatch[1]), - int.parse(urlMatch[2]), - int.parse(urlMatch[3]), - member); - } - - // V8 stack frames can be in two forms. - if (match[2] != null) { - // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists - // anonymous functions within eval as "", while IE10 lists them - // as "Anonymous function". - return parseLocation(match[2], - match[1].replaceAll("", "") + var match = _v8Frame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // v8 location strings can be arbitrarily-nested, since it adds a layer of + // nesting for each eval performed on that line. + parseLocation(location, member) { + var evalMatch = _v8EvalLocation.firstMatch(location); + while (evalMatch != null) { + location = evalMatch[1]; + evalMatch = _v8EvalLocation.firstMatch(location); + } + + if (location == 'native') { + return new Frame(Uri.parse('native'), null, null, member); + } + + var urlMatch = _v8UrlLocation.firstMatch(location); + if (urlMatch == null) return new UnparsedFrame(frame); + + return new Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]), + int.parse(urlMatch[3]), member); + } + + // V8 stack frames can be in two forms. + if (match[2] != null) { + // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists + // anonymous functions within eval as "", while IE10 lists them + // as "Anonymous function". + return parseLocation( + match[2], + match[1] + .replaceAll("", "") .replaceAll("Anonymous function", "") .replaceAll("(anonymous function)", "")); - } else { - // The second form looks like " at LOCATION", and is used for anonymous - // functions. - return parseLocation(match[3], ""); - } - }); + } else { + // The second form looks like " at LOCATION", and is used for anonymous + // functions. + return parseLocation(match[3], ""); + } + }); /// Parses a string representation of a JavaScriptCore stack trace. factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame); @@ -208,31 +207,31 @@ class Frame { /// Parses a string representation of a Firefox stack frame. factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { - var match = _firefoxSafariFrame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); - - // Normally this is a URI, but in a jsshell trace it can be a path. - var uri = _uriOrPathToUri(match[3]); - - var member; - if (match[1] != null) { - member = match[1]; - member += - new List.filled('/'.allMatches(match[2]).length, ".").join(); - if (member == '') member = ''; - - // Some Firefox members have initial dots. We remove them for consistency - // with other platforms. - member = member.replaceFirst(_initialDot, ''); - } else { - member = ''; - } - - var line = match[4] == '' ? null : int.parse(match[4]); - var column = match[5] == null || match[5] == '' ? - null : int.parse(match[5]); - return new Frame(uri, line, column, member); - }); + var match = _firefoxSafariFrame.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + + // Normally this is a URI, but in a jsshell trace it can be a path. + var uri = _uriOrPathToUri(match[3]); + + var member; + if (match[1] != null) { + member = match[1]; + member += + new List.filled('/'.allMatches(match[2]).length, ".").join(); + if (member == '') member = ''; + + // Some Firefox members have initial dots. We remove them for consistency + // with other platforms. + member = member.replaceFirst(_initialDot, ''); + } else { + member = ''; + } + + var line = match[4] == '' ? null : int.parse(match[4]); + var column = + match[5] == null || match[5] == '' ? null : int.parse(match[5]); + return new Frame(uri, line, column, member); + }); /// Parses a string representation of a Safari 6.0 stack frame. @Deprecated("Use Frame.parseSafari instead.") @@ -247,26 +246,26 @@ class Frame { /// Parses this package's string representation of a stack frame. factory Frame.parseFriendly(String frame) => _catchFormatException(frame, () { - var match = _friendlyFrame.firstMatch(frame); - if (match == null) { - throw new FormatException( - "Couldn't parse package:stack_trace stack trace line '$frame'."); - } - // Fake truncated data urls generated by the friendly stack trace format - // cause Uri.parse to throw an exception so we have to special case them. - var uri = match[1] == 'data:...' - ? new Uri.dataFromString('') - : Uri.parse(match[1]); - // If there's no scheme, this is a relative URI. We should interpret it as - // relative to the current working directory. - if (uri.scheme == '') { - uri = path.toUri(path.absolute(path.fromUri(uri))); - } - - var line = match[2] == null ? null : int.parse(match[2]); - var column = match[3] == null ? null : int.parse(match[3]); - return new Frame(uri, line, column, match[4]); - }); + var match = _friendlyFrame.firstMatch(frame); + if (match == null) { + throw new FormatException( + "Couldn't parse package:stack_trace stack trace line '$frame'."); + } + // Fake truncated data urls generated by the friendly stack trace format + // cause Uri.parse to throw an exception so we have to special case them. + var uri = match[1] == 'data:...' + ? new Uri.dataFromString('') + : Uri.parse(match[1]); + // If there's no scheme, this is a relative URI. We should interpret it as + // relative to the current working directory. + if (uri.scheme == '') { + uri = path.toUri(path.absolute(path.fromUri(uri))); + } + + var line = match[2] == null ? null : int.parse(match[2]); + var column = match[3] == null ? null : int.parse(match[3]); + return new Frame(uri, line, column, match[4]); + }); /// A regular expression matching an absolute URI. static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 618f00794..97bb391a6 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -26,7 +26,7 @@ class LazyTrace implements Trace { StackTrace get vmTrace => _trace.vmTrace; Trace get terse => new LazyTrace(() => _trace.terse); Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) => - new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); + new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); String toString() => _trace.toString(); // Work around issue 14075. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 948ef309e..1cccd3af6 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -77,7 +77,7 @@ class StackZoneSpecification { /// By default, the first frame of the first trace will be the line where /// [currentChain] is called. If [level] is passed, the first trace will start /// that many frames up instead. - Chain currentChain([int level=0]) => _createNode(level + 1).toChain(); + Chain currentChain([int level = 0]) => _createNode(level + 1).toChain(); /// Returns the stack chain associated with [trace], if one exists. /// @@ -92,8 +92,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneCallback _registerCallback(Zone self, ZoneDelegate parent, Zone zone, - Function f) { + ZoneCallback _registerCallback( + Zone self, ZoneDelegate parent, Zone zone, Function f) { if (f == null || _disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); @@ -101,8 +101,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneUnaryCallback _registerUnaryCallback(Zone self, ZoneDelegate parent, - Zone zone, Function f) { + ZoneUnaryCallback _registerUnaryCallback( + Zone self, ZoneDelegate parent, Zone zone, Function f) { if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { @@ -112,8 +112,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneBinaryCallback _registerBinaryCallback(Zone self, ZoneDelegate parent, - Zone zone, Function f) { + ZoneBinaryCallback _registerBinaryCallback( + Zone self, ZoneDelegate parent, Zone zone, Function f) { if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); var node = _createNode(1); @@ -124,8 +124,8 @@ class StackZoneSpecification { /// Looks up the chain associated with [stackTrace] and passes it either to /// [_onError] or [parent]'s error handler. - _handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, error, - StackTrace stackTrace) { + _handleUncaughtError( + Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { if (_disabled) { return parent.handleUncaughtError(zone, error, stackTrace); } @@ -171,8 +171,8 @@ class StackZoneSpecification { /// By default, the first frame of the first trace will be the line where /// [_createNode] is called. If [level] is passed, the first trace will start /// that many frames up instead. - _Node _createNode([int level=0]) => - new _Node(_currentTrace(level + 1), _currentNode); + _Node _createNode([int level = 0]) => + new _Node(_currentTrace(level + 1), _currentNode); // TODO(nweiz): use a more robust way of detecting and tracking errors when // issue 15105 is fixed. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 9edee6e07..6296df5cf 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -43,16 +43,17 @@ final _v8TraceLine = new RegExp(r" ?at "); final _firefoxSafariTrace = new RegExp( r"^" r"(" // Member description. Not present in some Safari frames. - r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. - r"@" + r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. + r"@" r")?" r"[^\s]*" // Frame URL. r":\d*" // Line or column number. Some older frames only have a line number. - r"$", multiLine: true); + r"$", + multiLine: true); /// A RegExp to match this package's stack traces. -final _friendlyTrace = new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", - multiLine: true); +final _friendlyTrace = + new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { @@ -74,7 +75,7 @@ class Trace implements StackTrace { /// By default, the first frame of this trace will be the line where /// [Trace.current] is called. If [level] is passed, the trace will start that /// many frames up instead. - factory Trace.current([int level=0]) { + factory Trace.current([int level = 0]) { if (level < 0) { throw new ArgumentError("Argument [level] must be greater than or equal " "to 0."); @@ -133,14 +134,14 @@ class Trace implements StackTrace { } /// Parses a string representation of a Dart VM stack trace. - Trace.parseVM(String trace) - : this(_parseVM(trace)); + Trace.parseVM(String trace) : this(_parseVM(trace)); static List _parseVM(String trace) { // Ignore [vmChainGap]. This matches the behavior of // `Chain.parse().toTrace()`. var lines = trace.trim().replaceAll(vmChainGap, '').split("\n"); - var frames = lines.take(lines.length - 1) + var frames = lines + .take(lines.length - 1) .map((line) => new Frame.parseVM(line)) .toList(); @@ -154,16 +155,19 @@ class Trace implements StackTrace { /// Parses a string representation of a Chrome/V8 stack trace. Trace.parseV8(String trace) - : this(trace.split("\n").skip(1) - // It's possible that an Exception's description contains a line that - // looks like a V8 trace line, which will screw this up. - // Unfortunately, that's impossible to detect. - .skipWhile((line) => !line.startsWith(_v8TraceLine)) - .map((line) => new Frame.parseV8(line))); + : this(trace + .split("\n") + .skip(1) + // It's possible that an Exception's description contains a line that + // looks like a V8 trace line, which will screw this up. + // Unfortunately, that's impossible to detect. + .skipWhile((line) => !line.startsWith(_v8TraceLine)) + .map((line) => new Frame.parseV8(line))); /// Parses a string representation of a JavaScriptCore stack trace. Trace.parseJSCore(String trace) - : this(trace.split("\n") + : this(trace + .split("\n") .where((line) => line != "\tat ") .map((line) => new Frame.parseV8(line))); @@ -171,30 +175,31 @@ class Trace implements StackTrace { /// /// IE10+ traces look just like V8 traces. Prior to IE10, stack traces can't /// be retrieved. - Trace.parseIE(String trace) - : this.parseV8(trace); + Trace.parseIE(String trace) : this.parseV8(trace); /// Parses a string representation of a Firefox stack trace. Trace.parseFirefox(String trace) - : this(trace.trim().split("\n") - .where((line) => line.isNotEmpty && line != '[native code]') - .map((line) => new Frame.parseFirefox(line))); + : this(trace + .trim() + .split("\n") + .where((line) => line.isNotEmpty && line != '[native code]') + .map((line) => new Frame.parseFirefox(line))); /// Parses a string representation of a Safari stack trace. - Trace.parseSafari(String trace) - : this.parseFirefox(trace); + Trace.parseSafari(String trace) : this.parseFirefox(trace); /// Parses a string representation of a Safari 6.1+ stack trace. @Deprecated("Use Trace.parseSafari instead.") - Trace.parseSafari6_1(String trace) - : this.parseSafari(trace); + Trace.parseSafari6_1(String trace) : this.parseSafari(trace); /// Parses a string representation of a Safari 6.0 stack trace. @Deprecated("Use Trace.parseSafari instead.") Trace.parseSafari6_0(String trace) - : this(trace.trim().split("\n") - .where((line) => line != '[native code]') - .map((line) => new Frame.parseFirefox(line))); + : this(trace + .trim() + .split("\n") + .where((line) => line != '[native code]') + .map((line) => new Frame.parseFirefox(line))); /// Parses this package's string representation of a stack trace. /// @@ -203,14 +208,15 @@ class Trace implements StackTrace { Trace.parseFriendly(String trace) : this(trace.isEmpty ? [] - : trace.trim().split("\n") + : trace + .trim() + .split("\n") // Filter out asynchronous gaps from [Chain]s. .where((line) => !line.startsWith('=====')) .map((line) => new Frame.parseFriendly(line))); /// Returns a new [Trace] comprised of [frames]. - Trace(Iterable frames) - : frames = new List.unmodifiable(frames); + Trace(Iterable frames) : frames = new List.unmodifiable(frames); /// Returns a VM-style [StackTrace] object. /// @@ -274,8 +280,8 @@ class Trace implements StackTrace { if (frame is UnparsedFrame || !predicate(frame)) { newFrames.add(frame); } else if (newFrames.isEmpty || !predicate(newFrames.last)) { - newFrames.add(new Frame( - frame.uri, frame.line, frame.column, frame.member)); + newFrames + .add(new Frame(frame.uri, frame.line, frame.column, frame.member)); } } @@ -297,8 +303,8 @@ class Trace implements StackTrace { /// Returns a human-readable string representation of [this]. String toString() { // Figure out the longest path so we know how much to pad. - var longest = frames.map((frame) => frame.location.length) - .fold(0, math.max); + var longest = + frames.map((frame) => frame.location.length).fold(0, math.max); // Print out the stack trace nicely formatted. return frames.map((frame) { diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index 7ba9a6391..78ac738e8 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -21,4 +21,4 @@ class UnparsedFrame implements Frame { UnparsedFrame(this.member); String toString() => member; -} \ No newline at end of file +} diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index b974aa98a..407cc2b9c 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -28,9 +28,9 @@ void main() { }); test('parses a chain containing empty traces', () { - var chain = new Chain.parse( - '===== asynchronous gap ===========================\n' - '===== asynchronous gap ===========================\n'); + var chain = + new Chain.parse('===== asynchronous gap ===========================\n' + '===== asynchronous gap ===========================\n'); expect(chain.traces, hasLength(3)); expect(chain.traces[0].frames, isEmpty); expect(chain.traces[1].frames, isEmpty); @@ -136,67 +136,63 @@ void main() { new Trace.parse('loooooooooooong 10:11 Zop.zoop') ]); - expect(chain.toString(), equals( - 'short 10:11 Foo.bar\n' - '===== asynchronous gap ===========================\n' - 'loooooooooooong 10:11 Zop.zoop\n')); + expect( + chain.toString(), + equals('short 10:11 Foo.bar\n' + '===== asynchronous gap ===========================\n' + 'loooooooooooong 10:11 Zop.zoop\n')); }); var userSlashCode = p.join('user', 'code.dart'); group('Chain.terse', () { test('makes each trace terse', () { var chain = new Chain([ - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' + new Trace.parse('dart:core 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n' 'user/code.dart 10:11 Bang.qux\n' 'dart:core 10:11 Zip.zap\n' 'dart:core 10:11 Zop.zoop'), - new Trace.parse( - 'user/code.dart 10:11 Bang.qux\n' + new Trace.parse('user/code.dart 10:11 Bang.qux\n' 'dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap\n' 'user/code.dart 10:11 Zop.zoop') ]); - expect(chain.terse.toString(), equals( - 'dart:core Bar.baz\n' - '$userSlashCode 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Bang.qux\n' - 'dart:core Zip.zap\n' - '$userSlashCode 10:11 Zop.zoop\n')); + expect( + chain.terse.toString(), + equals('dart:core Bar.baz\n' + '$userSlashCode 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Bang.qux\n' + 'dart:core Zip.zap\n' + '$userSlashCode 10:11 Zop.zoop\n')); }); test('eliminates internal-only traces', () { var chain = new Chain([ - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' + new Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz'), - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' + new Trace.parse('dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap'), - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' + new Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz') ]); - expect(chain.terse.toString(), equals( - '$userSlashCode 10:11 Foo.bar\n' - '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Foo.bar\n')); + expect( + chain.terse.toString(), + equals('$userSlashCode 10:11 Foo.bar\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Foo.bar\n')); }); test("doesn't return an empty chain", () { var chain = new Chain([ - new Trace.parse( - 'dart:core 10:11 Foo.bar\n' + new Trace.parse('dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap'), - new Trace.parse( - 'dart:core 10:11 A.b\n' + new Trace.parse('dart:core 10:11 A.b\n' 'package:stack_trace/stack_trace.dart 10:11 C.d\n' 'dart:core 10:11 E.f') ]); @@ -212,24 +208,23 @@ void main() { new Trace.parse('user/code.dart 10:11 Bang.qux') ]); - expect(chain.terse.toString(), equals( - '$userSlashCode 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - '$userSlashCode 10:11 Bang.qux\n')); + expect( + chain.terse.toString(), + equals('$userSlashCode 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + '$userSlashCode 10:11 Bang.qux\n')); }); }); group('Chain.foldFrames', () { test('folds each trace', () { var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'b.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' 'a.dart 10:11 Zop.zoop'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'a.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' @@ -237,67 +232,64 @@ void main() { ]); var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); - expect(folded.toString(), equals( - 'a.dart 10:11 Bar.baz\n' - 'b.dart 10:11 Bang.qux\n' - 'a.dart 10:11 Zop.zoop\n' - '===== asynchronous gap ===========================\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); + expect( + folded.toString(), + equals('a.dart 10:11 Bar.baz\n' + 'b.dart 10:11 Bang.qux\n' + 'a.dart 10:11 Zop.zoop\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); }); test('with terse: true, folds core frames as well', () { var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'dart:async-patch/future.dart 10:11 Zip.zap\n' 'b.dart 10:11 Bang.qux\n' 'dart:core 10:11 Bar.baz\n' 'a.dart 10:11 Zop.zoop'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'a.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' 'b.dart 10:11 Zop.zoop') ]); - var folded = chain.foldFrames((frame) => frame.library == 'a.dart', - terse: true); - expect(folded.toString(), equals( - 'dart:async Zip.zap\n' - 'b.dart 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - 'a.dart Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); + var folded = + chain.foldFrames((frame) => frame.library == 'a.dart', terse: true); + expect( + folded.toString(), + equals('dart:async Zip.zap\n' + 'b.dart 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + 'a.dart Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); }); test('eliminates completely-folded traces', () { var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'b.dart 10:11 Bang.qux'), - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bang.qux'), - new Trace.parse( - 'a.dart 10:11 Zip.zap\n' + new Trace.parse('a.dart 10:11 Zip.zap\n' 'b.dart 10:11 Zop.zoop') ]); var folded = chain.foldFrames((frame) => frame.library == 'a.dart'); - expect(folded.toString(), equals( - 'a.dart 10:11 Foo.bar\n' - 'b.dart 10:11 Bang.qux\n' - '===== asynchronous gap ===========================\n' - 'a.dart 10:11 Zip.zap\n' - 'b.dart 10:11 Zop.zoop\n')); + expect( + folded.toString(), + equals('a.dart 10:11 Foo.bar\n' + 'b.dart 10:11 Bang.qux\n' + '===== asynchronous gap ===========================\n' + 'a.dart 10:11 Zip.zap\n' + 'b.dart 10:11 Zop.zoop\n')); }); test("doesn't return an empty trace", () { var chain = new Chain([ - new Trace.parse( - 'a.dart 10:11 Foo.bar\n' + new Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bang.qux') ]); @@ -308,18 +300,17 @@ void main() { test('Chain.toTrace eliminates asynchronous gaps', () { var trace = new Chain([ - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' + new Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz'), - new Trace.parse( - 'user/code.dart 10:11 Foo.bar\n' + new Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz') ]).toTrace(); - expect(trace.toString(), equals( - '$userSlashCode 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz\n' - '$userSlashCode 10:11 Foo.bar\n' - 'dart:core 10:11 Bar.baz\n')); + expect( + trace.toString(), + equals('$userSlashCode 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n' + '$userSlashCode 10:11 Foo.bar\n' + 'dart:core 10:11 Bar.baz\n')); }); } diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index b8d3a825d..df3d07bd9 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -28,14 +28,14 @@ void main() { }); test('thrown in a one-shot timer', () async { - var chain = await captureFuture( - () => inOneShotTimer(() => throw 'error')); + var chain = + await captureFuture(() => inOneShotTimer(() => throw 'error')); expect(chain.traces, hasLength(2)); }); test('thrown in a periodic timer', () async { - var chain = await captureFuture( - () => inPeriodicTimer(() => throw 'error')); + var chain = + await captureFuture(() => inPeriodicTimer(() => throw 'error')); expect(chain.traces, hasLength(2)); }); @@ -238,7 +238,8 @@ void main() { }); }); - test('current() outside of capture() returns a chain wrapping the current ' + test( + 'current() outside of capture() returns a chain wrapping the current ' 'trace', () { // The test runner runs all tests with chains enabled. return Chain.disable(() async { @@ -281,7 +282,8 @@ void main() { expect(chain.traces, hasLength(3)); }); - test('called for a stack trace from a nested series of asynchronous ' + test( + 'called for a stack trace from a nested series of asynchronous ' 'operations', () async { var chain = await Chain.capture(() { return chainForTrace((callback) { @@ -300,7 +302,8 @@ void main() { expect(chain.traces, hasLength(3)); }); - test('called for an unregistered stack trace returns a chain wrapping that ' + test( + 'called for an unregistered stack trace returns a chain wrapping that ' 'trace', () { var trace; var chain = Chain.capture(() { @@ -318,7 +321,8 @@ void main() { }); }); - test('forTrace() outside of capture() returns a chain wrapping the given ' + test( + 'forTrace() outside of capture() returns a chain wrapping the given ' 'trace', () { var trace; var chain = Chain.capture(() { diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index f345fc007..bf821588d 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -70,7 +70,8 @@ Future chainForTrace(asyncFn(callback()), callback()) { // [new Future.sync] because those methods don't pass the exception through // the zone specification before propagating it, so there's no chance to // attach a chain to its stack trace. See issue 15105. - new Future.value().then((_) => callback()) + new Future.value() + .then((_) => callback()) .catchError(completer.completeError); }); diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 716b146bc..daf7f8f11 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -17,11 +17,10 @@ import 'utils.dart'; void main() { group('capture() with onError catches exceptions', () { test('thrown synchronously', () { - return captureFuture(() => throw 'error') - .then((chain) { + return captureFuture(() => throw 'error').then((chain) { expect(chain.traces, hasLength(1)); - expect(chain.traces.single.frames.first, - frameMember(startsWith('main'))); + expect( + chain.traces.single.frames.first, frameMember(startsWith('main'))); }); }); @@ -349,7 +348,8 @@ void main() { }); }); - test('current() outside of capture() returns a chain wrapping the current ' + test( + 'current() outside of capture() returns a chain wrapping the current ' 'trace', () { // The test runner runs all tests with chains enabled. return Chain.disable(() { @@ -361,8 +361,8 @@ void main() { // chain isn't available and it just returns the current stack when // called. expect(chain.traces, hasLength(1)); - expect(chain.traces.first.frames.first, - frameMember(startsWith('main'))); + expect( + chain.traces.first.frames.first, frameMember(startsWith('main'))); }); }); }); @@ -410,7 +410,8 @@ void main() { }); }); - test('called for a stack trace from a nested series of asynchronous ' + test( + 'called for a stack trace from a nested series of asynchronous ' 'operations', () { return Chain.capture(() { return chainForTrace((callback) { @@ -443,7 +444,8 @@ void main() { }); }); - test('called for an unregistered stack trace returns a chain wrapping that ' + test( + 'called for an unregistered stack trace returns a chain wrapping that ' 'trace', () { var trace; var chain = Chain.capture(() { @@ -461,7 +463,8 @@ void main() { }); }); - test('forTrace() outside of capture() returns a chain wrapping the given ' + test( + 'forTrace() outside of capture() returns a chain wrapping the given ' 'trace', () { var trace; var chain = Chain.capture(() { diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index a5f8b2344..42df4cddf 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -11,8 +11,8 @@ void main() { test('parses a stack frame with column correctly', () { var frame = new Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:42:21)"); - expect(frame.uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect( + frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); expect(frame.line, equals(42)); expect(frame.column, equals(21)); expect(frame.member, equals('Foo._bar')); @@ -21,8 +21,8 @@ void main() { test('parses a stack frame without column correctly', () { var frame = new Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:24)"); - expect(frame.uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect( + frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); expect(frame.line, equals(24)); expect(frame.column, null); expect(frame.member, equals('Foo._bar')); @@ -32,8 +32,8 @@ void main() { test('parses a stack frame without line or column correctly', () { var frame = new Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart)"); - expect(frame.uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + expect( + frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('Foo._bar')); @@ -55,8 +55,8 @@ void main() { }); test('converts "" to ""', () { - var frame = new Frame.parseVM( - '#0 Foo. (foo:0:0)'); + var frame = + new Frame.parseVM('#0 Foo. (foo:0:0)'); expect(frame.member, equals('Foo.')); }); @@ -112,8 +112,8 @@ void main() { test('parses a stack frame with a Windows UNC path correctly', () { var frame = new Frame.parseV8(" at VW.call\$0 " r"(\\mount\path\to\stuff.dart.js:560:28)"); - expect(frame.uri, - equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + expect( + frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); @@ -148,8 +148,7 @@ void main() { }); test('parses a native stack frame correctly', () { - var frame = new Frame.parseV8( - " at Object.stringify (native)"); + var frame = new Frame.parseV8(" at Object.stringify (native)"); expect(frame.uri, Uri.parse('native')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -213,8 +212,8 @@ void main() { new Frame.parseV8(' at $member (foo:0:0)').member; expect(parsedMember('Foo.'), equals('Foo.')); - expect(parsedMember('..bar'), - equals('..bar')); + expect( + parsedMember('..bar'), equals('..bar')); }); test('returns an UnparsedFrame for malformed frames', () { @@ -227,12 +226,12 @@ void main() { ' at (dart:async/future.dart:10:15)'); expectIsUnparsed((text) => new Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); - expectIsUnparsed((text) => new Frame.parseV8(text), - ' at dart:async/future.dart'); + expectIsUnparsed( + (text) => new Frame.parseV8(text), ' at dart:async/future.dart'); expectIsUnparsed((text) => new Frame.parseV8(text), ' at dart:async/future.dart:10'); - expectIsUnparsed((text) => new Frame.parseV8(text), - 'dart:async/future.dart:10:15'); + expectIsUnparsed( + (text) => new Frame.parseV8(text), 'dart:async/future.dart:10:15'); }); }); @@ -248,8 +247,8 @@ void main() { }); test('parses a stack frame with an absolute POSIX path correctly', () { - var frame = new Frame.parseFirefox( - ".VW.call\$0@/path/to/stuff.dart.js:560"); + var frame = + new Frame.parseFirefox(".VW.call\$0@/path/to/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -257,8 +256,8 @@ void main() { }); test('parses a stack frame with an absolute Windows path correctly', () { - var frame = new Frame.parseFirefox( - r".VW.call$0@C:\path\to\stuff.dart.js:560"); + var frame = + new Frame.parseFirefox(r".VW.call$0@C:\path\to\stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -268,16 +267,16 @@ void main() { test('parses a stack frame with a Windows UNC path correctly', () { var frame = new Frame.parseFirefox( r".VW.call$0@\\mount\path\to\stuff.dart.js:560"); - expect(frame.uri, - equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + expect( + frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a relative POSIX path correctly', () { - var frame = new Frame.parseFirefox( - ".VW.call\$0@path/to/stuff.dart.js:560"); + var frame = + new Frame.parseFirefox(".VW.call\$0@path/to/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -285,8 +284,8 @@ void main() { }); test('parses a stack frame with a relative Windows path correctly', () { - var frame = new Frame.parseFirefox( - r".VW.call$0@path\to\stuff.dart.js:560"); + var frame = + new Frame.parseFirefox(r".VW.call$0@path\to\stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -294,8 +293,8 @@ void main() { }); test('parses a simple anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( - "@http://pub.dartlang.org/stuff.dart.js:560"); + var frame = + new Frame.parseFirefox("@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -350,8 +349,7 @@ void main() { }); test('parses a nested anonymous stack frame with parameters correctly', () { - var frame = new Frame.parseFirefox( - '.foo(12, "@)()/<")/.fn<@' + var frame = new Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' 'http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -360,11 +358,12 @@ void main() { expect(frame.member, equals("foo.")); }); - test('parses a deeply-nested anonymous stack frame with parameters ' + test( + 'parses a deeply-nested anonymous stack frame with parameters ' 'correctly', () { - var frame = new Frame.parseFirefox( - '.convertDartClosureToJS/\$function new Frame.parseFirefox(text), '.foo(@dart:async/future.dart:10'); - expectIsUnparsed((text) => new Frame.parseFirefox(text), - '@dart:async/future.dart'); + expectIsUnparsed( + (text) => new Frame.parseFirefox(text), '@dart:async/future.dart'); }); test('parses a simple stack frame correctly', () { @@ -393,8 +392,8 @@ void main() { }); test('parses an anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( - "http://dartlang.org/foo/bar.dart:10:11"); + var frame = + new Frame.parseFirefox("http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -459,8 +458,8 @@ void main() { test('parses a stack frame with a relative path correctly', () { var frame = new Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); - expect(frame.uri, equals( - path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); + expect(frame.uri, + equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('Foo..bar')); @@ -469,13 +468,12 @@ void main() { test('returns an UnparsedFrame for malformed frames', () { expectIsUnparsed((text) => new Frame.parseFriendly(text), ''); expectIsUnparsed((text) => new Frame.parseFriendly(text), 'foo/bar.dart'); - expectIsUnparsed((text) => new Frame.parseFriendly(text), - 'foo/bar.dart 10:11'); + expectIsUnparsed( + (text) => new Frame.parseFriendly(text), 'foo/bar.dart 10:11'); }); test('parses a data url stack frame with no line or column correctly', () { - var frame = new Frame.parseFriendly( - "data:... main"); + var frame = new Frame.parseFriendly("data:... main"); expect(frame.uri.scheme, equals('data')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -483,8 +481,7 @@ void main() { }); test('parses a data url stack frame correctly', () { - var frame = new Frame.parseFriendly( - "data:... 10:11 main"); + var frame = new Frame.parseFriendly("data:... 10:11 main"); expect(frame.uri.scheme, equals('data')); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -501,12 +498,12 @@ void main() { expect(frame.member, equals('(anonymous function).dart.fn')); }); - test('parses a stack frame with spaces in the member name and no line or ' - 'column correctly', () { + test( + 'parses a stack frame with spaces in the member name and no line or ' + 'column correctly', () { var frame = new Frame.parseFriendly( "http://dartlang.org/foo/bar.dart (anonymous function).dart.fn"); - expect( - frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('(anonymous function).dart.fn')); @@ -515,7 +512,7 @@ void main() { test('only considers dart URIs to be core', () { bool isCore(String library) => - new Frame.parseVM('#0 Foo ($library:0:0)').isCore; + new Frame.parseVM('#0 Foo ($library:0:0)').isCore; expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); @@ -531,8 +528,10 @@ void main() { test('returns the URI string for non-file URIs', () { expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, equals('dart:async/future.dart')); - expect(new Frame.parseVM('#0 Foo ' - '(http://dartlang.org/stuff/thing.dart:0:0)').library, + expect( + new Frame.parseVM('#0 Foo ' + '(http://dartlang.org/stuff/thing.dart:0:0)') + .library, equals('http://dartlang.org/stuff/thing.dart')); }); @@ -549,10 +548,13 @@ void main() { }); group('.location', () { - test('returns the library and line/column numbers for non-core ' + test( + 'returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parseVM('#0 Foo ' - '(http://dartlang.org/thing.dart:5:10)').location, + expect( + new Frame.parseVM('#0 Foo ' + '(http://dartlang.org/thing.dart:5:10)') + .location, equals('http://dartlang.org/thing.dart 5:10')); expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); @@ -563,8 +565,10 @@ void main() { test('returns null for non-package URIs', () { expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, isNull); - expect(new Frame.parseVM('#0 Foo ' - '(http://dartlang.org/stuff/thing.dart:0:0)').package, + expect( + new Frame.parseVM('#0 Foo ' + '(http://dartlang.org/stuff/thing.dart:0:0)') + .package, isNull); }); @@ -577,16 +581,20 @@ void main() { }); group('.toString()', () { - test('returns the library and line/column numbers for non-core ' + test( + 'returns the library and line/column numbers for non-core ' 'libraries', () { - expect(new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') + expect( + new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') .toString(), equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { - expect(new Frame.parseVM('#0 Foo. ' - '(dart:core/uri.dart:5:10)').toString(), + expect( + new Frame.parseVM('#0 Foo. ' + '(dart:core/uri.dart:5:10)') + .toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 1297932ee..33d4f4ee8 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -20,7 +20,7 @@ void main() { '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' '#1 zip..zap (dart:async/future.dart:0:2)\n' '#2 zip..zap (http://pub.dartlang.org/thing.' - 'dart:1:100)'); + 'dart:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); @@ -30,12 +30,11 @@ void main() { }); test('parses a V8 stack trace correctly', () { - var trace = new Trace.parse( - 'Error\n' + var trace = new Trace.parse('Error\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -44,12 +43,11 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( - "Exception: foo\n" + trace = new Trace.parse("Exception: foo\n" ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -58,13 +56,12 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( - 'Exception: foo\n' + trace = new Trace.parse('Exception: foo\n' ' bar\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -73,13 +70,12 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( - 'Exception: foo\n' + trace = new Trace.parse('Exception: foo\n' ' bar\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at (anonymous function).zip.zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -98,7 +94,7 @@ void main() { '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' '\tat http://pub.dartlang.org/stuff.js:0:2\n' '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -111,7 +107,7 @@ void main() { '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' '\tat \n' '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -120,10 +116,10 @@ void main() { }); test('parses a Firefox/Safari stack trace correctly', () { - var trace = new Trace.parse( - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = + new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -132,8 +128,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + trace = new Trace.parse('zip/<@http://pub.dartlang.org/stuff.js:0\n' 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); @@ -159,11 +154,11 @@ void main() { test('parses a Firefox/Safari stack trace containing native code correctly', () { - var trace = new Trace.parse( - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' - '[native code]'); + var trace = + new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + '[native code]'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -176,8 +171,7 @@ void main() { test('parses a Firefox/Safari stack trace without a method name correctly', () { - var trace = new Trace.parse( - 'http://pub.dartlang.org/stuff.js:42\n' + var trace = new Trace.parse('http://pub.dartlang.org/stuff.js:42\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); @@ -192,11 +186,11 @@ void main() { test('parses a Firefox/Safari stack trace with an empty line correctly', () { - var trace = new Trace.parse( - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - '\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = + new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + '\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -208,10 +202,10 @@ void main() { test('parses a Firefox/Safari stack trace with a column number correctly', () { - var trace = new Trace.parse( - 'Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = + new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -286,10 +280,11 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap new Frame(Uri.parse('dart:async'), 15, null, 'baz'), ]); - expect(trace.vmTrace.toString(), equals( - '#1 Foo. ($uri:10:20)\n' - '#2 bar (http://dartlang.org/foo.dart:0:0)\n' - '#3 baz (dart:async:15:0)\n')); + expect( + trace.vmTrace.toString(), + equals('#1 Foo. ($uri:10:20)\n' + '#2 bar (http://dartlang.org/foo.dart:0:0)\n' + '#3 baz (dart:async:15:0)\n')); }); group("folding", () { @@ -335,7 +330,7 @@ foo.dart 42:21 notCore #4 bottom (dart:async-patch/future.dart:9:11) '''); - expect(trace.terse.toString(), equals(''' + expect(trace.terse.toString(), equals(''' foo.dart 42:21 notCore ''')); }); @@ -367,7 +362,8 @@ dart:core bottom #5 fooBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo')); + var folded = + trace.foldFrames((frame) => frame.member.startsWith('foo')); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo foo.dart 1:100 fooBottom @@ -401,14 +397,15 @@ dart:async-patch/future.dart 9:11 fooBottom #5 coreBottom (dart:async-patch/future.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + var folded = trace.foldFrames( + (frame) => frame.member.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo dart:async coreBottom bar.dart 10:20 alsoNotFoo ''')); - }); + }); test('shortens folded frames', () { var trace = new Trace.parse(''' @@ -421,7 +418,8 @@ bar.dart 10:20 alsoNotFoo #6 againNotFoo (bar.dart:20:20) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + var folded = trace.foldFrames( + (frame) => frame.member.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo @@ -439,7 +437,8 @@ bar.dart 20:20 againNotFoo #5 fooBottom (foo/bar.dart:9:11) '''); - var folded = trace.foldFrames((frame) => frame.member.startsWith('foo'), + var folded = trace.foldFrames( + (frame) => frame.member.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' package:foo fooTop diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index afa384c47..0241b3737 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -6,11 +6,11 @@ import 'package:test/test.dart'; /// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. Matcher frameMember(matcher) => - transform((frame) => frame.member, matcher, 'member'); + transform((frame) => frame.member, matcher, 'member'); /// Returns a matcher that runs [matcher] against a [Frame]'s `library` field. Matcher frameLibrary(matcher) => - transform((frame) => frame.library, matcher, 'library'); + transform((frame) => frame.library, matcher, 'library'); /// Returns a matcher that runs [transformation] on its input, then matches /// the output against [matcher]. @@ -18,7 +18,7 @@ Matcher frameLibrary(matcher) => /// [description] should be a noun phrase that describes the relation of the /// output of [transformation] to its input. Matcher transform(transformation(value), matcher, String description) => - new _TransformMatcher(transformation, wrapMatcher(matcher), description); + new _TransformMatcher(transformation, wrapMatcher(matcher), description); class _TransformMatcher extends Matcher { final Function _transformation; @@ -28,8 +28,8 @@ class _TransformMatcher extends Matcher { _TransformMatcher(this._transformation, this._matcher, this._description); bool matches(item, Map matchState) => - _matcher.matches(_transformation(item), matchState); + _matcher.matches(_transformation(item), matchState); Description describe(Description description) => - description.add(_description).add(' ').addDescriptionOf(_matcher); + description.add(_description).add(' ').addDescriptionOf(_matcher); } From c20f164cda14a6f207fe1d3ba46b88c8e6405366 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 6 Apr 2017 21:08:48 -0700 Subject: [PATCH 0295/1215] add Travis-CI support --- pkgs/stack_trace/.travis.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 pkgs/stack_trace/.travis.yml diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml new file mode 100644 index 000000000..b6198f750 --- /dev/null +++ b/pkgs/stack_trace/.travis.yml @@ -0,0 +1,24 @@ +language: dart +sudo: false +dart: + - stable + - dev + - 1.22.1 + - 1.21.1 + - 1.20.1 + - 1.19.1 +dart_task: + - test: -p vm + - test: -p firefox + - test: -p dartium + install_dartium: true + - dartanalyzer +matrix: + include: + # Only validate formatting using the dev release + # Formatted with 1.23.0+ which has (good) changes since 1.22.1 + - dart: dev + dart_task: dartfmt +cache: + directories: + - $HOME/.pub-cache From 0d937ca452af7c40cf5b5fbe1b4dd5080fd16c15 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 7 Apr 2017 10:05:43 -0700 Subject: [PATCH 0296/1215] use the recommended analysis_options file name --- pkgs/stack_trace/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/stack_trace/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/stack_trace/.analysis_options b/pkgs/stack_trace/analysis_options.yaml similarity index 100% rename from pkgs/stack_trace/.analysis_options rename to pkgs/stack_trace/analysis_options.yaml From 22917e7bc5d37ac7e538d8b5027ed6b2bb50fcb7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 7 Apr 2017 10:09:45 -0700 Subject: [PATCH 0297/1215] =?UTF-8?q?Bump=20the=20minimum=20required=20SDK?= =?UTF-8?q?=20=E2=80=93=C2=A0use=20official=20generic=20method=20syntax?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/stack_trace/.travis.yml | 4 +--- pkgs/stack_trace/lib/src/chain.dart | 10 ++++------ pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index b6198f750..fff84941a 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -1,12 +1,10 @@ language: dart sudo: false dart: - - stable - dev + - stable - 1.22.1 - 1.21.1 - - 1.20.1 - - 1.19.1 dart_task: - test: -p vm - test: -p firefox diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 04a153a75..e93b2b445 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -70,7 +70,7 @@ class Chain implements StackTrace { /// considered unhandled. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static/*=T*/ capture/**/(/*=T*/ callback(), + static T capture(T callback(), {void onError(error, Chain chain), bool when: true}) { if (!when) { var newOnError; @@ -95,11 +95,9 @@ class Chain implements StackTrace { // TODO(nweiz): Don't special-case this when issue 19566 is fixed. return Zone.current.handleUncaughtError(error, stackTrace); } - }, zoneSpecification: spec.toSpec(), zoneValues: { - _specKey: spec, - StackZoneSpecification.disableKey: false - }) as dynamic/*=T*/; - // TODO(rnystrom): Remove this cast if runZoned() gets a generic type. + }, + zoneSpecification: spec.toSpec(), + zoneValues: {_specKey: spec, StackZoneSpecification.disableKey: false}); } /// If [when] is `true` and this is called within a [Chain.capture] zone, runs diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 93f059eaa..94054ecae 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -17,4 +17,4 @@ dependencies: dev_dependencies: test: '^0.12.17' environment: - sdk: ">=1.14.0 <2.0.0" + sdk: ">=1.21.0 <2.0.0" From 84801f0abe640562f0943fba39332a654ef6c2aa Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 1 May 2017 12:38:59 -0700 Subject: [PATCH 0298/1215] New package stream_transform --- pkgs/stream_transform/.gitignore | 5 +++ pkgs/stream_transform/analysis_options.yaml | 37 +++++++++++++++++++++ pkgs/stream_transform/pubspec.yaml | 10 ++++++ 3 files changed, 52 insertions(+) create mode 100644 pkgs/stream_transform/.gitignore create mode 100644 pkgs/stream_transform/analysis_options.yaml create mode 100644 pkgs/stream_transform/pubspec.yaml diff --git a/pkgs/stream_transform/.gitignore b/pkgs/stream_transform/.gitignore new file mode 100644 index 000000000..47f11e5fc --- /dev/null +++ b/pkgs/stream_transform/.gitignore @@ -0,0 +1,5 @@ +.pub/ +build/ +packages +pubspec.lock +.packages diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml new file mode 100644 index 000000000..590a8e5da --- /dev/null +++ b/pkgs/stream_transform/analysis_options.yaml @@ -0,0 +1,37 @@ +analyzer: + strong-mode: true + errors: + unused_import: error + unused_local_variable: error + dead_code: error + override_on_non_overriding_method: error + +linter: + rules: + # Errors + - avoid_empty_else + # Wait for FutureOr to work + #- await_only_futures + - comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - test_types_in_equals + - throw_in_finally + - unawaited_futures + - unrelated_type_equality_checks + - valid_regexps + + # Style + - annotate_overrides + - avoid_init_to_null + - avoid_return_types_on_setters + - camel_case_types + - empty_catches + - empty_constructor_bodies + - library_names + - library_prefixes + - non_constant_identifier_names + - prefer_is_not_empty + - slash_for_doc_comments + - type_init_formals diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml new file mode 100644 index 000000000..129aa9c5e --- /dev/null +++ b/pkgs/stream_transform/pubspec.yaml @@ -0,0 +1,10 @@ +name: stream_transform +description: A collection of utilities to transform and manipulate streams. +author: Dart Team +homepage: https://www.github.com/dart-lang/stream_transform + +environment: + sdk: ">=1.22.0 <2.0.0" + +dev_dependencies: + test: ^0.12.0 From 05740a167c15b2161b70918f33c78f19992bc0bc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 1 May 2017 14:24:16 -0700 Subject: [PATCH 0299/1215] Add public library and buffer utility (dart-lang/stream_transform#2) - Add `buffer` utility and tests - Export buffer from package library - Add travis config - Add README, CHANGELOG, and version --- pkgs/stream_transform/.travis.yml | 13 ++ pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/README.md | 7 + pkgs/stream_transform/lib/src/buffer.dart | 144 ++++++++++++++ .../lib/stream_transform.dart | 5 + pkgs/stream_transform/pubspec.yaml | 1 + pkgs/stream_transform/test/buffer_test.dart | 185 ++++++++++++++++++ 7 files changed, 359 insertions(+) create mode 100644 pkgs/stream_transform/.travis.yml create mode 100644 pkgs/stream_transform/CHANGELOG.md create mode 100644 pkgs/stream_transform/README.md create mode 100644 pkgs/stream_transform/lib/src/buffer.dart create mode 100644 pkgs/stream_transform/lib/stream_transform.dart create mode 100644 pkgs/stream_transform/test/buffer_test.dart diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml new file mode 100644 index 000000000..ed6c5bb16 --- /dev/null +++ b/pkgs/stream_transform/.travis.yml @@ -0,0 +1,13 @@ +language: dart +sudo: false +dart: + - dev + - stable + - 1.22.1 +cache: + directories: + - $HOME/.pub-cache +dart_task: + - test + - dartfmt + - dartanalyzer diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md new file mode 100644 index 000000000..af394b66e --- /dev/null +++ b/pkgs/stream_transform/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.0.1 + +- Add `buffer` utility. Collects events in a `List` until a `trigger` stream + fires. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md new file mode 100644 index 000000000..ecab8a4e2 --- /dev/null +++ b/pkgs/stream_transform/README.md @@ -0,0 +1,7 @@ +Contains utility methods to create `StreamTransfomer` instances to manipulate +Streams. + +# buffer + +Collects values from a source stream until a `trigger` stream fires and the +collected values are emitted. diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart new file mode 100644 index 000000000..4f2976d9c --- /dev/null +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -0,0 +1,144 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Creates a [StreamTransformer] which collects values and emits when it sees a +/// value on [trigger]. +/// +/// If there are no pending values when [trigger] emits, the next value on the +/// source Stream will immediately flow through. Otherwise, the pending values +/// are released when [trigger] emits. +/// +/// Errors from the source stream or the trigger are immediately forwarded to +/// the output. +StreamTransformer> buffer(Stream trigger) => new _Buffer(trigger); + +List _collectToList(T element, List soFar) { + soFar ??= []; + soFar.add(element); + return soFar; +} + +/// A StreamTransformer which aggregates values and emits when it sees a value +/// on [_trigger]. +/// +/// If there are no pending values when [_trigger] emits the first value on the +/// source Stream will immediately flow through. Otherwise, the pending values +/// and released when [_trigger] emits. +/// +/// Errors from the source stream or the trigger are immediately forwarded to +/// the output. +class _Buffer implements StreamTransformer> { + final Stream _trigger; + + _Buffer(this._trigger); + + @override + Stream> bind(Stream values) { + StreamController> controller; + if (values.isBroadcast) { + controller = new StreamController>.broadcast(); + } else { + controller = new StreamController>(); + } + + List currentResults; + bool waitingForTrigger = true; + StreamSubscription valuesSub; + StreamSubscription triggerSub; + + cancelValues() { + var sub = valuesSub; + valuesSub = null; + return sub?.cancel() ?? new Future.value(); + } + + cancelTrigger() { + var sub = triggerSub; + triggerSub = null; + return sub?.cancel() ?? new Future.value(); + } + + closeController() { + var ctl = controller; + controller = null; + return ctl?.close() ?? new Future.value(); + } + + emit() { + controller.add(currentResults); + currentResults = null; + waitingForTrigger = true; + } + + onValue(T value) { + currentResults = _collectToList(value, currentResults); + if (!waitingForTrigger) { + emit(); + } + } + + valuesDone() { + valuesSub = null; + if (currentResults == null) { + closeController(); + cancelTrigger(); + } + } + + onTrigger(_) { + if (currentResults == null) { + waitingForTrigger = false; + return; + } + emit(); + if (valuesSub == null) { + closeController(); + cancelTrigger(); + } + } + + triggerDone() { + cancelValues(); + closeController(); + } + + controller.onListen = () { + if (valuesSub != null) return; + valuesSub = values.listen(onValue, + onError: controller.addError, onDone: valuesDone); + if (triggerSub != null) { + if (triggerSub.isPaused) triggerSub.resume(); + } else { + triggerSub = _trigger.listen(onTrigger, + onError: controller.addError, onDone: triggerDone); + } + }; + + // Forward methods from listener + if (!values.isBroadcast) { + controller.onPause = () { + valuesSub?.pause(); + triggerSub?.pause(); + }; + controller.onResume = () { + valuesSub?.resume(); + triggerSub?.resume(); + }; + controller.onCancel = + () => Future.wait([cancelValues(), cancelTrigger()]); + } else { + controller.onCancel = () { + if (controller?.hasListener ?? false) return; + if (_trigger.isBroadcast) { + cancelTrigger(); + } else { + triggerSub.pause(); + } + cancelValues(); + }; + } + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart new file mode 100644 index 000000000..02069f59c --- /dev/null +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +export 'src/buffer.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 129aa9c5e..b260f12d2 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,6 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform +version: 0.0.1-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart new file mode 100644 index 000000000..c371ac576 --- /dev/null +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -0,0 +1,185 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var triggerType in streamTypes.keys) { + for (var valuesType in streamTypes.keys) { + group('Trigger type: [$triggerType], Values type: [$valuesType]', () { + StreamController trigger; + StreamController values; + List emittedValues; + bool valuesCanceled; + bool triggerCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + + setUp(() async { + valuesCanceled = false; + triggerCanceled = false; + trigger = streamTypes[triggerType]() + ..onCancel = () { + triggerCanceled = true; + }; + values = streamTypes[triggerType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + subscription = values.stream + .transform(buffer(trigger.stream)) + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('does not emit before `trigger`', () async { + values.add(1); + await new Future(() {}); + expect(emittedValues, isEmpty); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); + + test('emits immediately if trigger emits before a value', () async { + trigger.add(null); + await new Future(() {}); + expect(emittedValues, isEmpty); + values.add(1); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); + + test('two triggers in a row - emit then emit next value', () async { + values.add(1); + values.add(2); + await new Future(() {}); + trigger.add(null); + trigger.add(null); + await new Future(() {}); + values.add(3); + await new Future(() {}); + expect(emittedValues, [ + [1, 2], + [3] + ]); + }); + + test('pre-emptive trigger then trigger after values', () async { + trigger.add(null); + await new Future(() {}); + values.add(1); + values.add(2); + await new Future(() {}); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1], + [2] + ]); + }); + + test('multiple pre-emptive triggers, only emits first value', () async { + trigger.add(null); + trigger.add(null); + await new Future(() {}); + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); + + test('groups values between trigger', () async { + values.add(1); + values.add(2); + await new Future(() {}); + trigger.add(null); + values.add(3); + values.add(4); + await new Future(() {}); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1, 2], + [3, 4] + ]); + }); + + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('cancels trigger subscription when output canceled', () async { + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + }); + + test('closes when trigger ends', () async { + expect(isDone, false); + await trigger.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('closes after outputting final values when source closes', + () async { + expect(isDone, false); + values.add(1); + await values.close(); + expect(isDone, false); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + expect(isDone, true); + }); + + test( + 'closes immediately if there are no pending values when source closes', + () async { + expect(isDone, false); + values.add(1); + trigger.add(null); + await values.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('forwards errors from trigger', () async { + trigger.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors from values', () async { + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + }); + } + } +} From c24bf71b9686cf7bca01b68d25889c2908bc8b8b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 May 2017 14:17:29 -0700 Subject: [PATCH 0300/1215] Add `debounce` utilities and prepare for publish (dart-lang/stream_transform#3) - Add `debounce` and `debounceBuffer` to drop or collect values that occur quickly - Add tests - Drop `-dev` from pubspec to prepare for publishing very early version - Add LICENSE file - Exclude dartanalyzer and dartfmt test from 1.22.1 SDK --- pkgs/stream_transform/.travis.yml | 6 + pkgs/stream_transform/CHANGELOG.md | 6 +- pkgs/stream_transform/LICENSE | 26 +++++ pkgs/stream_transform/lib/src/debounce.dart | 57 +++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/debounce_test.dart | 110 ++++++++++++++++++ 7 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_transform/LICENSE create mode 100644 pkgs/stream_transform/lib/src/debounce.dart create mode 100644 pkgs/stream_transform/test/debounce_test.dart diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index ed6c5bb16..4c02d8e9a 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -11,3 +11,9 @@ dart_task: - test - dartfmt - dartanalyzer +matrix: + exclude: + - dart: 1.22.1 + dart_task: dartfmt + - dart: 1.22.1 + dart_task: dartanalyzer diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index af394b66e..cf303c7ee 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,6 @@ ## 0.0.1 -- Add `buffer` utility. Collects events in a `List` until a `trigger` stream - fires. +- Initial release with the following utilities: + - `buffer`: Collects events in a `List` until a `trigger` stream fires. + - `debounce`, `debounceBuffer`: Collect or drop events which occur closer in + time than a given duration. diff --git a/pkgs/stream_transform/LICENSE b/pkgs/stream_transform/LICENSE new file mode 100644 index 000000000..389ce9856 --- /dev/null +++ b/pkgs/stream_transform/LICENSE @@ -0,0 +1,26 @@ +Copyright 2017, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart new file mode 100644 index 000000000..980c37182 --- /dev/null +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Creates a StreamTransformer which only emits when the source stream does not +/// emit for [duration]. +/// +/// Source values will always be delayed by at least [duration], and values +/// which come within this time will replace the old values, only the most +/// recent value will be emitted. +StreamTransformer debounce(Duration duration) => + _debounceAggregate(duration, _dropPrevious); + +/// Creates a StreamTransformer which collects values until the source stream +/// does not emit for [duration] then emits the collected values. +/// +/// This differs from [debounce] in that values are aggregated instead of +/// skipped. +StreamTransformer> debounceBuffer(Duration duration) => + _debounceAggregate(duration, _collectToList); + +List _collectToList(T element, List soFar) { + soFar ??= []; + soFar.add(element); + return soFar; +} + +T _dropPrevious(T element, _) => element; + +/// Creates a StreamTransformer which aggregates values until the source stream +/// does not emit for [duration], then emits the aggregated values. +StreamTransformer _debounceAggregate( + Duration duration, R collect(T element, R soFar)) { + Timer timer; + R soFar; + bool shouldClose = false; + return new StreamTransformer.fromHandlers( + handleData: (T value, EventSink sink) { + timer?.cancel(); + timer = new Timer(duration, () { + sink.add(soFar); + if (shouldClose) { + sink.close(); + } + soFar = null; + timer = null; + }); + soFar = collect(value, soFar); + }, handleDone: (EventSink sink) { + if (soFar != null) { + shouldClose = true; + } else { + sink.close(); + } + }); +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 02069f59c..49a714e69 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -3,3 +3,4 @@ // BSD-style license that can be found in the LICENSE file. export 'src/buffer.dart'; +export 'src/debounce.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index b260f12d2..1cf40346a 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.1-dev +version: 0.0.1 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart new file mode 100644 index 000000000..a556b41e7 --- /dev/null +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -0,0 +1,110 @@ +import 'dart:async'; +import 'package:test/test.dart'; +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var streamType in streamTypes.keys) { + group('Stream type [$streamType]', () { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + + void setUpStreams(StreamTransformer transformer) { + valuesCanceled = false; + values = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + subscription = values.stream + .transform(transformer) + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + + group('debounce', () { + setUp(() async { + setUpStreams(debounce(const Duration(milliseconds: 5))); + }); + + test('cancels values', () async { + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('swallows values that come faster than duration', () async { + values.add(1); + values.add(2); + await values.close(); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [2]); + }); + + test('outputs multiple values spaced further than duration', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [1, 2]); + }); + + test('waits for pending value to close', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + await values.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('closes output if there are no pending values', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future(() {}); + await values.close(); + expect(isDone, false); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(isDone, true); + }); + }); + + group('debounceBuffer', () { + setUp(() async { + setUpStreams(debounceBuffer(const Duration(milliseconds: 5))); + }); + + test('Emits all values as a list', () async { + values.add(1); + values.add(2); + await values.close(); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [ + [1, 2] + ]); + }); + + test('separate lists for multiple values spaced further than duration', + () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [ + [1], + [2] + ]); + }); + }); + }); + } +} From 92af9f8222254078aa0c1baf0336124b4dc69160 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 3 May 2017 10:28:06 -0700 Subject: [PATCH 0301/1215] Implement concat (dart-lang/stream_transform#6) Closes dart-lang/stream_transform#5 concat implementation and tests. Relatively few tests since most behavior is through StreamController.addStream and we have high confidence in that method. Test the thing that is easy to get wrong in this utility - stream closing. Add missing README entry for already added debounce. --- pkgs/stream_transform/CHANGELOG.md | 4 ++ pkgs/stream_transform/README.md | 9 ++++ pkgs/stream_transform/lib/src/concat.dart | 27 +++++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/concat_test.dart | 47 +++++++++++++++++++ 6 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/lib/src/concat.dart create mode 100644 pkgs/stream_transform/test/concat_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index cf303c7ee..1d323aa55 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.2 + +- Add `concat`: Appends streams in series + ## 0.0.1 - Initial release with the following utilities: diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index ecab8a4e2..ac3236287 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -5,3 +5,12 @@ Streams. Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. + +# concat + +Appends the values of a stream after another stream finishes. + +# debounce, debounceBuffer + +Prevents a source stream from emitting too frequently by dropping or collecting +values that occur within a given duration. diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart new file mode 100644 index 000000000..0a2c27ad0 --- /dev/null +++ b/pkgs/stream_transform/lib/src/concat.dart @@ -0,0 +1,27 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Starts emitting values from [next] after the original stream is complete. +/// +/// If the initial stream never finishes, the [next] stream will never be +/// listened to. +StreamTransformer concat(Stream next) => new _Concat(next); + +class _Concat implements StreamTransformer { + final Stream _next; + + _Concat(this._next); + + @override + Stream bind(Stream first) { + var controller = new StreamController(); + controller + .addStream(first) + .then((_) => controller.addStream(_next)) + .then((_) => controller.close()); + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 49a714e69..c128e4bf7 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -4,3 +4,4 @@ export 'src/buffer.dart'; export 'src/debounce.dart'; +export 'src/concat.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 1cf40346a..735204958 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.1 +version: 0.0.2-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/concat_test.dart b/pkgs/stream_transform/test/concat_test.dart new file mode 100644 index 000000000..6cf041b8e --- /dev/null +++ b/pkgs/stream_transform/test/concat_test.dart @@ -0,0 +1,47 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + group('concat', () { + test('adds all values from both streams', () async { + var first = new Stream.fromIterable([1, 2, 3]); + var second = new Stream.fromIterable([4, 5, 6]); + var all = await first.transform(concat(second)).toList(); + expect(all, [1, 2, 3, 4, 5, 6]); + }); + + test('closes first stream on cancel', () async { + var firstStreamClosed = false; + var first = new StreamController() + ..onCancel = () { + firstStreamClosed = true; + }; + var second = new StreamController(); + var subscription = + first.stream.transform(concat(second.stream)).listen((_) {}); + await subscription.cancel(); + expect(firstStreamClosed, true); + }); + + test('closes second stream on cancel if first stream done', () async { + var first = new StreamController(); + var secondStreamClosed = false; + var second = new StreamController() + ..onCancel = () { + secondStreamClosed = true; + }; + var subscription = + first.stream.transform(concat(second.stream)).listen((_) {}); + await first.close(); + await new Future(() {}); + await subscription.cancel(); + expect(secondStreamClosed, true); + }); + }); +} From 4d7b85887f600e71af18fe22100ad3611d885e09 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 May 2017 10:58:31 -0700 Subject: [PATCH 0302/1215] Fix analyzer error (dart-lang/stream_transform#8) Had a typo, dev version of the analyzer caught this. --- pkgs/stream_transform/lib/src/debounce.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart index 980c37182..8d7870e15 100644 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -47,7 +47,7 @@ StreamTransformer _debounceAggregate( timer = null; }); soFar = collect(value, soFar); - }, handleDone: (EventSink sink) { + }, handleDone: (EventSink sink) { if (soFar != null) { shouldClose = true; } else { From ef70491486401f2e468f48d9bd603cba990e930e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 May 2017 11:24:30 -0700 Subject: [PATCH 0303/1215] Implement merge and mergeAll (dart-lang/stream_transform#7) Closes dart-lang/stream_transform#4 merge and mergeAll combine/interleave streams. Handles both broadcast and single-subscription streams. Add implementation of containsAllInOrder in test/util - once this is submitted in package:matcher it can be removed here. Submitting here since the other package is blocked. Remove -dev from pubspec for publishing. --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/README.md | 4 + pkgs/stream_transform/lib/src/merge.dart | 71 ++++++++++++ .../lib/stream_transform.dart | 3 +- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/merge_test.dart | 104 ++++++++++++++++++ pkgs/stream_transform/test/util/matchers.dart | 42 +++++++ 7 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/merge.dart create mode 100644 pkgs/stream_transform/test/merge_test.dart create mode 100644 pkgs/stream_transform/test/util/matchers.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 1d323aa55..c82083343 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.0.2 - Add `concat`: Appends streams in series +- Add `merge` and `mergeAll`: Interleaves streams ## 0.0.1 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index ac3236287..b5ffaa1d1 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -14,3 +14,7 @@ Appends the values of a stream after another stream finishes. Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. + +# merge, mergeAll + +Interleaves events from multiple streams into a single stream. diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart new file mode 100644 index 000000000..d2e53a6a1 --- /dev/null +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -0,0 +1,71 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Emits values from the source stream and [other] in any order as they arrive. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the type of stream [other] is. +StreamTransformer merge(Stream other) => new _Merge([other]); + +/// Emits values from the source stream and all streams in [others] in any order +/// as they arrive. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the types of streams in [others]. +StreamTransformer mergeAll(List> others) => + new _Merge(others); + +class _Merge implements StreamTransformer { + final List> _others; + + _Merge(this._others); + + @override + Stream bind(Stream first) { + StreamController controller; + if (first.isBroadcast) { + controller = new StreamController.broadcast(); + } else { + controller = new StreamController(); + } + List subscriptions; + List> allStreams = [first]..addAll(_others); + var activeStreamCount = 0; + + controller.onListen = () { + if (subscriptions != null) return; + subscriptions = allStreams.map((stream) { + activeStreamCount++; + return stream.listen(controller.add, onError: controller.addError, + onDone: () { + if (--activeStreamCount <= 0) controller.close(); + }); + }).toList(); + }; + + // Forward methods from listener + if (!first.isBroadcast) { + controller.onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } + }; + controller.onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; + controller.onCancel = + () => Future.wait(subscriptions.map((s) => s.cancel())); + } else { + controller.onCancel = () { + if (controller?.hasListener ?? false) return new Future.value(null); + return Future.wait(subscriptions.map((s) => s.cancel())); + }; + } + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index c128e4bf7..de66dbe75 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -3,5 +3,6 @@ // BSD-style license that can be found in the LICENSE file. export 'src/buffer.dart'; -export 'src/debounce.dart'; export 'src/concat.dart'; +export 'src/debounce.dart'; +export 'src/merge.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 735204958..3d096dc64 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.2-dev +version: 0.0.2 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart new file mode 100644 index 000000000..2199ecb6c --- /dev/null +++ b/pkgs/stream_transform/test/merge_test.dart @@ -0,0 +1,104 @@ +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +import 'util/matchers.dart'; + +void main() { + group('merge', () { + test('includes all values', () async { + var first = new Stream.fromIterable([1, 2, 3]); + var second = new Stream.fromIterable([4, 5, 6]); + var allValues = await first.transform(merge(second)).toList(); + expect(allValues, containsAllInOrder([1, 2, 3])); + expect(allValues, containsAllInOrder([4, 5, 6])); + expect(allValues, hasLength(6)); + }); + + test('cancels both sources', () async { + var firstCanceled = false; + var first = new StreamController() + ..onCancel = () { + firstCanceled = true; + }; + var secondCanceled = false; + var second = new StreamController() + ..onCancel = () { + secondCanceled = true; + }; + var subscription = + first.stream.transform(merge(second.stream)).listen((_) {}); + await subscription.cancel(); + expect(firstCanceled, true); + expect(secondCanceled, true); + }); + }); + + group('mergeAll', () { + test('includes all values', () async { + var first = new Stream.fromIterable([1, 2, 3]); + var second = new Stream.fromIterable([4, 5, 6]); + var third = new Stream.fromIterable([7, 8, 9]); + var allValues = await first.transform(mergeAll([second, third])).toList(); + expect(allValues, containsAllInOrder([1, 2, 3])); + expect(allValues, containsAllInOrder([4, 5, 6])); + expect(allValues, containsAllInOrder([7, 8, 9])); + expect(allValues, hasLength(9)); + }); + + test('handles mix of broadcast and single-subscription', () async { + var firstCanceled = false; + var first = new StreamController.broadcast() + ..onCancel = () { + firstCanceled = true; + }; + var secondBroadcastCanceled = false; + var secondBroadcast = new StreamController.broadcast() + ..onCancel = () { + secondBroadcastCanceled = true; + }; + var secondSingleCanceled = false; + var secondSingle = new StreamController() + ..onCancel = () { + secondSingleCanceled = true; + }; + + var merged = first.stream + .transform(mergeAll([secondBroadcast.stream, secondSingle.stream])); + + var firstListenerValues = []; + var secondListenerValues = []; + + var firstSubscription = merged.listen(firstListenerValues.add); + var secondSubscription = merged.listen(secondListenerValues.add); + + first.add(1); + secondBroadcast.add(2); + secondSingle.add(3); + + await new Future(() {}); + await firstSubscription.cancel(); + + expect(firstCanceled, false); + expect(secondBroadcastCanceled, false); + expect(secondSingleCanceled, false); + + first.add(4); + secondBroadcast.add(5); + secondSingle.add(6); + + await new Future(() {}); + await secondSubscription.cancel(); + + await new Future(() {}); + expect(firstCanceled, true); + expect(secondBroadcastCanceled, true); + expect(secondSingleCanceled, true); + + expect(firstListenerValues, [1, 2, 3]); + expect(secondListenerValues, [1, 2, 3, 4, 5, 6]); + }); + }); +} diff --git a/pkgs/stream_transform/test/util/matchers.dart b/pkgs/stream_transform/test/util/matchers.dart new file mode 100644 index 000000000..4028b7361 --- /dev/null +++ b/pkgs/stream_transform/test/util/matchers.dart @@ -0,0 +1,42 @@ +import 'package:test/test.dart'; + +/// Matches [Iterable]s which contain an element matching every value in +/// [expected] in the same order, but may contain additional values interleaved +/// throughout. +Matcher containsAllInOrder(Iterable expected) => + new _ContainsAllInOrder(expected); + +class _ContainsAllInOrder implements Matcher { + final Iterable _expected; + + _ContainsAllInOrder(this._expected); + + String _test(item, Map matchState) { + if (item is! Iterable) return 'not iterable'; + var matchers = _expected.map(wrapMatcher).toList(); + var matcherIndex = 0; + for (var value in item) { + if (matchers[matcherIndex].matches(value, matchState)) matcherIndex++; + if (matcherIndex == matchers.length) return null; + } + return new StringDescription() + .add('did not find a value matching ') + .addDescriptionOf(matchers[matcherIndex]) + .add(' following expected prior values') + .toString(); + } + + @override + bool matches(item, Map matchState) => _test(item, matchState) == null; + + @override + Description describe(Description description) => description + .add('contains in order(') + .addDescriptionOf(_expected) + .add(')'); + + @override + Description describeMismatch(item, Description mismatchDescription, + Map matchState, bool verbose) => + mismatchDescription.add(_test(item, matchState)); +} From 6c0c44d049600a1edd531ddfe2dd4788b2d65eff Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 May 2017 13:45:56 -0700 Subject: [PATCH 0304/1215] Drop copy of combineAllMatcher This can be pulled in from the latest package:test --- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/merge_test.dart | 2 - pkgs/stream_transform/test/util/matchers.dart | 42 ------------------- 3 files changed, 1 insertion(+), 45 deletions(-) delete mode 100644 pkgs/stream_transform/test/util/matchers.dart diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 3d096dc64..15c2bbea8 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -8,4 +8,4 @@ environment: sdk: ">=1.22.0 <2.0.0" dev_dependencies: - test: ^0.12.0 + test: ^0.12.20+13 diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 2199ecb6c..c604f9184 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -4,8 +4,6 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; -import 'util/matchers.dart'; - void main() { group('merge', () { test('includes all values', () async { diff --git a/pkgs/stream_transform/test/util/matchers.dart b/pkgs/stream_transform/test/util/matchers.dart deleted file mode 100644 index 4028b7361..000000000 --- a/pkgs/stream_transform/test/util/matchers.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:test/test.dart'; - -/// Matches [Iterable]s which contain an element matching every value in -/// [expected] in the same order, but may contain additional values interleaved -/// throughout. -Matcher containsAllInOrder(Iterable expected) => - new _ContainsAllInOrder(expected); - -class _ContainsAllInOrder implements Matcher { - final Iterable _expected; - - _ContainsAllInOrder(this._expected); - - String _test(item, Map matchState) { - if (item is! Iterable) return 'not iterable'; - var matchers = _expected.map(wrapMatcher).toList(); - var matcherIndex = 0; - for (var value in item) { - if (matchers[matcherIndex].matches(value, matchState)) matcherIndex++; - if (matcherIndex == matchers.length) return null; - } - return new StringDescription() - .add('did not find a value matching ') - .addDescriptionOf(matchers[matcherIndex]) - .add(' following expected prior values') - .toString(); - } - - @override - bool matches(item, Map matchState) => _test(item, matchState) == null; - - @override - Description describe(Description description) => description - .add('contains in order(') - .addDescriptionOf(_expected) - .add(')'); - - @override - Description describeMismatch(item, Description mismatchDescription, - Map matchState, bool verbose) => - mismatchDescription.add(_test(item, matchState)); -} From 95ec1fc5d9b6c32942e25898575c192c2bcec9d7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 May 2017 15:13:50 -0700 Subject: [PATCH 0305/1215] Implement tap (dart-lang/stream_transform#9) This is like the Rx function `do`, but that is a reserved word in Dart. --- pkgs/stream_transform/CHANGELOG.md | 4 ++ pkgs/stream_transform/README.md | 5 ++ pkgs/stream_transform/lib/src/tap.dart | 31 ++++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/tap_test.dart | 56 +++++++++++++++++++ 6 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/lib/src/tap.dart create mode 100644 pkgs/stream_transform/test/tap_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index c82083343..e33fbb1e7 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.3 + +- Add `tap`: React to values as they pass without being a subscriber on a stream + ## 0.0.2 - Add `concat`: Appends streams in series diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index b5ffaa1d1..ea2685a85 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -18,3 +18,8 @@ values that occur within a given duration. # merge, mergeAll Interleaves events from multiple streams into a single stream. + +# tap + +Taps into a single-subscriber stream to react to values as they pass, without +being a real subscriber. diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart new file mode 100644 index 000000000..2ec8cf8f9 --- /dev/null +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -0,0 +1,31 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Taps into a Stream to allow additional handling on a single-subscriber +/// stream without first wrapping as a broadcast stream. +/// +/// The callback will be called with every value from the stream before it is +/// forwarded to listeners on the stream. Errors from the callbacks are ignored. +/// +/// The tapped stream may not emit any values until the result stream has a +/// listener, and may be canceled only by the listener. +StreamTransformer tap(void fn(T value), + {void onError(error, stackTrace), void onDone()}) => + new StreamTransformer.fromHandlers(handleData: (value, sink) { + try { + fn(value); + } catch (_) {/*Ignore*/} + sink.add(value); + }, handleError: (error, stackTrace, sink) { + try { + onError?.call(error, stackTrace); + } catch (_) {/*Ignore*/} + sink.addError(error, stackTrace); + }, handleDone: (sink) { + try { + onDone?.call(); + } catch (_) {/*Ignore*/} + sink.close(); + }); diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index de66dbe75..62d6df75c 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -6,3 +6,4 @@ export 'src/buffer.dart'; export 'src/concat.dart'; export 'src/debounce.dart'; export 'src/merge.dart'; +export 'src/tap.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 15c2bbea8..75415ef4f 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.2 +version: 0.0.3-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart new file mode 100644 index 000000000..8aecee626 --- /dev/null +++ b/pkgs/stream_transform/test/tap_test.dart @@ -0,0 +1,56 @@ +import 'package:test/test.dart'; +import 'dart:async'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + test('calls function for values', () async { + var valuesSeen = []; + var stream = new Stream.fromIterable([1, 2, 3]); + await stream.transform(tap(valuesSeen.add)).last; + expect(valuesSeen, [1, 2, 3]); + }); + + test('forwards values', () async { + var stream = new Stream.fromIterable([1, 2, 3]); + var values = await stream.transform(tap((_) {})).toList(); + expect(values, [1, 2, 3]); + }); + + test('calls function for errors', () async { + var error; + var source = new StreamController(); + source.stream + .transform(tap((_) {}, onError: (e, st) { + error = e; + })) + .listen((_) {}, onError: (_) {}); + source.addError('error'); + await new Future(() {}); + expect(error, 'error'); + }); + + test('forwards errors', () async { + var error; + var source = new StreamController(); + source.stream.transform(tap((_) {}, onError: (e, st) {})).listen((_) {}, + onError: (e) { + error = e; + }); + source.addError('error'); + await new Future(() {}); + expect(error, 'error'); + }); + + test('calls function on done', () async { + var doneCalled = false; + var source = new StreamController(); + source.stream + .transform((tap((_) {}, onDone: () { + doneCalled = true; + }))) + .listen((_) {}); + await source.close(); + expect(doneCalled, true); + }); +} From 6610696b93c43071677d3fb558fc016231a4f64a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 5 May 2017 18:16:52 -0700 Subject: [PATCH 0306/1215] Implement switchMap and switchLatest (dart-lang/stream_transform#10) switchLatest is like Rx switch but not with a reserved word. switchMap is a convenience for the case where the Stream isn't already a Stream of Strams. Drop `-dev` from version for publishing --- pkgs/stream_transform/CHANGELOG.md | 2 + pkgs/stream_transform/README.md | 5 + pkgs/stream_transform/lib/src/switch.dart | 89 +++++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/switch_test.dart | 147 ++++++++++++++++++ 6 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/lib/src/switch.dart create mode 100644 pkgs/stream_transform/test/switch_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index e33fbb1e7..c66484df4 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,8 @@ ## 0.0.3 - Add `tap`: React to values as they pass without being a subscriber on a stream +- Add `switchMap` and `switchLatest`: Flatten a Stream of Streams into a Stream + which forwards values from the most recent Stream ## 0.0.2 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index ea2685a85..356869ed9 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -19,6 +19,11 @@ values that occur within a given duration. Interleaves events from multiple streams into a single stream. +# switchMap, switchLatest + +Flatten a Stream of Streams into a Stream which forwards values from the most +recent Stream + # tap Taps into a single-subscriber stream to react to values as they pass, without diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart new file mode 100644 index 000000000..e6ccd70f9 --- /dev/null +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Maps events to a Stream and emits values from the most recently created +/// Stream. +/// +/// When the source emits a value it will be converted to a [Stream] using [map] +/// and the output will switch to emitting events from that result. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the types of the streams produced by [map]. +StreamTransformer switchMap(Stream map(S event)) => + new StreamTransformer((stream, cancelOnError) => stream + .map(map) + .transform(switchLatest()) + .listen(null, cancelOnError: cancelOnError)); + +/// Emits values from the most recently emitted Stream. +/// +/// When the source emits a stream the output will switch to emitting events +/// from that stream. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the types of streams emitted. +StreamTransformer, T> switchLatest() => + const _SwitchTransformer(); + +class _SwitchTransformer implements StreamTransformer, T> { + const _SwitchTransformer(); + + @override + Stream bind(Stream> outer) { + StreamController controller; + if (outer.isBroadcast) { + controller = new StreamController.broadcast(); + } else { + controller = new StreamController(); + } + StreamSubscription innerSubscription; + StreamSubscription> outerSubscription; + controller.onListen = () { + var outerStreamDone = false; + var innerStreamDone = false; + outerSubscription = outer.listen((innerStream) { + innerSubscription?.cancel(); + innerSubscription = innerStream.listen(controller.add); + innerSubscription.onDone(() { + innerStreamDone = true; + if (outerStreamDone) { + controller.close(); + } + }); + innerSubscription.onError(controller.addError); + }); + outerSubscription.onDone(() { + outerStreamDone = true; + if (innerStreamDone) { + controller.close(); + } + }); + outerSubscription.onError(controller.addError); + }; + + cancelSubscriptions() => Future.wait([ + innerSubscription?.cancel() ?? new Future.value(), + outerSubscription?.cancel() ?? new Future.value() + ]); + + if (!outer.isBroadcast) { + controller.onPause = () { + innerSubscription?.pause(); + outerSubscription?.pause(); + }; + controller.onResume = () { + innerSubscription?.resume(); + outerSubscription?.resume(); + }; + controller.onCancel = () => cancelSubscriptions(); + } else { + controller.onCancel = () { + if (controller.hasListener) return new Future.value(); + return cancelSubscriptions(); + }; + } + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 62d6df75c..96555ab82 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -6,4 +6,5 @@ export 'src/buffer.dart'; export 'src/concat.dart'; export 'src/debounce.dart'; export 'src/merge.dart'; +export 'src/switch.dart'; export 'src/tap.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 75415ef4f..b868bd4aa 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.3-dev +version: 0.0.3 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart new file mode 100644 index 000000000..fbae7d7b5 --- /dev/null +++ b/pkgs/stream_transform/test/switch_test.dart @@ -0,0 +1,147 @@ +import 'package:test/test.dart'; +import 'dart:async'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var outerType in streamTypes.keys) { + for (var innerType in streamTypes.keys) { + group('Outer type: [$outerType], Inner type: [$innerType]', () { + StreamController first; + StreamController second; + StreamController outer; + + List emittedValues; + bool firstCanceled; + bool outerCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + + setUp(() async { + firstCanceled = false; + outerCanceled = false; + outer = streamTypes[outerType]() + ..onCancel = () { + outerCanceled = true; + }; + first = streamTypes[innerType]() + ..onCancel = () { + firstCanceled = true; + }; + second = streamTypes[innerType](); + emittedValues = []; + errors = []; + isDone = false; + subscription = outer.stream + .transform(switchLatest()) + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('forwards events', () async { + outer.add(first.stream); + await new Future(() {}); + first.add(1); + first.add(2); + await new Future(() {}); + + outer.add(second.stream); + await new Future(() {}); + second.add(3); + second.add(4); + await new Future(() {}); + + expect(emittedValues, [1, 2, 3, 4]); + }); + + test('forwards errors from outer Stream', () async { + outer.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors from inner Stream', () async { + outer.add(first.stream); + await new Future(() {}); + first.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('closes when final stream is done', () async { + outer.add(first.stream); + await new Future(() {}); + + outer.add(second.stream); + await new Future(() {}); + + await outer.close(); + + expect(isDone, false); + + await second.close(); + + await new Future(() {}); + expect(isDone, true); + }); + + test( + 'closes when outer stream closes if latest inner stream already ' + 'closed', () async { + outer.add(first.stream); + await new Future(() {}); + await first.close(); + await new Future(() {}); + expect(isDone, false); + + await outer.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('cancels listeners on previous streams', () async { + outer.add(first.stream); + await new Future(() {}); + + outer.add(second.stream); + await new Future(() {}); + expect(firstCanceled, true); + }); + + test('cancels listener on current and outer stream on cancel', + () async { + outer.add(first.stream); + await new Future(() {}); + await subscription.cancel(); + + await new Future(() {}); + expect(outerCanceled, true); + expect(firstCanceled, true); + }); + }); + } + } + + group('switchMap', () { + test('uses map function', () async { + var outer = new StreamController(); + + var values = []; + outer.stream + .transform(switchMap((l) => new Stream.fromIterable(l))) + .listen(values.add); + + outer.add([1, 2, 3]); + await new Future(() {}); + outer.add([4, 5, 6]); + await new Future(() {}); + expect(values, [1, 2, 3, 4, 5, 6]); + }); + }); +} From 507dd7029b1c552e1a0f0a7d66455b67dba3e14a Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Sat, 6 May 2017 22:02:36 -0700 Subject: [PATCH 0307/1215] Add throttle, audit, and scan (dart-lang/stream_transform#11) - Add `scan`: fold which returns intermediate values - Add `throttle`: block events for a duration after emitting a value - Add `audit`: emits the last event received after a duration --- pkgs/stream_transform/CHANGELOG.md | 5 ++ pkgs/stream_transform/README.md | 14 ++++ pkgs/stream_transform/lib/src/audit.dart | 33 ++++++++ pkgs/stream_transform/lib/src/scan.dart | 15 ++++ pkgs/stream_transform/lib/src/throttle.dart | 21 +++++ .../lib/stream_transform.dart | 3 + pkgs/stream_transform/test/audit_test.dart | 82 +++++++++++++++++++ pkgs/stream_transform/test/scan_test.dart | 17 ++++ pkgs/stream_transform/test/throttle_test.dart | 72 ++++++++++++++++ 9 files changed, 262 insertions(+) create mode 100644 pkgs/stream_transform/lib/src/audit.dart create mode 100644 pkgs/stream_transform/lib/src/scan.dart create mode 100644 pkgs/stream_transform/lib/src/throttle.dart create mode 100644 pkgs/stream_transform/test/audit_test.dart create mode 100644 pkgs/stream_transform/test/scan_test.dart create mode 100644 pkgs/stream_transform/test/throttle_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index c66484df4..9afdbe4b2 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.4 +- Add `scan`: fold which returns intermediate values +- Add `throttle`: block events for a duration after emitting a value +- Add `audit`: emits the last event received after a duration + ## 0.0.3 - Add `tap`: React to values as they pass without being a subscriber on a stream diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 356869ed9..0c640874d 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,6 +1,11 @@ Contains utility methods to create `StreamTransfomer` instances to manipulate Streams. +# audit + +Audit waits for a period of time after receiving a value and then only emits +the most recent value. + # buffer Collects values from a source stream until a `trigger` stream fires and the @@ -19,6 +24,11 @@ values that occur within a given duration. Interleaves events from multiple streams into a single stream. +# scan + +Scan is like fold, but instead of producing a single value it yields each +intermediate accumulation. + # switchMap, switchLatest Flatten a Stream of Streams into a Stream which forwards values from the most @@ -28,3 +38,7 @@ recent Stream Taps into a single-subscriber stream to react to values as they pass, without being a real subscriber. + +# throttle + +Blocks events for a duration after an event is successfully emitted. \ No newline at end of file diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart new file mode 100644 index 000000000..f4cadffbb --- /dev/null +++ b/pkgs/stream_transform/lib/src/audit.dart @@ -0,0 +1,33 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Creates a StreamTransformer which only emits once per [duration], at the +/// end of the period. +/// +/// Like `throttle`, except it always emits the most recently received event in +/// a period. Always introduces a delay of at most [duration]. +StreamTransformer audit(Duration duration) { + Timer timer; + bool shouldClose = false; + T recentData; + + return new StreamTransformer.fromHandlers( + handleData: (T data, EventSink sink) { + recentData = data; + timer ??= new Timer(duration, () { + sink.add(recentData); + timer = null; + if (shouldClose) { + sink.close(); + } + }); + }, handleDone: (EventSink sink) { + if (timer != null) { + shouldClose = true; + } else { + sink.close(); + } + }); +} diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart new file mode 100644 index 000000000..518d33299 --- /dev/null +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -0,0 +1,15 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Scan is like fold, but instead of producing a single value it yields +/// each intermediate accumulation. +StreamTransformer scan( + T initialValue, T combine(T previousValue, S element)) => + new StreamTransformer((stream, cancelOnError) { + T accumulated = initialValue; + return stream + .map((value) => accumulated = combine(accumulated, value)) + .listen(null, cancelOnError: cancelOnError); + }); diff --git a/pkgs/stream_transform/lib/src/throttle.dart b/pkgs/stream_transform/lib/src/throttle.dart new file mode 100644 index 000000000..030c3fd7e --- /dev/null +++ b/pkgs/stream_transform/lib/src/throttle.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Creates a StreamTransformer which only emits once per [duration], at the +/// beginning of the period. +StreamTransformer throttle(Duration duration) { + Timer timer; + + return new StreamTransformer.fromHandlers(handleData: (data, sink) { + if (timer == null) { + sink.add(data); + timer = new Timer(duration, () { + timer = null; + }); + } + }, handleDone: (sink) { + sink.close(); + }); +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 96555ab82..ba49b0b5a 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -8,3 +8,6 @@ export 'src/debounce.dart'; export 'src/merge.dart'; export 'src/switch.dart'; export 'src/tap.dart'; +export 'src/scan.dart'; +export 'src/throttle.dart'; +export 'src/audit.dart'; diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart new file mode 100644 index 000000000..b4e315175 --- /dev/null +++ b/pkgs/stream_transform/test/audit_test.dart @@ -0,0 +1,82 @@ +import 'dart:async'; +import 'package:test/test.dart'; +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var streamType in streamTypes.keys) { + group('Stream type [$streamType]', () { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + + void setUpStreams(StreamTransformer transformer) { + valuesCanceled = false; + values = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + subscription = values.stream + .transform(transformer) + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + + group('audit', () { + setUp(() async { + setUpStreams(audit(const Duration(milliseconds: 5))); + }); + + test('cancels values', () async { + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('swallows values that come faster than duration', () async { + values.add(1); + values.add(2); + await values.close(); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [2]); + }); + + test('outputs multiple values spaced further than duration', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [1, 2]); + }); + + test('waits for pending value to close', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + await values.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('closes output if there are no pending values', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future(() {}); + await values.close(); + expect(isDone, false); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(isDone, true); + }); + }); + }); + } +} diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart new file mode 100644 index 000000000..51456f2ef --- /dev/null +++ b/pkgs/stream_transform/test/scan_test.dart @@ -0,0 +1,17 @@ +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + group('Scan', () { + test('produces intermediate values', () async { + var source = new Stream.fromIterable([1, 2, 3, 4]); + var sum = (int x, int y) => x + y; + var result = await source.transform(scan(0, sum)).toList(); + + expect(result, [1, 3, 6, 10]); + }); + }); +} diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart new file mode 100644 index 000000000..888caec95 --- /dev/null +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -0,0 +1,72 @@ +import 'dart:async'; +import 'package:test/test.dart'; +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var streamType in streamTypes.keys) { + group('Stream type [$streamType]', () { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + + void setUpStreams(StreamTransformer transformer) { + valuesCanceled = false; + values = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + subscription = values.stream + .transform(transformer) + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + + group('throttle', () { + setUp(() async { + setUpStreams(throttle(const Duration(milliseconds: 5))); + }); + + test('cancels values', () async { + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('swallows values that come faster than duration', () async { + values.add(1); + values.add(2); + await values.close(); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [1]); + }); + + test('outputs multiple values spaced further than duration', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [1, 2]); + }); + + test('closes output immediately', () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 10)); + values.add(2); + await new Future(() {}); + await values.close(); + expect(isDone, true); + }); + }); + }); + } +} From df9ae5cd011ad68f16615f50b9fc3abb366cb19a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sat, 6 May 2017 22:05:01 -0700 Subject: [PATCH 0308/1215] Bump version for publish --- pkgs/stream_transform/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index b868bd4aa..abba4b77f 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.3 +version: 0.0.4 environment: sdk: ">=1.22.0 <2.0.0" From 7f491e9347dab280f5814e310be97f4095bc59d2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 8 May 2017 10:40:00 -0700 Subject: [PATCH 0309/1215] Fix non-strong compile (dart-lang/stream_transform#12) Did not see this with strong mode analyzer. In Dart2Js generic type arguments are not allowed on const constructor calls. --- pkgs/stream_transform/CHANGELOG.md | 4 ++++ pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 9afdbe4b2..6cee6e0ce 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.5 + +- Bug Fix: Allow compiling switchLatest with Dart2Js. + ## 0.0.4 - Add `scan`: fold which returns intermediate values - Add `throttle`: block events for a duration after emitting a value diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index e6ccd70f9..be9eeeb2f 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -25,7 +25,7 @@ StreamTransformer switchMap(Stream map(S event)) => /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of streams emitted. StreamTransformer, T> switchLatest() => - const _SwitchTransformer(); + new _SwitchTransformer(); class _SwitchTransformer implements StreamTransformer, T> { const _SwitchTransformer(); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index abba4b77f..6da6df884 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.4 +version: 0.0.5-dev environment: sdk: ">=1.22.0 <2.0.0" From 164a80dce405195644abb71d4a7827d9610de7e6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 8 May 2017 12:28:55 -0700 Subject: [PATCH 0310/1215] Add `asyncWhere` (dart-lang/stream_transform#13) Relatively few tests since most of the complex stuff is handled by StreamTransformer.fromHandlers --- pkgs/stream_transform/CHANGELOG.md | 1 + .../stream_transform/lib/src/async_where.dart | 21 +++++++++++ .../lib/stream_transform.dart | 5 ++- pkgs/stream_transform/pubspec.yaml | 2 +- .../test/async_where_test.dart | 37 +++++++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/async_where.dart create mode 100644 pkgs/stream_transform/test/async_where_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 6cee6e0ce..6f632db14 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.0.5 - Bug Fix: Allow compiling switchLatest with Dart2Js. +- Add `asyncWhere`: Like `where` but allows an asynchronous predicate. ## 0.0.4 - Add `scan`: fold which returns intermediate values diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/async_where.dart new file mode 100644 index 000000000..1bb2d6432 --- /dev/null +++ b/pkgs/stream_transform/lib/src/async_where.dart @@ -0,0 +1,21 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +/// Like [Stream.where] but allows the [test] to return a [Future]. +StreamTransformer asyncWhere(FutureOr test(T element)) { + var valuesWaiting = 0; + var sourceDone = false; + return new StreamTransformer.fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + if (await test(element)) sink.add(element); + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + }); +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index ba49b0b5a..8b4d601e2 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -2,12 +2,13 @@ // 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. +export 'src/async_where.dart'; +export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/concat.dart'; export 'src/debounce.dart'; export 'src/merge.dart'; +export 'src/scan.dart'; export 'src/switch.dart'; export 'src/tap.dart'; -export 'src/scan.dart'; export 'src/throttle.dart'; -export 'src/audit.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 6da6df884..e8267308d 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.5-dev +version: 0.0.5 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart new file mode 100644 index 000000000..919f93164 --- /dev/null +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -0,0 +1,37 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + test('forwards only events that pass the predicate', () async { + var values = new Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(asyncWhere((e) async => e > 2)); + expect(await filtered.toList(), [3, 4]); + }); + + test('allows predicates that go through event loop', () async { + var values = new Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(asyncWhere((e) async { + await new Future(() {}); + return e > 2; + })); + expect(await filtered.toList(), [3, 4]); + }); + + test('allows synchronous predicate', () async { + var values = new Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(asyncWhere((e) => e > 2)); + expect(await filtered.toList(), [3, 4]); + }); + + test('can result in empty stream', () async { + var values = new Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(asyncWhere((e) => e > 4)); + expect(await filtered.isEmpty, true); + }); +} From 5139e4034217f312d276aa5dbda373cc309dfa0e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 8 May 2017 12:59:33 -0700 Subject: [PATCH 0311/1215] README for asyncWhere --- pkgs/stream_transform/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 0c640874d..bf69198d6 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,6 +1,10 @@ Contains utility methods to create `StreamTransfomer` instances to manipulate Streams. +# asyncWhere + +Like `where` but allows an asynchronous predicate. + # audit Audit waits for a period of time after receiving a value and then only emits @@ -41,4 +45,4 @@ being a real subscriber. # throttle -Blocks events for a duration after an event is successfully emitted. \ No newline at end of file +Blocks events for a duration after an event is successfully emitted. From b878740c72b4da240e62f69d3a9b0002e423ae89 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 8 May 2017 13:15:00 -0700 Subject: [PATCH 0312/1215] Run non-strong analyzer on travis (dart-lang/stream_transform#15) Fixes dart-lang/stream_transform#14 --- pkgs/stream_transform/.travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 4c02d8e9a..1d18a7ea0 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -11,6 +11,7 @@ dart_task: - test - dartfmt - dartanalyzer + - dartanalyzer: --no-strong . matrix: exclude: - dart: 1.22.1 From 5a7db37bc30b683f437501c668a21f679630d36e Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Wed, 17 May 2017 17:38:39 +0200 Subject: [PATCH 0313/1215] Fix code for strong zones. --- .../lib/src/stack_zone_specification.dart | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 1cccd3af6..53ab775d6 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -92,8 +92,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneCallback _registerCallback( - Zone self, ZoneDelegate parent, Zone zone, Function f) { + ZoneCallback _registerCallback( + Zone self, ZoneDelegate parent, Zone zone, R f()) { if (f == null || _disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); @@ -101,8 +101,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneUnaryCallback _registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, Function f) { + ZoneUnaryCallback _registerUnaryCallback( + Zone self, ZoneDelegate parent, Zone zone, R f(T arg) { if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { @@ -112,7 +112,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneBinaryCallback _registerBinaryCallback( + ZoneBinaryCallback _registerBinaryCallback( Zone self, ZoneDelegate parent, Zone zone, Function f) { if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); @@ -124,26 +124,26 @@ class StackZoneSpecification { /// Looks up the chain associated with [stackTrace] and passes it either to /// [_onError] or [parent]'s error handler. - _handleUncaughtError( + void _handleUncaughtError( Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { if (_disabled) { - return parent.handleUncaughtError(zone, error, stackTrace); + parent.handleUncaughtError(zone, error, stackTrace); } var stackChain = chainFor(stackTrace); if (_onError == null) { - return parent.handleUncaughtError(zone, error, stackChain); + parent.handleUncaughtError(zone, error, stackChain); } // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just // allow [runBinary] to throw instead once issue 18134 is fixed. try { - return parent.runBinary(zone, _onError, error, stackChain); + parent.runBinary(zone, _onError, error, stackChain); } catch (newError, newStackTrace) { if (identical(newError, error)) { - return parent.handleUncaughtError(zone, error, stackChain); + parent.handleUncaughtError(zone, error, stackChain); } else { - return parent.handleUncaughtError(zone, newError, newStackTrace); + parent.handleUncaughtError(zone, newError, newStackTrace); } } } @@ -180,7 +180,7 @@ class StackZoneSpecification { /// /// If [f] throws an error, this associates [node] with that error's stack /// trace. - _run(Function f, _Node node) { + T _run(T f(), _Node node) { var previousNode = _currentNode; _currentNode = node; try { From d8016d4a42fd2bcde4b301f97bb2f6229c1d64bc Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 22 May 2017 12:50:06 -0700 Subject: [PATCH 0314/1215] Don't crash on surrogate pairs. (dart-lang/string_scanner#5) Closes dart-lang/string_scanner#4 --- pkgs/string_scanner/CHANGELOG.md | 5 +++++ pkgs/string_scanner/lib/src/span_scanner.dart | 2 +- .../lib/src/string_scanner.dart | 2 +- pkgs/string_scanner/pubspec.yaml | 4 ++-- .../test/span_scanner_test.dart | 20 ++++++++++++++----- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index fa4cb6e43..83ca15b3f 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.2 + +* `SpanScanner` no longer crashes when creating a span that contains a UTF-16 + surrogate pair. + ## 1.0.1 * Fix the error text emitted by `StringScanner.expectChar()`. diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 043021b4d..f362223b2 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -56,7 +56,7 @@ class SpanScanner extends StringScanner implements LineScanner { /// [FileSpan]s as well as for error reporting. It can be a [String], a /// [Uri], or `null`. SpanScanner(String string, {sourceUrl, int position}) - : _sourceFile = new SourceFile(string, url: sourceUrl), + : _sourceFile = new SourceFile.fromString(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); /// Creates a new [SpanScanner] that eagerly computes line and column numbers. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 5817d562f..712292c60 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -204,7 +204,7 @@ class StringScanner { } if (length == null) length = match == null ? 0 : match.end - match.start; - var sourceFile = new SourceFile(string, url: sourceUrl); + var sourceFile = new SourceFile.fromString(string, url: sourceUrl); var span = sourceFile.span(position, position + length); throw new StringScannerException(message, span, string); } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index ac893e26d..f0862eeb9 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 1.0.1 +version: 1.0.2 author: "Dart Team " homepage: https://github.com/dart-lang/string_scanner description: > A class for parsing strings using a sequence of patterns. dependencies: charcode: "^1.1.0" - source_span: "^1.0.0" + source_span: "^1.4.0" dev_dependencies: test: ">=0.12.0 <0.13.0" environment: diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 84d7b94ee..ab3cc8087 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -9,12 +9,13 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - testForImplementation("lazy", () { - return new SpanScanner('foo\nbar\nbaz', sourceUrl: 'source'); + testForImplementation("lazy", ([string]) { + return new SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); - testForImplementation("eager", () { - return new SpanScanner.eager('foo\nbar\nbaz', sourceUrl: 'source'); + testForImplementation("eager", ([string]) { + return new SpanScanner.eager(string ?? 'foo\nbar\nbaz', + sourceUrl: 'source'); }); group("within", () { @@ -23,7 +24,7 @@ void main() { var scanner; setUp(() { - var file = new SourceFile(text, url: 'source'); + var file = new SourceFile.fromString(text, url: 'source'); scanner = new SpanScanner.within( file.span(startOffset, text.indexOf(' :after'))); }); @@ -136,6 +137,15 @@ void testForImplementation(String name, SpanScanner create()) { expect(span.text, equals('o\nbar\nba')); }); + test(".spanFrom() handles surrogate pairs correctly", () { + scanner = create('fo\u{12345}o'); + scanner.scan('fo'); + var state = scanner.state; + scanner.scan('\u{12345}o'); + var span = scanner.spanFrom(state); + expect(span.text, equals('\u{12345}o')); + }); + test(".emptySpan returns an empty span at the current location", () { scanner.scan('foo\nba'); From 2805fa9aea1f1f2c221550545925628e8100bb75 Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 12 Jun 2017 11:28:42 +0200 Subject: [PATCH 0315/1215] Fix typo and update handling of error. --- pkgs/stack_trace/lib/src/chain.dart | 3 ++- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index e93b2b445..08aabb0dd 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -93,7 +93,8 @@ class Chain implements StackTrace { return callback(); } catch (error, stackTrace) { // TODO(nweiz): Don't special-case this when issue 19566 is fixed. - return Zone.current.handleUncaughtError(error, stackTrace); + Zone.current.handleUncaughtError(error, stackTrace); + return null; } }, zoneSpecification: spec.toSpec(), diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 53ab775d6..f71f610d2 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -102,7 +102,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. ZoneUnaryCallback _registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, R f(T arg) { + Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) { if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { From 59769002a5afe7a09af53ab0806e966434ebeb3f Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 19 Jun 2017 16:39:20 +0200 Subject: [PATCH 0316/1215] Update pubspec to require Dart 1.25. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 94054ecae..b99f7d150 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -17,4 +17,4 @@ dependencies: dev_dependencies: test: '^0.12.17' environment: - sdk: ">=1.21.0 <2.0.0" + sdk: ">=1.25.0 <2.0.0" From 9f817bc9be4211f10c413d3516cd1620171e7999 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 21 Jun 2017 14:32:16 -0700 Subject: [PATCH 0317/1215] Add `fromHandlers` for easier broadcast streams (dart-lang/stream_transform#21) Fixes dart-lang/stream_transform#18 StreamTransformer.fromHandlers constructor does not behave as expected for broadcast streams - handlers are called once per listener rather than once per event. This means that closures which share state for a single source stream won't work correctly for broadcast streams with multiple listeners. The transformers currently using this pattern are most readable with it vs a custom StreamTransformer class for each one, so add a `fromHandlers` utility which mimics that constructor but only calls the handlers once per event and the broadcast multiplexing is done on the other side. - Add _StreamTransformers with an overridable handleData and handleDone. Eventually handleError will be needed, but this is all that is required to solve the bug with `debounce`. - Add tests for _StreamTransformers across both single-subscrption and broadcast streams. All these tests pass with either `new StreamTransformers.fromhandlers` or the new `fromhandlers` except the 'called once' tests. - Add a pair of tests for debounce and debounceBuffer which exhibit the bug - data is only added to one of the listeners because the Timer is overridden to the last listener whose handleData is called. - Update debounce to use `fromHandlers` and see that the tests pass. Other StreamTransformers in this package have the same bug and will be fixed in subsequent commits. --- pkgs/stream_transform/CHANGELOG.md | 5 + pkgs/stream_transform/lib/src/debounce.dart | 5 +- .../lib/src/from_handlers.dart | 60 +++++++ pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/debounce_test.dart | 33 +++- .../test/from_handlers_test.dart | 165 ++++++++++++++++++ 6 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/from_handlers.dart create mode 100644 pkgs/stream_transform/test/from_handlers_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 6f632db14..50c23d83e 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.6 + +- Bug Fix: `debounce` correctly adds data to all listeners on a broadcast + stream. + ## 0.0.5 - Bug Fix: Allow compiling switchLatest with Dart2Js. diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart index 8d7870e15..fffb2213f 100644 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'from_handlers.dart'; + /// Creates a StreamTransformer which only emits when the source stream does not /// emit for [duration]. /// @@ -35,8 +37,7 @@ StreamTransformer _debounceAggregate( Timer timer; R soFar; bool shouldClose = false; - return new StreamTransformer.fromHandlers( - handleData: (T value, EventSink sink) { + return fromHandlers(handleData: (T value, EventSink sink) { timer?.cancel(); timer = new Timer(duration, () { sink.add(soFar); diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart new file mode 100644 index 000000000..8157ea169 --- /dev/null +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -0,0 +1,60 @@ +import 'dart:async'; + +typedef void HandleData(S value, EventSink sink); +typedef void HandleDone(EventSink sink); + +/// Like [new StreamTransformer.fromHandlers] but the handlers are called once +/// per event rather than once per listener for broadcast streams. +StreamTransformer fromHandlers( + {HandleData handleData, HandleDone handleDone}) => + new _StreamTransformer(handleData: handleData, handleDone: handleDone); + +class _StreamTransformer implements StreamTransformer { + final HandleData _handleData; + final HandleDone _handleDone; + + _StreamTransformer({HandleData handleData, HandleDone handleDone}) + : _handleData = handleData ?? _defaultHandleData, + _handleDone = handleDone ?? _defaultHandleDone; + + static _defaultHandleData(S value, EventSink sink) { + sink.add(value as T); + } + + static _defaultHandleDone(EventSink sink) { + sink.close(); + } + + @override + Stream bind(Stream values) { + StreamController controller; + if (values.isBroadcast) { + controller = new StreamController.broadcast(); + } else { + controller = new StreamController(); + } + StreamSubscription subscription; + controller.onListen = () { + if (subscription != null) { + return; + } + subscription = values.listen((value) => _handleData(value, controller), + onError: controller.addError, onDone: () { + _handleDone(controller); + }); + }; + if (!values.isBroadcast) { + controller.onPause = () => subscription?.pause(); + controller.onResume = () => subscription?.resume(); + } + controller.onCancel = () { + if (controller.hasListener || subscription == null) { + return new Future.value(); + } + var toCancel = subscription; + subscription = null; + return toCancel.cancel(); + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index e8267308d..f1c647ee8 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.5 +version: 0.0.6-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index a556b41e7..a28d2ca32 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -15,6 +15,7 @@ void main() { bool isDone; List errors; StreamSubscription subscription; + Stream transformed; void setUpStreams(StreamTransformer transformer) { valuesCanceled = false; @@ -25,8 +26,8 @@ void main() { emittedValues = []; errors = []; isDone = false; - subscription = values.stream - .transform(transformer) + transformed = values.stream.transform(transformer); + subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); @@ -76,6 +77,18 @@ void main() { await new Future.delayed(const Duration(milliseconds: 10)); expect(isDone, true); }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [2]); + expect(otherValues, [2]); + }); + } }); group('debounceBuffer', () { @@ -104,6 +117,22 @@ void main() { [2] ]); }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [ + [1, 2] + ]); + expect(otherValues, [ + [1, 2] + ]); + }); + } }); }); } diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart new file mode 100644 index 000000000..28436bd6b --- /dev/null +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -0,0 +1,165 @@ +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/src/from_handlers.dart'; + +void main() { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + void setUpForController( + StreamController controller, StreamTransformer transformer) { + valuesCanceled = false; + values = controller + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = values.stream.transform(transformer); + subscription = + transformed.listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + + group('default from_handlers', () { + group('Single subscription stream', () { + setUp(() { + setUpForController(new StreamController(), fromHandlers()); + }); + + test('has correct stream type', () { + expect(transformed.isBroadcast, false); + }); + + test('forwards values', () async { + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [1, 2]); + }); + + test('forwards errors', () async { + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('forwards done', () async { + await values.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('forwards cancel', () async { + await subscription.cancel(); + expect(valuesCanceled, true); + }); + }); + + group('broadcast stream with muliple listeners', () { + List emittedValues2; + List errors2; + bool isDone2; + StreamSubscription subscription2; + + setUp(() { + setUpForController(new StreamController.broadcast(), fromHandlers()); + emittedValues2 = []; + errors2 = []; + isDone2 = false; + subscription2 = transformed + .listen(emittedValues2.add, onError: errors2.add, onDone: () { + isDone2 = true; + }); + }); + + test('has correct stream type', () { + expect(transformed.isBroadcast, true); + }); + + test('forwards values', () async { + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [1, 2]); + expect(emittedValues2, [1, 2]); + }); + + test('forwards errors', () async { + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + expect(errors2, ['error']); + }); + + test('forwards done', () async { + await values.close(); + await new Future(() {}); + expect(isDone, true); + expect(isDone2, true); + }); + + test('forwards cancel', () async { + await subscription.cancel(); + expect(valuesCanceled, false); + await subscription2.cancel(); + expect(valuesCanceled, true); + }); + }); + }); + + group('custom handlers', () { + group('single subscription', () { + setUp(() async { + setUpForController(new StreamController(), + fromHandlers(handleData: (value, sink) { + sink.add(value + 1); + })); + }); + test('uses transform from handleData', () async { + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [2, 3]); + }); + }); + + group('broadcast stream with multiple listeners', () { + int dataCallCount; + int doneCallCount; + + setUp(() async { + dataCallCount = 0; + doneCallCount = 0; + setUpForController( + new StreamController.broadcast(), + fromHandlers(handleData: (value, sink) { + dataCallCount++; + }, handleDone: (sink) { + doneCallCount++; + })); + transformed.listen((_) {}); + }); + + test('handles data once', () async { + values.add(1); + await new Future(() {}); + expect(dataCallCount, 1); + }); + + test('handles done once', () async { + await values.close(); + expect(doneCallCount, 1); + }); + }); + }); +} From 03eed275933d1e7b79bc3901650eeb87f0ba7875 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 23 Jun 2017 11:11:38 -0700 Subject: [PATCH 0318/1215] Fix broadcast bug for Audit and clarify behavior (dart-lang/stream_transform#22) - Use `fromHandlers` to correctly handle broadcast Streams. - Clarify in the Doc comment the behavior difference from `debounce` - Add a test which makes explicit the difference from `debounce` - all the other tests also pass with `debounce`. --- pkgs/stream_transform/CHANGELOG.md | 4 ++-- pkgs/stream_transform/lib/src/audit.dart | 15 ++++++++---- pkgs/stream_transform/test/audit_test.dart | 27 ++++++++++++++++++++-- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 50c23d83e..e59591991 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.0.6 -- Bug Fix: `debounce` correctly adds data to all listeners on a broadcast - stream. +- Bug Fix: Some transformers did not correctly add data to all listeners on + broadcast streams. Fixed for `debounce`, and `audit`. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart index f4cadffbb..12bb9d537 100644 --- a/pkgs/stream_transform/lib/src/audit.dart +++ b/pkgs/stream_transform/lib/src/audit.dart @@ -3,18 +3,25 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'from_handlers.dart'; + /// Creates a StreamTransformer which only emits once per [duration], at the /// end of the period. /// -/// Like `throttle`, except it always emits the most recently received event in -/// a period. Always introduces a delay of at most [duration]. +/// Always introduces a delay of at most [duration]. +/// +/// Differs from `throttle` in that it always emits the most recently received +/// event rather than the first in the period. +/// +/// Differs from `debounce` in that a value will always be emitted after +/// [duration], the output will not be starved by values coming in repeatedly +/// within [duration]. StreamTransformer audit(Duration duration) { Timer timer; bool shouldClose = false; T recentData; - return new StreamTransformer.fromHandlers( - handleData: (T data, EventSink sink) { + return fromHandlers(handleData: (T data, EventSink sink) { recentData = data; timer ??= new Timer(duration, () { sink.add(recentData); diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index b4e315175..d65fd7f2b 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -14,6 +14,7 @@ void main() { bool valuesCanceled; bool isDone; List errors; + Stream transformed; StreamSubscription subscription; void setUpStreams(StreamTransformer transformer) { @@ -25,8 +26,8 @@ void main() { emittedValues = []; errors = []; isDone = false; - subscription = values.stream - .transform(transformer) + transformed = values.stream.transform(transformer); + subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); @@ -76,6 +77,28 @@ void main() { await new Future.delayed(const Duration(milliseconds: 10)); expect(isDone, true); }); + + test('does not starve output if many values come closer than duration', + () async { + values.add(1); + await new Future.delayed(const Duration(milliseconds: 3)); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 3)); + values.add(3); + expect(emittedValues, [2]); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + values.add(2); + await new Future.delayed(const Duration(milliseconds: 10)); + expect(emittedValues, [2]); + expect(otherValues, [2]); + }); + } }); }); } From dff871c14642097907ae3207e67e27a2f62e853f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 26 Jun 2017 10:40:47 -0700 Subject: [PATCH 0319/1215] Fix throttle broadcast bug (dart-lang/stream_transform#23) - Switch to `fromHandlers` utility. - Add a test which fails with the old implementation. - Add an extra `await new Future(() {})` in the test for handling the Stream done event. The new StreamTransformer is not sync like this old one - this behavior is still correct. - Remove extra `handleDone` which matches the default behavior. --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/lib/src/throttle.dart | 6 +++--- pkgs/stream_transform/test/throttle_test.dart | 17 +++++++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index e59591991..00e260053 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.0.6 - Bug Fix: Some transformers did not correctly add data to all listeners on - broadcast streams. Fixed for `debounce`, and `audit`. + broadcast streams. Fixed for `throttle`, `debounce`, and `audit`. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/throttle.dart b/pkgs/stream_transform/lib/src/throttle.dart index 030c3fd7e..b8faa25aa 100644 --- a/pkgs/stream_transform/lib/src/throttle.dart +++ b/pkgs/stream_transform/lib/src/throttle.dart @@ -3,19 +3,19 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'from_handlers.dart'; + /// Creates a StreamTransformer which only emits once per [duration], at the /// beginning of the period. StreamTransformer throttle(Duration duration) { Timer timer; - return new StreamTransformer.fromHandlers(handleData: (data, sink) { + return fromHandlers(handleData: (data, sink) { if (timer == null) { sink.add(data); timer = new Timer(duration, () { timer = null; }); } - }, handleDone: (sink) { - sink.close(); }); } diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 888caec95..3647cb418 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -14,6 +14,7 @@ void main() { bool valuesCanceled; bool isDone; List errors; + Stream transformed; StreamSubscription subscription; void setUpStreams(StreamTransformer transformer) { @@ -25,8 +26,8 @@ void main() { emittedValues = []; errors = []; isDone = false; - subscription = values.stream - .transform(transformer) + transformed = values.stream.transform(transformer); + subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); @@ -64,8 +65,20 @@ void main() { values.add(2); await new Future(() {}); await values.close(); + await new Future(() {}); expect(isDone, true); }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + await new Future(() {}); + expect(emittedValues, [1]); + expect(otherValues, [1]); + }); + } }); }); } From 11bb00f6f3d0f0d743d55991959658febaa14688 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 26 Jun 2017 10:47:17 -0700 Subject: [PATCH 0320/1215] Call `tap` data callback once per event (dart-lang/stream_transform#26) This is slightly different from the other bugs. In this case the output stream correctly forwarded values to all listeners, but the callback was also called once per listener. - Add `handleError` to `fromHandlers` and tests. - Add tests for expected single-call behavior. These fail on the old implementation. - Add test for the values getting to multiple listeners. This passes on both the old and new implementation. - Switch to `fromHandlers`. --- pkgs/stream_transform/CHANGELOG.md | 2 + .../lib/src/from_handlers.dart | 31 +++++++++-- pkgs/stream_transform/lib/src/tap.dart | 4 +- .../test/from_handlers_test.dart | 13 ++++- pkgs/stream_transform/test/tap_test.dart | 55 +++++++++++++++++++ 5 files changed, 97 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 00e260053..7f1aedf0d 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -2,6 +2,8 @@ - Bug Fix: Some transformers did not correctly add data to all listeners on broadcast streams. Fixed for `throttle`, `debounce`, and `audit`. +- Bug Fix: Only call the `tap` data callback once per event rather than once per + listener. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 8157ea169..315de961a 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -2,26 +2,43 @@ import 'dart:async'; typedef void HandleData(S value, EventSink sink); typedef void HandleDone(EventSink sink); +typedef void HandleError( + Object error, StackTrace stackTrace, EventSink sink); /// Like [new StreamTransformer.fromHandlers] but the handlers are called once /// per event rather than once per listener for broadcast streams. StreamTransformer fromHandlers( - {HandleData handleData, HandleDone handleDone}) => - new _StreamTransformer(handleData: handleData, handleDone: handleDone); + {HandleData handleData, + HandleError handleError, + HandleDone handleDone}) => + new _StreamTransformer( + handleData: handleData, + handleError: handleError, + handleDone: handleDone); class _StreamTransformer implements StreamTransformer { final HandleData _handleData; final HandleDone _handleDone; + final HandleError _handleError; - _StreamTransformer({HandleData handleData, HandleDone handleDone}) + _StreamTransformer( + {HandleData handleData, + HandleError handleError, + HandleDone handleDone}) : _handleData = handleData ?? _defaultHandleData, + _handleError = handleError ?? _defaultHandleError, _handleDone = handleDone ?? _defaultHandleDone; - static _defaultHandleData(S value, EventSink sink) { + static void _defaultHandleData(S value, EventSink sink) { sink.add(value as T); } - static _defaultHandleDone(EventSink sink) { + static void _defaultHandleError( + Object error, StackTrace stackTrace, EventSink sink) { + sink.addError(error, stackTrace); + } + + static void _defaultHandleDone(EventSink sink) { sink.close(); } @@ -39,7 +56,9 @@ class _StreamTransformer implements StreamTransformer { return; } subscription = values.listen((value) => _handleData(value, controller), - onError: controller.addError, onDone: () { + onError: (error, stackTrace) { + _handleError(error, stackTrace, controller); + }, onDone: () { _handleDone(controller); }); }; diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 2ec8cf8f9..804664004 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'from_handlers.dart'; + /// Taps into a Stream to allow additional handling on a single-subscriber /// stream without first wrapping as a broadcast stream. /// @@ -13,7 +15,7 @@ import 'dart:async'; /// listener, and may be canceled only by the listener. StreamTransformer tap(void fn(T value), {void onError(error, stackTrace), void onDone()}) => - new StreamTransformer.fromHandlers(handleData: (value, sink) { + fromHandlers(handleData: (value, sink) { try { fn(value); } catch (_) {/*Ignore*/} diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 28436bd6b..268b55efe 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -136,18 +136,23 @@ void main() { group('broadcast stream with multiple listeners', () { int dataCallCount; int doneCallCount; + int errorCallCount; setUp(() async { dataCallCount = 0; doneCallCount = 0; + errorCallCount = 0; setUpForController( new StreamController.broadcast(), fromHandlers(handleData: (value, sink) { dataCallCount++; + }, handleError: (error, stackTrace, sink) { + errorCallCount++; + sink.addError(error, stackTrace); }, handleDone: (sink) { doneCallCount++; })); - transformed.listen((_) {}); + transformed.listen((_) {}, onError: (_, __) {}); }); test('handles data once', () async { @@ -160,6 +165,12 @@ void main() { await values.close(); expect(doneCallCount, 1); }); + + test('handles errors once', () async { + values.addError('error'); + await new Future(() {}); + expect(errorCallCount, 1); + }); }); }); } diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 8aecee626..eb64eeed7 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -53,4 +53,59 @@ void main() { await source.close(); expect(doneCalled, true); }); + + test('forwards only once with multiple listeners on a broadcast stream', + () async { + var dataCallCount = 0; + var source = new StreamController.broadcast(); + source.stream.transform(tap((_) { + dataCallCount++; + })) + ..listen((_) {}) + ..listen((_) {}); + source.add(1); + await new Future(() {}); + expect(dataCallCount, 1); + }); + + test( + 'forwards errors only once with multiple listeners on a broadcast stream', + () async { + var errorCallCount = 0; + var source = new StreamController.broadcast(); + source.stream.transform(tap((_) {}, onError: (_, __) { + errorCallCount++; + })) + ..listen((_) {}, onError: (_, __) {}) + ..listen((_) {}, onError: (_, __) {}); + source.addError('error'); + await new Future(() {}); + expect(errorCallCount, 1); + }); + + test('calls onDone only once with multiple listeners on a broadcast stream', + () async { + var doneCallCount = 0; + var source = new StreamController.broadcast(); + source.stream.transform(tap((_) {}, onDone: () { + doneCallCount++; + })) + ..listen((_) {}) + ..listen((_) {}); + await source.close(); + expect(doneCallCount, 1); + }); + + test('forwards values to multiple listeners', () async { + var source = new StreamController.broadcast(); + var emittedValues1 = []; + var emittedValues2 = []; + source.stream.transform(tap((_) {})) + ..listen(emittedValues1.add) + ..listen(emittedValues2.add); + source.add(1); + await new Future(() {}); + expect(emittedValues1, [1]); + expect(emittedValues2, [1]); + }); } From 7e49242284a44e84622086d42e63fcd9aa469995 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 28 Jun 2017 13:31:45 -0700 Subject: [PATCH 0321/1215] Always run onError callbacks for Chain.capture() in the parent zone (dart-lang/stack_trace#31) Closes dart-lang/stack_trace#30 --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 5e56d8d6f..abb5b0a65 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.7.4 + +* Always run `onError` callbacks for `Chain.capture()` in the parent zone. + ## 1.7.3 * Fix broken links in the README. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 1cccd3af6..924f2efde 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -138,7 +138,7 @@ class StackZoneSpecification { // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just // allow [runBinary] to throw instead once issue 18134 is fixed. try { - return parent.runBinary(zone, _onError, error, stackChain); + return self.parent.runBinary(_onError, error, stackChain); } catch (newError, newStackTrace) { if (identical(newError, error)) { return parent.handleUncaughtError(zone, error, stackChain); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 94054ecae..3c25051dd 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.4-dev +version: 1.7.4 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From d7a7825a69a9339cc3d2b87b129114ca6dc473c9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 29 Jun 2017 14:43:39 -0700 Subject: [PATCH 0322/1215] Use sync forwarders in `fromHandlers` (dart-lang/stream_transform#27) Towards dart-lang/stream_transform#24 - Switch to sync StreamControllers - Set onPause, onResume, and onCancel in the onListen callback - Don't wrap pause and resume callbacks - they are guaranteed to not be called outside of the subscription lifetime - Only cancel the subscription when the values stream is not done - in stream closure path the onCancel is called but does not need to return a future. - Drop the now unnecessary `await new Future(() {})` from tests. --- pkgs/stream_transform/CHANGELOG.md | 1 + .../lib/src/from_handlers.dart | 36 +++++++++---------- pkgs/stream_transform/test/audit_test.dart | 5 ++- .../test/from_handlers_test.dart | 2 -- pkgs/stream_transform/test/throttle_test.dart | 2 -- 5 files changed, 19 insertions(+), 27 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 7f1aedf0d..b684adbde 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -4,6 +4,7 @@ broadcast streams. Fixed for `throttle`, `debounce`, and `audit`. - Bug Fix: Only call the `tap` data callback once per event rather than once per listener. +- Use sync `StreamControllers` for forwarding where possible. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 315de961a..1303584ae 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -44,35 +44,31 @@ class _StreamTransformer implements StreamTransformer { @override Stream bind(Stream values) { - StreamController controller; - if (values.isBroadcast) { - controller = new StreamController.broadcast(); - } else { - controller = new StreamController(); - } + var controller = values.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + StreamSubscription subscription; controller.onListen = () { - if (subscription != null) { - return; - } + if (subscription != null) return; + bool valuesDone = false; subscription = values.listen((value) => _handleData(value, controller), onError: (error, stackTrace) { _handleError(error, stackTrace, controller); }, onDone: () { + valuesDone = true; _handleDone(controller); }); - }; - if (!values.isBroadcast) { - controller.onPause = () => subscription?.pause(); - controller.onResume = () => subscription?.resume(); - } - controller.onCancel = () { - if (controller.hasListener || subscription == null) { - return new Future.value(); + if (!values.isBroadcast) { + controller.onPause = subscription.pause; + controller.onResume = subscription.resume; } - var toCancel = subscription; - subscription = null; - return toCancel.cancel(); + controller.onCancel = () { + var toCancel = subscription; + subscription = null; + if (!valuesDone) return toCancel.cancel(); + return null; + }; }; return controller.stream; } diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index d65fd7f2b..a3b2fefc3 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -61,9 +61,9 @@ void main() { test('waits for pending value to close', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); await values.close(); - await new Future(() {}); + expect(isDone, false); + await new Future.delayed(const Duration(milliseconds: 10)); expect(isDone, true); }); @@ -71,7 +71,6 @@ void main() { values.add(1); await new Future.delayed(const Duration(milliseconds: 10)); values.add(2); - await new Future(() {}); await values.close(); expect(isDone, false); await new Future.delayed(const Duration(milliseconds: 10)); diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 268b55efe..fe9e91658 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -55,7 +55,6 @@ void main() { test('forwards done', () async { await values.close(); - await new Future(() {}); expect(isDone, true); }); @@ -103,7 +102,6 @@ void main() { test('forwards done', () async { await values.close(); - await new Future(() {}); expect(isDone, true); expect(isDone2, true); }); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 3647cb418..10a34fded 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -63,9 +63,7 @@ void main() { values.add(1); await new Future.delayed(const Duration(milliseconds: 10)); values.add(2); - await new Future(() {}); await values.close(); - await new Future(() {}); expect(isDone, true); }); From 9a20c980313a1d696afd94344935a586021a5c0e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 30 Jun 2017 13:29:57 -0700 Subject: [PATCH 0323/1215] Use sync forwarders for `merge` (dart-lang/stream_transform#28) Towards dart-lang/stream_transform#24 Also fix a bug where canceling the subscription on a broadcast stream would cancel single-subscription streams merged in and not allow subsequent listeners. - Use sync StreamControllers - If the first stream is a broadcast, also translate all merged streams to broadcast so they can be canceled and relistened. Add a note to the Doc comment warning that single-subscription streams merged into a broadcast stream may never be canceled. - Move onPause, onResume, and onCancel initialization inside onListen callback - they don't need to exist before initialization. - Only cancel input subscriptions if they aren't all done. - Add test for onDone forwarding. - Add test for canceling and relistening on broadcast streams. --- pkgs/stream_transform/CHANGELOG.md | 2 + pkgs/stream_transform/lib/src/merge.dart | 60 ++++++++++++---------- pkgs/stream_transform/test/merge_test.dart | 38 +++++++++++++- 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index b684adbde..d6bd7a9a0 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -4,6 +4,8 @@ broadcast streams. Fixed for `throttle`, `debounce`, and `audit`. - Bug Fix: Only call the `tap` data callback once per event rather than once per listener. +- Bug Fix: Allow canceling and re-listening to broadcast streams after a + `merge` transform. - Use sync `StreamControllers` for forwarding where possible. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index d2e53a6a1..563cff027 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -7,14 +7,17 @@ import 'dart:async'; /// Emits values from the source stream and [other] in any order as they arrive. /// /// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the type of stream [other] is. +/// well, regardless of [other]'s type. If a single subscription stream is +/// merged into a broadcast stream it may never be canceled. StreamTransformer merge(Stream other) => new _Merge([other]); /// Emits values from the source stream and all streams in [others] in any order /// as they arrive. /// /// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of streams in [others]. +/// well, regardless of the types of streams in [others]. If single +/// subscription streams are merged into a broadcast stream they may never be +/// canceled. StreamTransformer mergeAll(List> others) => new _Merge(others); @@ -25,18 +28,22 @@ class _Merge implements StreamTransformer { @override Stream bind(Stream first) { - StreamController controller; + var controller = first.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + + List> allStreams = [first]..addAll(_others); if (first.isBroadcast) { - controller = new StreamController.broadcast(); - } else { - controller = new StreamController(); + allStreams = allStreams + .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) + .toList(); } + List subscriptions; - List> allStreams = [first]..addAll(_others); - var activeStreamCount = 0; controller.onListen = () { if (subscriptions != null) return; + var activeStreamCount = 0; subscriptions = allStreams.map((stream) { activeStreamCount++; return stream.listen(controller.add, onError: controller.addError, @@ -44,28 +51,25 @@ class _Merge implements StreamTransformer { if (--activeStreamCount <= 0) controller.close(); }); }).toList(); - }; - - // Forward methods from listener - if (!first.isBroadcast) { - controller.onPause = () { - for (var subscription in subscriptions) { - subscription.pause(); - } - }; - controller.onResume = () { - for (var subscription in subscriptions) { - subscription.resume(); - } - }; - controller.onCancel = - () => Future.wait(subscriptions.map((s) => s.cancel())); - } else { + if (!first.isBroadcast) { + controller.onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } + }; + controller.onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; + } controller.onCancel = () { - if (controller?.hasListener ?? false) return new Future.value(null); - return Future.wait(subscriptions.map((s) => s.cancel())); + var toCancel = subscriptions; + subscriptions = null; + if (activeStreamCount <= 0) return null; + return Future.wait(toCancel.map((s) => s.cancel())); }; - } + }; return controller.stream; } } diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index c604f9184..8108b9586 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -32,6 +32,40 @@ void main() { expect(firstCanceled, true); expect(secondCanceled, true); }); + + test('completes when both sources complete', () async { + var first = new StreamController(); + var second = new StreamController(); + var isDone = false; + first.stream.transform(merge(second.stream)).listen((_) {}, onDone: () { + isDone = true; + }); + await first.close(); + expect(isDone, false); + await second.close(); + expect(isDone, true); + }); + + test('can cancel and relisten to broadcast stream', () async { + var first = new StreamController.broadcast(); + var second = new StreamController(); + var emittedValues = []; + var transformed = first.stream.transform((merge(second.stream))); + var subscription = transformed.listen(emittedValues.add); + first.add(1); + second.add(2); + await new Future(() {}); + expect(emittedValues, contains(1)); + expect(emittedValues, contains(2)); + await subscription.cancel(); + emittedValues = []; + subscription = transformed.listen(emittedValues.add); + first.add(3); + second.add(4); + await new Future(() {}); + expect(emittedValues, contains(3)); + expect(emittedValues, contains(4)); + }); }); group('mergeAll', () { @@ -93,7 +127,9 @@ void main() { await new Future(() {}); expect(firstCanceled, true); expect(secondBroadcastCanceled, true); - expect(secondSingleCanceled, true); + expect(secondSingleCanceled, false, + reason: 'Single subscription streams merged into broadcast streams ' + 'are not canceled'); expect(firstListenerValues, [1, 2, 3]); expect(secondListenerValues, [1, 2, 3, 4, 5, 6]); From 5b3c27cd557890725d630281f1d6e650d88f79eb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 30 Jun 2017 18:05:30 -0700 Subject: [PATCH 0324/1215] Ensure timers are started before awaits in tests (dart-lang/stream_transform#29) Fixes dart-lang/stream_transform#25 These tests were relying on a 5ms Timer getting started asynchronously and firing before a 10ms delay which is not guaranteed. By waiting an extra cycle through the event loop to ensure that the Timer starts before the delay we can have a better guarantee of ordering. - Add a test util to wait for Timers to start and then elapse. - Replace `await new Future.delayed(arbitraryDelay)` with the new utility. - Add missing copyright notices on touched files. --- pkgs/stream_transform/test/audit_test.dart | 24 ++++++++++----- pkgs/stream_transform/test/debounce_test.dart | 29 ++++++++++++------- pkgs/stream_transform/test/throttle_test.dart | 15 +++++++--- pkgs/stream_transform/test/utils.dart | 11 +++++++ 4 files changed, 56 insertions(+), 23 deletions(-) create mode 100644 pkgs/stream_transform/test/utils.dart diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index a3b2fefc3..b61a8dbc8 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -1,7 +1,14 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; + import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { var streamTypes = { 'single subscription': () => new StreamController(), @@ -47,15 +54,15 @@ void main() { values.add(1); values.add(2); await values.close(); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [2]); }); test('outputs multiple values spaced further than duration', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [1, 2]); }); @@ -63,17 +70,17 @@ void main() { values.add(1); await values.close(); expect(isDone, false); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(isDone, true); }); test('closes output if there are no pending values', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); await values.close(); expect(isDone, false); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(isDone, true); }); @@ -84,7 +91,8 @@ void main() { values.add(2); await new Future.delayed(const Duration(milliseconds: 3)); values.add(3); - expect(emittedValues, [2]); + await waitForTimer(5); + expect(emittedValues, [2, 3]); }); if (streamType == 'broadcast') { @@ -93,7 +101,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); }); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index a28d2ca32..59cb809fe 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -1,7 +1,14 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; + import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { var streamTypes = { 'single subscription': () => new StreamController(), @@ -47,21 +54,21 @@ void main() { values.add(1); values.add(2); await values.close(); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [2]); }); test('outputs multiple values spaced further than duration', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [1, 2]); }); test('waits for pending value to close', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); await values.close(); await new Future(() {}); expect(isDone, true); @@ -69,12 +76,12 @@ void main() { test('closes output if there are no pending values', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); await new Future(() {}); await values.close(); expect(isDone, false); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(isDone, true); }); @@ -84,7 +91,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); }); @@ -100,7 +107,7 @@ void main() { values.add(1); values.add(2); await values.close(); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [ [1, 2] ]); @@ -109,9 +116,9 @@ void main() { test('separate lists for multiple values spaced further than duration', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [ [1], [2] @@ -124,7 +131,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [ [1, 2] ]); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 10a34fded..94e1851eb 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -1,7 +1,14 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; + import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { var streamTypes = { 'single subscription': () => new StreamController(), @@ -47,21 +54,21 @@ void main() { values.add(1); values.add(2); await values.close(); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [1]); }); test('outputs multiple values spaced further than duration', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); expect(emittedValues, [1, 2]); }); test('closes output immediately', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 10)); + await waitForTimer(5); values.add(2); await values.close(); expect(isDone, true); diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart new file mode 100644 index 000000000..4e38ef7f7 --- /dev/null +++ b/pkgs/stream_transform/test/utils.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Cycle the event loop to ensure timers are started, then wait for a delay +/// longer than [milliseconds] to allow for the timer to fire. +Future waitForTimer(int milliseconds) => + new Future(() {/* ensure Timer is started*/}).then((_) => + new Future.delayed(new Duration(milliseconds: milliseconds + 1))); From cb14253aaa8638037d3b3f866715b443d9c07619 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 30 Jun 2017 18:06:14 -0700 Subject: [PATCH 0325/1215] Use sync forwarders for `switchLatest` (dart-lang/stream_transform#30) Towards dart-lang/stream_transform#24 - Don't return a Future from `onCancel` when the values were already done. - Use `sync: true` - Drop unnecessary `await new Future(() {})`s - Set onPause, onResume, and onCancel inside onListen. --- pkgs/stream_transform/lib/src/switch.dart | 88 ++++++++++----------- pkgs/stream_transform/test/switch_test.dart | 5 -- 2 files changed, 42 insertions(+), 51 deletions(-) diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index be9eeeb2f..b7fc110e5 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -32,58 +32,54 @@ class _SwitchTransformer implements StreamTransformer, T> { @override Stream bind(Stream> outer) { - StreamController controller; - if (outer.isBroadcast) { - controller = new StreamController.broadcast(); - } else { - controller = new StreamController(); - } - StreamSubscription innerSubscription; + var controller = outer.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + StreamSubscription> outerSubscription; + controller.onListen = () { - var outerStreamDone = false; - var innerStreamDone = false; - outerSubscription = outer.listen((innerStream) { - innerSubscription?.cancel(); - innerSubscription = innerStream.listen(controller.add); - innerSubscription.onDone(() { - innerStreamDone = true; - if (outerStreamDone) { - controller.close(); - } - }); - innerSubscription.onError(controller.addError); - }); - outerSubscription.onDone(() { - outerStreamDone = true; - if (innerStreamDone) { - controller.close(); - } - }); - outerSubscription.onError(controller.addError); - }; + if (outerSubscription != null) return; - cancelSubscriptions() => Future.wait([ - innerSubscription?.cancel() ?? new Future.value(), - outerSubscription?.cancel() ?? new Future.value() - ]); + StreamSubscription innerSubscription; + var outerStreamDone = false; - if (!outer.isBroadcast) { - controller.onPause = () { - innerSubscription?.pause(); - outerSubscription?.pause(); - }; - controller.onResume = () { - innerSubscription?.resume(); - outerSubscription?.resume(); - }; - controller.onCancel = () => cancelSubscriptions(); - } else { + outerSubscription = outer.listen( + (innerStream) { + innerSubscription?.cancel(); + innerSubscription = innerStream.listen(controller.add, + onError: controller.addError, onDone: () { + innerSubscription = null; + if (outerStreamDone) controller.close(); + }); + }, + onError: controller.addError, + onDone: () { + outerStreamDone = true; + if (innerSubscription == null) controller.close(); + }); + if (!outer.isBroadcast) { + controller.onPause = () { + innerSubscription?.pause(); + outerSubscription.pause(); + }; + controller.onResume = () { + innerSubscription?.resume(); + outerSubscription.resume(); + }; + } controller.onCancel = () { - if (controller.hasListener) return new Future.value(); - return cancelSubscriptions(); + var toCancel = []; + if (!outerStreamDone) toCancel.add(outerSubscription); + if (innerSubscription != null) { + toCancel.add(innerSubscription); + } + outerSubscription = null; + innerSubscription = null; + if (toCancel.isEmpty) return null; + return Future.wait(toCancel.map((s) => s.cancel())); }; - } + }; return controller.stream; } } diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index fbae7d7b5..91f10c88e 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -82,12 +82,9 @@ void main() { await new Future(() {}); await outer.close(); - expect(isDone, false); await second.close(); - - await new Future(() {}); expect(isDone, true); }); @@ -97,11 +94,9 @@ void main() { outer.add(first.stream); await new Future(() {}); await first.close(); - await new Future(() {}); expect(isDone, false); await outer.close(); - await new Future(() {}); expect(isDone, true); }); From a7466a637f245390680d8b3835c95e82ed3221d5 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Jul 2017 13:38:43 -0700 Subject: [PATCH 0326/1215] Rewrite concat (dart-lang/stream_transform#32) Uses sync forwarders for dart-lang/stream_transform#24 The simple implementation leaves out a lot of edge cases around single-subscription vs broadcast streams and how they combine. Rewrite to handle pause, resume, and cancel manually. - Loop over stream types in tests - Add test for onDone and canceling and relistening - Force _next to broadcast when first is broadcast - Document behavior of broadcast stream as second stream - Add tests for pause/resume --- pkgs/stream_transform/CHANGELOG.md | 2 + pkgs/stream_transform/lib/src/concat.dart | 69 +++++++- pkgs/stream_transform/test/concat_test.dart | 183 ++++++++++++++++---- 3 files changed, 213 insertions(+), 41 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index d6bd7a9a0..da8fd25a7 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -6,6 +6,8 @@ listener. - Bug Fix: Allow canceling and re-listening to broadcast streams after a `merge` transform. +- Bug Fix: Single-subscription streams concatted after broadcast streams are + handled correctly. - Use sync `StreamControllers` for forwarding where possible. ## 0.0.5 diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart index 0a2c27ad0..955918a85 100644 --- a/pkgs/stream_transform/lib/src/concat.dart +++ b/pkgs/stream_transform/lib/src/concat.dart @@ -8,6 +8,15 @@ import 'dart:async'; /// /// If the initial stream never finishes, the [next] stream will never be /// listened to. +/// +/// If a single-subscription is concatted to the end of a broadcast stream it +/// may be listened to and never canceled. +/// +/// If a broadcast stream is concatted to any other stream it will miss any +/// events which occur before the first stream is done. If a broadcast stream is +/// concatted to a single-subscription stream, pausing the stream while it is +/// listening to the second stream will cause events to be dropped rather than +/// buffered. StreamTransformer concat(Stream next) => new _Concat(next); class _Concat implements StreamTransformer { @@ -17,11 +26,61 @@ class _Concat implements StreamTransformer { @override Stream bind(Stream first) { - var controller = new StreamController(); - controller - .addStream(first) - .then((_) => controller.addStream(_next)) - .then((_) => controller.close()); + var controller = first.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + + var next = first.isBroadcast && !_next.isBroadcast + ? _next.asBroadcastStream() + : _next; + + StreamSubscription subscription; + var currentStream = first; + var firstDone = false; + var secondDone = false; + + Function currentDoneHandler; + + listen() { + subscription = currentStream.listen(controller.add, + onError: controller.addError, onDone: () => currentDoneHandler()); + } + + onSecondDone() { + secondDone = true; + controller.close(); + } + + onFirstDone() { + firstDone = true; + currentStream = next; + currentDoneHandler = onSecondDone; + listen(); + } + + currentDoneHandler = onFirstDone; + + controller.onListen = () { + if (subscription != null) return; + listen(); + if (!first.isBroadcast) { + controller.onPause = () { + if (!firstDone || !next.isBroadcast) return subscription.pause(); + subscription.cancel(); + subscription = null; + }; + controller.onResume = () { + if (!firstDone || !next.isBroadcast) return subscription.resume(); + listen(); + }; + } + controller.onCancel = () { + if (secondDone) return null; + var toCancel = subscription; + subscription = null; + return toCancel.cancel(); + }; + }; return controller.stream; } } diff --git a/pkgs/stream_transform/test/concat_test.dart b/pkgs/stream_transform/test/concat_test.dart index 6cf041b8e..37a46f700 100644 --- a/pkgs/stream_transform/test/concat_test.dart +++ b/pkgs/stream_transform/test/concat_test.dart @@ -8,40 +8,151 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; void main() { - group('concat', () { - test('adds all values from both streams', () async { - var first = new Stream.fromIterable([1, 2, 3]); - var second = new Stream.fromIterable([4, 5, 6]); - var all = await first.transform(concat(second)).toList(); - expect(all, [1, 2, 3, 4, 5, 6]); - }); - - test('closes first stream on cancel', () async { - var firstStreamClosed = false; - var first = new StreamController() - ..onCancel = () { - firstStreamClosed = true; - }; - var second = new StreamController(); - var subscription = - first.stream.transform(concat(second.stream)).listen((_) {}); - await subscription.cancel(); - expect(firstStreamClosed, true); - }); - - test('closes second stream on cancel if first stream done', () async { - var first = new StreamController(); - var secondStreamClosed = false; - var second = new StreamController() - ..onCancel = () { - secondStreamClosed = true; - }; - var subscription = - first.stream.transform(concat(second.stream)).listen((_) {}); - await first.close(); - await new Future(() {}); - await subscription.cancel(); - expect(secondStreamClosed, true); - }); - }); + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var firstType in streamTypes.keys) { + for (var secondType in streamTypes.keys) { + group('concat [$firstType] with [$secondType]', () { + StreamController first; + StreamController second; + + List emittedValues; + bool firstCanceled; + bool secondCanceled; + bool secondListened; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + setUp(() async { + firstCanceled = false; + secondCanceled = false; + secondListened = false; + first = streamTypes[firstType]() + ..onCancel = () { + firstCanceled = true; + }; + second = streamTypes[secondType]() + ..onCancel = () { + secondCanceled = true; + } + ..onListen = () { + secondListened = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = first.stream.transform(concat(second.stream)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('adds all values from both streams', () async { + first..add(1)..add(2); + await first.close(); + await new Future(() {}); + second..add(3)..add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + + test('Does not listen to second stream before first stream finishes', + () async { + expect(secondListened, false); + await first.close(); + expect(secondListened, true); + }); + + test('closes stream after both inputs close', () async { + await first.close(); + await second.close(); + expect(isDone, true); + }); + + test('cancels any type of first stream on cancel', () async { + await subscription.cancel(); + expect(firstCanceled, true); + }); + + if (firstType == 'single subscription') { + test( + 'cancels any type of second stream on cancel if first is ' + 'broadcast', () async { + await first.close(); + await subscription.cancel(); + expect(secondCanceled, true); + }); + + if (secondType == 'broadcast') { + test('can pause and resume during second stream - dropping values', + () async { + await first.close(); + subscription.pause(); + second.add(1); + await new Future(() {}); + subscription.resume(); + second.add(2); + await new Future(() {}); + expect(emittedValues, [2]); + }); + } else { + test('can pause and resume during second stream - buffering values', + () async { + await first.close(); + subscription.pause(); + second.add(1); + await new Future(() {}); + subscription.resume(); + second.add(2); + await new Future(() {}); + expect(emittedValues, [1, 2]); + }); + } + } + + if (firstType == 'broadcast') { + test('can cancel and relisten during first stream', () async { + await subscription.cancel(); + first.add(1); + subscription = transformed.listen(emittedValues.add); + first.add(2); + await new Future(() {}); + expect(emittedValues, [2]); + }); + + test('can cancel and relisten during second stream', () async { + await first.close(); + await subscription.cancel(); + second.add(2); + await new Future(() {}); + subscription = transformed.listen(emittedValues.add); + second.add(3); + await new Future((() {})); + expect(emittedValues, [3]); + }); + + test('forwards values to multiple listeners', () async { + var otherValues = []; + transformed.listen(otherValues.add); + first.add(1); + await first.close(); + second.add(2); + await new Future(() {}); + var thirdValues = []; + transformed.listen(thirdValues.add); + second.add(3); + await new Future(() {}); + expect(emittedValues, [1, 2, 3]); + expect(otherValues, [1, 2, 3]); + expect(thirdValues, [3]); + }); + } + }); + } + } } From 652eeaded577c544137f9e714f2c69abb2be8ee0 Mon Sep 17 00:00:00 2001 From: Ivan Evsikov Date: Mon, 10 Jul 2017 23:57:49 +0300 Subject: [PATCH 0327/1215] Add a Trace.original field (dart-lang/stack_trace#29) Closes dart-lang/stack_trace#28 --- pkgs/stack_trace/CHANGELOG.md | 6 ++ pkgs/stack_trace/lib/src/chain.dart | 5 +- pkgs/stack_trace/lib/src/lazy_trace.dart | 1 + .../lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/lib/src/trace.dart | 84 +++++++++++-------- pkgs/stack_trace/pubspec.yaml | 2 +- 6 files changed, 62 insertions(+), 38 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index abb5b0a65..cd78a9aec 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.8.0 + +* Add a `Trace.original` field to provide access to the original `StackTrace`s + from which the `Trace` was created, and a matching constructor parameter to + `new Trace()`. + ## 1.7.4 * Always run `onError` callbacks for `Chain.capture()` in the parent zone. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index e93b2b445..2d1349de2 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -134,8 +134,9 @@ class Chain implements StackTrace { return new LazyChain(() { // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - var first = - new Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1))); + var first = new Trace( + chain.traces.first.frames.skip(level + (inJS ? 2 : 1)), + original: chain.traces.first.original.toString()); return new Chain([first]..addAll(chain.traces.skip(1))); }); } diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 97bb391a6..a31b75fde 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -23,6 +23,7 @@ class LazyTrace implements Trace { } List get frames => _trace.frames; + StackTrace get original => _trace.original; StackTrace get vmTrace => _trace.vmTrace; Trace get terse => new LazyTrace(() => _trace.terse); Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) => diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 924f2efde..eb06beb32 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -232,6 +232,6 @@ Trace _currentTrace([int level]) { var trace = new Trace.parse(text); // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - return new Trace(trace.frames.skip(level + (inJS ? 2 : 1))); + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: text); }); } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 6296df5cf..972c33e4c 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -60,6 +60,9 @@ class Trace implements StackTrace { /// The stack frames that comprise this stack trace. final List frames; + /// The original stack trace from which this trace was parsed. + final StackTrace original; + /// Returns a human-readable representation of [stackTrace]. If [terse] is /// set, this folds together multiple stack frames from the Dart core /// libraries, so that only the core library method directly called from user @@ -85,7 +88,8 @@ class Trace implements StackTrace { return new LazyTrace(() { // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - return new Trace(trace.frames.skip(level + (inJS ? 2 : 1))); + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + original: trace.original.toString()); }); } @@ -134,7 +138,7 @@ class Trace implements StackTrace { } /// Parses a string representation of a Dart VM stack trace. - Trace.parseVM(String trace) : this(_parseVM(trace)); + Trace.parseVM(String trace) : this(_parseVM(trace), original: trace); static List _parseVM(String trace) { // Ignore [vmChainGap]. This matches the behavior of @@ -155,21 +159,25 @@ class Trace implements StackTrace { /// Parses a string representation of a Chrome/V8 stack trace. Trace.parseV8(String trace) - : this(trace - .split("\n") - .skip(1) - // It's possible that an Exception's description contains a line that - // looks like a V8 trace line, which will screw this up. - // Unfortunately, that's impossible to detect. - .skipWhile((line) => !line.startsWith(_v8TraceLine)) - .map((line) => new Frame.parseV8(line))); + : this( + trace + .split("\n") + .skip(1) + // It's possible that an Exception's description contains a line that + // looks like a V8 trace line, which will screw this up. + // Unfortunately, that's impossible to detect. + .skipWhile((line) => !line.startsWith(_v8TraceLine)) + .map((line) => new Frame.parseV8(line)), + original: trace); /// Parses a string representation of a JavaScriptCore stack trace. Trace.parseJSCore(String trace) - : this(trace - .split("\n") - .where((line) => line != "\tat ") - .map((line) => new Frame.parseV8(line))); + : this( + trace + .split("\n") + .where((line) => line != "\tat ") + .map((line) => new Frame.parseV8(line)), + original: trace); /// Parses a string representation of an Internet Explorer stack trace. /// @@ -179,11 +187,13 @@ class Trace implements StackTrace { /// Parses a string representation of a Firefox stack trace. Trace.parseFirefox(String trace) - : this(trace - .trim() - .split("\n") - .where((line) => line.isNotEmpty && line != '[native code]') - .map((line) => new Frame.parseFirefox(line))); + : this( + trace + .trim() + .split("\n") + .where((line) => line.isNotEmpty && line != '[native code]') + .map((line) => new Frame.parseFirefox(line)), + original: trace); /// Parses a string representation of a Safari stack trace. Trace.parseSafari(String trace) : this.parseFirefox(trace); @@ -195,28 +205,34 @@ class Trace implements StackTrace { /// Parses a string representation of a Safari 6.0 stack trace. @Deprecated("Use Trace.parseSafari instead.") Trace.parseSafari6_0(String trace) - : this(trace - .trim() - .split("\n") - .where((line) => line != '[native code]') - .map((line) => new Frame.parseFirefox(line))); + : this( + trace + .trim() + .split("\n") + .where((line) => line != '[native code]') + .map((line) => new Frame.parseFirefox(line)), + original: trace); /// Parses this package's string representation of a stack trace. /// /// This also parses string representations of [Chain]s. They parse to the /// same trace that [Chain.toTrace] would return. Trace.parseFriendly(String trace) - : this(trace.isEmpty - ? [] - : trace - .trim() - .split("\n") - // Filter out asynchronous gaps from [Chain]s. - .where((line) => !line.startsWith('=====')) - .map((line) => new Frame.parseFriendly(line))); + : this( + trace.isEmpty + ? [] + : trace + .trim() + .split("\n") + // Filter out asynchronous gaps from [Chain]s. + .where((line) => !line.startsWith('=====')) + .map((line) => new Frame.parseFriendly(line)), + original: trace); /// Returns a new [Trace] comprised of [frames]. - Trace(Iterable frames) : frames = new List.unmodifiable(frames); + Trace(Iterable frames, {String original}) + : frames = new List.unmodifiable(frames), + original = new StackTrace.fromString(original); /// Returns a VM-style [StackTrace] object. /// @@ -297,7 +313,7 @@ class Trace implements StackTrace { } } - return new Trace(newFrames.reversed); + return new Trace(newFrames.reversed, original: this.original.toString()); } /// Returns a human-readable string representation of [this]. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3c25051dd..a4552acb3 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.7.4 +version: 1.8.0 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From 52ecefcaa17ff6cb378dfc7971d5655474a84285 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 11 Jul 2017 09:39:28 -0700 Subject: [PATCH 0328/1215] Use sync forwarders in buffer (dart-lang/stream_transform#31) Towards dart-lang/stream_transform#24 Fixes a bug where the output would close too soon if there was a pending trigger. Fixes some bugs in the test. Fixes a bug with canceling when values are broadcast but trigger is single subscription. Refactor for better readability - Fix tests to pass the valuesType instead of the triggerType for both streams. - Refactor for more clear parallel structure between handlers for values and triggers. - Inline _collectToList - Add booleans to track when streams are done rather than overload what it means for their subscriptions to be null. - Only return a Future from onCancel when there were streams open that needed to be canceled. This means that some of the extra awaits in tests need to be left in to properly forward errors closing stream. - Pull the trigger canceling tests out of the loops since the behavior depends on both stream types. - Cancel rather than pause trigger subscription if we won't need it again. - Add tests that broadcast stream (from values) can be canceled and relistened - Set up onPause, onResume, and onCancel in onListen --- pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/lib/src/buffer.dart | 126 ++++++++--------- pkgs/stream_transform/test/buffer_test.dart | 142 +++++++++++++++----- 3 files changed, 163 insertions(+), 109 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index da8fd25a7..25d39a54b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -6,6 +6,10 @@ listener. - Bug Fix: Allow canceling and re-listening to broadcast streams after a `merge` transform. +- Bug Fix: Broadcast streams which are buffered using a single-subscription + trigger can be canceled and re-listened. +- Bug Fix: Buffer outputs one more value if there is a pending trigger before + the trigger closes. - Bug Fix: Single-subscription streams concatted after broadcast streams are handled correctly. - Use sync `StreamControllers` for forwarding where possible. diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index 4f2976d9c..f5ef7bf1f 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -14,12 +14,6 @@ import 'dart:async'; /// the output. StreamTransformer> buffer(Stream trigger) => new _Buffer(trigger); -List _collectToList(T element, List soFar) { - soFar ??= []; - soFar.add(element); - return soFar; -} - /// A StreamTransformer which aggregates values and emits when it sees a value /// on [_trigger]. /// @@ -36,36 +30,17 @@ class _Buffer implements StreamTransformer> { @override Stream> bind(Stream values) { - StreamController> controller; - if (values.isBroadcast) { - controller = new StreamController>.broadcast(); - } else { - controller = new StreamController>(); - } + var controller = values.isBroadcast + ? new StreamController>.broadcast(sync: true) + : new StreamController>(sync: true); List currentResults; bool waitingForTrigger = true; - StreamSubscription valuesSub; + bool isTriggerDone = false; + bool isValueDone = false; + StreamSubscription valueSub; StreamSubscription triggerSub; - cancelValues() { - var sub = valuesSub; - valuesSub = null; - return sub?.cancel() ?? new Future.value(); - } - - cancelTrigger() { - var sub = triggerSub; - triggerSub = null; - return sub?.cancel() ?? new Future.value(); - } - - closeController() { - var ctl = controller; - controller = null; - return ctl?.close() ?? new Future.value(); - } - emit() { controller.add(currentResults); currentResults = null; @@ -73,72 +48,77 @@ class _Buffer implements StreamTransformer> { } onValue(T value) { - currentResults = _collectToList(value, currentResults); - if (!waitingForTrigger) { - emit(); + (currentResults ??= []).add(value); + + if (!waitingForTrigger) emit(); + + if (isTriggerDone) { + valueSub.cancel(); + controller.close(); } } - valuesDone() { - valuesSub = null; + onValuesDone() { + isValueDone = true; if (currentResults == null) { - closeController(); - cancelTrigger(); + triggerSub?.cancel(); + controller.close(); } } onTrigger(_) { - if (currentResults == null) { - waitingForTrigger = false; - return; - } - emit(); - if (valuesSub == null) { - closeController(); - cancelTrigger(); + waitingForTrigger = false; + + if (currentResults != null) emit(); + + if (isValueDone) { + triggerSub.cancel(); + controller.close(); } } - triggerDone() { - cancelValues(); - closeController(); + onTriggerDone() { + isTriggerDone = true; + if (waitingForTrigger) { + valueSub?.cancel(); + controller.close(); + } } controller.onListen = () { - if (valuesSub != null) return; - valuesSub = values.listen(onValue, - onError: controller.addError, onDone: valuesDone); + if (valueSub != null) return; + valueSub = values.listen(onValue, + onError: controller.addError, onDone: onValuesDone); if (triggerSub != null) { if (triggerSub.isPaused) triggerSub.resume(); } else { triggerSub = _trigger.listen(onTrigger, - onError: controller.addError, onDone: triggerDone); + onError: controller.addError, onDone: onTriggerDone); + } + if (!values.isBroadcast) { + controller.onPause = () { + valueSub?.pause(); + triggerSub?.pause(); + }; + controller.onResume = () { + valueSub?.resume(); + triggerSub?.resume(); + }; } - }; - - // Forward methods from listener - if (!values.isBroadcast) { - controller.onPause = () { - valuesSub?.pause(); - triggerSub?.pause(); - }; - controller.onResume = () { - valuesSub?.resume(); - triggerSub?.resume(); - }; - controller.onCancel = - () => Future.wait([cancelValues(), cancelTrigger()]); - } else { controller.onCancel = () { - if (controller?.hasListener ?? false) return; - if (_trigger.isBroadcast) { - cancelTrigger(); + var toCancel = []; + if (!isValueDone) toCancel.add(valueSub); + valueSub = null; + if (_trigger.isBroadcast || !values.isBroadcast) { + if (!isTriggerDone) toCancel.add(triggerSub); + triggerSub = null; } else { triggerSub.pause(); } - cancelValues(); + if (toCancel.isEmpty) return null; + return Future.wait(toCancel.map((s) => s.cancel())); }; - } + }; return controller.stream; } } diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index c371ac576..4d3a2b65c 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -12,37 +12,49 @@ void main() { 'single subscription': () => new StreamController(), 'broadcast': () => new StreamController.broadcast() }; + StreamController trigger; + StreamController values; + List emittedValues; + bool valuesCanceled; + bool triggerCanceled; + bool triggerPaused; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + void setUpForStreamTypes(String triggerType, String valuesType) { + valuesCanceled = false; + triggerCanceled = false; + triggerPaused = false; + trigger = streamTypes[triggerType]() + ..onCancel = () { + triggerCanceled = true; + }; + if (triggerType == 'single subscription') { + trigger.onPause = () { + triggerPaused = true; + }; + } + values = streamTypes[valuesType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = values.stream.transform(buffer(trigger.stream)); + subscription = + transformed.listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + for (var triggerType in streamTypes.keys) { for (var valuesType in streamTypes.keys) { group('Trigger type: [$triggerType], Values type: [$valuesType]', () { - StreamController trigger; - StreamController values; - List emittedValues; - bool valuesCanceled; - bool triggerCanceled; - bool isDone; - List errors; - StreamSubscription subscription; - - setUp(() async { - valuesCanceled = false; - triggerCanceled = false; - trigger = streamTypes[triggerType]() - ..onCancel = () { - triggerCanceled = true; - }; - values = streamTypes[triggerType]() - ..onCancel = () { - valuesCanceled = true; - }; - emittedValues = []; - errors = []; - isDone = false; - subscription = values.stream - .transform(buffer(trigger.stream)) - .listen(emittedValues.add, onError: errors.add, onDone: () { - isDone = true; - }); + setUp(() { + setUpForStreamTypes(triggerType, valuesType); }); test('does not emit before `trigger`', () async { @@ -130,12 +142,6 @@ void main() { expect(valuesCanceled, true); }); - test('cancels trigger subscription when output canceled', () async { - expect(triggerCanceled, false); - await subscription.cancel(); - expect(triggerCanceled, true); - }); - test('closes when trigger ends', () async { expect(isDone, false); await trigger.close(); @@ -157,8 +163,7 @@ void main() { expect(isDone, true); }); - test( - 'closes immediately if there are no pending values when source closes', + test('closes if there are no pending values when source closes', () async { expect(isDone, false); values.add(1); @@ -168,6 +173,19 @@ void main() { expect(isDone, true); }); + test('waits to emit if there is a pending trigger when trigger closes', + () async { + trigger.add(null); + await trigger.close(); + expect(isDone, false); + values.add(1); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + expect(isDone, true); + }); + test('forwards errors from trigger', () async { trigger.addError('error'); await new Future(() {}); @@ -182,4 +200,56 @@ void main() { }); } } + + test('always cancels trigger if values is singlesubscription', () async { + setUpForStreamTypes('broadcast', 'single subscription'); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + + setUpForStreamTypes('single subscription', 'single subscription'); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + }); + + test('cancels trigger if trigger is broadcast', () async { + setUpForStreamTypes('broadcast', 'broadcast'); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + }); + + test('pauses single subscription trigger for broadcast values', () async { + setUpForStreamTypes('single subscription', 'broadcast'); + expect(triggerCanceled, false); + expect(triggerPaused, false); + await subscription.cancel(); + expect(triggerCanceled, false); + expect(triggerPaused, true); + }); + + for (var triggerType in streamTypes.keys) { + test('cancel and relisten with [$triggerType] trigger', () async { + setUpForStreamTypes(triggerType, 'broadcast'); + values.add(1); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + await subscription.cancel(); + values.add(2); + trigger.add(null); + await new Future(() {}); + subscription = transformed.listen(emittedValues.add); + values.add(3); + trigger.add(null); + await new Future(() {}); + expect(emittedValues, [ + [1], + [3] + ]); + }); + } } From 1ef29b6fa84b837be96c1b5a83b7a0e6bc09aabd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 11 Jul 2017 10:35:55 -0700 Subject: [PATCH 0329/1215] Fix asyncWhere for broadcast streams (dart-lang/stream_transform#33) Previous implementation may have failed to send onDone for some listeners since each listener would increment `valuesWaiting` and only the last listener would decrement it back to zero. There were also potential bugs if the predicate was non-deterministic. --- pkgs/stream_transform/CHANGELOG.md | 2 +- .../stream_transform/lib/src/async_where.dart | 4 ++- .../test/async_where_test.dart | 32 +++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 25d39a54b..1abe6056b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.0.6 - Bug Fix: Some transformers did not correctly add data to all listeners on - broadcast streams. Fixed for `throttle`, `debounce`, and `audit`. + broadcast streams. Fixed for `throttle`, `debounce`, `asyncWhere` and `audit`. - Bug Fix: Only call the `tap` data callback once per event rather than once per listener. - Bug Fix: Allow canceling and re-listening to broadcast streams after a diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/async_where.dart index 1bb2d6432..6a4fc329f 100644 --- a/pkgs/stream_transform/lib/src/async_where.dart +++ b/pkgs/stream_transform/lib/src/async_where.dart @@ -3,11 +3,13 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'from_handlers.dart'; + /// Like [Stream.where] but allows the [test] to return a [Future]. StreamTransformer asyncWhere(FutureOr test(T element)) { var valuesWaiting = 0; var sourceDone = false; - return new StreamTransformer.fromHandlers(handleData: (element, sink) { + return fromHandlers(handleData: (element, sink) { valuesWaiting++; () async { if (await test(element)) sink.add(element); diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 919f93164..18c34bc76 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -34,4 +34,36 @@ void main() { var filtered = values.transform(asyncWhere((e) => e > 4)); expect(await filtered.isEmpty, true); }); + + test('forwards values to multiple listeners', () async { + var values = new StreamController.broadcast(); + var filtered = values.stream.transform(asyncWhere((e) async => e > 2)); + var firstValues = []; + var secondValues = []; + filtered..listen(firstValues.add)..listen(secondValues.add); + values..add(1)..add(2)..add(3)..add(4); + await new Future(() {}); + expect(firstValues, [3, 4]); + expect(secondValues, [3, 4]); + }); + + test('closes streams with multiple listeners', () async { + var values = new StreamController.broadcast(); + var predicate = new Completer(); + var filtered = values.stream.transform(asyncWhere((_) => predicate.future)); + var firstDone = false; + var secondDone = false; + filtered + ..listen(null, onDone: () => firstDone = true) + ..listen(null, onDone: () => secondDone = true); + values.add(1); + await values.close(); + expect(firstDone, false); + expect(secondDone, false); + + predicate.complete(true); + await new Future(() {}); + expect(firstDone, true); + expect(secondDone, true); + }); } From ffb0e4374ab8804c1a8013f4fadddb97d40109a1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 11 Jul 2017 10:49:01 -0700 Subject: [PATCH 0330/1215] Prepare to publish 0.0.6 --- pkgs/stream_transform/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index f1c647ee8..92b2cbe8d 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.6-dev +version: 0.0.6 environment: sdk: ">=1.22.0 <2.0.0" From 17ede9263b8fd69fb857f043db572996dd928c11 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 12 Jul 2017 13:27:49 -0700 Subject: [PATCH 0331/1215] Add fromBind to replace direct StreamTransformer (dart-lang/stream_transform#35) Fixes dart-lang/stream_transform#34 `new StreamTransformer(onListen)` produces a Stream which can not know whether it is a Broadcast stream. The `bind` method can more directly express the intent of these transformers but adding a class is a lot of boilerplate. Add fromBind to handle these cases. --- pkgs/stream_transform/CHANGELOG.md | 5 +++++ pkgs/stream_transform/lib/src/bind.dart | 22 +++++++++++++++++++++ pkgs/stream_transform/lib/src/scan.dart | 8 ++++---- pkgs/stream_transform/lib/src/switch.dart | 7 +++---- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/scan_test.dart | 8 ++++++++ pkgs/stream_transform/test/switch_test.dart | 8 ++++++++ 7 files changed, 51 insertions(+), 9 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/bind.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 1abe6056b..20f2e9b36 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.7 + +- Bug Fix: Streams produces with `scan` and `switchMap` now correctly report + `isBroadcast`. + ## 0.0.6 - Bug Fix: Some transformers did not correctly add data to all listeners on diff --git a/pkgs/stream_transform/lib/src/bind.dart b/pkgs/stream_transform/lib/src/bind.dart new file mode 100644 index 000000000..603cc0f54 --- /dev/null +++ b/pkgs/stream_transform/lib/src/bind.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Matches [StreamTransformer.bind]. +typedef Stream Bind(Stream values); + +/// Creates a [StreamTransformer] which overrides [StreamTransformer.bind] to +/// [bindFn]. +StreamTransformer fromBind(Bind bindFn) => + new _StreamTransformer(bindFn); + +class _StreamTransformer implements StreamTransformer { + final Bind _bind; + + _StreamTransformer(this._bind); + + @override + Stream bind(Stream values) => _bind(values); +} diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index 518d33299..7c26076c4 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -3,13 +3,13 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'bind.dart'; + /// Scan is like fold, but instead of producing a single value it yields /// each intermediate accumulation. StreamTransformer scan( T initialValue, T combine(T previousValue, S element)) => - new StreamTransformer((stream, cancelOnError) { + fromBind((stream) { T accumulated = initialValue; - return stream - .map((value) => accumulated = combine(accumulated, value)) - .listen(null, cancelOnError: cancelOnError); + return stream.map((value) => accumulated = combine(accumulated, value)); }); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index b7fc110e5..193cbaa5f 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'bind.dart'; + /// Maps events to a Stream and emits values from the most recently created /// Stream. /// @@ -12,10 +14,7 @@ import 'dart:async'; /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of the streams produced by [map]. StreamTransformer switchMap(Stream map(S event)) => - new StreamTransformer((stream, cancelOnError) => stream - .map(map) - .transform(switchLatest()) - .listen(null, cancelOnError: cancelOnError)); + fromBind((stream) => stream.map(map).transform(switchLatest())); /// Emits values from the most recently emitted Stream. /// diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 92b2cbe8d..c5f0a226d 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.6 +version: 0.0.7-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 51456f2ef..717b80854 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -13,5 +13,13 @@ void main() { expect(result, [1, 3, 6, 10]); }); + + test('can create a broadcast stream', () async { + var source = new StreamController.broadcast(); + + var transformed = source.stream.transform(scan(null, null)); + + expect(transformed.isBroadcast, true); + }); }); } diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 91f10c88e..ccc987755 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -138,5 +138,13 @@ void main() { await new Future(() {}); expect(values, [1, 2, 3, 4, 5, 6]); }); + + test('can create a broadcast stream', () async { + var outer = new StreamController.broadcast(); + + var transformed = outer.stream.transform(switchMap(null)); + + expect(transformed.isBroadcast, true); + }); }); } From a365c36ddf3c2de4d0db612edb4886ed3cbf9229 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 12 Jul 2017 14:35:50 -0700 Subject: [PATCH 0332/1215] Add startWith, startWithMany, and startWithStream (dart-lang/stream_transform#36) Closes dart-lang/stream_transform#19, closes dart-lang/stream_transform#20 --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/README.md | 4 + pkgs/stream_transform/lib/src/start_with.dart | 35 ++++ .../lib/stream_transform.dart | 1 + .../test/start_with_test.dart | 156 ++++++++++++++++++ 5 files changed, 197 insertions(+) create mode 100644 pkgs/stream_transform/lib/src/start_with.dart create mode 100644 pkgs/stream_transform/test/start_with_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 20f2e9b36..93645f7b6 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -2,6 +2,7 @@ - Bug Fix: Streams produces with `scan` and `switchMap` now correctly report `isBroadcast`. +- Add `startWith`, `startWithMany`, and `startWithStream`. ## 0.0.6 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index bf69198d6..2b88382c6 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -33,6 +33,10 @@ Interleaves events from multiple streams into a single stream. Scan is like fold, but instead of producing a single value it yields each intermediate accumulation. +# startWith, startWithMany, startWithStream + +Prepend a value, an iterable, or a stream to the beginning of another stream. + # switchMap, switchLatest Flatten a Stream of Streams into a Stream which forwards values from the most diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart new file mode 100644 index 000000000..a98eb6d8a --- /dev/null +++ b/pkgs/stream_transform/lib/src/start_with.dart @@ -0,0 +1,35 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'bind.dart'; +import 'concat.dart'; + +/// Emits [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. +StreamTransformer startWith(T initial) => + startWithStream(new Future.value(initial).asStream()); + +/// Emits all values in [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. If +/// the original stream is a broadcast stream it will miss any events which +/// occur before the initial values are all emitted. +StreamTransformer startWithMany(Iterable initial) => + startWithStream(new Stream.fromIterable(initial)); + +/// Emits all values in [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. If +/// the original stream is a broadcast stream it will miss any events which +/// occur before [initial] closes. +StreamTransformer startWithStream(Stream initial) => + fromBind((values) { + if (values.isBroadcast && !initial.isBroadcast) { + initial = initial.asBroadcastStream(); + } + return initial.transform(concat(values)); + }); diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 8b4d601e2..498363996 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -9,6 +9,7 @@ export 'src/concat.dart'; export 'src/debounce.dart'; export 'src/merge.dart'; export 'src/scan.dart'; +export 'src/start_with.dart'; export 'src/switch.dart'; export 'src/tap.dart'; export 'src/throttle.dart'; diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart new file mode 100644 index 000000000..97f0529b6 --- /dev/null +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -0,0 +1,156 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + StreamController values; + Stream transformed; + StreamSubscription subscription; + + List emittedValues; + bool isDone; + + setupForStreamType(String streamType, StreamTransformer transformer) { + emittedValues = []; + isDone = false; + values = streamTypes[streamType](); + transformed = values.stream.transform(transformer); + subscription = + transformed.listen(emittedValues.add, onDone: () => isDone = true); + } + + for (var streamType in streamTypes.keys) { + group('startWith then [$streamType]', () { + setUp(() => setupForStreamType(streamType, startWith(1))); + + test('outputs all values', () async { + values..add(2)..add(3); + await new Future(() {}); + expect(emittedValues, [1, 2, 3]); + }); + + test('outputs initial when followed by empty stream', () async { + await values.close(); + expect(emittedValues, [1]); + }); + + test('closes with values', () async { + expect(isDone, false); + await values.close(); + expect(isDone, true); + }); + + if (streamType == 'broadcast') { + test('can cancel and relisten', () async { + values.add(2); + await new Future(() {}); + await subscription.cancel(); + subscription = transformed.listen(emittedValues.add); + values.add(3); + await new Future(() {}); + await new Future(() {}); + expect(emittedValues, [1, 2, 3]); + }); + } + }); + + group('startWithMany then [$streamType]', () { + setUp(() async { + setupForStreamType(streamType, startWithMany([1, 2])); + // Ensure all initial values go through + await new Future(() {}); + }); + + test('outputs all values', () async { + values..add(3)..add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + + test('outputs initial when followed by empty stream', () async { + await values.close(); + expect(emittedValues, [1, 2]); + }); + + test('closes with values', () async { + expect(isDone, false); + await values.close(); + expect(isDone, true); + }); + + if (streamType == 'broadcast') { + test('can cancel and relisten', () async { + values.add(3); + await new Future(() {}); + await subscription.cancel(); + subscription = transformed.listen(emittedValues.add); + values.add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + } + }); + + for (var startingStreamType in streamTypes.keys) { + group('startWithStream [$startingStreamType] then [$streamType]', () { + StreamController starting; + setUp(() async { + starting = streamTypes[startingStreamType](); + setupForStreamType(streamType, startWithStream(starting.stream)); + }); + + test('outputs all values', () async { + starting..add(1)..add(2); + await starting.close(); + values..add(3)..add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + + test('closes with values', () async { + expect(isDone, false); + await starting.close(); + expect(isDone, false); + await values.close(); + expect(isDone, true); + }); + + if (streamType == 'broadcast') { + test('can cancel and relisten during starting', () async { + starting.add(1); + await new Future(() {}); + await subscription.cancel(); + subscription = transformed.listen(emittedValues.add); + starting.add(2); + await starting.close(); + values..add(3)..add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + + test('can cancel and relisten during values', () async { + starting..add(1)..add(2); + await starting.close(); + values.add(3); + await new Future(() {}); + await subscription.cancel(); + subscription = transformed.listen(emittedValues.add); + values.add(4); + await new Future(() {}); + expect(emittedValues, [1, 2, 3, 4]); + }); + } + }); + } + } +} From a5980fe7c62225492f43bb9727c5490ea64504f6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 12 Jul 2017 14:36:28 -0700 Subject: [PATCH 0333/1215] Prepare to publish 0.0.7 Clean up typo in CHANGELOG and trailing whitespace in README --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/README.md | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 93645f7b6..7788ddf61 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.0.7 -- Bug Fix: Streams produces with `scan` and `switchMap` now correctly report +- Bug Fix: Streams produced with `scan` and `switchMap` now correctly report `isBroadcast`. - Add `startWith`, `startWithMany`, and `startWithStream`. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 2b88382c6..26022430e 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -30,7 +30,7 @@ Interleaves events from multiple streams into a single stream. # scan -Scan is like fold, but instead of producing a single value it yields each +Scan is like fold, but instead of producing a single value it yields each intermediate accumulation. # startWith, startWithMany, startWithStream diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c5f0a226d..879c5ab84 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.7-dev +version: 0.0.7 environment: sdk: ">=1.22.0 <2.0.0" From 48080d014f179add2150a1e82f78e85708cf29f5 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Wed, 26 Jul 2017 14:54:07 -0700 Subject: [PATCH 0334/1215] Update comment style generic syntax BUG= R=kevmoo@google.com Review-Url: https://codereview.chromium.org//2987963002 . --- .../lib/src/stream_channel_transformer.dart | 4 ++-- pkgs/stream_channel/lib/stream_channel.dart | 12 ++++++------ pkgs/stream_channel/pubspec.yaml | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 46232d74c..d6d10ff5e 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -41,9 +41,9 @@ class StreamChannelTransformer { /// throws a [CastError]. This also means that calls to [StreamSink.add] on /// the transformed channel's sink may throw a [CastError] if the argument /// type doesn't match the reified type of the sink. - static StreamChannelTransformer/**/ typed/**/( + static StreamChannelTransformer typed( StreamChannelTransformer transformer) => - transformer is StreamChannelTransformer/**/ + transformer is StreamChannelTransformer ? transformer : new TypeSafeStreamChannelTransformer(transformer); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 34be085ea..dcbc9a07e 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -108,8 +108,8 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel/**/ transform/**/( - StreamChannelTransformer transformer); + StreamChannel transform( + StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -130,7 +130,7 @@ abstract class StreamChannel { /// If any events emitted by [stream] aren't of type [S], they're converted /// into [CastError] events. Similarly, if any events are added to [sync] that /// aren't of type [S], a [CastError] is thrown. - StreamChannel/**/ cast/**/(); + StreamChannel cast(); } /// An implementation of [StreamChannel] that simply takes a stream and a sink @@ -153,8 +153,8 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel/**/ transform/**/( - StreamChannelTransformer transformer) => + StreamChannel transform( + StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => @@ -169,6 +169,6 @@ abstract class StreamChannelMixin implements StreamChannel { StreamChannel changeSink(StreamSink change(StreamSink sink)) => new StreamChannel.withCloseGuarantee(stream, change(sink)); - StreamChannel/**/ cast/**/() => new StreamChannel( + StreamChannel cast() => new StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 7d395a3ea..19a3bd07c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,10 @@ name: stream_channel -version: 1.6.1 +version: 1.6.2-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.21.0 <2.0.0-dev.infinity' dependencies: async: '^1.11.0' stack_trace: '^1.0.0' From 6f2269b5438c1460e5b4e71b787f2ceebf795491 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:35:03 -0700 Subject: [PATCH 0335/1215] Rename analysis options --- pkgs/stream_channel/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/stream_channel/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/stream_channel/.analysis_options b/pkgs/stream_channel/analysis_options.yaml similarity index 100% rename from pkgs/stream_channel/.analysis_options rename to pkgs/stream_channel/analysis_options.yaml From 398407eeaeba3fc852123300b6f65c3215a9b3bf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:37:58 -0700 Subject: [PATCH 0336/1215] dartfmt --- pkgs/stream_channel/lib/src/disconnector.dart | 14 +++--- .../lib/src/guarantee_channel.dart | 31 +++++++------ .../lib/src/isolate_channel.dart | 18 ++++---- .../lib/src/stream_channel_completer.dart | 4 +- .../lib/src/stream_channel_transformer.dart | 7 +-- .../lib/src/transformer/typed.dart | 2 +- pkgs/stream_channel/lib/stream_channel.dart | 10 ++--- .../test/disconnector_test.dart | 18 ++++---- .../test/isolate_channel_test.dart | 3 +- .../test/json_document_transformer_test.dart | 4 +- .../test/multi_channel_test.dart | 44 ++++++++++++------- .../test/stream_channel_completer_test.dart | 12 ++--- .../test/stream_channel_controller_test.dart | 21 ++++++--- .../test/stream_channel_test.dart | 31 ++++++++----- pkgs/stream_channel/test/utils.dart | 3 +- .../test/with_close_guarantee_test.dart | 22 ++++++---- .../test/with_guarantees_test.dart | 39 +++++++++------- 17 files changed, 160 insertions(+), 123 deletions(-) diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index b23813e96..37a376c31 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -34,10 +34,10 @@ class Disconnector implements StreamChannelTransformer { /// futures have completed. Note that a [StreamController]'s sink won't close /// until the corresponding stream has a listener. Future disconnect() => _disconnectMemo.runOnce(() { - var futures = _sinks.map((sink) => sink._disconnect()).toList(); - _sinks.clear(); - return Future.wait(futures, eagerError: true); - }); + var futures = _sinks.map((sink) => sink._disconnect()).toList(); + _sinks.clear(); + return Future.wait(futures, eagerError: true); + }); final _disconnectMemo = new AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { @@ -111,10 +111,8 @@ class _DisconnectorSink implements StreamSink { if (_isDisconnected) return new Future.value(); _addStreamCompleter = new Completer.sync(); - _addStreamSubscription = stream.listen( - _inner.add, - onError: _inner.addError, - onDone: _addStreamCompleter.complete); + _addStreamSubscription = stream.listen(_inner.add, + onError: _inner.addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index a874799c1..f18cbb973 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -32,28 +32,29 @@ class GuaranteeChannel extends StreamChannelMixin { GuaranteeChannel(Stream innerStream, StreamSink innerSink, {bool allowSinkErrors: true}) { - _sink = new _GuaranteeSink(innerSink, this, - allowErrors: allowSinkErrors); + _sink = + new _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. if (innerStream.isBroadcast) { - innerStream = innerStream.transform( - const SingleSubscriptionTransformer()); + innerStream = + innerStream.transform(const SingleSubscriptionTransformer()); } - _streamController = new StreamController(onListen: () { - // If the sink has disconnected, we've already called - // [_streamController.close]. - if (_disconnected) return; + _streamController = new StreamController( + onListen: () { + // If the sink has disconnected, we've already called + // [_streamController.close]. + if (_disconnected) return; - _subscription = innerStream.listen(_streamController.add, - onError: _streamController.addError, - onDone: () { + _subscription = innerStream.listen(_streamController.add, + onError: _streamController.addError, onDone: () { _sink._onStreamDisconnected(); _streamController.close(); }); - }, sync: true); + }, + sync: true); } /// Called by [_GuaranteeSink] when the user closes it. @@ -159,10 +160,8 @@ class _GuaranteeSink implements StreamSink { if (_disconnected) return new Future.value(); _addStreamCompleter = new Completer.sync(); - _addStreamSubscription = stream.listen( - _inner.add, - onError: _addError, - onDone: _addStreamCompleter.complete); + _addStreamSubscription = stream.listen(_inner.add, + onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c725fef8e..f1328c03d 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -44,8 +44,8 @@ class IsolateChannel extends StreamChannelMixin { // value to be an [IsolateChannel]. var streamCompleter = new StreamCompleter(); var sinkCompleter = new StreamSinkCompleter(); - var channel = new IsolateChannel._( - streamCompleter.stream, sinkCompleter.sink); + var channel = + new IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error @@ -56,9 +56,8 @@ class IsolateChannel extends StreamChannelMixin { var controller = new StreamChannelController( allowForeignErrors: false, sync: true); new SubscriptionStream(subscription).pipe(controller.local.sink); - controller.local.stream.listen( - (data) => message.send(data), - onDone: receivePort.close); + controller.local.stream + .listen((data) => message.send(data), onDone: receivePort.close); streamCompleter.setSourceStream(controller.foreign.stream); sinkCompleter.setDestinationSink(controller.foreign.sink); @@ -93,12 +92,11 @@ class IsolateChannel extends StreamChannelMixin { /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { - var controller = new StreamChannelController( - allowForeignErrors: false, sync: true); + var controller = + new StreamChannelController(allowForeignErrors: false, sync: true); receivePort.pipe(controller.local.sink); - controller.local.stream.listen( - (data) => sendPort.send(data), - onDone: receivePort.close); + controller.local.stream + .listen((data) => sendPort.send(data), onDone: receivePort.close); return new IsolateChannel._( controller.foreign.stream, controller.foreign.sink); } diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index d15adcf94..b9881b913 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -42,8 +42,8 @@ class StreamChannelCompleter { } StreamChannelCompleter() { - _channel = new StreamChannel( - _streamCompleter.stream, _sinkCompleter.sink); + _channel = + new StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); } /// Set a channel as the source and destination for [channel]. diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index d6d10ff5e..1a4afcae2 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -58,9 +58,10 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this( - typedStreamTransformer(codec.decoder), - StreamSinkTransformer.typed( - new StreamSinkTransformer.fromStreamTransformer(codec.encoder))); + typedStreamTransformer(codec.decoder), + StreamSinkTransformer.typed( + new StreamSinkTransformer.fromStreamTransformer( + codec.encoder))); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart index f35e01c98..9c2d72b41 100644 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -8,7 +8,7 @@ import '../../stream_channel.dart'; /// transformer to `S`. class TypeSafeStreamChannelTransformer implements StreamChannelTransformer { - final StreamChannelTransformer _inner; + final StreamChannelTransformer _inner; TypeSafeStreamChannelTransformer(this._inner); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index dcbc9a07e..8d0e60421 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -97,8 +97,8 @@ abstract class StreamChannel { /// transforming it with a [StreamTransformer]. This is a lighter-weight way /// of preserving that guarantee in particular than /// [StreamChannel.withGuarantees]. - factory StreamChannel.withCloseGuarantee(Stream stream, - StreamSink sink) => + factory StreamChannel.withCloseGuarantee( + Stream stream, StreamSink sink) => new CloseGuaranteeChannel(stream, sink); /// Connects [this] to [other], so that any values emitted by either are sent @@ -108,8 +108,7 @@ abstract class StreamChannel { /// Transforms [this] using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. - StreamChannel transform( - StreamChannelTransformer transformer); + StreamChannel transform(StreamChannelTransformer transformer); /// Transforms only the [stream] component of [this] using [transformer]. StreamChannel transformStream(StreamTransformer transformer); @@ -153,8 +152,7 @@ abstract class StreamChannelMixin implements StreamChannel { other.stream.pipe(sink); } - StreamChannel transform( - StreamChannelTransformer transformer) => + StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); StreamChannel transformStream(StreamTransformer transformer) => diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 311a41c9a..e194ee3cf 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -84,14 +84,16 @@ void main() { var sinkController = new StreamController(); var disconnector = new Disconnector(); var sink = new _CloseCompleterSink(sinkController.sink); - var channel = new StreamChannel.withGuarantees( - streamController.stream, sink) - .transform(disconnector); + var channel = + new StreamChannel.withGuarantees(streamController.stream, sink) + .transform(disconnector); var disconnectFutureFired = false; - expect(disconnector.disconnect().then((_) { - disconnectFutureFired = true; - }), completes); + expect( + disconnector.disconnect().then((_) { + disconnectFutureFired = true; + }), + completes); // Give the future time to fire early if it's going to. await pumpEventQueue(); @@ -114,7 +116,7 @@ void main() { channel.sink.add(2); channel.sink.add(3); channel.sink.close(); - + expect(sinkController.stream.toList(), completion(isEmpty)); }); @@ -126,7 +128,7 @@ void main() { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.done, completes); }); - + test("still emits state errors after explicit close", () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.close(), completes); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index fa4d8d532..7316c6a42 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -64,7 +64,8 @@ void main() { }); group("stream channel rules", () { - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { sendPort.send(1); sendPort.send(2); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 6f18e361f..22bb83009 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -15,8 +15,8 @@ void main() { setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( - streamController.stream, sinkController.sink); + channel = + new StreamChannel(streamController.stream, sinkController.sink); }); test("decodes JSON emitted by the channel", () { diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0e58d382e..69059b682 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -47,7 +47,8 @@ void main() { channel1.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { channel1.sink.done.then(expectAsync((_) {}, count: 0)); @@ -58,7 +59,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () { expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); @@ -66,7 +68,8 @@ void main() { channel1.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -126,7 +129,8 @@ void main() { virtual1.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { virtual1.sink.done.then(expectAsync((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); @@ -136,7 +140,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. @@ -149,7 +154,8 @@ void main() { virtual1.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -169,10 +175,10 @@ void main() { // we're properly testing two channels with the same id. expect(virtual1.id, equals(virtual3.id)); - virtual2.stream.listen( - expectAsync((message) => expect(message, equals("hello")))); - virtual4.stream.listen( - expectAsync((message) => expect(message, equals("goodbye")))); + virtual2.stream + .listen(expectAsync((message) => expect(message, equals("hello")))); + virtual4.stream + .listen(expectAsync((message) => expect(message, equals("goodbye")))); virtual1.sink.add("hello"); virtual3.sink.add("goodbye"); @@ -223,7 +229,8 @@ void main() { virtual2.sink.close(); }); - test("doesn't closes the local virtual channel when the stream " + test( + "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { virtual2.sink.done.then(expectAsync((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); @@ -233,7 +240,8 @@ void main() { return pumpEventQueue(); }); - test("closes the underlying channel when it closes without any other " + test( + "closes the underlying channel when it closes without any other " "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. @@ -246,7 +254,8 @@ void main() { virtual2.sink.close(); }); - test("doesn't close the underlying channel when it closes with other " + test( + "doesn't close the underlying channel when it closes with other " "virtual channels", () { controller.local.sink.done.then(expectAsync((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); @@ -259,8 +268,7 @@ void main() { }); test("doesn't allow another virtual channel with the same id", () { - expect(() => channel2.virtualChannel(virtual1.id), - throwsArgumentError); + expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); }); @@ -314,7 +322,8 @@ void main() { group("stream channel rules", () { group("for the main stream:", () { - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { channel1.sink.add(1); channel1.sink.add(2); @@ -380,7 +389,8 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("closing the sink causes the stream to close before it emits any more " + test( + "closing the sink causes the stream to close before it emits any more " "events", () { virtual1.sink.add(1); virtual1.sink.add(2); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 1ee40a5ca..e08dd8a7a 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -18,8 +18,8 @@ void main() { completer = new StreamChannelCompleter(); streamController = new StreamController(); sinkController = new StreamController(); - innerChannel = new StreamChannel( - streamController.stream, sinkController.sink); + innerChannel = + new StreamChannel(streamController.stream, sinkController.sink); }); group("when a channel is set before accessing", () { @@ -98,8 +98,8 @@ void main() { group("forFuture", () { test("forwards a StreamChannel", () { - var channel = StreamChannelCompleter.fromFuture( - new Future.value(innerChannel)); + var channel = + StreamChannelCompleter.fromFuture(new Future.value(innerChannel)); channel.sink.add(1); channel.sink.close(); streamController.sink.add(2); @@ -110,8 +110,8 @@ void main() { }); test("forwards an error", () { - var channel = StreamChannelCompleter.fromFuture( - new Future.error("oh no")); + var channel = + StreamChannelCompleter.fromFuture(new Future.error("oh no")); expect(channel.stream.toList(), throwsA("oh no")); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 7503387d5..8162a1746 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -13,16 +13,25 @@ void main() { }); test("forwards events from the local sink to the foreign stream", () { - controller.local.sink..add(1)..add(2)..add(3)..close(); + controller.local.sink + ..add(1) + ..add(2) + ..add(3) + ..close(); expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); }); test("forwards events from the foreign sink to the local stream", () { - controller.foreign.sink..add(1)..add(2)..add(3)..close(); + controller.foreign.sink + ..add(1) + ..add(2) + ..add(3) + ..close(); expect(controller.local.stream.toList(), completion(equals([1, 2, 3]))); }); - test("with allowForeignErrors: false, shuts down the connection if an " + test( + "with allowForeignErrors: false, shuts down the connection if an " "error is added to the foreign channel", () { controller = new StreamChannelController(allowForeignErrors: false); @@ -40,7 +49,8 @@ void main() { controller = new StreamChannelController(sync: true); }); - test("synchronously forwards events from the local sink to the foreign " + test( + "synchronously forwards events from the local sink to the foreign " "stream", () { var receivedEvent = false; var receivedError = false; @@ -65,7 +75,8 @@ void main() { expect(receivedDone, isTrue); }); - test("synchronously forwards events from the foreign sink to the local " + test( + "synchronously forwards events from the foreign sink to the local " "stream", () { var receivedEvent = false; var receivedError = false; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 41f4c32ec..f0a838385 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -16,8 +16,7 @@ void main() { setUp(() { streamController = new StreamController(); sinkController = new StreamController(); - channel = new StreamChannel( - streamController.stream, sinkController.sink); + channel = new StreamChannel(streamController.stream, sinkController.sink); }); test("pipe() pipes data from each channel's stream into the other's sink", @@ -42,8 +41,8 @@ void main() { }); test("transform() transforms the channel", () async { - var transformed = channel.transform( - new StreamChannelTransformer.fromCodec(UTF8)); + var transformed = + channel.transform(new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); @@ -51,8 +50,11 @@ void main() { transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals([[102, 98, 108, 116, 104, 112]]))); + expect( + sinkController.stream.toList(), + completion(equals([ + [102, 98, 108, 116, 104, 112] + ]))); }); test("transformStream() transforms only the stream", () async { @@ -64,8 +66,7 @@ void main() { transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals(["fblthp"]))); + expect(sinkController.stream.toList(), completion(equals(["fblthp"]))); }); test("transformSink() transforms only the sink", () async { @@ -74,13 +75,19 @@ void main() { streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); - expect(await transformed.stream.toList(), - equals([[102, 111, 111, 98, 97, 114]])); + expect( + await transformed.stream.toList(), + equals([ + [102, 111, 111, 98, 97, 114] + ])); transformed.sink.add("fblthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), - completion(equals([[102, 98, 108, 116, 104, 112]]))); + expect( + sinkController.stream.toList(), + completion(equals([ + [102, 98, 108, 116, 104, 112] + ]))); }); test("changeStream() changes the stream", () { diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart index 130a3e12b..e53389540 100644 --- a/pkgs/stream_channel/test/utils.dart +++ b/pkgs/stream_channel/test/utils.dart @@ -9,7 +9,7 @@ import 'dart:async'; /// /// By default, this should pump the event queue enough times to allow any code /// to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times=20]) { +Future pumpEventQueue([int times = 20]) { if (times == 0) return new Future.value(); // Use [new Future] future to allow microtask events to finish. The [new // Future.value] constructor uses scheduleMicrotask itself and would therefore @@ -17,4 +17,3 @@ Future pumpEventQueue([int times=20]) { // method. return new Future(() => pumpEventQueue(times - 1)); } - diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index caf48cf1c..dafbfeffb 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -35,26 +35,30 @@ void main() { channel = new StreamChannel.withCloseGuarantee(stream, sink); }); - test("closing the event sink causes the stream to close before it emits any " + test( + "closing the event sink causes the stream to close before it emits any " "more events", () async { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.close(); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)) + .asFuture(), + completes); await pumpEventQueue(); }); - test("closing the event sink before events are emitted causes the stream to " + test( + "closing the event sink before events are emitted causes the stream to " "close immediately", () async { channel.sink.close(); - channel.stream.listen( - expectAsync((_) {}, count: 0), - onError: expectAsync((_, __) {}, count: 0), - onDone: expectAsync(() {})); + channel.stream.listen(expectAsync((_) {}, count: 0), + onError: expectAsync((_, __) {}, count: 0), onDone: expectAsync(() {})); controller.local.sink.add(1); controller.local.sink.add(2); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 409b28fdd..b8156f20a 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -43,15 +43,20 @@ void main() { }); }); - test("closing the event sink causes the stream to close before it emits any " + test( + "closing the event sink causes the stream to close before it emits any " "more events", () { streamController.add(1); streamController.add(2); streamController.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.close(); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.close(); + }, count: 2)) + .asFuture(), + completes); }); test("after the stream closes, the sink ignores events", () async { @@ -65,8 +70,7 @@ void main() { channel.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - sinkController.stream.listen( - expectAsync((_) {}, count: 0), + sinkController.stream.listen(expectAsync((_) {}, count: 0), onDone: expectAsync(() {}, count: 0)); await pumpEventQueue(); }); @@ -97,8 +101,7 @@ void main() { channel.sink.close(); // The sink should be ignoring events because the stream closed. - sinkController.stream.listen( - expectAsync((_) {}, count: 0), + sinkController.stream.listen(expectAsync((_) {}, count: 0), onDone: expectAsync(() {}, count: 0)); await pumpEventQueue(); }); @@ -142,14 +145,15 @@ void main() { streamController = new StreamController(); sinkController = new StreamController(); channel = new StreamChannel.withGuarantees( - streamController.stream, sinkController.sink, allowSinkErrors: false); + streamController.stream, sinkController.sink, + allowSinkErrors: false); }); test("forwards errors to Sink.done but not the stream", () { channel.sink.addError("oh no"); expect(channel.sink.done, throwsA("oh no")); - sinkController.stream.listen(null, - onError: expectAsync((_) {}, count: 0)); + sinkController.stream + .listen(null, onError: expectAsync((_) {}, count: 0)); }); test("adding an error causes the stream to emit a done event", () { @@ -159,9 +163,13 @@ void main() { streamController.add(2); streamController.add(3); - expect(channel.stream.listen(expectAsync((event) { - if (event == 2) channel.sink.addError("oh no"); - }, count: 2)).asFuture(), completes); + expect( + channel.stream + .listen(expectAsync((event) { + if (event == 2) channel.sink.addError("oh no"); + }, count: 2)) + .asFuture(), + completes); }); test("adding an error closes the inner sink", () { @@ -170,7 +178,8 @@ void main() { expect(sinkController.stream.toList(), completion(isEmpty)); }); - test("adding an error via via addStream causes the stream to emit a done " + test( + "adding an error via via addStream causes the stream to emit a done " "event", () async { var canceled = false; var controller = new StreamController(onCancel: () { From 045a8c6f5e1b02ab696c5d80e03e2013d9a06257 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:40:50 -0700 Subject: [PATCH 0337/1215] Stop using deprecated pkg/test expect methods --- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/isolate_channel_test.dart | 4 +- .../test/multi_channel_test.dart | 58 +++++++++---------- .../test/stream_channel_controller_test.dart | 12 ++-- .../test/stream_channel_test.dart | 2 +- .../test/with_close_guarantee_test.dart | 7 ++- .../test/with_guarantees_test.dart | 14 ++--- 7 files changed, 50 insertions(+), 49 deletions(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 19a3bd07c..5813c4a0e 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -9,4 +9,4 @@ dependencies: async: '^1.11.0' stack_trace: '^1.0.0' dev_dependencies: - test: '^0.12.0' + test: '^0.12.18' diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 7316c6a42..b3b252e6e 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -73,7 +73,7 @@ void main() { sendPort.send(4); sendPort.send(5); - channel.stream.listen(expectAsync((message) { + channel.stream.listen(expectAsync1((message) { expect(message, equals(1)); channel.sink.close(); }, count: 1)); @@ -100,7 +100,7 @@ void main() { // The other end shouldn't receive the next event, since the sink was // closed. Pump the event queue to give it a chance to. - receivePort.listen(expectAsync((_) {}, count: 0)); + receivePort.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 69059b682..b1156738a 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -20,7 +20,7 @@ void main() { group("the default virtual channel", () { test("begins connected", () { var first = true; - channel2.stream.listen(expectAsync((message) { + channel2.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -50,7 +50,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - channel1.sink.done.then(expectAsync((_) {}, count: 0)); + channel1.sink.done.then(expectAsync1((_) {}, count: 0)); channel1.stream.listen((_) {}).cancel(); @@ -71,8 +71,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); // Establish another virtual connection which should keep the underlying // connection open. @@ -95,7 +95,7 @@ void main() { test("sends messages only to the other virtual channel", () { var first = true; - virtual2.stream.listen(expectAsync((message) { + virtual2.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -107,9 +107,9 @@ void main() { // No other virtual channels should receive the message. for (var i = 0; i < 10; i++) { var virtual = channel2.virtualChannel(channel1.virtualChannel().id); - virtual.stream.listen(expectAsync((_) {}, count: 0)); + virtual.stream.listen(expectAsync1((_) {}, count: 0)); } - channel2.stream.listen(expectAsync((_) {}, count: 0)); + channel2.stream.listen(expectAsync1((_) {}, count: 0)); virtual1.sink.add("hello"); virtual1.sink.add("world"); @@ -132,7 +132,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - virtual1.sink.done.then(expectAsync((_) {}, count: 0)); + virtual1.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); // Ensure that there's enough time for the channel to close if it's going @@ -157,8 +157,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.sink.close(); @@ -176,9 +176,9 @@ void main() { expect(virtual1.id, equals(virtual3.id)); virtual2.stream - .listen(expectAsync((message) => expect(message, equals("hello")))); - virtual4.stream - .listen(expectAsync((message) => expect(message, equals("goodbye")))); + .listen(expectAsync1((message) => expect(message, equals("hello")))); + virtual4.stream.listen( + expectAsync1((message) => expect(message, equals("goodbye")))); virtual1.sink.add("hello"); virtual3.sink.add("goodbye"); @@ -195,7 +195,7 @@ void main() { test("sends messages only to the other virtual channel", () { var first = true; - virtual1.stream.listen(expectAsync((message) { + virtual1.stream.listen(expectAsync1((message) { if (first) { expect(message, equals("hello")); first = false; @@ -207,9 +207,9 @@ void main() { // No other virtual channels should receive the message. for (var i = 0; i < 10; i++) { var virtual = channel2.virtualChannel(channel1.virtualChannel().id); - virtual.stream.listen(expectAsync((_) {}, count: 0)); + virtual.stream.listen(expectAsync1((_) {}, count: 0)); } - channel1.stream.listen(expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0)); virtual2.sink.add("hello"); virtual2.sink.add("world"); @@ -232,7 +232,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " "subscription is canceled", () { - virtual2.sink.done.then(expectAsync((_) {}, count: 0)); + virtual2.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); // Ensure that there's enough time for the channel to close if it's going @@ -257,8 +257,8 @@ void main() { test( "doesn't close the underlying channel when it closes with other " "virtual channels", () { - controller.local.sink.done.then(expectAsync((_) {}, count: 0)); - controller.foreign.sink.done.then(expectAsync((_) {}, count: 0)); + controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); + controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.sink.close(); @@ -311,10 +311,10 @@ void main() { }); test("emits an error, the error is sent only to the default channel", () { - channel1.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((error) => expect(error, equals("oh no")))); - virtual1.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync1((error) => expect(error, equals("oh no")))); + virtual1.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync1((_) {}, count: 0)); controller.foreign.sink.addError("oh no"); }); @@ -329,7 +329,7 @@ void main() { channel1.sink.add(2); channel1.sink.add(3); - channel2.stream.listen(expectAsync((message) { + channel2.stream.listen(expectAsync1((message) { expect(message, equals(1)); channel2.sink.close(); }, count: 1)); @@ -346,7 +346,7 @@ void main() { channel2.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - channel1.stream.listen(expectAsync((_) {}, count: 0)); + channel1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -376,7 +376,7 @@ void main() { channel1.sink.close(); // The sink should be ignoring events because the channel closed. - channel2.stream.listen(expectAsync((_) {}, count: 0)); + channel2.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); }); @@ -396,7 +396,7 @@ void main() { virtual1.sink.add(2); virtual1.sink.add(3); - virtual2.stream.listen(expectAsync((message) { + virtual2.stream.listen(expectAsync1((message) { expect(message, equals(1)); virtual2.sink.close(); }, count: 1)); @@ -413,7 +413,7 @@ void main() { virtual2.sink.close(); // None of our virtual.sink additions should make it to the other endpoint. - virtual1.stream.listen(expectAsync((_) {}, count: 0)); + virtual1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -443,7 +443,7 @@ void main() { virtual1.sink.close(); // The sink should be ignoring events because the stream closed. - virtual2.stream.listen(expectAsync((_) {}, count: 0)); + virtual2.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 8162a1746..c092570f5 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -55,13 +55,13 @@ void main() { var receivedEvent = false; var receivedError = false; var receivedDone = false; - controller.foreign.stream.listen(expectAsync((event) { + controller.foreign.stream.listen(expectAsync1((event) { expect(event, equals(1)); receivedEvent = true; - }), onError: expectAsync((error) { + }), onError: expectAsync1((error) { expect(error, equals("oh no")); receivedError = true; - }), onDone: expectAsync(() { + }), onDone: expectAsync0(() { receivedDone = true; })); @@ -81,13 +81,13 @@ void main() { var receivedEvent = false; var receivedError = false; var receivedDone = false; - controller.local.stream.listen(expectAsync((event) { + controller.local.stream.listen(expectAsync1((event) { expect(event, equals(1)); receivedEvent = true; - }), onError: expectAsync((error) { + }), onError: expectAsync1((error) { expect(error, equals("oh no")); receivedError = true; - }), onDone: expectAsync(() { + }), onDone: expectAsync0(() { receivedDone = true; })); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index f0a838385..b8ebcbd85 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -114,7 +114,7 @@ void main() { }); expect(newController.stream.toList(), completion(equals([10]))); - streamController.stream.listen(expectAsync((_) {}, count: 0)); + streamController.stream.listen(expectAsync1((_) {}, count: 0)); changed.sink.add(10); changed.sink.close(); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index dafbfeffb..bed6f0db6 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -44,7 +44,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) .asFuture(), @@ -57,8 +57,9 @@ void main() { "closing the event sink before events are emitted causes the stream to " "close immediately", () async { channel.sink.close(); - channel.stream.listen(expectAsync((_) {}, count: 0), - onError: expectAsync((_, __) {}, count: 0), onDone: expectAsync(() {})); + channel.stream.listen(expectAsync1((_) {}, count: 0), + onError: expectAsync2((_, __) {}, count: 0), + onDone: expectAsync0(() {})); controller.local.sink.add(1); controller.local.sink.add(2); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index b8156f20a..07dd8e52f 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -52,7 +52,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) .asFuture(), @@ -70,8 +70,8 @@ void main() { channel.sink.close(); // None of our channel.sink additions should make it to the other endpoint. - sinkController.stream.listen(expectAsync((_) {}, count: 0), - onDone: expectAsync(() {}, count: 0)); + sinkController.stream.listen(expectAsync1((_) {}, count: 0), + onDone: expectAsync0(() {}, count: 0)); await pumpEventQueue(); }); @@ -101,8 +101,8 @@ void main() { channel.sink.close(); // The sink should be ignoring events because the stream closed. - sinkController.stream.listen(expectAsync((_) {}, count: 0), - onDone: expectAsync(() {}, count: 0)); + sinkController.stream.listen(expectAsync1((_) {}, count: 0), + onDone: expectAsync0(() {}, count: 0)); await pumpEventQueue(); }); @@ -153,7 +153,7 @@ void main() { channel.sink.addError("oh no"); expect(channel.sink.done, throwsA("oh no")); sinkController.stream - .listen(null, onError: expectAsync((_) {}, count: 0)); + .listen(null, onError: expectAsync1((_) {}, count: 0)); }); test("adding an error causes the stream to emit a done event", () { @@ -165,7 +165,7 @@ void main() { expect( channel.stream - .listen(expectAsync((event) { + .listen(expectAsync1((event) { if (event == 2) channel.sink.addError("oh no"); }, count: 2)) .asFuture(), From d63ae51d3157c7cb1fe7480d04cdc54cde2a813e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:41:31 -0700 Subject: [PATCH 0338/1215] Remove unused var --- pkgs/stream_channel/test/disconnector_test.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index e194ee3cf..cd1300c66 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -84,9 +84,8 @@ void main() { var sinkController = new StreamController(); var disconnector = new Disconnector(); var sink = new _CloseCompleterSink(sinkController.sink); - var channel = - new StreamChannel.withGuarantees(streamController.stream, sink) - .transform(disconnector); + new StreamChannel.withGuarantees(streamController.stream, sink) + .transform(disconnector); var disconnectFutureFired = false; expect( From 97446793a44967a0257a1a5356ab33e8e7c2672e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jul 2017 14:43:24 -0700 Subject: [PATCH 0339/1215] enable travis-ci --- pkgs/stream_channel/.travis.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 pkgs/stream_channel/.travis.yml diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml new file mode 100644 index 000000000..d5c64e9dd --- /dev/null +++ b/pkgs/stream_channel/.travis.yml @@ -0,0 +1,20 @@ +language: dart +sudo: false +dart: + - dev + - stable +dart_task: + - test: --platform vm + - test: --platform firefox -j 1 + - test: --platform dartium + install_dartium: true + - dartfmt + - dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From 09210cd043bd077e162dc86d324846120831c6eb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 4 Aug 2017 14:20:14 -0700 Subject: [PATCH 0340/1215] Add takeUntil (dart-lang/stream_transform#38) Closes dart-lang/stream_transform#37 --- pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/README.md | 7 +- pkgs/stream_transform/lib/src/take_until.dart | 56 ++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- .../test/take_until_test.dart | 121 ++++++++++++++++++ 6 files changed, 188 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/take_until.dart create mode 100644 pkgs/stream_transform/test/take_until_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 7788ddf61..9c3e05776 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.8 + +- Add `takeUntil`. + ## 0.0.7 - Bug Fix: Streams produced with `scan` and `switchMap` now correctly report diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 26022430e..261972eaa 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,5 +1,4 @@ -Contains utility methods to create `StreamTransfomer` instances to manipulate -Streams. +Utility methods to create `StreamTransfomer` instances to manipulate Streams. # asyncWhere @@ -42,6 +41,10 @@ Prepend a value, an iterable, or a stream to the beginning of another stream. Flatten a Stream of Streams into a Stream which forwards values from the most recent Stream +# takeUntil + +Let values through until a Future fires. + # tap Taps into a single-subscriber stream to react to values as they pass, without diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart new file mode 100644 index 000000000..27674c20c --- /dev/null +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Emits values from the stream until [trigger] fires. +/// +/// Completing [trigger] differs from canceling a subscription in that values +/// which are emitted before the trigger, but have further asynchronous delays +/// in transformations following the takeUtil, will still go through. Cancelling +/// a subscription immediately stops values. +StreamTransformer takeUntil(Future trigger) => new _TakeUntil(trigger); + +class _TakeUntil implements StreamTransformer { + final Future _trigger; + + _TakeUntil(this._trigger); + + @override + Stream bind(Stream values) { + var controller = values.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + + StreamSubscription subscription; + var isDone = false; + _trigger.then((_) { + if (isDone) return; + isDone = true; + subscription?.cancel(); + controller.close(); + }); + + controller.onListen = () { + if (isDone) return; + subscription = values.listen(controller.add, onError: controller.addError, + onDone: () { + if (isDone) return; + isDone = true; + controller.close(); + }); + if (!values.isBroadcast) { + controller.onPause = subscription.pause; + controller.onResume = subscription.resume; + } + controller.onCancel = () { + if (isDone) return null; + var toCancel = subscription; + subscription = null; + return toCancel.cancel(); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 498363996..55cefa358 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -11,5 +11,6 @@ export 'src/merge.dart'; export 'src/scan.dart'; export 'src/start_with.dart'; export 'src/switch.dart'; +export 'src/take_until.dart'; export 'src/tap.dart'; export 'src/throttle.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 879c5ab84..1dd2f270f 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.7 +version: 0.0.8 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart new file mode 100644 index 000000000..1ed2f7999 --- /dev/null +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -0,0 +1,121 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + for (var streamType in streamTypes.keys) { + group('takeUntil on Stream type [$streamType]', () { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + Completer closeTrigger; + + setUp(() { + valuesCanceled = false; + values = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + closeTrigger = new Completer(); + transformed = values.stream.transform(takeUntil(closeTrigger.future)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('forwards cancellation', () async { + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('lets values through before trigger', () async { + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [1, 2]); + }); + + test('forwards errors', () async { + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('sends done if original strem ends', () async { + await values.close(); + expect(isDone, true); + }); + + test('sends done when trigger fires', () async { + closeTrigger.complete(); + await new Future(() {}); + expect(isDone, true); + }); + + test('cancels value subscription when trigger fires', () async { + closeTrigger.complete(); + await new Future(() {}); + expect(valuesCanceled, true); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + values.add(2); + await new Future(() {}); + expect(emittedValues, [1, 2]); + expect(otherValues, [1, 2]); + }); + + test('multiple listeners get done when trigger fires', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + closeTrigger.complete(); + await new Future(() {}); + expect(otherDone, true); + expect(isDone, true); + }); + + test('multiple listeners get done when values end', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + await values.close(); + expect(otherDone, true); + expect(isDone, true); + }); + + test('can cancel and relisten before trigger fires', () async { + values.add(1); + await new Future(() {}); + await subscription.cancel(); + values.add(2); + await new Future(() {}); + subscription = transformed.listen(emittedValues.add); + values.add(3); + await new Future(() {}); + expect(emittedValues, [1, 3]); + }); + } + }); + } +} From 8d577d006d672a84e5ce00c2ae673a99f5f950cf Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 7 Aug 2017 10:50:24 -0700 Subject: [PATCH 0341/1215] Add asyncMapBuffer (dart-lang/stream_transform#39) In one use case for `buffer` the `trigger` depended on the output from the resulting stream so the handling was awkward and used a manual StreamController. The intention was to avoid re-entry into a block of work, and asyncMapBuffer lets us express that intention directly. --- pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/README.md | 5 + .../lib/src/async_map_buffer.dart | 55 +++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- .../test/async_map_buffer_test.dart | 207 ++++++++++++++++++ 6 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/lib/src/async_map_buffer.dart create mode 100644 pkgs/stream_transform/test/async_map_buffer_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 9c3e05776..056eebda3 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.9 + +- Add `asyncMapBuffer`. + ## 0.0.8 - Add `takeUntil`. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 261972eaa..b504e6cee 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,5 +1,10 @@ Utility methods to create `StreamTransfomer` instances to manipulate Streams. +# asyncMapBuffer + +Like `asyncMap` but events are buffered until previous events have been +processed. + # asyncWhere Like `where` but allows an asynchronous predicate. diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart new file mode 100644 index 000000000..315e77a36 --- /dev/null +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -0,0 +1,55 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'bind.dart'; +import 'buffer.dart'; +import 'from_handlers.dart'; + +/// Like [Stream.asyncMap] but events are buffered until previous events have +/// been processed by [convert]. +/// +/// If the source stream is a broadcast stream the result will be as well. When +/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in +/// that the [convert] function is only called once per event, rather than once +/// per listener per event. +/// +/// The first event from the source stream is always passed to [convert] as a +/// List with a single element. After that events are buffered until the +/// previous Future returned from [convert] has fired. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// Errors during the conversion are also forwarded to the result stream and are +/// considered completing work so the next values are let through. +/// +/// The result stream will not close until the source stream closes and all +/// pending conversions have finished. +StreamTransformer asyncMapBuffer( + Future convert(List collected)) { + var workFinished = new StreamController(); + // Let the first event through. + workFinished.add(null); + return fromBind((values) => values + .transform(buffer(workFinished.stream)) + .transform(_asyncMapThen(convert, workFinished.add))); +} + +/// Like [Stream.asyncMap] but the [convert] is only called once per event, +/// rather than once per listener, and [then] is called after completing the +/// work. +StreamTransformer _asyncMapThen( + Future convert(S event), void then(_)) { + Future pendingEvent; + return fromHandlers(handleData: (event, sink) { + pendingEvent = + convert(event).then(sink.add).catchError(sink.addError).then(then); + }, handleDone: (sink) { + if (pendingEvent != null) { + pendingEvent.then((_) => sink.close()); + } else { + sink.close(); + } + }); +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 55cefa358..dced90813 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.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. +export 'src/async_map_buffer.dart'; export 'src/async_where.dart'; export 'src/audit.dart'; export 'src/buffer.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 1dd2f270f..c9bdfac89 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.8 +version: 0.0.9 environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart new file mode 100644 index 000000000..f8b73a7a2 --- /dev/null +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -0,0 +1,207 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + Completer finishWork; + List workArgument; + + /// Represents the async `convert` function and asserts that is is only called + /// after the previous iteration has completed. + Future work(List values) { + expect(finishWork, isNull, + reason: 'See $values befor previous work is complete'); + workArgument = values; + finishWork = new Completer(); + finishWork.future.then((_) { + workArgument = null; + finishWork = null; + }).catchError((_) { + workArgument = null; + finishWork = null; + }); + return finishWork.future; + } + + for (var streamType in streamTypes.keys) { + group('asyncMapBuffer for stream type: [$streamType]', () { + setUp(() { + valuesCanceled = false; + values = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + finishWork = null; + workArgument = null; + transformed = values.stream.transform(asyncMapBuffer(work)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('does not emit before work finishes', () async { + values.add(1); + await new Future(() {}); + expect(emittedValues, isEmpty); + expect(workArgument, [1]); + finishWork.complete(workArgument); + await new Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); + + test('buffers values while work is ongoing', () async { + values.add(1); + await new Future(() {}); + values.add(2); + values.add(3); + await new Future(() {}); + finishWork.complete(); + await new Future(() {}); + expect(workArgument, [2, 3]); + }); + + test('forwards errors without waiting for work', () async { + values.add(1); + await new Future(() {}); + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors which occur during the work', () async { + values.add(1); + await new Future(() {}); + finishWork.completeError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('can continue handling events after an error', () async { + values.add(1); + await new Future(() {}); + finishWork.completeError('error'); + values.add(2); + await new Future(() {}); + expect(workArgument, [2]); + finishWork.completeError('another'); + await new Future(() {}); + expect(errors, ['error', 'another']); + }); + + test('does not start next work early due to an error in values', + () async { + values.add(1); + await new Future(() {}); + values.addError('error'); + values.add(2); + await new Future(() {}); + expect(errors, ['error']); + // [work] will assert that the second iteration is not called because + // the first has not completed. + }); + + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('closes when values end if no work is pending', () async { + expect(isDone, false); + await values.close(); + await new Future(() {}); + expect(isDone, true); + }); + + test('waits for pending work when values close', () async { + values.add(1); + await new Future(() {}); + expect(isDone, false); + values.add(2); + await values.close(); + expect(isDone, false); + finishWork.complete(null); + await new Future(() {}); + // Still a pending value + expect(isDone, false); + finishWork.complete(null); + await new Future(() {}); + expect(isDone, true); + }); + + test('forwards errors from values', () async { + values.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + await new Future(() {}); + finishWork.complete('result'); + await new Future(() {}); + expect(emittedValues, ['result']); + expect(otherValues, ['result']); + }); + + test('multiple listeners get done when values end', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + values.add(1); + await new Future(() {}); + await values.close(); + expect(isDone, false); + expect(otherDone, false); + finishWork.complete(); + await new Future(() {}); + expect(isDone, true); + expect(otherDone, true); + }); + + test('can cancel and relisten', () async { + values.add(1); + await new Future(() {}); + finishWork.complete('first'); + await new Future(() {}); + await subscription.cancel(); + values.add(2); + await new Future(() {}); + subscription = transformed.listen(emittedValues.add); + values.add(3); + await new Future(() {}); + expect(workArgument, [3]); + finishWork.complete('second'); + await new Future(() {}); + expect(emittedValues, ['first', 'second']); + }); + } + }); + } +} From 8e5f36f814357715e2ae0be31ea16be438656d7f Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Thu, 17 Aug 2017 14:38:26 +0200 Subject: [PATCH 0342/1215] Insert missing 'return's. --- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index f71f610d2..12a8d81e1 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -128,11 +128,13 @@ class StackZoneSpecification { Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { if (_disabled) { parent.handleUncaughtError(zone, error, stackTrace); + return; } var stackChain = chainFor(stackTrace); if (_onError == null) { parent.handleUncaughtError(zone, error, stackChain); + return; } // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just From 06b18f8f755d80a3b8e79dee5cb601b92bee6c6e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 15 Sep 2017 13:35:20 -0700 Subject: [PATCH 0343/1215] Update sdk constraint --- pkgs/stack_trace/.travis.yml | 8 ++++++-- pkgs/stack_trace/CHANGELOG.md | 6 ++++++ pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index fff84941a..2ec03bbf7 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -3,8 +3,7 @@ sudo: false dart: - dev - stable - - 1.22.1 - - 1.21.1 + - 1.23.0 dart_task: - test: -p vm - test: -p firefox @@ -17,6 +16,11 @@ matrix: # Formatted with 1.23.0+ which has (good) changes since 1.22.1 - dart: dev dart_task: dartfmt + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + cache: directories: - $HOME/.pub-cache diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index cd78a9aec..6e6b5ffc8 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.8.1 + +* Use official generic function syntax. + +* Updated minimum SDK to 1.23.0. + ## 1.8.0 * Add a `Trace.original` field to provide access to the original `StackTrace`s diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 2d1349de2..07966fc2e 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -104,7 +104,7 @@ class Chain implements StackTrace { /// [callback] in a [Zone] in which chain capturing is disabled. /// /// If [callback] returns a value, it will be returned by [disable] as well. - static/*=T*/ disable/**/(/*=T*/ callback(), {bool when: true}) { + static T disable(T callback(), {bool when: true}) { var zoneValues = when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index a4552acb3..3aca7a7a7 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.0 +version: 1.8.1 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. @@ -17,4 +17,4 @@ dependencies: dev_dependencies: test: '^0.12.17' environment: - sdk: ">=1.21.0 <2.0.0" + sdk: ">=1.23.0 <2.0.0" From 207fb51ab59ada955e169837cc2bac1d9b681c75 Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 18 Sep 2017 20:55:25 +0200 Subject: [PATCH 0344/1215] Update version constraints. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3aca7a7a7..3dc38b05e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -17,4 +17,4 @@ dependencies: dev_dependencies: test: '^0.12.17' environment: - sdk: ">=1.23.0 <2.0.0" + sdk: ">=2.0-dev.0.1 <2.0-dev.infinity" From b7811c48b883dddf39a0229169670a051f217e1a Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 18 Sep 2017 21:08:36 +0200 Subject: [PATCH 0345/1215] No need to increase the version number. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3dc38b05e..3aca7a7a7 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -17,4 +17,4 @@ dependencies: dev_dependencies: test: '^0.12.17' environment: - sdk: ">=2.0-dev.0.1 <2.0-dev.infinity" + sdk: ">=1.23.0 <2.0.0" From a1be94651b2a9e2b76d092e0be7aacf803b10932 Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 18 Sep 2017 21:10:24 +0200 Subject: [PATCH 0346/1215] Update version number. --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3aca7a7a7..a6e5b929f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.1 +version: 1.8.2 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From c21f30873fc3551565e5a25f147abdfb9c40306d Mon Sep 17 00:00:00 2001 From: Florian Loitsch Date: Mon, 18 Sep 2017 21:53:59 +0200 Subject: [PATCH 0347/1215] Change version number and update Changelog. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 6e6b5ffc8..19fb82bb5 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.8.2 + +* Update to use strong-mode clean Zone API. + ## 1.8.1 * Use official generic function syntax. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index a6e5b929f..8db41c467 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.2 +version: 1.8.2-dev author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From 2a9b499e0759a514025163f7819db32e58b35773 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 18 Sep 2017 18:12:56 -0700 Subject: [PATCH 0348/1215] Remove -dev.infinity in SDK upper constraint --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5813c4a0e..2d863620b 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -4,7 +4,7 @@ description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.21.0 <2.0.0-dev.infinity' + sdk: '>=1.21.0 <2.0.0' dependencies: async: '^1.11.0' stack_trace: '^1.0.0' From 62635622c5585969b641d38f94a20a1c152496a6 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Tue, 19 Sep 2017 11:09:25 -0700 Subject: [PATCH 0349/1215] Update pubspec.yaml --- pkgs/stack_trace/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 8db41c467..a6e5b929f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.2-dev +version: 1.8.2 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From 8c535f2473dd159be6675e35ff8893e19f2df51a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Sep 2017 19:50:20 -0700 Subject: [PATCH 0350/1215] Update to use strong-mode clean Zone API. --- pkgs/stack_trace/CHANGELOG.md | 4 +++ pkgs/stack_trace/lib/src/chain.dart | 3 ++- .../lib/src/stack_zone_specification.dart | 26 ++++++++++--------- pkgs/stack_trace/pubspec.yaml | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 6e6b5ffc8..19fb82bb5 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.8.2 + +* Update to use strong-mode clean Zone API. + ## 1.8.1 * Use official generic function syntax. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 07966fc2e..01bf06fb7 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -93,7 +93,8 @@ class Chain implements StackTrace { return callback(); } catch (error, stackTrace) { // TODO(nweiz): Don't special-case this when issue 19566 is fixed. - return Zone.current.handleUncaughtError(error, stackTrace); + Zone.current.handleUncaughtError(error, stackTrace); + return null; } }, zoneSpecification: spec.toSpec(), diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index eb06beb32..6749d5695 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -92,8 +92,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneCallback _registerCallback( - Zone self, ZoneDelegate parent, Zone zone, Function f) { + ZoneCallback _registerCallback( + Zone self, ZoneDelegate parent, Zone zone, R f()) { if (f == null || _disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); @@ -101,8 +101,8 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneUnaryCallback _registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, Function f) { + ZoneUnaryCallback _registerUnaryCallback( + Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) { if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { @@ -112,7 +112,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. - ZoneBinaryCallback _registerBinaryCallback( + ZoneBinaryCallback _registerBinaryCallback( Zone self, ZoneDelegate parent, Zone zone, Function f) { if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); @@ -124,26 +124,28 @@ class StackZoneSpecification { /// Looks up the chain associated with [stackTrace] and passes it either to /// [_onError] or [parent]'s error handler. - _handleUncaughtError( + void _handleUncaughtError( Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { if (_disabled) { - return parent.handleUncaughtError(zone, error, stackTrace); + parent.handleUncaughtError(zone, error, stackTrace); + return; } var stackChain = chainFor(stackTrace); if (_onError == null) { - return parent.handleUncaughtError(zone, error, stackChain); + parent.handleUncaughtError(zone, error, stackChain); + return; } // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just // allow [runBinary] to throw instead once issue 18134 is fixed. try { - return self.parent.runBinary(_onError, error, stackChain); + self.parent.runBinary(_onError, error, stackChain); } catch (newError, newStackTrace) { if (identical(newError, error)) { - return parent.handleUncaughtError(zone, error, stackChain); + parent.handleUncaughtError(zone, error, stackChain); } else { - return parent.handleUncaughtError(zone, newError, newStackTrace); + parent.handleUncaughtError(zone, newError, newStackTrace); } } } @@ -180,7 +182,7 @@ class StackZoneSpecification { /// /// If [f] throws an error, this associates [node] with that error's stack /// trace. - _run(Function f, _Node node) { + T _run(T f(), _Node node) { var previousNode = _currentNode; _currentNode = node; try { diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3aca7a7a7..a6e5b929f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.1 +version: 1.8.2 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From 5ecc1d63c2938d4fdd8dd5f852b854f5996d142f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 21 Sep 2017 15:50:46 -0700 Subject: [PATCH 0351/1215] Support async 2.0.0. (dart-lang/watcher#37) --- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index c3acaf53e..f07ceaf0a 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+4 + +* Declare support for `async` 2.0.0. + # 0.9.7+3 * Fix a crashing bug on Linux. diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 90f96f5a7..15c51c6ae 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.8-dev +version: 0.9.7+4 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > @@ -8,7 +8,7 @@ description: > environment: sdk: '>=1.9.0 <2.0.0' dependencies: - async: '^1.10.0' + async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' dev_dependencies: benchmark_harness: '^1.0.4' From 6cac0360526f12590c1320f762448bdfa6c1bc99 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 22 Sep 2017 13:44:15 -0700 Subject: [PATCH 0352/1215] Declare support for async 2.0.0 (dart-lang/stream_channel#10) --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8d44b214a..a1cf9edec 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.2 + +* Declare support for `async` 2.0.0. + ## 1.6.1 * Fix the type of `StreamChannel.transform()`. This previously inverted the diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 2d863620b..fee64337e 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_channel -version: 1.6.2-dev +version: 1.6.2 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: sdk: '>=1.21.0 <2.0.0' dependencies: - async: '^1.11.0' + async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.18' From 47bec762667f343bbd260215cde5233204ada2b6 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 17 Oct 2017 14:24:33 -0700 Subject: [PATCH 0353/1215] Modify type on _onBatch to reflect call argument types --- pkgs/watcher/CHANGELOG.md | 5 +++++ pkgs/watcher/lib/src/directory_watcher/linux.dart | 3 ++- pkgs/watcher/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index f07ceaf0a..89da684fa 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7+5 + +* Change the type on a local function (_onBatch) to reflect the fact that its + caller does not statically guarantee its contract. + # 0.9.7+4 * Declare support for `async` 2.0.0. diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index df1365c76..c291aad2d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -127,7 +127,8 @@ class _LinuxDirectoryWatcher } /// The callback that's run when a batch of changes comes in. - void _onBatch(List batch) { + void _onBatch(Object data) { + var batch = data as List; var files = new Set(); var dirs = new Set(); var changed = new Set(); diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 15c51c6ae..41fbd8b0c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+4 +version: 0.9.7+5 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > From c25297863a55aa1a1493654f92e853b0910bc415 Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 17 Oct 2017 14:34:36 -0700 Subject: [PATCH 0354/1215] Update changelog per comments --- pkgs/watcher/CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 89da684fa..b4ca0bac9 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,7 +1,6 @@ # 0.9.7+5 -* Change the type on a local function (_onBatch) to reflect the fact that its - caller does not statically guarantee its contract. +* Fix an analysis warning. # 0.9.7+4 From e1dbf52bb0f0e047ed8fbf4b550c1c5a1c28820f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 23 Oct 2017 15:42:48 -0700 Subject: [PATCH 0355/1215] Return full stack chains for unregistered traces Previously we were just returning these traces as-is, even when we had a _currentNode chain context available. --- pkgs/stack_trace/CHANGELOG.md | 6 +++ .../lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/vm_test.dart | 47 +++++++++++-------- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 19fb82bb5..e8e717e74 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.8.3 + +* `Chain.forTrace()` now returns a full stack chain for *all* `StackTrace`s + within `Chain.capture()`, even those that haven't been processed by + `dart:async` yet. + ## 1.8.2 * Update to use strong-mode clean Zone API. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 6749d5695..7205a4e6c 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -86,7 +86,7 @@ class StackZoneSpecification { /// with [trace], this just returns a single-trace chain containing [trace]. Chain chainFor(StackTrace trace) { if (trace is Chain) return trace; - var previous = trace == null ? null : _chains[trace]; + var previous = (trace == null ? null : _chains[trace]) ?? _currentNode; return new _Node(trace, previous).toChain(); } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index a6e5b929f..79cf0b0ac 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.2 +version: 1.8.3-dev author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index daf7f8f11..3378bc24b 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -8,9 +8,11 @@ import 'dart:async'; -import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:stack_trace/src/utils.dart'; + import '../utils.dart'; import 'utils.dart'; @@ -444,11 +446,10 @@ void main() { }); }); - test( - 'called for an unregistered stack trace returns a chain wrapping that ' - 'trace', () { + test('called for an unregistered stack trace uses the current chain', + () async { var trace; - var chain = Chain.capture(() { + var chain = await Chain.capture(() async { try { throw 'error'; } catch (_, stackTrace) { @@ -457,27 +458,33 @@ void main() { } }); - expect(chain.traces, hasLength(1)); + expect(chain.traces, hasLength(2)); expect(chain.traces.first.toString(), equals(new Trace.from(trace).toString())); + expect( + chain.traces.last.frames, contains(frameMember(startsWith('main')))); }); }); test( - 'forTrace() outside of capture() returns a chain wrapping the given ' - 'trace', () { - var trace; - var chain = Chain.capture(() { - try { - throw 'error'; - } catch (_, stackTrace) { - trace = stackTrace; - return new Chain.forTrace(stackTrace); - } - }); + 'forTrace() outside of capture() returns a chain describing the VM stack ' + 'chain', () { + // Disable the test package's chain-tracking. + return Chain.disable(() async { + var trace; + await Chain.capture(() async { + try { + throw 'error'; + } catch (_, stackTrace) { + trace = stackTrace; + } + }); - expect(chain.traces, hasLength(1)); - expect(chain.traces.first.toString(), - equals(new Trace.from(trace).toString())); + var chain = new Chain.forTrace(trace); + expect(chain.traces, + hasLength(vmChainGap.allMatches(trace.toString()).length + 1)); + expect( + chain.traces.first.frames, contains(frameMember(startsWith('main')))); + }); }); } From 5ef183ff7c95c4a0bb89665f167feb6b3f77a58c Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 23 Oct 2017 15:57:14 -0700 Subject: [PATCH 0356/1215] Chain.forTrace() falls back on VM stack chains This wasn't happening previously when it was called synchronously within Chain.capture(). --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 1 + .../lib/src/stack_zone_specification.dart | 13 +++++++++++-- pkgs/stack_trace/test/chain/vm_test.dart | 19 ++++++++++++++----- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index e8e717e74..916448c3b 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -4,6 +4,10 @@ within `Chain.capture()`, even those that haven't been processed by `dart:async` yet. +* `Chain.forTrace()` now uses the Dart VM's stack chain information when called + synchronously within `Chain.capture()`. This matches the existing behavior + outside `Chain.capture()`. + ## 1.8.2 * Update to use strong-mode clean Zone API. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 01bf06fb7..56c533382 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -153,6 +153,7 @@ class Chain implements StackTrace { factory Chain.forTrace(StackTrace trace) { if (trace is Chain) return trace; if (_currentSpec != null) return _currentSpec.chainFor(trace); + if (trace is Trace) return new Chain([trace]); return new LazyChain(() => new Chain.parse(trace.toString())); } diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 7205a4e6c..2db98b7ee 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'chain.dart'; +import 'lazy_chain.dart'; import 'lazy_trace.dart'; import 'trace.dart'; import 'utils.dart'; @@ -86,8 +87,16 @@ class StackZoneSpecification { /// with [trace], this just returns a single-trace chain containing [trace]. Chain chainFor(StackTrace trace) { if (trace is Chain) return trace; - var previous = (trace == null ? null : _chains[trace]) ?? _currentNode; - return new _Node(trace, previous).toChain(); + trace ??= StackTrace.current; + + var previous = _chains[trace] ?? _currentNode; + if (previous != null) return new _Node(trace, previous).toChain(); + + // If there's no [_currentNode], we're running synchronously beneath + // [Chain.capture] and we should fall back to the VM's stack chaining. We + // can't use [Chain.from] here because it'll just call [chainFor] again. + if (trace is Trace) return new Chain([trace]); + return new LazyChain(() => new Chain.parse(trace.toString())); } /// Tracks the current stack chain so it can be set to [_currentChain] when diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 3378bc24b..6f793c4ca 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -18,12 +18,21 @@ import 'utils.dart'; void main() { group('capture() with onError catches exceptions', () { - test('thrown synchronously', () { - return captureFuture(() => throw 'error').then((chain) { - expect(chain.traces, hasLength(1)); - expect( - chain.traces.single.frames.first, frameMember(startsWith('main'))); + test('thrown synchronously', () async { + StackTrace vmTrace; + var chain = await captureFuture(() { + try { + throw 'error'; + } catch (_, stackTrace) { + vmTrace = stackTrace; + rethrow; + } }); + + // Because there's no chain context for a synchronous error, we fall back + // on the VM's stack chain tracking. + expect(chain.toString(), + equals(new Chain.parse(vmTrace.toString()).toString())); }); test('thrown in a microtask', () { From 4e93049088e178c2f74c19ebab094a5adc9b2f54 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 23 Oct 2017 19:00:48 -0700 Subject: [PATCH 0357/1215] Enable some lints --- pkgs/stream_transform/analysis_options.yaml | 41 ++++++++++--------- .../lib/src/async_map_buffer.dart | 4 +- pkgs/stream_transform/lib/src/audit.dart | 2 +- pkgs/stream_transform/lib/src/buffer.dart | 9 ++-- pkgs/stream_transform/lib/src/concat.dart | 2 +- pkgs/stream_transform/lib/src/debounce.dart | 2 +- .../lib/src/from_handlers.dart | 4 +- pkgs/stream_transform/lib/src/merge.dart | 2 +- pkgs/stream_transform/lib/src/scan.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- .../test/async_where_test.dart | 2 +- pkgs/stream_transform/test/switch_test.dart | 5 ++- pkgs/stream_transform/test/tap_test.dart | 3 +- 13 files changed, 43 insertions(+), 37 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 590a8e5da..5741706ca 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -1,37 +1,40 @@ analyzer: - strong-mode: true + strong-mode: + implicit-casts: false errors: - unused_import: error - unused_local_variable: error dead_code: error override_on_non_overriding_method: error - + unused_element: error + unused_import: error + unused_local_variable: error linter: rules: - # Errors - - avoid_empty_else - # Wait for FutureOr to work - #- await_only_futures - - comment_references - - control_flow_in_finally - - empty_statements - - hash_and_equals - - test_types_in_equals - - throw_in_finally - - unawaited_futures - - unrelated_type_equality_checks - - valid_regexps - - # Style - annotate_overrides + - avoid_empty_else - avoid_init_to_null - avoid_return_types_on_setters + - await_only_futures - camel_case_types + - comment_references + - control_flow_in_finally + - directives_ordering - empty_catches - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports - library_names - library_prefixes - non_constant_identifier_names + - omit_local_variable_types + - only_throw_errors + - prefer_final_fields - prefer_is_not_empty + - prefer_single_quotes - slash_for_doc_comments + - test_types_in_equals + - test_types_in_equals + - throw_in_finally - type_init_formals + - unrelated_type_equality_checks + - valid_regexps diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index 315e77a36..f2fd2a4e1 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -28,7 +28,7 @@ import 'from_handlers.dart'; /// pending conversions have finished. StreamTransformer asyncMapBuffer( Future convert(List collected)) { - var workFinished = new StreamController(); + var workFinished = new StreamController(); // Let the first event through. workFinished.add(null); return fromBind((values) => values @@ -40,7 +40,7 @@ StreamTransformer asyncMapBuffer( /// rather than once per listener, and [then] is called after completing the /// work. StreamTransformer _asyncMapThen( - Future convert(S event), void then(_)) { + Future convert(S event), void then(Object _)) { Future pendingEvent; return fromHandlers(handleData: (event, sink) { pendingEvent = diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart index 12bb9d537..2463ee631 100644 --- a/pkgs/stream_transform/lib/src/audit.dart +++ b/pkgs/stream_transform/lib/src/audit.dart @@ -18,7 +18,7 @@ import 'from_handlers.dart'; /// within [duration]. StreamTransformer audit(Duration duration) { Timer timer; - bool shouldClose = false; + var shouldClose = false; T recentData; return fromHandlers(handleData: (T data, EventSink sink) { diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index f5ef7bf1f..5c594c80b 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -12,7 +12,8 @@ import 'dart:async'; /// /// Errors from the source stream or the trigger are immediately forwarded to /// the output. -StreamTransformer> buffer(Stream trigger) => new _Buffer(trigger); +StreamTransformer> buffer(Stream trigger) => + new _Buffer(trigger); /// A StreamTransformer which aggregates values and emits when it sees a value /// on [_trigger]. @@ -35,9 +36,9 @@ class _Buffer implements StreamTransformer> { : new StreamController>(sync: true); List currentResults; - bool waitingForTrigger = true; - bool isTriggerDone = false; - bool isValueDone = false; + var waitingForTrigger = true; + var isTriggerDone = false; + var isValueDone = false; StreamSubscription valueSub; StreamSubscription triggerSub; diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart index 955918a85..39e747ba5 100644 --- a/pkgs/stream_transform/lib/src/concat.dart +++ b/pkgs/stream_transform/lib/src/concat.dart @@ -20,7 +20,7 @@ import 'dart:async'; StreamTransformer concat(Stream next) => new _Concat(next); class _Concat implements StreamTransformer { - final Stream _next; + final Stream _next; _Concat(this._next); diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart index fffb2213f..1ff91deb1 100644 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -36,7 +36,7 @@ StreamTransformer _debounceAggregate( Duration duration, R collect(T element, R soFar)) { Timer timer; R soFar; - bool shouldClose = false; + var shouldClose = false; return fromHandlers(handleData: (T value, EventSink sink) { timer?.cancel(); timer = new Timer(duration, () { diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 1303584ae..cf1c24dab 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -51,9 +51,9 @@ class _StreamTransformer implements StreamTransformer { StreamSubscription subscription; controller.onListen = () { if (subscription != null) return; - bool valuesDone = false; + var valuesDone = false; subscription = values.listen((value) => _handleData(value, controller), - onError: (error, stackTrace) { + onError: (error, StackTrace stackTrace) { _handleError(error, stackTrace, controller); }, onDone: () { valuesDone = true; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 563cff027..3653eb923 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -32,7 +32,7 @@ class _Merge implements StreamTransformer { ? new StreamController.broadcast(sync: true) : new StreamController(sync: true); - List> allStreams = [first]..addAll(_others); + var allStreams = [first]..addAll(_others); if (first.isBroadcast) { allStreams = allStreams .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index 7c26076c4..fb8c745f2 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -10,6 +10,6 @@ import 'bind.dart'; StreamTransformer scan( T initialValue, T combine(T previousValue, S element)) => fromBind((stream) { - T accumulated = initialValue; + var accumulated = initialValue; return stream.map((value) => accumulated = combine(accumulated, value)); }); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c9bdfac89..996e405dd 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.9 +version: 0.0.10-dev environment: sdk: ">=1.22.0 <2.0.0" diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 18c34bc76..4cf8af6f6 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -36,7 +36,7 @@ void main() { }); test('forwards values to multiple listeners', () async { - var values = new StreamController.broadcast(); + var values = new StreamController.broadcast(); var filtered = values.stream.transform(asyncWhere((e) async => e > 2)); var firstValues = []; var secondValues = []; diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index ccc987755..624c1a56d 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -1,6 +1,7 @@ -import 'package:test/test.dart'; import 'dart:async'; +import 'package:test/test.dart'; + import 'package:stream_transform/stream_transform.dart'; void main() { @@ -125,7 +126,7 @@ void main() { group('switchMap', () { test('uses map function', () async { - var outer = new StreamController(); + var outer = new StreamController(); var values = []; outer.stream diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index eb64eeed7..1f384ffb3 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -1,6 +1,7 @@ -import 'package:test/test.dart'; import 'dart:async'; +import 'package:test/test.dart'; + import 'package:stream_transform/stream_transform.dart'; void main() { From 5d9b0676528620641ee83905df04f5bb35a457f8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 23 Oct 2017 19:03:52 -0700 Subject: [PATCH 0358/1215] Add missing copyright headers --- pkgs/stream_transform/lib/src/from_handlers.dart | 4 ++++ pkgs/stream_transform/test/from_handlers_test.dart | 4 ++++ pkgs/stream_transform/test/merge_test.dart | 4 ++++ pkgs/stream_transform/test/scan_test.dart | 4 ++++ pkgs/stream_transform/test/switch_test.dart | 4 ++++ pkgs/stream_transform/test/tap_test.dart | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index cf1c24dab..52ad5b4d1 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; typedef void HandleData(S value, EventSink sink); diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index fe9e91658..8240b1c0c 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; import 'package:test/test.dart'; diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 8108b9586..75df0e81e 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; import 'package:test/test.dart'; diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 717b80854..b2b976050 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; import 'package:test/test.dart'; diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 624c1a56d..dda658ca2 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; import 'package:test/test.dart'; diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 1f384ffb3..f3ef8e32c 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -1,3 +1,7 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; import 'package:test/test.dart'; From f5af29b60b5b5f210f9db89c9025cdfdb86e5055 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 23 Oct 2017 19:04:26 -0700 Subject: [PATCH 0359/1215] test on Chrome and Firefox --- pkgs/stream_transform/.travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 1d18a7ea0..57bec9449 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -9,6 +9,8 @@ cache: - $HOME/.pub-cache dart_task: - test + - test -p chrome + - test -p firefox - dartfmt - dartanalyzer - dartanalyzer: --no-strong . From 9bf15bc9d3fbbc6e9f900a6ea24412141f227f2e Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 23 Oct 2017 16:42:17 -0700 Subject: [PATCH 0360/1215] Chain.forTrace() trims the innermost trace's VM chain This was already being trimmed for all other stack traces, but the innermost one requires different logic, so we missed it. --- pkgs/stack_trace/CHANGELOG.md | 5 ++ .../lib/src/stack_zone_specification.dart | 64 +++++++++++-------- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/vm_test.dart | 5 +- 4 files changed, 47 insertions(+), 29 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 916448c3b..b0c972a86 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -8,6 +8,11 @@ synchronously within `Chain.capture()`. This matches the existing behavior outside `Chain.capture()`. +* `Chain.forTrace()` now trims the VM's stack chains for the innermost stack + trace within `Chain.capture()` (unless it's called synchronously, as above). + This avoids duplicated frames and makes the format of the innermost traces + consistent with the other traces in the chain. + ## 1.8.2 * Update to use strong-mode clean Zone API. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 2db98b7ee..cd5d06870 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -90,13 +90,20 @@ class StackZoneSpecification { trace ??= StackTrace.current; var previous = _chains[trace] ?? _currentNode; - if (previous != null) return new _Node(trace, previous).toChain(); + if (previous == null) { + // If there's no [_currentNode], we're running synchronously beneath + // [Chain.capture] and we should fall back to the VM's stack chaining. We + // can't use [Chain.from] here because it'll just call [chainFor] again. + if (trace is Trace) return new Chain([trace]); + return new LazyChain(() => new Chain.parse(trace.toString())); + } else { + if (trace is! Trace) { + var original = trace; + trace = new LazyTrace(() => new Trace.parse(_trimVMChain(original))); + } - // If there's no [_currentNode], we're running synchronously beneath - // [Chain.capture] and we should fall back to the VM's stack chaining. We - // can't use [Chain.from] here because it'll just call [chainFor] again. - if (trace is Trace) return new Chain([trace]); - return new LazyChain(() => new Chain.parse(trace.toString())); + return new _Node(trace, previous).toChain(); + } } /// Tracks the current stack chain so it can be set to [_currentChain] when @@ -203,6 +210,29 @@ class StackZoneSpecification { _currentNode = previousNode; } } + + /// Like [new Trace.current], but if the current stack trace has VM chaining + /// enabled, this only returns the innermost sub-trace. + Trace _currentTrace([int level]) { + level ??= 0; + var stackTrace = StackTrace.current; + return new LazyTrace(() { + var text = _trimVMChain(stackTrace); + var trace = new Trace.parse(text); + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + original: text); + }); + } + + /// Removes the VM's stack chains from the native [trace], since we're + /// generating our own and we don't want duplicate frames. + String _trimVMChain(StackTrace trace) { + var text = trace.toString(); + var index = text.indexOf(vmChainGap); + return index == -1 ? text : text.substring(0, index); + } } /// A linked list node representing a single entry in a stack chain. @@ -213,8 +243,7 @@ class _Node { /// The previous node in the chain. final _Node previous; - _Node(StackTrace trace, [this.previous]) - : trace = trace == null ? _currentTrace() : new Trace.from(trace); + _Node(StackTrace trace, [this.previous]) : trace = new Trace.from(trace); /// Converts this to a [Chain]. Chain toChain() { @@ -227,22 +256,3 @@ class _Node { return new Chain(nodes); } } - -/// Like [new Trace.current], but if the current stack trace has VM chaining -/// enabled, this only returns the innermost sub-trace. -Trace _currentTrace([int level]) { - level ??= 0; - var stackTrace = StackTrace.current; - return new LazyTrace(() { - // Ignore the VM's stack chains when we generate our own. Otherwise we'll - // end up with duplicate frames all over the place. - var text = stackTrace.toString(); - var index = text.indexOf(vmChainGap); - if (index != -1) text = text.substring(0, index); - - var trace = new Trace.parse(text); - // JS includes a frame for the call to StackTrace.current, but the VM - // doesn't, so we skip an extra frame in a JS context. - return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: text); - }); -} diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 79cf0b0ac..65d3ef6ac 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.3-dev +version: 1.8.3 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 6f793c4ca..a47cbf7e5 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -468,8 +468,11 @@ void main() { }); expect(chain.traces, hasLength(2)); + + // Assert that we've trimmed the VM's stack chains here to avoid + // duplication. expect(chain.traces.first.toString(), - equals(new Trace.from(trace).toString())); + equals(new Chain.parse(trace.toString()).traces.first.toString())); expect( chain.traces.last.frames, contains(frameMember(startsWith('main')))); }); From 5339349ad4e60f2c9ae8939edde0338480cc1b7f Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 1 Nov 2017 14:48:48 -0700 Subject: [PATCH 0361/1215] Add an option to Chain.capture() not to create an error zone (dart-lang/stack_trace#36) Some users (like test) manually convert traces to chains, so they don't need the error zone behavior. In fact, it can cause problems, such as those described in dart-lang/testdart-lang/stack_trace#713. --- pkgs/stack_trace/CHANGELOG.md | 5 ++ pkgs/stack_trace/lib/src/chain.dart | 18 +++-- .../lib/src/stack_zone_specification.dart | 8 ++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 68 ++++++++++++++----- 5 files changed, 75 insertions(+), 26 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index b0c972a86..18ffda8e3 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.9.0 + +* Add an `errorZone` parameter to `Chain.capture()` that makes it avoid creating + an error zone. + ## 1.8.3 * `Chain.forTrace()` now returns a full stack chain for *all* `StackTrace`s diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 56c533382..8685a9ee9 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -65,13 +65,21 @@ class Chain implements StackTrace { /// parent Zone's `unhandledErrorHandler` will be called with the error and /// its chain. /// - /// Note that even if [onError] isn't passed, this zone will still be an error - /// zone. This means that any errors that would cross the zone boundary are - /// considered unhandled. + /// If [errorZone] is `true`, the zone this creates will be an error zone, + /// even if [onError] isn't passed. This means that any errors that would + /// cross the zone boundary are considered unhandled. If [errorZone] is + /// `false`, [onError] must be `null`. /// /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T callback(), - {void onError(error, Chain chain), bool when: true}) { + {void onError(error, Chain chain), + bool when: true, + bool errorZone: true}) { + if (!errorZone && onError != null) { + throw new ArgumentError.value( + onError, "onError", "must be null if errorZone is false"); + } + if (!when) { var newOnError; if (onError != null) { @@ -87,7 +95,7 @@ class Chain implements StackTrace { return runZoned(callback, onError: newOnError); } - var spec = new StackZoneSpecification(onError); + var spec = new StackZoneSpecification(onError, errorZone: errorZone); return runZoned(() { try { return callback(); diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index cd5d06870..5be8dd3a2 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -61,12 +61,16 @@ class StackZoneSpecification { /// The most recent node of the current stack chain. _Node _currentNode; - StackZoneSpecification([this._onError]); + /// Whether this is an error zone. + final bool _errorZone; + + StackZoneSpecification(this._onError, {bool errorZone: true}) + : _errorZone = errorZone; /// Converts [this] to a real [ZoneSpecification]. ZoneSpecification toSpec() { return new ZoneSpecification( - handleUncaughtError: _handleUncaughtError, + handleUncaughtError: _errorZone ? _handleUncaughtError : null, registerCallback: _registerCallback, registerUnaryCallback: _registerUnaryCallback, registerBinaryCallback: _registerBinaryCallback, diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 65d3ef6ac..3218be15a 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.8.3 +version: 1.9.0 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 407cc2b9c..26b04a158 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -38,33 +38,65 @@ void main() { }); }); - group("Chain.capture() with when: false", () { - test("with no onError doesn't block errors", () { - expect(Chain.capture(() => new Future.error("oh no"), when: false), - throwsA("oh no")); - }); - + group("Chain.capture()", () { test("with onError blocks errors", () { Chain.capture(() { return new Future.error("oh no"); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); expect(chain, new isInstanceOf()); - }), when: false); + })); }); - test("doesn't enable chain-tracking", () { - return Chain.disable(() { - return Chain.capture(() { - var completer = new Completer(); - inMicrotask(() { - completer.complete(new Chain.current()); - }); + test("with no onError blocks errors", () { + runZoned(() { + var future = + Chain.capture(() => new Future.error("oh no"), when: false); + future.then(expectAsync1((_) {}, count: 0)); + }, onError: expectAsync2((error, chain) { + expect(error, equals("oh no")); + expect(chain, new isInstanceOf()); + })); + }); - return completer.future.then((chain) { - expect(chain.traces, hasLength(1)); - }); - }, when: false); + test("with errorZone: false doesn't block errors", () { + expect(Chain.capture(() => new Future.error("oh no"), errorZone: false), + throwsA("oh no")); + }); + + test("doesn't allow onError and errorZone: false", () { + expect(() => Chain.capture(() {}, onError: (_, __) {}, errorZone: false), + throwsArgumentError); + }); + + group("with when: false", () { + test("with no onError doesn't block errors", () { + expect(Chain.capture(() => new Future.error("oh no"), when: false), + throwsA("oh no")); + }); + + test("with onError blocks errors", () { + Chain.capture(() { + return new Future.error("oh no"); + }, onError: expectAsync2((error, chain) { + expect(error, equals("oh no")); + expect(chain, new isInstanceOf()); + }), when: false); + }); + + test("doesn't enable chain-tracking", () { + return Chain.disable(() { + return Chain.capture(() { + var completer = new Completer(); + inMicrotask(() { + completer.complete(new Chain.current()); + }); + + return completer.future.then((chain) { + expect(chain.traces, hasLength(1)); + }); + }, when: false); + }); }); }); }); From aef53847af8bd2ce6709163d23c810b5df67bbd2 Mon Sep 17 00:00:00 2001 From: vsmenon Date: Wed, 8 Nov 2017 15:32:15 -0800 Subject: [PATCH 0362/1215] Avoid overwriting chain for trace if one exists (dart-lang/stack_trace#37) --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/stack_zone_specification.dart | 5 ++++- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 18ffda8e3..2627e7114 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.1 +* Preserve the original chain for a trace to handle cases where an + error is rethrown. + ## 1.9.0 * Add an `errorZone` parameter to `Chain.capture()` that makes it avoid creating diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 5be8dd3a2..6c31d1280 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -208,7 +208,10 @@ class StackZoneSpecification { try { return f(); } catch (e, stackTrace) { - _chains[stackTrace] = node; + // We can see the same stack trace multiple times if it's rethrown through + // guarded callbacks. The innermost chain will have the most + // information so it should take precedence. + _chains[stackTrace] ??= node; rethrow; } finally { _currentNode = previousNode; diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3218be15a..f7c562d4a 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.9.0 +version: 1.9.1 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From dc0bf362a58ad38e78d04d1b3e4032abb3d3c941 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 20 Nov 2017 13:49:39 -0800 Subject: [PATCH 0363/1215] Use pumpEventQueue() from test (dart-lang/stream_channel#12) --- pkgs/stream_channel/pubspec.yaml | 4 ++-- .../test/disconnector_test.dart | 2 -- .../test/isolate_channel_test.dart | 2 -- .../test/multi_channel_test.dart | 2 -- .../test/stream_channel_completer_test.dart | 2 -- pkgs/stream_channel/test/utils.dart | 19 ------------------- .../test/with_close_guarantee_test.dart | 2 -- .../test/with_guarantees_test.dart | 2 -- 8 files changed, 2 insertions(+), 33 deletions(-) delete mode 100644 pkgs/stream_channel/test/utils.dart diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index fee64337e..6faac8570 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.2 +version: 1.6.3-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel @@ -9,4 +9,4 @@ dependencies: async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' dev_dependencies: - test: '^0.12.18' + test: '^0.12.28' diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index cd1300c66..5b725740c 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -8,8 +8,6 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index b3b252e6e..66834cace 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -8,8 +8,6 @@ import 'dart:isolate'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var receivePort; var sendPort; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index b1156738a..2a87cafa3 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -5,8 +5,6 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var controller; var channel1; diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index e08dd8a7a..8d830058a 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var completer; var streamController; diff --git a/pkgs/stream_channel/test/utils.dart b/pkgs/stream_channel/test/utils.dart deleted file mode 100644 index e53389540..000000000 --- a/pkgs/stream_channel/test/utils.dart +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// Returns a [Future] that completes after pumping the event queue [times] -/// times. -/// -/// By default, this should pump the event queue enough times to allow any code -/// to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times = 20]) { - if (times == 0) return new Future.value(); - // Use [new Future] future to allow microtask events to finish. The [new - // Future.value] constructor uses scheduleMicrotask itself and would therefore - // not wait for microtask callbacks that are scheduled after invoking this - // method. - return new Future(() => pumpEventQueue(times - 1)); -} diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index bed6f0db6..a6527a716 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -8,8 +8,6 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - final _delayTransformer = new StreamTransformer.fromHandlers( handleData: (data, sink) => new Future.microtask(() => sink.add(data)), handleDone: (sink) => new Future.microtask(() => sink.close())); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 07dd8e52f..e1302f64c 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -import 'utils.dart'; - void main() { var streamController; var sinkController; From 6ed30e41fb183f50fd709d4b82b63eba2b7c58f5 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 6 Dec 2017 23:02:04 -0800 Subject: [PATCH 0364/1215] handle exceptions to zone handlers in @failingTests --- pkgs/test_reflective_loader/.gitignore | 1 + pkgs/test_reflective_loader/CHANGELOG.md | 12 +++++++++--- .../test_reflective_loader/analysis_options.yaml | 5 +++++ .../lib/test_reflective_loader.dart | 16 ++++++++++------ pkgs/test_reflective_loader/pubspec.yaml | 2 +- 5 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 pkgs/test_reflective_loader/analysis_options.yaml diff --git a/pkgs/test_reflective_loader/.gitignore b/pkgs/test_reflective_loader/.gitignore index 65b96beca..67a390f24 100644 --- a/pkgs/test_reflective_loader/.gitignore +++ b/pkgs/test_reflective_loader/.gitignore @@ -6,4 +6,5 @@ .settings/ build/ packages +.packages pubspec.lock diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 49931bb3b..0ecc4c4ad 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,11 +1,17 @@ # Changelog +## 0.1.1 + +- For `@failingTest` tests, properly handle when the test fails by throwing an + exception in a timer task +- Analyze this package in strong mode + ## 0.1.0 - Switched from 'package:unittest' to 'package:test'. -- Since 'package:test' does not define 'solo_test', in order to keep - this functionality, `defineReflectiveSuite` must be used to wrap - all `defineReflectiveTests` invocations. +- Since 'package:test' does not define 'solo_test', in order to keep this + functionality, `defineReflectiveSuite` must be used to wrap all + `defineReflectiveTests` invocations. ## 0.0.4 diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml new file mode 100644 index 000000000..cee71221b --- /dev/null +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -0,0 +1,5 @@ +analyzer: + strong-mode: true +linter: + rules: + - directives_ordering diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 375f5843c..c833e6103 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -223,14 +223,18 @@ Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { * This properly handles the following cases: * - The test fails by throwing an exception * - The test returns a future which completes with an error. - * - * However, it does not handle the case where the test creates an asynchronous - * callback using expectAsync(), and that callback generates a failure. + * - An exception is thrown to the zone handler from a timer task. */ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { - return new Future(() => _runTest(classMirror, symbol)).then((_) { - test_package.fail('Test passed - expected to fail.'); - }, onError: (_) {}); + return runZoned(() { + return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { + test_package.fail('Test passed - expected to fail.'); + }).catchError((e) { + // an exception is not a failure for _runFailingTest + }); + }, onError: (e) { + // an exception is not a failure for _runFailingTest + }); } _runTest(ClassMirror classMirror, Symbol symbol) { diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 9373aec3b..b0ab5d3aa 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.0 +version: 0.1.1 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From f68b6268b5e2a5d470178c44273ca8801baa48c5 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 7 Dec 2017 18:48:05 -0800 Subject: [PATCH 0365/1215] Update pubspec.yaml --- pkgs/test_reflective_loader/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index b0ab5d3aa..73e6d63d7 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.1 +version: 0.1.2 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader @@ -7,5 +7,5 @@ homepage: https://github.com/dart-lang/test_reflective_loader environment: sdk: '>=1.0.0 <2.0.0' -dev_dependencies: +dependencies: test: ^0.12.0 From b34ceea36d819dd634a7d10c03d7cfd85e68a04a Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 7 Dec 2017 18:50:27 -0800 Subject: [PATCH 0366/1215] update the changelog --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 0ecc4c4ad..59b2b0093 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.1.2 + +- Update the pubspec `dependencies` section to include `package:test` + ## 0.1.1 - For `@failingTest` tests, properly handle when the test fails by throwing an From 7d0d18b879e991c5e2b1f68aedf334b708c6fee5 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 8 Dec 2017 10:35:48 -0800 Subject: [PATCH 0367/1215] Fail @failingTest when the test passes. --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ .../lib/test_reflective_loader.dart | 14 ++++++++++++-- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 59b2b0093..6e5b8519c 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 0.1.3 + +- Fix `@failingTest` to fail when the test passes. + ## 0.1.2 - Update the pubspec `dependencies` section to include `package:test` diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index c833e6103..9ebaf84e4 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -226,14 +226,24 @@ Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { * - An exception is thrown to the zone handler from a timer task. */ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { + bool passed = false; return runZoned(() { return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { + passed = true; test_package.fail('Test passed - expected to fail.'); }).catchError((e) { - // an exception is not a failure for _runFailingTest + // if passed, and we call fail(), rethrow this exception + if (passed) { + throw e; + } + // otherwise, an exception is not a failure for _runFailingTest }); }, onError: (e) { - // an exception is not a failure for _runFailingTest + // if passed, and we call fail(), rethrow this exception + if (passed) { + throw e; + } + // otherwise, an exception is not a failure for _runFailingTest }); } diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 73e6d63d7..1360d687b 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.2 +version: 0.1.3 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From b2e03b735317f1ac5b8af6c0e22caa0ef4b81548 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 8 Dec 2017 10:49:32 -0800 Subject: [PATCH 0368/1215] Require at least SDK 1.8.0 because 'pub publish' demands this. --- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 1360d687b..7e5440438 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -5,7 +5,7 @@ author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.8.0 <2.0.0' dependencies: test: ^0.12.0 From 4638060da73eb38927ed277228dcdca4162d5f86 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 8 Dec 2017 13:10:56 -0800 Subject: [PATCH 0369/1215] add tests, travis support, some lints --- pkgs/test_reflective_loader/.travis.yml | 2 + .../analysis_options.yaml | 2 + .../lib/test_reflective_loader.dart | 12 +++--- .../test/test_reflective_loader_test.dart | 40 +++++++++++++++++++ pkgs/test_reflective_loader/tool/travis.sh | 16 ++++++++ 5 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 pkgs/test_reflective_loader/.travis.yml create mode 100644 pkgs/test_reflective_loader/test/test_reflective_loader_test.dart create mode 100755 pkgs/test_reflective_loader/tool/travis.sh diff --git a/pkgs/test_reflective_loader/.travis.yml b/pkgs/test_reflective_loader/.travis.yml new file mode 100644 index 000000000..9c3a39f97 --- /dev/null +++ b/pkgs/test_reflective_loader/.travis.yml @@ -0,0 +1,2 @@ +language: dart +script: ./tool/travis.sh diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml index cee71221b..5f425e0e1 100644 --- a/pkgs/test_reflective_loader/analysis_options.yaml +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -2,4 +2,6 @@ analyzer: strong-mode: true linter: rules: + - always_declare_return_types - directives_ordering + - public_member_api_docs diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 9ebaf84e4..fa0d91df7 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -27,7 +27,7 @@ const _FailingTest failingTest = const _FailingTest(); * A marker annotation used to instruct dart2js to keep reflection information * for the annotated classes. */ -const ReflectiveTest reflectiveTest = const ReflectiveTest(); +const _ReflectiveTest reflectiveTest = const _ReflectiveTest(); /** * A marker annotation used to annotate "solo" groups and tests. @@ -92,7 +92,7 @@ void defineReflectiveSuite(void define(), {String name}) { void defineReflectiveTests(Type type) { ClassMirror classMirror = reflectClass(type); if (!classMirror.metadata.any((InstanceMirror annotation) => - annotation.type.reflectedType == ReflectiveTest)) { + annotation.type.reflectedType == _ReflectiveTest)) { String name = MirrorSystem.getName(classMirror.qualifiedName); throw new Exception('Class $name must have annotation "@reflectiveTest" ' 'in order to be run by runReflectiveTests.'); @@ -247,21 +247,21 @@ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { }); } -_runTest(ClassMirror classMirror, Symbol symbol) { +Future _runTest(ClassMirror classMirror, Symbol symbol) { InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); return _invokeSymbolIfExists(instanceMirror, #setUp) .then((_) => instanceMirror.invoke(symbol, []).reflectee) .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); } -typedef _TestFunction(); +typedef dynamic _TestFunction(); /** * A marker annotation used to instruct dart2js to keep reflection information * for the annotated classes. */ -class ReflectiveTest { - const ReflectiveTest(); +class _ReflectiveTest { + const _ReflectiveTest(); } /** diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart new file mode 100644 index 000000000..be070a0dd --- /dev/null +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -0,0 +1,40 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; + +// ignore_for_file: always_declare_return_types + +void main() { + defineReflectiveSuite(() { + defineReflectiveTests(TestReflectiveLoaderTest); + }); +} + +@reflectiveTest +class TestReflectiveLoaderTest { + String pathname; + + test_passes() { + expect(true, true); + } + + @failingTest + test_fails() { + expect(false, true); + } + + @failingTest + test_fails_throws_sync() { + throw 'foo'; + } + + @failingTest + test_fails_throws_async() { + return new Future.error('foo'); + } +} diff --git a/pkgs/test_reflective_loader/tool/travis.sh b/pkgs/test_reflective_loader/tool/travis.sh new file mode 100755 index 000000000..ea0f1c495 --- /dev/null +++ b/pkgs/test_reflective_loader/tool/travis.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +# 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. + +# Fast fail the script on failures. +set -e + +# Verify that the libraries are error free. +dartanalyzer --fatal-warnings \ + lib/test_reflective_loader.dart \ + test/test_reflective_loader_test.dart + +# Run the tests. +dart test/test_reflective_loader_test.dart From 0dd69713f42f352247f07443f5e4bc9ff7ddb502 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 8 Dec 2017 13:18:43 -0800 Subject: [PATCH 0370/1215] add return types --- .../test/test_reflective_loader_test.dart | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index be070a0dd..952fe0a1d 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -7,8 +7,6 @@ import 'dart:async'; import 'package:test/test.dart'; import 'package:test_reflective_loader/test_reflective_loader.dart'; -// ignore_for_file: always_declare_return_types - void main() { defineReflectiveSuite(() { defineReflectiveTests(TestReflectiveLoaderTest); @@ -19,22 +17,22 @@ void main() { class TestReflectiveLoaderTest { String pathname; - test_passes() { + void test_passes() { expect(true, true); } @failingTest - test_fails() { + void test_fails() { expect(false, true); } @failingTest - test_fails_throws_sync() { + void test_fails_throws_sync() { throw 'foo'; } @failingTest - test_fails_throws_async() { + Future test_fails_throws_async() { return new Future.error('foo'); } } From 3b8a376858f82b52a9393d9721e82def3da16d17 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 8 Dec 2017 14:11:39 -0800 Subject: [PATCH 0371/1215] Update README.md --- pkgs/test_reflective_loader/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index e65e6fc90..66dca98c2 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -1,5 +1,7 @@ # test_reflective_loader +[![Build Status](https://travis-ci.org/dart-lang/test_reflective_loader.svg?branch=master)](https://travis-ci.org/dart-lang/test_reflective_loader) + Support for discovering tests and test suites using reflection. This package follows the xUnit style where each class is a test suite, and each From 677ee9a08c296eb78feed772c195e3d266aa2efc Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Tue, 19 Dec 2017 13:07:03 -0800 Subject: [PATCH 0372/1215] prep for release --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a1cf9edec..ece9e1d5a 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.3 + +* Use `pumpEventQueue()` from test. + ## 1.6.2 * Declare support for `async` 2.0.0. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 6faac8570..9a123b128 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.3-dev +version: 1.6.3 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From b4fbbfd5968240deed75249a7f517490f8657606 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Dec 2017 15:32:58 -0800 Subject: [PATCH 0373/1215] Use suggested analysis_options file name --- pkgs/watcher/{.analysis_options => analysis_options.yaml} | 0 pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename pkgs/watcher/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/watcher/.analysis_options b/pkgs/watcher/analysis_options.yaml similarity index 100% rename from pkgs/watcher/.analysis_options rename to pkgs/watcher/analysis_options.yaml diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 41fbd8b0c..987e7b72a 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+5 +version: 0.9.7+6.dev author: Dart Team homepage: https://github.com/dart-lang/watcher description: > From e3b509a6d761f973b09f10a972e84223a7d25def Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Dec 2017 15:34:43 -0800 Subject: [PATCH 0374/1215] migrate to the new function syntax --- pkgs/watcher/lib/src/utils.dart | 4 ++-- pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/utils.dart | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 6f3ff0215..022c8c1c1 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -31,10 +31,10 @@ Set unionAll(Iterable sets) => /// If [broadcast] is true, a broadcast stream is returned. This assumes that /// the stream returned by [future] will be a broadcast stream as well. /// [broadcast] defaults to false. -Stream/**/ futureStream/**/(Future*/> future, +Stream futureStream(Future> future, {bool broadcast: false}) { var subscription; - StreamController/**/ controller; + StreamController controller; future = DelegatingFuture.typed(future.catchError((e, stackTrace) { // Since [controller] is synchronous, it's likely that emitting an error diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 987e7b72a..6bdb39a46 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -6,7 +6,7 @@ description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: - sdk: '>=1.9.0 <2.0.0' + sdk: '>=1.21.0 <2.0.0' dependencies: async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index e3c2a1b4d..e91ed1578 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -344,10 +344,10 @@ void deleteDir(String path) { /// Returns a set of all values returns by [callback]. /// /// [limit] defaults to 3. -Set/**/ withPermutations/**/(/*=S*/ callback(int i, int j, int k), +Set withPermutations(S callback(int i, int j, int k), {int limit}) { if (limit == null) limit = 3; - var results = new Set/**/(); + var results = new Set(); for (var i = 0; i < limit; i++) { for (var j = 0; j < limit; j++) { for (var k = 0; k < limit; k++) { From dd1ecce0b0b8149992aa633eb6c46c147a56365e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Dec 2017 15:36:13 -0800 Subject: [PATCH 0375/1215] Add travis support --- pkgs/watcher/.travis.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 pkgs/watcher/.travis.yml diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml new file mode 100644 index 000000000..deb901b6e --- /dev/null +++ b/pkgs/watcher/.travis.yml @@ -0,0 +1,25 @@ +language: dart +dart: + - dev + - stable + +dart_task: + - test + +matrix: + include: + - dart: dev + dart_task: dartfmt + # Only care about being analyzer clean for dev and stable + - dart: dev + dart_task: dartanalyzer + - dart: stable + dart_task: dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master, 0-9-7] + +cache: + directories: + - $HOME/.pub-cache From ba07d4a61634229c4069143644042f6814b8d7f7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Dec 2017 15:36:57 -0800 Subject: [PATCH 0376/1215] dartfmt --- pkgs/watcher/lib/src/async_queue.dart | 3 +- .../src/constructable_file_system_event.dart | 8 +- .../lib/src/directory_watcher/linux.dart | 12 +-- .../lib/src/directory_watcher/mac_os.dart | 42 +++++----- .../lib/src/directory_watcher/polling.dart | 10 +-- .../lib/src/directory_watcher/windows.dart | 39 ++++----- pkgs/watcher/lib/src/file_watcher/native.dart | 3 +- .../watcher/lib/src/file_watcher/polling.dart | 6 +- pkgs/watcher/lib/src/resubscribable.dart | 32 +++---- pkgs/watcher/lib/src/utils.dart | 9 +- .../test/directory_watcher/linux_test.dart | 20 ++--- .../test/directory_watcher/mac_os_test.dart | 23 ++--- .../test/directory_watcher/shared.dart | 84 +++++++------------ .../test/directory_watcher/windows_test.dart | 4 +- pkgs/watcher/test/file_watcher/shared.dart | 3 +- pkgs/watcher/test/path_set_test.dart | 56 +++++++------ pkgs/watcher/test/utils.dart | 41 ++++----- 17 files changed, 190 insertions(+), 205 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index adf667101..1895c804e 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -34,8 +34,7 @@ class AsyncQueue { /// Used to avoid top-leveling asynchronous errors. final Function _errorHandler; - AsyncQueue(this._processor, {Function onError}) - : _errorHandler = onError; + AsyncQueue(this._processor, {Function onError}) : _errorHandler = onError; /// Enqueues [item] to be processed and starts asynchronously processing it /// if a process isn't already running. diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index 63b51c192..a0f153e53 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -37,8 +37,8 @@ class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent final bool contentChanged; final type = FileSystemEvent.MODIFY; - ConstructableFileSystemModifyEvent(String path, bool isDirectory, - this.contentChanged) + ConstructableFileSystemModifyEvent( + String path, bool isDirectory, this.contentChanged) : super(path, isDirectory); String toString() => @@ -50,8 +50,8 @@ class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent final String destination; final type = FileSystemEvent.MOVE; - ConstructableFileSystemMoveEvent(String path, bool isDirectory, - this.destination) + ConstructableFileSystemMoveEvent( + String path, bool isDirectory, this.destination) : super(path, isDirectory); String toString() => "FileSystemMoveEvent('$path', '$destination')"; diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index c291aad2d..717e4209c 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -62,10 +62,10 @@ class _LinuxDirectoryWatcher /// watcher is closed. final _subscriptions = new Set(); - _LinuxDirectoryWatcher(String path) - : _files = new PathSet(path) { - _nativeEvents.add(new Directory(path).watch().transform( - new StreamTransformer.fromHandlers(handleDone: (sink) { + _LinuxDirectoryWatcher(String path) : _files = new PathSet(path) { + _nativeEvents.add(new Directory(path) + .watch() + .transform(new StreamTransformer.fromHandlers(handleDone: (sink) { // Handle the done event here rather than in the call to [_listen] because // [innerStream] won't close until we close the [StreamGroup]. However, if // we close the [StreamGroup] here, we run the risk of new-directory @@ -251,8 +251,8 @@ class _LinuxDirectoryWatcher /// Like [Stream.listen], but automatically adds the subscription to /// [_subscriptions] so that it can be canceled when [close] is called. - void _listen(Stream stream, void onData(event), {Function onError, - void onDone(), bool cancelOnError}) { + void _listen(Stream stream, void onData(event), + {Function onError, void onDone(), bool cancelOnError}) { var subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 8a17e2e79..759765f72 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -81,10 +81,8 @@ class _MacOSDirectoryWatcher // // If we do receive a batch of events, [_onBatch] will ensure that these // futures don't fire and that the directory is re-listed. - Future.wait([ - _listDir(), - _waitForBogusEvents() - ]).then((_) => _readyCompleter.complete()); + Future.wait([_listDir(), _waitForBogusEvents()]).then( + (_) => _readyCompleter.complete()); } void close() { @@ -116,8 +114,9 @@ class _MacOSDirectoryWatcher _sortEvents(batch).forEach((path, eventSet) { var canonicalEvent = _canonicalEvent(eventSet); - var events = canonicalEvent == null ? - _eventsBasedOnFileSystem(path) : [canonicalEvent]; + var events = canonicalEvent == null + ? _eventsBasedOnFileSystem(path) + : [canonicalEvent]; for (var event in events) { if (event is FileSystemCreateEvent) { @@ -126,9 +125,8 @@ class _MacOSDirectoryWatcher // This can happen if a file is copied on top of an existing one. // We'll see an ADD event for the latter file when from the user's // perspective, the file's contents just changed. - var type = _files.contains(path) - ? ChangeType.MODIFY - : ChangeType.ADD; + var type = + _files.contains(path) ? ChangeType.MODIFY : ChangeType.ADD; _emitEvent(type, path); _files.add(path); @@ -138,8 +136,8 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; StreamSubscription subscription; - subscription = new Directory(path).list(recursive: true) - .listen((entity) { + subscription = + new Directory(path).list(recursive: true).listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -259,7 +257,8 @@ class _MacOSDirectoryWatcher // from FSEvents reporting an add that happened prior to the watch // beginning. If we also received a MODIFY event, we want to report that, // but not the CREATE. - if (type == FileSystemEvent.CREATE && hadModifyEvent && + if (type == FileSystemEvent.CREATE && + hadModifyEvent && _files.contains(batch.first.path)) { type = FileSystemEvent.MODIFY; } @@ -277,7 +276,8 @@ class _MacOSDirectoryWatcher case FileSystemEvent.MODIFY: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); - default: throw 'unreachable'; + default: + throw 'unreachable'; } } @@ -347,11 +347,11 @@ class _MacOSDirectoryWatcher /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = new Directory(path).watch(recursive: true) + var innerStream = new Directory(path) + .watch(recursive: true) .transform(new BatchedStreamTransformer()); _watchSubscription = innerStream.listen(_onBatch, - onError: _eventsController.addError, - onDone: _onDone); + onError: _eventsController.addError, onDone: _onDone); } /// Starts or restarts listing the watched directory to get an initial picture @@ -365,10 +365,7 @@ class _MacOSDirectoryWatcher var stream = new Directory(path).list(recursive: true); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); - }, - onError: _emitError, - onDone: completer.complete, - cancelOnError: true); + }, onError: _emitError, onDone: completer.complete, cancelOnError: true); return completer.future; } @@ -379,9 +376,8 @@ class _MacOSDirectoryWatcher /// bogus events will be signaled in that time frame. Future _waitForBogusEvents() { var completer = new Completer(); - _bogusEventTimer = new Timer( - new Duration(milliseconds: 200), - completer.complete); + _bogusEventTimer = + new Timer(new Duration(milliseconds: 200), completer.complete); return completer.future; } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index ebc170963..fa72a2f54 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -25,9 +25,9 @@ class PollingDirectoryWatcher extends ResubscribableWatcher /// and higher CPU usage. Defaults to one second. PollingDirectoryWatcher(String directory, {Duration pollingDelay}) : super(directory, () { - return new _PollingDirectoryWatcher(directory, - pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); - }); + return new _PollingDirectoryWatcher(directory, + pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + }); } class _PollingDirectoryWatcher @@ -73,8 +73,8 @@ class _PollingDirectoryWatcher final _polledFiles = new Set(); _PollingDirectoryWatcher(this.path, this._pollingDelay) { - _filesToProcess = new AsyncQueue(_processFile, - onError: (e, stackTrace) { + _filesToProcess = + new AsyncQueue(_processFile, onError: (e, stackTrace) { if (!_events.isClosed) _events.addError(e, stackTrace); }); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index ec119f75e..3352b68fe 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -80,8 +80,8 @@ class _WindowsDirectoryWatcher /// The subscriptions to the [Directory.list] calls for listing the contents /// of subdirectories that were moved into the watched directory. - final Set> _listSubscriptions - = new HashSet>(); + final Set> _listSubscriptions = + new HashSet>(); _WindowsDirectoryWatcher(String path) : path = path, @@ -132,8 +132,7 @@ class _WindowsDirectoryWatcher // the directory is now gone. if (event is FileSystemMoveEvent || event is FileSystemDeleteEvent || - (FileSystemEntity.typeSync(path) == - FileSystemEntityType.NOT_FOUND)) { + (FileSystemEntity.typeSync(path) == FileSystemEntityType.NOT_FOUND)) { for (var path in _files.paths) { _emitEvent(ChangeType.REMOVE, path); } @@ -151,8 +150,8 @@ class _WindowsDirectoryWatcher void _onEvent(FileSystemEvent event) { assert(isReady); - final batcher = _eventBatchers.putIfAbsent( - event.path, () => new _EventBatcher()); + final batcher = + _eventBatchers.putIfAbsent(event.path, () => new _EventBatcher()); batcher.addEvent(event, () { _eventBatchers.remove(event.path); _onBatch(batcher.events); @@ -162,10 +161,10 @@ class _WindowsDirectoryWatcher /// The callback that's run when [Directory.watch] emits a batch of events. void _onBatch(List batch) { _sortEvents(batch).forEach((path, eventSet) { - var canonicalEvent = _canonicalEvent(eventSet); - var events = canonicalEvent == null ? - _eventsBasedOnFileSystem(path) : [canonicalEvent]; + var events = canonicalEvent == null + ? _eventsBasedOnFileSystem(path) + : [canonicalEvent]; for (var event in events) { if (event is FileSystemCreateEvent) { @@ -278,8 +277,8 @@ class _WindowsDirectoryWatcher // (respectively) that will be contradictory. if (event is FileSystemModifyEvent) continue; assert(event is FileSystemCreateEvent || - event is FileSystemDeleteEvent || - event is FileSystemMoveEvent); + event is FileSystemDeleteEvent || + event is FileSystemMoveEvent); // If we previously thought this was a MODIFY, we now consider it to be a // CREATE or REMOVE event. This is safe for the same reason as above. @@ -290,8 +289,8 @@ class _WindowsDirectoryWatcher // A CREATE event contradicts a REMOVE event and vice versa. assert(type == FileSystemEvent.CREATE || - type == FileSystemEvent.DELETE || - type == FileSystemEvent.MOVE); + type == FileSystemEvent.DELETE || + type == FileSystemEvent.MOVE); if (type != event.type) return null; } @@ -305,7 +304,8 @@ class _WindowsDirectoryWatcher batch.first.path, isDir, false); case FileSystemEvent.MOVE: return null; - default: throw 'unreachable'; + default: + throw 'unreachable'; } } @@ -369,8 +369,7 @@ class _WindowsDirectoryWatcher // Batch the events together so that we can dedup events. var innerStream = new Directory(path).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, - onError: _eventsController.addError, - onDone: _onDone); + onError: _eventsController.addError, onDone: _onDone); } /// Starts or restarts listing the watched directory to get an initial picture @@ -385,11 +384,9 @@ class _WindowsDirectoryWatcher void handleEntity(entity) { if (entity is! Directory) _files.add(entity.path); } - _initialListSubscription = stream.listen( - handleEntity, - onError: _emitError, - onDone: completer.complete, - cancelOnError: true); + + _initialListSubscription = stream.listen(handleEntity, + onError: _emitError, onDone: completer.complete, cancelOnError: true); return completer.future; } diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index f413a72c4..8e7dd0981 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -42,7 +42,8 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { void _listen() { // Batch the events together so that we can dedup them. - _subscription = new File(path).watch() + _subscription = new File(path) + .watch() .transform(new BatchedStreamTransformer()) .listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); } diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 3f2e9f143..97a4f9533 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -14,9 +14,9 @@ import '../watch_event.dart'; class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { PollingFileWatcher(String path, {Duration pollingDelay}) : super(path, () { - return new _PollingFileWatcher(path, - pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); - }); + return new _PollingFileWatcher(path, + pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + }); } class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index aeefe9366..28c425ff4 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -44,22 +44,24 @@ abstract class ResubscribableWatcher implements Watcher { _eventsController = new StreamController.broadcast( onListen: () { - watcher = _factory(); - subscription = watcher.events.listen(_eventsController.add, - onError: _eventsController.addError, - onDone: _eventsController.close); + watcher = _factory(); + subscription = watcher.events.listen(_eventsController.add, + onError: _eventsController.addError, + onDone: _eventsController.close); - // It's important that we complete the value of [_readyCompleter] at the - // time [onListen] is called, as opposed to the value when [watcher.ready] - // fires. A new completer may be created by that time. - watcher.ready.then(_readyCompleter.complete); - }, onCancel: () { - // Cancel the subscription before closing the watcher so that the - // watcher's `onDone` event doesn't close [events]. - subscription.cancel(); - watcher.close(); - _readyCompleter = new Completer(); - }, sync: true); + // It's important that we complete the value of [_readyCompleter] at the + // time [onListen] is called, as opposed to the value when [watcher.ready] + // fires. A new completer may be created by that time. + watcher.ready.then(_readyCompleter.complete); + }, + onCancel: () { + // Cancel the subscription before closing the watcher so that the + // watcher's `onDone` event doesn't close [events]. + subscription.cancel(); + watcher.close(); + _readyCompleter = new Completer(); + }, + sync: true); } } diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 022c8c1c1..ef39eef48 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -31,8 +31,7 @@ Set unionAll(Iterable sets) => /// If [broadcast] is true, a broadcast stream is returned. This assumes that /// the stream returned by [future] will be a broadcast stream as well. /// [broadcast] defaults to false. -Stream futureStream(Future> future, - {bool broadcast: false}) { +Stream futureStream(Future> future, {bool broadcast: false}) { var subscription; StreamController controller; @@ -47,10 +46,8 @@ Stream futureStream(Future> future, onListen() { future.then((stream) { if (controller == null) return; - subscription = stream.listen( - controller.add, - onError: controller.addError, - onDone: controller.close); + subscription = stream.listen(controller.add, + onError: controller.addError, onDone: controller.close); }); } diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 897b1301b..34e689683 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -19,28 +19,28 @@ void main() { sharedTests(); test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { - expect(new DirectoryWatcher('.'), - new isInstanceOf()); + expect( + new DirectoryWatcher('.'), new isInstanceOf()); }); test('emits events for many nested files moved out then immediately back in', () { - withPermutations((i, j, k) => - writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + withPermutations( + (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); startWatcher(path: "dir"); renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); allowEither(() { - inAnyOrder(withPermutations((i, j, k) => - isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); - inAnyOrder(withPermutations((i, j, k) => - isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }, () { - inAnyOrder(withPermutations((i, j, k) => - isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 2c82f34c5..46b7ca2e1 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -19,11 +19,12 @@ void main() { sharedTests(); test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { - expect(new DirectoryWatcher('.'), - new isInstanceOf()); + expect( + new DirectoryWatcher('.'), new isInstanceOf()); }); - test('does not notify about the watched directory being deleted and ' + test( + 'does not notify about the watched directory being deleted and ' 'recreated immediately before watching', () { createDir("dir"); writeFile("dir/old.txt"); @@ -37,8 +38,8 @@ void main() { test('emits events for many nested files moved out then immediately back in', () { - withPermutations((i, j, k) => - writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + withPermutations( + (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); startWatcher(path: "dir"); @@ -46,14 +47,14 @@ void main() { renameDir("sub", "dir/sub"); allowEither(() { - inAnyOrder(withPermutations((i, j, k) => - isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); - inAnyOrder(withPermutations((i, j, k) => - isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }, () { - inAnyOrder(withPermutations((i, j, k) => - isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 148eee263..2bdc07714 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -59,10 +59,7 @@ void sharedTests() { writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "after"); - inAnyOrder([ - isModifyEvent("a.txt"), - isModifyEvent("b.txt") - ]); + inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]); }); test('when the watched directory is deleted, removes all files', () { @@ -72,10 +69,7 @@ void sharedTests() { startWatcher(path: "dir"); deleteDir("dir"); - inAnyOrder([ - isRemoveEvent("dir/a.txt"), - isRemoveEvent("dir/b.txt") - ]); + inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); test('when the watched directory is moved, removes all files', () { @@ -86,14 +80,12 @@ void sharedTests() { renameDir("dir", "moved_dir"); createDir("dir"); - inAnyOrder([ - isRemoveEvent("dir/a.txt"), - isRemoveEvent("dir/b.txt") - ]); + inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); // Regression test for b/30768513. - test("doesn't crash when the directory is moved immediately after a subdir " + test( + "doesn't crash when the directory is moved immediately after a subdir " "is added", () { writeFile("dir/a.txt"); writeFile("dir/b.txt"); @@ -103,10 +95,7 @@ void sharedTests() { createDir("dir/subdir"); renameDir("dir", "moved_dir"); createDir("dir"); - inAnyOrder([ - isRemoveEvent("dir/a.txt"), - isRemoveEvent("dir/b.txt") - ]); + inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); group("moves", () { @@ -115,10 +104,7 @@ void sharedTests() { startWatcher(); renameFile("old.txt", "new.txt"); - inAnyOrder([ - isAddEvent("new.txt"), - isRemoveEvent("old.txt") - ]); + inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]); }); test('notifies when a file is moved from outside the watched directory', @@ -145,10 +131,7 @@ void sharedTests() { startWatcher(); renameFile("from.txt", "to.txt"); - inAnyOrder([ - isRemoveEvent("from.txt"), - isModifyEvent("to.txt") - ]); + inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]); }); }); @@ -174,7 +157,8 @@ void sharedTests() { }); }); - test("reports a modification when a file is deleted and then immediately " + test( + "reports a modification when a file is deleted and then immediately " "recreated", () { writeFile("file.txt"); startWatcher(); @@ -191,7 +175,8 @@ void sharedTests() { }); }); - test("reports a modification when a file is moved and then immediately " + test( + "reports a modification when a file is moved and then immediately " "recreated", () { writeFile("old.txt"); startWatcher(); @@ -200,10 +185,7 @@ void sharedTests() { writeFile("old.txt", contents: "re-created"); allowEither(() { - inAnyOrder([ - isModifyEvent("old.txt"), - isAddEvent("new.txt") - ]); + inAnyOrder([isModifyEvent("old.txt"), isAddEvent("new.txt")]); }, () { // Backup case. expectRemoveEvent("old.txt"); @@ -212,7 +194,8 @@ void sharedTests() { }); }); - test("reports a removal when a file is modified and then immediately " + test( + "reports a removal when a file is modified and then immediately " "removed", () { writeFile("file.txt"); startWatcher(); @@ -248,16 +231,14 @@ void sharedTests() { expectAddEvent("a/b/c/d/file.txt"); }); - test('notifies when a subdirectory is moved within the watched directory ' + test( + 'notifies when a subdirectory is moved within the watched directory ' 'and then its contents are modified', () { writeFile("old/file.txt"); startWatcher(); renameDir("old", "new"); - inAnyOrder([ - isRemoveEvent("old/file.txt"), - isAddEvent("new/file.txt") - ]); + inAnyOrder([isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]); writeFile("new/file.txt", contents: "modified"); expectModifyEvent("new/file.txt"); @@ -295,20 +276,19 @@ void sharedTests() { }); test('emits events for many nested files added at once', () { - withPermutations((i, j, k) => - writeFile("sub/sub-$i/sub-$j/file-$k.txt")); + withPermutations((i, j, k) => writeFile("sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); startWatcher(path: "dir"); renameDir("sub", "dir/sub"); - inAnyOrder(withPermutations((i, j, k) => - isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); test('emits events for many nested files removed at once', () { - withPermutations((i, j, k) => - writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + withPermutations( + (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); startWatcher(path: "dir"); @@ -319,13 +299,13 @@ void sharedTests() { // directory. renameDir("dir/sub", "sub"); - inAnyOrder(withPermutations((i, j, k) => - isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + inAnyOrder(withPermutations( + (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); test('emits events for many nested files moved at once', () { - withPermutations((i, j, k) => - writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); + withPermutations( + (i, j, k) => writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); startWatcher(path: "dir"); @@ -339,18 +319,18 @@ void sharedTests() { }))); }); - test("emits events for many files added at once in a subdirectory with the " + test( + "emits events for many files added at once in a subdirectory with the " "same name as a removed file", () { writeFile("dir/sub"); - withPermutations((i, j, k) => - writeFile("old/sub-$i/sub-$j/file-$k.txt")); + withPermutations((i, j, k) => writeFile("old/sub-$i/sub-$j/file-$k.txt")); startWatcher(path: "dir"); deleteFile("dir/sub"); renameDir("old", "dir/sub"); - var events = withPermutations((i, j, k) => - isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); + var events = withPermutations( + (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); events.add(isRemoveEvent("dir/sub")); inAnyOrder(events); }); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 55e40a937..176fe2d71 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -19,7 +19,7 @@ void main() { sharedTests(); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { - expect(new DirectoryWatcher('.'), - new isInstanceOf()); + expect( + new DirectoryWatcher('.'), new isInstanceOf()); }); } diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 9a4965ccc..50f7aebba 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -50,7 +50,8 @@ void sharedTests() { expectRemoveEvent("file.txt"); }); - test("emits a modify event when another file is moved on top of the watched " + test( + "emits a modify event when another file is moved on top of the watched " "file", () { writeFile("old.txt"); startWatcher(path: "file.txt"); diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index d3420d377..be15c77c4 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -6,12 +6,11 @@ import 'package:path/path.dart' as p; import 'package:test/test.dart'; import 'package:watcher/src/path_set.dart'; -Matcher containsPath(String path) => predicate((set) => - set is PathSet && set.contains(path), - 'set contains "$path"'); +Matcher containsPath(String path) => predicate( + (set) => set is PathSet && set.contains(path), 'set contains "$path"'); -Matcher containsDir(String path) => predicate((set) => - set is PathSet && set.containsDir(path), +Matcher containsDir(String path) => predicate( + (set) => set is PathSet && set.containsDir(path), 'set contains directory "$path"'); void main() { @@ -61,11 +60,13 @@ void main() { set.add("root/path/to/two"); set.add("root/path/to/sub/three"); - expect(set.remove("root/path"), unorderedEquals([ - "root/path/to/one", - "root/path/to/two", - "root/path/to/sub/three" - ].map(p.normalize))); + expect( + set.remove("root/path"), + unorderedEquals([ + "root/path/to/one", + "root/path/to/two", + "root/path/to/sub/three" + ].map(p.normalize))); expect(set, containsPath("root/outside")); expect(set, isNot(containsPath("root/path/to/one"))); @@ -73,19 +74,22 @@ void main() { expect(set, isNot(containsPath("root/path/to/sub/three"))); }); - test("that's a directory in the set removes and returns it and all files " + test( + "that's a directory in the set removes and returns it and all files " "beneath it", () { set.add("root/path"); set.add("root/path/to/one"); set.add("root/path/to/two"); set.add("root/path/to/sub/three"); - expect(set.remove("root/path"), unorderedEquals([ - "root/path", - "root/path/to/one", - "root/path/to/two", - "root/path/to/sub/three" - ].map(p.normalize))); + expect( + set.remove("root/path"), + unorderedEquals([ + "root/path", + "root/path/to/one", + "root/path/to/two", + "root/path/to/sub/three" + ].map(p.normalize))); expect(set, isNot(containsPath("root/path"))); expect(set, isNot(containsPath("root/path/to/one"))); @@ -157,14 +161,16 @@ void main() { expect(set, isNot(containsDir("root/path/to/file"))); }); - test("returns false for a directory that was added implicitly and then " + test( + "returns false for a directory that was added implicitly and then " "removed implicitly", () { set.add("root/path/to/file"); set.remove("root/path/to/file"); expect(set, isNot(containsDir("root/path"))); }); - test("returns false for a directory that was added explicitly whose " + test( + "returns false for a directory that was added explicitly whose " "children were then removed", () { set.add("root/path"); set.add("root/path/to/file"); @@ -190,11 +196,13 @@ void main() { set.add("root/path/to/one"); set.add("root/path/to/two"); - expect(set.paths, unorderedEquals([ - "root/path", - "root/path/to/one", - "root/path/to/two", - ].map(p.normalize))); + expect( + set.paths, + unorderedEquals([ + "root/path", + "root/path/to/one", + "root/path/to/two", + ].map(p.normalize))); }); test("doesn't return paths removed from the set", () { diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index e91ed1578..6700500ad 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -35,6 +35,7 @@ typedef Watcher WatcherFactory(String directory); set watcherFactory(WatcherFactory factory) { _watcherFactory = factory; } + WatcherFactory _watcherFactory; /// Creates the sandbox directory the other functions in this library use and @@ -113,20 +114,22 @@ void startWatcher({String path}) { // Schedule [_watcher.events.listen] so that the watcher doesn't start // watching [path] before it exists. Expose [_watcherEvents] immediately so // that it can be accessed synchronously after this. - _watcherEvents = new ScheduledStream(futureStream(schedule(() { - currentSchedule.onComplete.schedule(() { - _watcher = null; - if (!_closePending) _watcherEvents.close(); - - // If there are already errors, don't add this to the output and make - // people think it might be the root cause. - if (currentSchedule.errors.isEmpty) { - _watcherEvents.expect(isDone); - } - }, "reset watcher"); - - return _watcher.events; - }, "create watcher"), broadcast: true)); + _watcherEvents = new ScheduledStream(futureStream( + schedule(() { + currentSchedule.onComplete.schedule(() { + _watcher = null; + if (!_closePending) _watcherEvents.close(); + + // If there are already errors, don't add this to the output and make + // people think it might be the root cause. + if (currentSchedule.errors.isEmpty) { + _watcherEvents.expect(isDone); + } + }, "reset watcher"); + + return _watcher.events; + }, "create watcher"), + broadcast: true)); schedule(() => _watcher.ready, "wait for watcher to be ready"); } @@ -193,8 +196,8 @@ void inAnyOrder(Iterable matchers) { /// /// If both blocks match, the one that consumed more events will be used. void allowEither(block1(), block2()) { - _expectOrCollect(either( - _collectStreamMatcher(block1), _collectStreamMatcher(block2))); + _expectOrCollect( + either(_collectStreamMatcher(block1), _collectStreamMatcher(block2))); } /// Allows the expectations established in [block] to match the emitted events. @@ -210,7 +213,8 @@ void allowEvents(block()) { /// [path]. Matcher isWatchEvent(ChangeType type, String path) { return predicate((e) { - return e is WatchEvent && e.type == type && + return e is WatchEvent && + e.type == type && e.path == p.join(_sandboxDir, p.normalize(path)); }, "is $type $path"); } @@ -344,8 +348,7 @@ void deleteDir(String path) { /// Returns a set of all values returns by [callback]. /// /// [limit] defaults to 3. -Set withPermutations(S callback(int i, int j, int k), - {int limit}) { +Set withPermutations(S callback(int i, int j, int k), {int limit}) { if (limit == null) limit = 3; var results = new Set(); for (var i = 0; i < limit; i++) { From 63df4ac5425597a55be6684c2dc57e4b72858e9a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Dec 2017 15:40:54 -0800 Subject: [PATCH 0377/1215] Stop using deprecated pkg/test apis --- pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/no_subscription/shared.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 6bdb39a46..d1260d56c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -13,4 +13,4 @@ dependencies: dev_dependencies: benchmark_harness: '^1.0.4' scheduled_test: '^0.12.0' - test: '^0.12.0' + test: '^0.12.18+1' diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 52649f1a7..58586567a 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -18,7 +18,7 @@ void sharedTests() { // Subscribe to the events. var completer = new Completer(); - var subscription = watcher.events.listen(expectAsync((event) { + var subscription = watcher.events.listen(expectAsync1((event) { expect(event, isWatchEvent(ChangeType.ADD, "file.txt")); completer.complete(); })); @@ -39,7 +39,7 @@ void sharedTests() { // Then start listening again. schedule(() { completer = new Completer(); - subscription = watcher.events.listen(expectAsync((event) { + subscription = watcher.events.listen(expectAsync1((event) { // We should get an event for the third file, not the one added while // we weren't subscribed. expect(event, isWatchEvent(ChangeType.ADD, "added.txt")); From 4890963844b7671c549a518a773c780c37ed1742 Mon Sep 17 00:00:00 2001 From: Gary Roumanis Date: Fri, 5 Jan 2018 13:16:34 -0800 Subject: [PATCH 0378/1215] Remove scheduled test (dart-lang/watcher#44) --- pkgs/watcher/.travis.yml | 18 +- pkgs/watcher/CHANGELOG.md | 4 + pkgs/watcher/lib/src/utils.dart | 12 - pkgs/watcher/pubspec.yaml | 6 +- .../test/directory_watcher/linux_test.dart | 10 +- .../test/directory_watcher/mac_os_test.dart | 16 +- .../test/directory_watcher/polling_test.dart | 10 +- .../test/directory_watcher/shared.dart | 164 ++++++------ .../test/directory_watcher/windows_test.dart | 10 +- .../test/file_watcher/native_test.dart | 3 +- .../test/file_watcher/polling_test.dart | 3 +- pkgs/watcher/test/file_watcher/shared.dart | 64 +++-- .../test/no_subscription/linux_test.dart | 4 +- .../test/no_subscription/mac_os_test.dart | 4 +- .../test/no_subscription/polling_test.dart | 3 - pkgs/watcher/test/no_subscription/shared.dart | 51 ++-- pkgs/watcher/test/ready/linux_test.dart | 4 +- pkgs/watcher/test/ready/mac_os_test.dart | 4 +- pkgs/watcher/test/ready/polling_test.dart | 3 - pkgs/watcher/test/ready/shared.dart | 86 ++----- pkgs/watcher/test/utils.dart | 239 ++++++------------ 21 files changed, 275 insertions(+), 443 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index deb901b6e..4c8c5ff75 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -1,20 +1,10 @@ language: dart -dart: - - dev - - stable +dart: dev dart_task: - - test - -matrix: - include: - - dart: dev - dart_task: dartfmt - # Only care about being analyzer clean for dev and stable - - dart: dev - dart_task: dartanalyzer - - dart: stable - dart_task: dartanalyzer + - test + - dartfmt + - dartanalyzer # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index b4ca0bac9..5e6c3d21f 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+6 + +* Internal changes only, namely removing dep on scheduled test. + # 0.9.7+5 * Fix an analysis warning. diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index ef39eef48..18b53c9e6 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -71,18 +71,6 @@ Stream futureStream(Future> future, {bool broadcast: false}) { /// under the covers. Future newFuture(callback()) => new Future.value().then((_) => callback()); -/// Returns a [Future] that completes after pumping the event queue [times] -/// times. By default, this should pump the event queue enough times to allow -/// any code to run, as long as it's not waiting on some external event. -Future pumpEventQueue([int times = 20]) { - if (times == 0) return new Future.value(); - // We use a delayed future to allow microtask events to finish. The - // Future.value or Future() constructors use scheduleMicrotask themselves and - // would therefore not wait for microtask callbacks that are scheduled after - // invoking this method. - return new Future.delayed(Duration.ZERO, () => pumpEventQueue(times - 1)); -} - /// A stream transformer that batches all events that are sent at the same time. /// /// When multiple events are synchronously added to a stream controller, the diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index d1260d56c..62abc69bc 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+6.dev +version: 0.9.7+6 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > @@ -12,5 +12,5 @@ dependencies: path: '>=0.9.0 <2.0.0' dev_dependencies: benchmark_harness: '^1.0.4' - scheduled_test: '^0.12.0' - test: '^0.12.18+1' + test: '^0.12.29' + test_descriptor: '^1.0.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 34e689683..25c550468 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -4,7 +4,7 @@ @TestOn('linux') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; import 'package:watcher/watcher.dart'; @@ -14,8 +14,6 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { @@ -24,15 +22,15 @@ void main() { }); test('emits events for many nested files moved out then immediately back in', - () { + () async { withPermutations( (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); - allowEither(() { + await allowEither(() { inAnyOrder(withPermutations( (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 46b7ca2e1..8fa76fd2d 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -4,7 +4,7 @@ @TestOn('mac-os') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'package:watcher/watcher.dart'; @@ -14,8 +14,6 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { @@ -25,28 +23,28 @@ void main() { test( 'does not notify about the watched directory being deleted and ' - 'recreated immediately before watching', () { + 'recreated immediately before watching', () async { createDir("dir"); writeFile("dir/old.txt"); deleteDir("dir"); createDir("dir"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); writeFile("dir/newer.txt"); - expectAddEvent("dir/newer.txt"); + await expectAddEvent("dir/newer.txt"); }); test('emits events for many nested files moved out then immediately back in', - () { + () async { withPermutations( (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameDir("dir/sub", "sub"); renameDir("sub", "dir/sub"); - allowEither(() { + await allowEither(() { inAnyOrder(withPermutations( (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 0192b2592..39bbbef0b 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -2,7 +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. -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; import 'shared.dart'; @@ -13,16 +13,14 @@ void main() { watcherFactory = (dir) => new PollingDirectoryWatcher(dir, pollingDelay: new Duration(milliseconds: 100)); - setUp(createSandbox); - sharedTests(); - test('does not notify if the modification time did not change', () { + test('does not notify if the modification time did not change', () async { writeFile("a.txt", contents: "before"); writeFile("b.txt", contents: "before"); - startWatcher(); + await startWatcher(); writeFile("a.txt", contents: "after", updateModified: false); writeFile("b.txt", contents: "after"); - expectModifyEvent("b.txt"); + await expectModifyEvent("b.txt"); }); } diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 2bdc07714..2c0f44116 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -2,136 +2,138 @@ // 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. -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/utils.dart'; import '../utils.dart'; void sharedTests() { - test('does not notify for files that already exist when started', () { + test('does not notify for files that already exist when started', () async { // Make some pre-existing files. writeFile("a.txt"); writeFile("b.txt"); - startWatcher(); + await startWatcher(); // Change one after the watcher is running. writeFile("b.txt", contents: "modified"); // We should get a modify event for the changed file, but no add events // for them before this. - expectModifyEvent("b.txt"); + await expectModifyEvent("b.txt"); }); - test('notifies when a file is added', () { - startWatcher(); + test('notifies when a file is added', () async { + await startWatcher(); writeFile("file.txt"); - expectAddEvent("file.txt"); + await expectAddEvent("file.txt"); }); - test('notifies when a file is modified', () { + test('notifies when a file is modified', () async { writeFile("file.txt"); - startWatcher(); + await startWatcher(); writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); - test('notifies when a file is removed', () { + test('notifies when a file is removed', () async { writeFile("file.txt"); - startWatcher(); + await startWatcher(); deleteFile("file.txt"); - expectRemoveEvent("file.txt"); + await expectRemoveEvent("file.txt"); }); - test('notifies when a file is modified multiple times', () { + test('notifies when a file is modified multiple times', () async { writeFile("file.txt"); - startWatcher(); + await startWatcher(); writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); writeFile("file.txt", contents: "modified again"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); - test('notifies even if the file contents are unchanged', () { + test('notifies even if the file contents are unchanged', () async { writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "before"); - startWatcher(); + await startWatcher(); writeFile("a.txt", contents: "same"); writeFile("b.txt", contents: "after"); - inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]); + await inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]); }); - test('when the watched directory is deleted, removes all files', () { + test('when the watched directory is deleted, removes all files', () async { writeFile("dir/a.txt"); writeFile("dir/b.txt"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); deleteDir("dir"); - inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); - test('when the watched directory is moved, removes all files', () { + test('when the watched directory is moved, removes all files', () async { writeFile("dir/a.txt"); writeFile("dir/b.txt"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameDir("dir", "moved_dir"); createDir("dir"); - inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); // Regression test for b/30768513. test( "doesn't crash when the directory is moved immediately after a subdir " - "is added", () { + "is added", () async { writeFile("dir/a.txt"); writeFile("dir/b.txt"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); createDir("dir/subdir"); renameDir("dir", "moved_dir"); createDir("dir"); - inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); }); group("moves", () { - test('notifies when a file is moved within the watched directory', () { + test('notifies when a file is moved within the watched directory', + () async { writeFile("old.txt"); - startWatcher(); + await startWatcher(); renameFile("old.txt", "new.txt"); - inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]); + await inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]); }); test('notifies when a file is moved from outside the watched directory', - () { + () async { writeFile("old.txt"); createDir("dir"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameFile("old.txt", "dir/new.txt"); expectAddEvent("dir/new.txt"); }); - test('notifies when a file is moved outside the watched directory', () { + test('notifies when a file is moved outside the watched directory', + () async { writeFile("dir/old.txt"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameFile("dir/old.txt", "new.txt"); expectRemoveEvent("dir/old.txt"); }); - test('notifies when a file is moved onto an existing one', () { + test('notifies when a file is moved onto an existing one', () async { writeFile("from.txt"); writeFile("to.txt"); - startWatcher(); + await startWatcher(); renameFile("from.txt", "to.txt"); - inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]); + await inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]); }); }); @@ -144,14 +146,15 @@ void sharedTests() { // that as well. group("clustered changes", () { test("doesn't notify when a file is created and then immediately removed", - () { - startWatcher(); + () async { + writeFile("test.txt"); + await startWatcher(); writeFile("file.txt"); deleteFile("file.txt"); // Backup case. startClosingEventStream(); - allowEvents(() { + await allowEvents(() { expectAddEvent("file.txt"); expectRemoveEvent("file.txt"); }); @@ -159,14 +162,14 @@ void sharedTests() { test( "reports a modification when a file is deleted and then immediately " - "recreated", () { + "recreated", () async { writeFile("file.txt"); - startWatcher(); + await startWatcher(); deleteFile("file.txt"); writeFile("file.txt", contents: "re-created"); - allowEither(() { + await allowEither(() { expectModifyEvent("file.txt"); }, () { // Backup case. @@ -177,14 +180,14 @@ void sharedTests() { test( "reports a modification when a file is moved and then immediately " - "recreated", () { + "recreated", () async { writeFile("old.txt"); - startWatcher(); + await startWatcher(); renameFile("old.txt", "new.txt"); writeFile("old.txt", contents: "re-created"); - allowEither(() { + await allowEither(() { inAnyOrder([isModifyEvent("old.txt"), isAddEvent("new.txt")]); }, () { // Backup case. @@ -196,76 +199,77 @@ void sharedTests() { test( "reports a removal when a file is modified and then immediately " - "removed", () { + "removed", () async { writeFile("file.txt"); - startWatcher(); + await startWatcher(); writeFile("file.txt", contents: "modified"); deleteFile("file.txt"); // Backup case. - allowModifyEvent("file.txt"); + await allowModifyEvent("file.txt"); - expectRemoveEvent("file.txt"); + await expectRemoveEvent("file.txt"); }); test("reports an add when a file is added and then immediately modified", - () { - startWatcher(); + () async { + await startWatcher(); writeFile("file.txt"); writeFile("file.txt", contents: "modified"); - expectAddEvent("file.txt"); + await expectAddEvent("file.txt"); // Backup case. startClosingEventStream(); - allowModifyEvent("file.txt"); + await allowModifyEvent("file.txt"); }); }); group("subdirectories", () { - test('watches files in subdirectories', () { - startWatcher(); + test('watches files in subdirectories', () async { + await startWatcher(); writeFile("a/b/c/d/file.txt"); expectAddEvent("a/b/c/d/file.txt"); }); test( 'notifies when a subdirectory is moved within the watched directory ' - 'and then its contents are modified', () { + 'and then its contents are modified', () async { writeFile("old/file.txt"); - startWatcher(); + await startWatcher(); renameDir("old", "new"); - inAnyOrder([isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]); + await inAnyOrder( + [isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]); writeFile("new/file.txt", contents: "modified"); - expectModifyEvent("new/file.txt"); + await expectModifyEvent("new/file.txt"); }); - test('notifies when a file is replaced by a subdirectory', () { + test('notifies when a file is replaced by a subdirectory', () async { writeFile("new"); writeFile("old/file.txt"); - startWatcher(); + await startWatcher(); deleteFile("new"); renameDir("old", "new"); - inAnyOrder([ + await inAnyOrder([ isRemoveEvent("new"), isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt") ]); }); - test('notifies when a subdirectory is replaced by a file', () { + test('notifies when a subdirectory is replaced by a file', () async { writeFile("old"); writeFile("new/file.txt"); - startWatcher(); + await startWatcher(); renameDir("new", "newer"); renameFile("old", "new"); - inAnyOrder([ + await inAnyOrder([ isRemoveEvent("new/file.txt"), isAddEvent("newer/file.txt"), isRemoveEvent("old"), @@ -275,23 +279,23 @@ void sharedTests() { "mac-os": new Skip("https://github.com/dart-lang/watcher/issues/21") }); - test('emits events for many nested files added at once', () { + test('emits events for many nested files added at once', () async { withPermutations((i, j, k) => writeFile("sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameDir("sub", "dir/sub"); - inAnyOrder(withPermutations( + await inAnyOrder(withPermutations( (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); - test('emits events for many nested files removed at once', () { + test('emits events for many nested files removed at once', () async { withPermutations( (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); // Rename the directory rather than deleting it because native watchers // report a rename as a single DELETE event for the directory, whereas @@ -299,19 +303,19 @@ void sharedTests() { // directory. renameDir("dir/sub", "sub"); - inAnyOrder(withPermutations( + await inAnyOrder(withPermutations( (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); }); - test('emits events for many nested files moved at once', () { + test('emits events for many nested files moved at once', () async { withPermutations( (i, j, k) => writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); createDir("dir"); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); renameDir("dir/old", "dir/new"); - inAnyOrder(unionAll(withPermutations((i, j, k) { + await inAnyOrder(unionAll(withPermutations((i, j, k) { return new Set.from([ isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"), isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt") @@ -321,10 +325,10 @@ void sharedTests() { test( "emits events for many files added at once in a subdirectory with the " - "same name as a removed file", () { + "same name as a removed file", () async { writeFile("dir/sub"); withPermutations((i, j, k) => writeFile("old/sub-$i/sub-$j/file-$k.txt")); - startWatcher(path: "dir"); + await startWatcher(path: "dir"); deleteFile("dir/sub"); renameDir("old", "dir/sub"); @@ -332,7 +336,7 @@ void sharedTests() { var events = withPermutations( (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); events.add(isRemoveEvent("dir/sub")); - inAnyOrder(events); + await inAnyOrder(events); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 176fe2d71..3696f9cb9 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -4,7 +4,7 @@ @TestOn('windows') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; import 'package:watcher/watcher.dart'; @@ -14,9 +14,11 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); - setUp(createSandbox); - - sharedTests(); + // TODO(grouma) - renable when https://github.com/dart-lang/sdk/issues/31760 + // is resolved. + group("Shared Tests:", () { + sharedTests(); + }, skip: "SDK issue see - https://github.com/dart-lang/sdk/issues/31760"); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { expect( diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart index cbf11b6cd..b6ed901bc 100644 --- a/pkgs/watcher/test/file_watcher/native_test.dart +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -4,7 +4,7 @@ @TestOn('linux || mac-os') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/file_watcher/native.dart'; import 'shared.dart'; @@ -14,7 +14,6 @@ void main() { watcherFactory = (file) => new NativeFileWatcher(file); setUp(() { - createSandbox(); writeFile("file.txt"); }); diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index e5025447f..01d579a9f 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -4,7 +4,7 @@ @TestOn('linux || mac-os') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; import 'shared.dart'; @@ -15,7 +15,6 @@ void main() { pollingDelay: new Duration(milliseconds: 100)); setUp(() { - createSandbox(); writeFile("file.txt"); }); diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 50f7aebba..286a04210 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -4,73 +4,67 @@ import 'dart:async'; -import 'package:scheduled_test/scheduled_test.dart'; -import 'package:watcher/src/utils.dart'; +import 'package:test/test.dart'; import '../utils.dart'; void sharedTests() { - test("doesn't notify if the file isn't modified", () { - startWatcher(path: "file.txt"); - // Give the watcher time to fire events if it's going to. - schedule(() => pumpEventQueue()); + test("doesn't notify if the file isn't modified", () async { + await startWatcher(path: "file.txt"); + await pumpEventQueue(); deleteFile("file.txt"); - expectRemoveEvent("file.txt"); + await expectRemoveEvent("file.txt"); }); - test("notifies when a file is modified", () { - startWatcher(path: "file.txt"); + test("notifies when a file is modified", () async { + await startWatcher(path: "file.txt"); writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); - test("notifies when a file is removed", () { - startWatcher(path: "file.txt"); + test("notifies when a file is removed", () async { + await startWatcher(path: "file.txt"); deleteFile("file.txt"); - expectRemoveEvent("file.txt"); + await expectRemoveEvent("file.txt"); }); - test("notifies when a file is modified multiple times", () { - startWatcher(path: "file.txt"); + test("notifies when a file is modified multiple times", () async { + await startWatcher(path: "file.txt"); writeFile("file.txt", contents: "modified"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); writeFile("file.txt", contents: "modified again"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); - test("notifies even if the file contents are unchanged", () { - startWatcher(path: "file.txt"); + test("notifies even if the file contents are unchanged", () async { + await startWatcher(path: "file.txt"); writeFile("file.txt"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); - test("emits a remove event when the watched file is moved away", () { - startWatcher(path: "file.txt"); + test("emits a remove event when the watched file is moved away", () async { + await startWatcher(path: "file.txt"); renameFile("file.txt", "new.txt"); - expectRemoveEvent("file.txt"); + await expectRemoveEvent("file.txt"); }); test( "emits a modify event when another file is moved on top of the watched " - "file", () { + "file", () async { writeFile("old.txt"); - startWatcher(path: "file.txt"); + await startWatcher(path: "file.txt"); renameFile("old.txt", "file.txt"); - expectModifyEvent("file.txt"); + await expectModifyEvent("file.txt"); }); // Regression test for a race condition. - test("closes the watcher immediately after deleting the file", () { + test("closes the watcher immediately after deleting the file", () async { writeFile("old.txt"); - var watcher = createWatcher(path: "file.txt", waitForReady: false); - var sub = schedule(() => watcher.events.listen(null)); + var watcher = createWatcher(path: "file.txt"); + var sub = watcher.events.listen(null); deleteFile("file.txt"); - schedule(() async { - // Reproducing the race condition will always be flaky, but this sleep - // helped it reproduce more consistently on my machine. - await new Future.delayed(new Duration(milliseconds: 10)); - (await sub).cancel(); - }); + await new Future.delayed(new Duration(milliseconds: 10)); + await sub.cancel(); }); } diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart index c8e8ae91c..e9bfd69ca 100644 --- a/pkgs/watcher/test/no_subscription/linux_test.dart +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -4,7 +4,7 @@ @TestOn('linux') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; import 'shared.dart'; @@ -13,7 +13,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index 499aff3ca..fc14ebf10 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -5,7 +5,7 @@ @TestOn('mac-os') @Skip("Flaky due to sdk#23877") -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'shared.dart'; @@ -14,7 +14,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart index 5c99bc061..75fa3a7a0 100644 --- a/pkgs/watcher/test/no_subscription/polling_test.dart +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -2,7 +2,6 @@ // 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. -import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; import 'shared.dart'; @@ -11,7 +10,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new PollingDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 58586567a..c7e050151 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -4,60 +4,51 @@ import 'dart:async'; -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:async/async.dart'; +import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; import '../utils.dart'; void sharedTests() { - test('does not notify for changes when there are no subscribers', () { + test('does not notify for changes when there are no subscribers', () async { // Note that this test doesn't rely as heavily on the test functions in // utils.dart because it needs to be very explicit about when the event // stream is and is not subscribed. var watcher = createWatcher(); + var queue = new StreamQueue(watcher.events); + queue.hasNext; - // Subscribe to the events. - var completer = new Completer(); - var subscription = watcher.events.listen(expectAsync1((event) { - expect(event, isWatchEvent(ChangeType.ADD, "file.txt")); - completer.complete(); - })); + var future = + expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "file.txt"))); + expect(queue, neverEmits(anything)); - writeFile("file.txt"); + await watcher.ready; - // Then wait until we get an event for it. - schedule(() => completer.future); + writeFile('file.txt'); + + await future; // Unsubscribe. - schedule(() { - subscription.cancel(); - }); + await queue.cancel(immediate: true); // Now write a file while we aren't listening. writeFile("unwatched.txt"); - // Then start listening again. - schedule(() { - completer = new Completer(); - subscription = watcher.events.listen(expectAsync1((event) { - // We should get an event for the third file, not the one added while - // we weren't subscribed. - expect(event, isWatchEvent(ChangeType.ADD, "added.txt")); - completer.complete(); - })); + queue = new StreamQueue(watcher.events); + future = + expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "added.txt"))); + expect(queue, neverEmits(isWatchEvent(ChangeType.ADD, "unwatched.txt"))); - // Wait until the watcher is ready to dispatch events again. - return watcher.ready; - }); + // Wait until the watcher is ready to dispatch events again. + await watcher.ready; // And add a third file. writeFile("added.txt"); // Wait until we get an event for the third file. - schedule(() => completer.future); + await future; - schedule(() { - subscription.cancel(); - }); + await queue.cancel(immediate: true); }); } diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart index c8e8ae91c..e9bfd69ca 100644 --- a/pkgs/watcher/test/ready/linux_test.dart +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -4,7 +4,7 @@ @TestOn('linux') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; import 'shared.dart'; @@ -13,7 +13,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart index d5b1c8e3f..9533cc818 100644 --- a/pkgs/watcher/test/ready/mac_os_test.dart +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -4,7 +4,7 @@ @TestOn('mac-os') -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'shared.dart'; @@ -13,7 +13,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart index 5c99bc061..75fa3a7a0 100644 --- a/pkgs/watcher/test/ready/polling_test.dart +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -2,7 +2,6 @@ // 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. -import 'package:scheduled_test/scheduled_test.dart'; import 'package:watcher/watcher.dart'; import 'shared.dart'; @@ -11,7 +10,5 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => new PollingDirectoryWatcher(dir); - setUp(createSandbox); - sharedTests(); } diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index 7be48331e..730d57953 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -2,97 +2,61 @@ // 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. -import 'package:scheduled_test/scheduled_test.dart'; +import 'package:test/test.dart'; import '../utils.dart'; void sharedTests() { - test('ready does not complete until after subscription', () { - var watcher = createWatcher(waitForReady: false); + test('ready does not complete until after subscription', () async { + var watcher = createWatcher(); var ready = false; watcher.ready.then((_) { ready = true; }); + await pumpEventQueue(); - // Should not be ready yet. - schedule(() { - expect(ready, isFalse); - }); + expect(ready, isFalse); // Subscribe to the events. - schedule(() { - var subscription = watcher.events.listen((event) {}); + watcher.events.listen((event) {}); - currentSchedule.onComplete.schedule(() { - subscription.cancel(); - }); - }); + await watcher.ready; // Should eventually be ready. - schedule(() => watcher.ready); - - schedule(() { - expect(ready, isTrue); - }); + expect(watcher.isReady, isTrue); }); - test('ready completes immediately when already ready', () { - var watcher = createWatcher(waitForReady: false); + test('ready completes immediately when already ready', () async { + var watcher = createWatcher(); // Subscribe to the events. - schedule(() { - var subscription = watcher.events.listen((event) {}); - - currentSchedule.onComplete.schedule(() { - subscription.cancel(); - }); - }); - - // Should eventually be ready. - schedule(() => watcher.ready); + watcher.events.listen((event) {}); - // Now ready should be a future that immediately completes. - var ready = false; - schedule(() { - watcher.ready.then((_) { - ready = true; - }); - }); + // Allow watcher to become ready + await watcher.ready; - schedule(() { - expect(ready, isTrue); - }); + // Ensure ready completes immediately + expect( + watcher.ready.timeout(new Duration(milliseconds: 0), + onTimeout: () => throw 'Does not complete immedately'), + completes); }); - test('ready returns a future that does not complete after unsubscribing', () { - var watcher = createWatcher(waitForReady: false); + test('ready returns a future that does not complete after unsubscribing', + () async { + var watcher = createWatcher(); // Subscribe to the events. - var subscription; - schedule(() { - subscription = watcher.events.listen((event) {}); - }); - - var ready = false; + var subscription = watcher.events.listen((event) {}); // Wait until ready. - schedule(() => watcher.ready); + await watcher.ready; // Now unsubscribe. - schedule(() { - subscription.cancel(); - - // Track when it's ready again. - ready = false; - watcher.ready.then((_) { - ready = true; - }); - }); + await subscription.cancel(); // Should be back to not ready. - schedule(() { - expect(ready, isFalse); - }); + expect(watcher.ready, doesNotComplete); }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 6700500ad..637eacff7 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -2,21 +2,23 @@ // 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. +import 'dart:async'; import 'dart:io'; +import 'package:async/async.dart'; import 'package:path/path.dart' as p; -import 'package:scheduled_test/scheduled_stream.dart'; -import 'package:scheduled_test/scheduled_test.dart'; -import 'package:watcher/watcher.dart'; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; + import 'package:watcher/src/stat.dart'; -import 'package:watcher/src/utils.dart'; +import 'package:watcher/watcher.dart'; -/// The path to the temporary sandbox created for each test. All file -/// operations are implicitly relative to this directory. -String _sandboxDir; +typedef Watcher WatcherFactory(String directory); -/// The [Watcher] being used for the current scheduled test. -Watcher _watcher; +/// Sets the function used to create the watcher. +set watcherFactory(WatcherFactory factory) { + _watcherFactory = factory; +} /// The mock modification times (in milliseconds since epoch) for each file. /// @@ -27,53 +29,10 @@ Watcher _watcher; /// /// Instead, we'll just mock that out. Each time a file is written, we manually /// increment the mod time for that file instantly. -Map _mockFileModificationTimes; - -typedef Watcher WatcherFactory(String directory); - -/// Sets the function used to create the watcher. -set watcherFactory(WatcherFactory factory) { - _watcherFactory = factory; -} +final _mockFileModificationTimes = {}; WatcherFactory _watcherFactory; -/// Creates the sandbox directory the other functions in this library use and -/// ensures it's deleted when the test ends. -/// -/// This should usually be called by [setUp]. -void createSandbox() { - var dir = Directory.systemTemp.createTempSync('watcher_test_'); - _sandboxDir = dir.path; - - _mockFileModificationTimes = new Map(); - mockGetModificationTime((path) { - path = p.normalize(p.relative(path, from: _sandboxDir)); - - // Make sure we got a path in the sandbox. - assert(p.isRelative(path) && !path.startsWith("..")); - - var mtime = _mockFileModificationTimes[path]; - return new DateTime.fromMillisecondsSinceEpoch(mtime == null ? 0 : mtime); - }); - - // Delete the sandbox when done. - currentSchedule.onComplete.schedule(() { - if (_sandboxDir != null) { - // TODO(rnystrom): Issue 19155. The watcher should already be closed when - // we clean up the sandbox. - if (_watcherEvents != null) { - _watcherEvents.close(); - } - new Directory(_sandboxDir).deleteSync(recursive: true); - _sandboxDir = null; - } - - _mockFileModificationTimes = null; - mockGetModificationTime(null); - }, "delete sandbox"); -} - /// Creates a new [Watcher] that watches a temporary file or directory. /// /// Normally, this will pause the schedule until the watcher is done scanning @@ -81,62 +40,43 @@ void createSandbox() { /// not schedule this delay. /// /// If [path] is provided, watches a subdirectory in the sandbox with that name. -Watcher createWatcher({String path, bool waitForReady}) { +Watcher createWatcher({String path}) { if (path == null) { - path = _sandboxDir; + path = d.sandbox; } else { - path = p.join(_sandboxDir, path); - } - - var watcher = _watcherFactory(path); - - // Wait until the scan is finished so that we don't miss changes to files - // that could occur before the scan completes. - if (waitForReady != false) { - schedule(() => watcher.ready, "wait for watcher to be ready"); + path = p.join(d.sandbox, path); } - return watcher; + return _watcherFactory(path); } /// The stream of events from the watcher started with [startWatcher]. -ScheduledStream _watcherEvents; +StreamQueue _watcherEvents; /// Creates a new [Watcher] that watches a temporary file or directory and /// starts monitoring it for events. /// /// If [path] is provided, watches a path in the sandbox with that name. -void startWatcher({String path}) { +Future startWatcher({String path}) async { + mockGetModificationTime((path) { + path = p.normalize(p.relative(path, from: d.sandbox)); + + // Make sure we got a path in the sandbox. + assert(p.isRelative(path) && !path.startsWith("..")); + + var mtime = _mockFileModificationTimes[path]; + return new DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); + }); + // We want to wait until we're ready *after* we subscribe to the watcher's // events. - _watcher = createWatcher(path: path, waitForReady: false); - - // Schedule [_watcher.events.listen] so that the watcher doesn't start - // watching [path] before it exists. Expose [_watcherEvents] immediately so - // that it can be accessed synchronously after this. - _watcherEvents = new ScheduledStream(futureStream( - schedule(() { - currentSchedule.onComplete.schedule(() { - _watcher = null; - if (!_closePending) _watcherEvents.close(); - - // If there are already errors, don't add this to the output and make - // people think it might be the root cause. - if (currentSchedule.errors.isEmpty) { - _watcherEvents.expect(isDone); - } - }, "reset watcher"); - - return _watcher.events; - }, "create watcher"), - broadcast: true)); - - schedule(() => _watcher.ready, "wait for watcher to be ready"); + var watcher = createWatcher(path: path); + _watcherEvents = new StreamQueue(watcher.events); + // Forces a subscription to the underlying stream. + _watcherEvents.hasNext; + await watcher.ready; } -/// Whether an event to close [_watcherEvents] has been scheduled. -bool _closePending = false; - /// Schedule closing the watcher stream after the event queue has been pumped. /// /// This is necessary when events are allowed to occur, but don't have to occur, @@ -144,12 +84,7 @@ bool _closePending = false; /// indefinitely because they might in the future and because the watcher is /// normally only closed after the test completes. void startClosingEventStream() { - schedule(() { - _closePending = true; - pumpEventQueue().then((_) => _watcherEvents.close()).whenComplete(() { - _closePending = false; - }); - }, 'start closing event stream'); + pumpEventQueue().then((_) => _watcherEvents.cancel(immediate: true)); } /// A list of [StreamMatcher]s that have been collected using @@ -165,7 +100,7 @@ StreamMatcher _collectStreamMatcher(block()) { _collectedStreamMatchers = new List(); try { block(); - return inOrder(_collectedStreamMatchers); + return emitsInOrder(_collectedStreamMatchers); } finally { _collectedStreamMatchers = oldStreamMatchers; } @@ -175,47 +110,45 @@ StreamMatcher _collectStreamMatcher(block()) { /// it with [_collectStreamMatcher]. /// /// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value. -void _expectOrCollect(streamMatcher) { +Future _expectOrCollect(streamMatcher) { if (_collectedStreamMatchers != null) { - _collectedStreamMatchers.add(new StreamMatcher.wrap(streamMatcher)); + _collectedStreamMatchers.add(emits(streamMatcher)); + return null; } else { - _watcherEvents.expect(streamMatcher); + return expectLater(_watcherEvents, emits(streamMatcher)); } } /// Expects that [matchers] will match emitted events in any order. /// /// [matchers] may be [Matcher]s or values, but not [StreamMatcher]s. -void inAnyOrder(Iterable matchers) { +Future inAnyOrder(Iterable matchers) { matchers = matchers.toSet(); - _expectOrCollect(nextValues(matchers.length, unorderedMatches(matchers))); + return _expectOrCollect(emitsInAnyOrder(matchers)); } /// Expects that the expectations established in either [block1] or [block2] /// will match the emitted events. /// /// If both blocks match, the one that consumed more events will be used. -void allowEither(block1(), block2()) { - _expectOrCollect( - either(_collectStreamMatcher(block1), _collectStreamMatcher(block2))); -} +Future allowEither(block1(), block2()) => _expectOrCollect( + emitsAnyOf([_collectStreamMatcher(block1), _collectStreamMatcher(block2)])); /// Allows the expectations established in [block] to match the emitted events. /// /// If the expectations in [block] don't match, no error will be raised and no /// events will be consumed. If this is used at the end of a test, /// [startClosingEventStream] should be called before it. -void allowEvents(block()) { - _expectOrCollect(allow(_collectStreamMatcher(block))); -} +Future allowEvents(block()) => + _expectOrCollect(mayEmit(_collectStreamMatcher(block))); -/// Returns a matcher that matches a [WatchEvent] with the given [type] and -/// [path]. +/// Returns a StreamMatcher that matches a [WatchEvent] with the given [type] +/// and [path]. Matcher isWatchEvent(ChangeType type, String path) { return predicate((e) { return e is WatchEvent && e.type == type && - e.path == p.join(_sandboxDir, p.normalize(path)); + e.path == p.join(d.sandbox, p.normalize(path)); }, "is $type $path"); } @@ -231,16 +164,16 @@ Matcher isModifyEvent(String path) => isWatchEvent(ChangeType.MODIFY, path); Matcher isRemoveEvent(String path) => isWatchEvent(ChangeType.REMOVE, path); /// Expects that the next event emitted will be for an add event for [path]. -void expectAddEvent(String path) => +Future expectAddEvent(String path) => _expectOrCollect(isWatchEvent(ChangeType.ADD, path)); /// Expects that the next event emitted will be for a modification event for /// [path]. -void expectModifyEvent(String path) => +Future expectModifyEvent(String path) => _expectOrCollect(isWatchEvent(ChangeType.MODIFY, path)); /// Expects that the next event emitted will be for a removal event for [path]. -void expectRemoveEvent(String path) => +Future expectRemoveEvent(String path) => _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path)); /// Consumes an add event for [path] if one is emitted at this point in the @@ -248,24 +181,24 @@ void expectRemoveEvent(String path) => /// /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. -void allowAddEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.ADD, path))); +Future allowAddEvent(String path) => + _expectOrCollect(mayEmit(isWatchEvent(ChangeType.ADD, path))); /// Consumes a modification event for [path] if one is emitted at this point in /// the schedule, but doesn't throw an error if it isn't. /// /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. -void allowModifyEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.MODIFY, path))); +Future allowModifyEvent(String path) => + _expectOrCollect(mayEmit(isWatchEvent(ChangeType.MODIFY, path))); /// Consumes a removal event for [path] if one is emitted at this point in the /// schedule, but doesn't throw an error if it isn't. /// /// If this is used at the end of a test, [startClosingEventStream] should be /// called before it. -void allowRemoveEvent(String path) => - _expectOrCollect(allow(isWatchEvent(ChangeType.REMOVE, path))); +Future allowRemoveEvent(String path) => + _expectOrCollect(mayEmit(isWatchEvent(ChangeType.REMOVE, path))); /// Schedules writing a file in the sandbox at [path] with [contents]. /// @@ -275,71 +208,55 @@ void writeFile(String path, {String contents, bool updateModified}) { if (contents == null) contents = ""; if (updateModified == null) updateModified = true; - schedule(() { - var fullPath = p.join(_sandboxDir, path); + var fullPath = p.join(d.sandbox, path); - // Create any needed subdirectories. - var dir = new Directory(p.dirname(fullPath)); - if (!dir.existsSync()) { - dir.createSync(recursive: true); - } + // Create any needed subdirectories. + var dir = new Directory(p.dirname(fullPath)); + if (!dir.existsSync()) { + dir.createSync(recursive: true); + } - new File(fullPath).writeAsStringSync(contents); + new File(fullPath).writeAsStringSync(contents); - // Manually update the mock modification time for the file. - if (updateModified) { - // Make sure we always use the same separator on Windows. - path = p.normalize(path); + if (updateModified) { + path = p.normalize(path); - _mockFileModificationTimes.putIfAbsent(path, () => 0); - _mockFileModificationTimes[path]++; - } - }, "write file $path"); + _mockFileModificationTimes.putIfAbsent(path, () => 0); + _mockFileModificationTimes[path]++; + } } /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { - schedule(() { - new File(p.join(_sandboxDir, path)).deleteSync(); - }, "delete file $path"); + new File(p.join(d.sandbox, path)).deleteSync(); } /// Schedules renaming a file in the sandbox from [from] to [to]. /// /// If [contents] is omitted, creates an empty file. void renameFile(String from, String to) { - schedule(() { - new File(p.join(_sandboxDir, from)).renameSync(p.join(_sandboxDir, to)); + new File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); - // Make sure we always use the same separator on Windows. - to = p.normalize(to); + // Make sure we always use the same separator on Windows. + to = p.normalize(to); - // Manually update the mock modification time for the file. - _mockFileModificationTimes.putIfAbsent(to, () => 0); - _mockFileModificationTimes[to]++; - }, "rename file $from to $to"); + _mockFileModificationTimes.putIfAbsent(to, () => 0); + _mockFileModificationTimes[to]++; } /// Schedules creating a directory in the sandbox at [path]. void createDir(String path) { - schedule(() { - new Directory(p.join(_sandboxDir, path)).createSync(); - }, "create directory $path"); + new Directory(p.join(d.sandbox, path)).createSync(); } /// Schedules renaming a directory in the sandbox from [from] to [to]. void renameDir(String from, String to) { - schedule(() { - new Directory(p.join(_sandboxDir, from)) - .renameSync(p.join(_sandboxDir, to)); - }, "rename directory $from to $to"); + new Directory(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); } /// Schedules deleting a directory in the sandbox at [path]. void deleteDir(String path) { - schedule(() { - new Directory(p.join(_sandboxDir, path)).deleteSync(recursive: true); - }, "delete directory $path"); + new Directory(p.join(d.sandbox, path)).deleteSync(recursive: true); } /// Runs [callback] with every permutation of non-negative [i], [j], and [k] From 8d31f47847f357f8ab8ca0211cd304a3b857b1b5 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Fri, 5 Jan 2018 16:26:47 -0800 Subject: [PATCH 0379/1215] Make _LinuxDirectoryWatcher._listen generic (dart-lang/watcher#45) --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 717e4209c..354ddc020 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -127,8 +127,7 @@ class _LinuxDirectoryWatcher } /// The callback that's run when a batch of changes comes in. - void _onBatch(Object data) { - var batch = data as List; + void _onBatch(List batch) { var files = new Set(); var dirs = new Set(); var changed = new Set(); @@ -251,7 +250,7 @@ class _LinuxDirectoryWatcher /// Like [Stream.listen], but automatically adds the subscription to /// [_subscriptions] so that it can be canceled when [close] is called. - void _listen(Stream stream, void onData(event), + void _listen(Stream stream, void onData(T event), {Function onError, void onDone(), bool cancelOnError}) { var subscription; subscription = stream.listen(onData, onError: onError, onDone: () { From 1a43a63fdd506b26d4798cdf781d4ebc3c8f957c Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Tue, 30 Jan 2018 18:00:34 -0800 Subject: [PATCH 0380/1215] Updates for Dart 2.0 corelib changes (wave 2.2) --- pkgs/watcher/CHANGELOG.md | 8 ++++++++ pkgs/watcher/lib/src/utils.dart | 2 +- pkgs/watcher/pubspec.yaml | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 5e6c3d21f..8f1ffc387 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,11 @@ +# 0.9.7+7 + +* Updates to support Dart 2.0 core library changes (wave 2.2). + See [issue 31847][sdk#31847] for details. + + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 + + # 0.9.7+6 * Internal changes only, namely removing dep on scheduled test. diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 18b53c9e6..0b2f79961 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -78,7 +78,7 @@ Future newFuture(callback()) => new Future.value().then((_) => callback()); /// asynchronous firing of each event. In order to recreate the synchronous /// batches, this collates all the events that are received in "nearby" /// microtasks. -class BatchedStreamTransformer implements StreamTransformer> { +class BatchedStreamTransformer extends StreamTransformerBase> { Stream> bind(Stream input) { var batch = new Queue(); return new StreamTransformer>.fromHandlers( diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 62abc69bc..daea75b00 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,12 +1,12 @@ name: watcher -version: 0.9.7+6 +version: 0.9.7+7 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: - sdk: '>=1.21.0 <2.0.0' + sdk: '>=2.0.0-dev.20.0 <2.0.0' dependencies: async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' From 75ed4c2dc45dd7f2d4547ba45034b49fd3c9b01d Mon Sep 17 00:00:00 2001 From: Leaf Petersen Date: Wed, 31 Jan 2018 13:04:58 -0800 Subject: [PATCH 0381/1215] Updates for Dart 2.0 core library changes (wave 2.2) --- pkgs/stream_transform/CHANGELOG.md | 7 +++++++ pkgs/stream_transform/lib/src/bind.dart | 2 +- pkgs/stream_transform/lib/src/buffer.dart | 2 +- pkgs/stream_transform/lib/src/concat.dart | 2 +- pkgs/stream_transform/lib/src/from_handlers.dart | 2 +- pkgs/stream_transform/lib/src/merge.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/lib/src/take_until.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 4 ++-- 9 files changed, 16 insertions(+), 9 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 056eebda3..fe8eaa27b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.0.10 + +- Updates to support Dart 2.0 core library changes (wave + 2.2). See [issue 31847][sdk#31847] for details. + + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 + ## 0.0.9 - Add `asyncMapBuffer`. diff --git a/pkgs/stream_transform/lib/src/bind.dart b/pkgs/stream_transform/lib/src/bind.dart index 603cc0f54..169653f4a 100644 --- a/pkgs/stream_transform/lib/src/bind.dart +++ b/pkgs/stream_transform/lib/src/bind.dart @@ -12,7 +12,7 @@ typedef Stream Bind(Stream values); StreamTransformer fromBind(Bind bindFn) => new _StreamTransformer(bindFn); -class _StreamTransformer implements StreamTransformer { +class _StreamTransformer extends StreamTransformerBase { final Bind _bind; _StreamTransformer(this._bind); diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index 5c594c80b..0d9b87fc0 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -24,7 +24,7 @@ StreamTransformer> buffer(Stream trigger) => /// /// Errors from the source stream or the trigger are immediately forwarded to /// the output. -class _Buffer implements StreamTransformer> { +class _Buffer extends StreamTransformerBase> { final Stream _trigger; _Buffer(this._trigger); diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart index 39e747ba5..bf0559d43 100644 --- a/pkgs/stream_transform/lib/src/concat.dart +++ b/pkgs/stream_transform/lib/src/concat.dart @@ -19,7 +19,7 @@ import 'dart:async'; /// buffered. StreamTransformer concat(Stream next) => new _Concat(next); -class _Concat implements StreamTransformer { +class _Concat extends StreamTransformerBase { final Stream _next; _Concat(this._next); diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 52ad5b4d1..36a0417f3 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -20,7 +20,7 @@ StreamTransformer fromHandlers( handleError: handleError, handleDone: handleDone); -class _StreamTransformer implements StreamTransformer { +class _StreamTransformer extends StreamTransformerBase { final HandleData _handleData; final HandleDone _handleDone; final HandleError _handleError; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 3653eb923..06dd9d31d 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -21,7 +21,7 @@ StreamTransformer merge(Stream other) => new _Merge([other]); StreamTransformer mergeAll(List> others) => new _Merge(others); -class _Merge implements StreamTransformer { +class _Merge extends StreamTransformerBase { final List> _others; _Merge(this._others); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 193cbaa5f..1774dd962 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -26,7 +26,7 @@ StreamTransformer switchMap(Stream map(S event)) => StreamTransformer, T> switchLatest() => new _SwitchTransformer(); -class _SwitchTransformer implements StreamTransformer, T> { +class _SwitchTransformer extends StreamTransformerBase, T> { const _SwitchTransformer(); @override diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 27674c20c..0c10856eb 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -12,7 +12,7 @@ import 'dart:async'; /// a subscription immediately stops values. StreamTransformer takeUntil(Future trigger) => new _TakeUntil(trigger); -class _TakeUntil implements StreamTransformer { +class _TakeUntil extends StreamTransformerBase { final Future _trigger; _TakeUntil(this._trigger); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 996e405dd..06d650d85 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,10 +2,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.10-dev +version: 0.0.10 environment: - sdk: ">=1.22.0 <2.0.0" + sdk: ">=2.0.0-dev.20.0 <2.0.0" dev_dependencies: test: ^0.12.20+13 From 9fc4f3a123cbf71a8d6cd5b6267cbeed45885cb2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 31 Jan 2018 13:31:53 -0800 Subject: [PATCH 0382/1215] Exclude stable and old SDK on travis --- pkgs/stream_transform/.travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 57bec9449..65c7fc39e 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -2,8 +2,6 @@ language: dart sudo: false dart: - dev - - stable - - 1.22.1 cache: directories: - $HOME/.pub-cache @@ -14,9 +12,3 @@ dart_task: - dartfmt - dartanalyzer - dartanalyzer: --no-strong . -matrix: - exclude: - - dart: 1.22.1 - dart_task: dartfmt - - dart: 1.22.1 - dart_task: dartanalyzer From 4ebce1098bfd9915fec2c0f94b3a66b165deea47 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Tue, 13 Feb 2018 16:51:53 -0800 Subject: [PATCH 0383/1215] Fix runtime cast failure in chainForTrace(). See: https://github.com/dart-lang/sdk/issues/27223 --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/utils.dart | 6 ++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 2627e7114..3c6e56c28 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,9 @@ +## 1.9.1+1 + +* Fix Dart 2.0 runtime cast failure in test. + ## 1.9.1 + * Preserve the original chain for a trace to handle cases where an error is rethrown. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index f7c562d4a..93ffeb3dc 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.9.1 +version: 1.9.1+1 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index bf821588d..0c5c98372 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -64,7 +64,7 @@ Stream controllerErrorStream([StackTrace trace]) { /// Runs [callback] within [asyncFn], then converts any errors raised into a /// [Chain] with [Chain.forTrace]. Future chainForTrace(asyncFn(callback()), callback()) { - var completer = new Completer(); + var completer = new Completer(); asyncFn(() { // We use `new Future.value().then(...)` here as opposed to [new Future] or // [new Future.sync] because those methods don't pass the exception through @@ -75,10 +75,8 @@ Future chainForTrace(asyncFn(callback()), callback()) { .catchError(completer.completeError); }); - // TODO(rnystrom): Remove this cast if catchError() gets a better type. return completer.future - .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)) - as Future; + .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); } /// Runs [callback] in a [Chain.capture] zone and returns a Future that From bdbd3be2a56ec67d2f3c3b211de9d6c157401ac1 Mon Sep 17 00:00:00 2001 From: Bob Nystrom Date: Wed, 14 Feb 2018 11:26:58 -0800 Subject: [PATCH 0384/1215] Bump patch version. --- pkgs/stack_trace/CHANGELOG.md | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 3c6e56c28..a2a4c4446 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.9.1+1 +## 1.9.2 * Fix Dart 2.0 runtime cast failure in test. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 93ffeb3dc..3824d641e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.9.1+1 +version: 1.9.2 author: "Dart Team " homepage: https://github.com/dart-lang/stack_trace description: A package for manipulating stack traces and printing them readably. From bde211d7e7da661dea7c22cc97a38c39a2af9ece Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 14 Feb 2018 13:21:03 -0800 Subject: [PATCH 0385/1215] Stop testing on Dartium (dart-lang/stack_trace#39) --- pkgs/stack_trace/.travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 2ec03bbf7..1d12365c9 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -7,8 +7,6 @@ dart: dart_task: - test: -p vm - test: -p firefox - - test: -p dartium - install_dartium: true - dartanalyzer matrix: include: From bc05d86f3d893e8cb1fecb702005ca171e6e1b81 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 14 Feb 2018 13:21:37 -0800 Subject: [PATCH 0386/1215] Run Travis against the stable branch (dart-lang/watcher#50) --- pkgs/watcher/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index 4c8c5ff75..c9774304b 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -8,7 +8,7 @@ dart_task: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, 0-9-7] + only: [master, 0.9.7+x] cache: directories: From 4c5a9c982d18be77a2b244d4f4cfdef64dbafb6f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 20 Feb 2018 13:12:32 -0800 Subject: [PATCH 0387/1215] Stop testing on Dartium (dart-lang/stream_channel#15) Fixes https://github.com/dart-lang/stream_channel/issues/14 --- pkgs/stream_channel/.travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index d5c64e9dd..a9510326d 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,13 +1,12 @@ language: dart -sudo: false + dart: - dev - stable + dart_task: - test: --platform vm - test: --platform firefox -j 1 - - test: --platform dartium - install_dartium: true - dartfmt - dartanalyzer From 7a53d88bd342312efa6cb4dce0f2c57d62f4e1cf Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 27 Feb 2018 14:59:26 -0800 Subject: [PATCH 0388/1215] Fix a race condition (dart-lang/stream_channel#16) MultiChannel wasn't buffering incoming remote events if their virtual channels hadn't been created locally yet. --- pkgs/stream_channel/CHANGELOG.md | 6 ++ .../stream_channel/lib/src/multi_channel.dart | 61 +++++++++++++------ pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 26 ++++++++ 4 files changed, 75 insertions(+), 20 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ece9e1d5a..093a2421d 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.4 + +* Fix a race condition in `MultiChannel` where messages from a remote virtual + channel could get dropped if the corresponding local channel wasn't registered + quickly enough. + ## 1.6.3 * Use `pumpEventQueue()` from test. diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 112997e57..e54154304 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -93,10 +93,18 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The controller for this channel. final _mainController = new StreamChannelController(sync: true); - /// A map from virtual channel ids to [StreamChannelController]s that should - /// be used to communicate over those channels. + /// A map from input IDs to [StreamChannelController]s that should be used to + /// communicate over those channels. final _controllers = {}; + /// Input IDs of controllers in [_controllers] that we've received messages + /// for but that have not yet had a local [virtualChannel] created. + final _pendingIds = new Set(); + + /// Input IDs of virtual channels that used to exist but have since been + /// closed. + final _closedIds = new Set(); + /// The next id to use for a local virtual channel. /// /// Ids are used to identify virtual channels. Each message is tagged with an @@ -114,8 +122,9 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// The trick is that each endpoint only uses odd ids for its own channels. /// When sending a message over a channel that was created by the remote /// endpoint, the channel's id plus one is used. This way each [MultiChannel] - /// knows that if an incoming message has an odd id, it's using the local id - /// scheme, but if it has an even id, it's using the remote id scheme. + /// knows that if an incoming message has an odd id, it's coming from a + /// channel that was originally created remotely, but if it has an even id, + /// it's coming from a channel that was originally created locally. var _nextId = 1; _MultiChannel(this._inner) { @@ -128,21 +137,28 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { _innerStreamSubscription = _inner.stream.listen((message) { var id = message[0]; - var controller = _controllers[id]; - // A controller might not exist if the channel was closed before an - // incoming message was processed. - if (controller == null) return; + // If the channel was closed before an incoming message was processed, + // ignore that message. + if (_closedIds.contains(id)) return; + + var controller = _controllers.putIfAbsent(id, () { + // If we receive a message for a controller that doesn't have a local + // counterpart yet, create a controller for it to buffer incoming + // messages for when a local connection is created. + _pendingIds.add(id); + return new StreamChannelController(sync: true); + }); + if (message.length > 1) { controller.local.sink.add(message[1]); - return; + } else { + // A message without data indicates that the channel has been closed. We + // can just close the sink here without doing any more cleanup, because + // the sink closing will cause the stream to emit a done event which + // will trigger more cleanup. + controller.local.sink.close(); } - - // A message without data indicates that the channel has been closed. We - // can only close the sink here without doing any more cleanup, because - // the sink closing will cause the stream to emit a done event which will - // trigger more cleanup. - controller.local.sink.close(); }, onDone: _closeInnerChannel, onError: _mainController.local.sink.addError); @@ -173,16 +189,22 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { this, inputId, new Stream.empty(), new NullStreamSink()); } - if (_controllers.containsKey(inputId)) { + StreamChannelController controller; + if (_pendingIds.remove(inputId)) { + // If we've already received messages for this channel, use the controller + // where those messages are buffered. + controller = _controllers[inputId]; + } else if (_controllers.containsKey(inputId) || + _closedIds.contains(inputId)) { throw new ArgumentError("A virtual channel with id $id already exists."); + } else { + controller = new StreamChannelController(sync: true); + _controllers[inputId] = controller; } - var controller = new StreamChannelController(sync: true); - _controllers[inputId] = controller; controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); - return new VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); } @@ -190,6 +212,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// Closes the virtual channel for which incoming messages have [inputId] and /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { + _closedIds.add(inputId); var controller = _controllers.remove(inputId); controller.local.sink.close(); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9a123b128..393e60f3b 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.3 +version: 1.6.4 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 2a87cafa3..0c9316abb 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -268,6 +268,32 @@ void main() { test("doesn't allow another virtual channel with the same id", () { expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); + + test("dispatches events received before the virtual channel is created", + () async { + virtual1 = channel1.virtualChannel(); + + virtual1.sink.add("hello"); + await pumpEventQueue(); + + virtual1.sink.add("world"); + await pumpEventQueue(); + + expect(channel2.virtualChannel(virtual1.id).stream, + emitsInOrder(["hello", "world"])); + }); + + test( + "dispatches close events received before the virtual channel is " + "created", () async { + virtual1 = channel1.virtualChannel(); + + virtual1.sink.close(); + await pumpEventQueue(); + + expect(channel2.virtualChannel(virtual1.id).stream.toList(), + completion(isEmpty)); + }); }); group("when the underlying stream", () { From e036c2eccec772079ad111b16a571a0648341162 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 1 Mar 2018 15:29:14 -0800 Subject: [PATCH 0389/1215] Enable Travis-CI (dart-lang/string_scanner#7) Fixes dart-lang/string_scanner#6 --- pkgs/string_scanner/.travis.yml | 24 +++++++++++++++++++ ...analysis_options => analysis_options.yaml} | 0 .../lib/src/eager_span_scanner.dart | 5 ++-- pkgs/string_scanner/lib/src/line_scanner.dart | 4 ++-- .../lib/src/relative_span_scanner.dart | 16 ++++++------- pkgs/string_scanner/lib/src/span_scanner.dart | 1 + .../lib/src/string_scanner.dart | 2 ++ .../test/span_scanner_test.dart | 10 ++++---- .../test/string_scanner_test.dart | 3 ++- 9 files changed, 45 insertions(+), 20 deletions(-) create mode 100644 pkgs/string_scanner/.travis.yml rename pkgs/string_scanner/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml new file mode 100644 index 000000000..4496f3a4e --- /dev/null +++ b/pkgs/string_scanner/.travis.yml @@ -0,0 +1,24 @@ +language: dart + +dart: + - dev + - stable + +dart_task: + - test: --platform vm,chrome + +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: analyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/string_scanner/.analysis_options b/pkgs/string_scanner/analysis_options.yaml similarity index 100% rename from pkgs/string_scanner/.analysis_options rename to pkgs/string_scanner/analysis_options.yaml diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index f80dce5c3..96c7362e0 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -58,8 +58,8 @@ class EagerSpanScanner extends SpanScanner { if (newlines.isEmpty) { _column -= oldPosition - newPosition; } else { - _column = newPosition - - string.lastIndexOf(_newlineRegExp, newPosition) - 1; + _column = + newPosition - string.lastIndexOf(_newlineRegExp, newPosition) - 1; } } } @@ -121,4 +121,3 @@ class _EagerSpanScannerState implements LineScannerState { _EagerSpanScannerState(this._scanner, this.position, this.line, this.column); } - diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 06f1cbc1e..518203530 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -66,8 +66,8 @@ class LineScanner extends StringScanner { if (newlines.isEmpty) { _column -= oldPosition - newPosition; } else { - _column = newPosition - - string.lastIndexOf(_newlineRegExp, newPosition) - 1; + _column = + newPosition - string.lastIndexOf(_newlineRegExp, newPosition) - 1; } } } diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index fdcd03fba..088ff481f 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -27,13 +27,14 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { /// This is used to convert between span-relative and file-relative fields. final FileLocation _startLocation; - int get line => _sourceFile.getLine(_startLocation.offset + position) - + int get line => + _sourceFile.getLine(_startLocation.offset + position) - _startLocation.line; int get column { var line = _sourceFile.getLine(_startLocation.offset + position); - var column = _sourceFile.getColumn(_startLocation.offset + position, - line: line); + var column = + _sourceFile.getColumn(_startLocation.offset + position, line: line); return line == _startLocation.line ? column - _startLocation.column : column; @@ -66,8 +67,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { var endPosition = endState == null ? position : endState.position; - return _sourceFile.span( - _startLocation.offset + startState.position, + return _sourceFile.span(_startLocation.offset + startState.position, _startLocation.offset + endPosition); } @@ -77,8 +77,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { return false; } - _lastSpan = _sourceFile.span( - _startLocation.offset + position, + _lastSpan = _sourceFile.span(_startLocation.offset + position, _startLocation.offset + lastMatch.end); return true; } @@ -92,8 +91,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { } if (length == null) length = match == null ? 1 : match.end - match.start; - var span = _sourceFile.span( - _startLocation.offset + position, + var span = _sourceFile.span(_startLocation.offset + position, _startLocation.offset + position + length); throw new StringScannerException(message, span, string); } diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index f362223b2..a629f1327 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -42,6 +42,7 @@ class SpanScanner extends StringScanner implements LineScanner { if (lastMatch == null) _lastSpan = null; return _lastSpan; } + FileSpan _lastSpan; /// The current location of the scanner. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 712292c60..ea3d6d60e 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -34,6 +34,7 @@ class StringScanner { _position = position; _lastMatch = null; } + int _position = 0; /// The data about the previous match made by the scanner. @@ -45,6 +46,7 @@ class StringScanner { if (_position != _lastMatchPosition) _lastMatch = null; return _lastMatch; } + Match _lastMatch; int _lastMatchPosition; diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index ab3cc8087..37a01e025 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -9,11 +9,11 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - testForImplementation("lazy", ([string]) { + testForImplementation("lazy", ([String string]) { return new SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); - testForImplementation("eager", ([string]) { + testForImplementation("eager", ([String string]) { return new SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); @@ -93,8 +93,8 @@ void main() { test(".error() uses an absolute span", () { scanner.expect("foo"); - expect(() => scanner.error('oh no!'), - throwsStringScannerException("foo")); + expect( + () => scanner.error('oh no!'), throwsStringScannerException("foo")); }); test(".isDone returns true at the end of the span", () { @@ -104,7 +104,7 @@ void main() { }); } -void testForImplementation(String name, SpanScanner create()) { +void testForImplementation(String name, SpanScanner create([String string])) { group("for a $name scanner", () { var scanner; setUp(() => scanner = create()); diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 55ffa0a9f..30711f5ae 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -178,7 +178,8 @@ void main() { expect(scanner.rest, equals(' bar')); }); - test("a non-matching expect throws a FormatException and sets lastMatch to " + test( + "a non-matching expect throws a FormatException and sets lastMatch to " "null", () { expect(scanner.matches(new RegExp('f(..)')), isTrue); expect(scanner.lastMatch, isNotNull); From 09090b486dc09bacdba507a04931e8d1e43db6ba Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Mar 2018 17:13:49 -0700 Subject: [PATCH 0390/1215] Enable Travis, add analysis_options, update .gitignore (dart-lang/term_glyph#3) --- pkgs/term_glyph/.gitignore | 7 +------ pkgs/term_glyph/.travis.yml | 24 ++++++++++++++++++++++++ pkgs/term_glyph/analysis_options.yaml | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 pkgs/term_glyph/.travis.yml create mode 100644 pkgs/term_glyph/analysis_options.yaml diff --git a/pkgs/term_glyph/.gitignore b/pkgs/term_glyph/.gitignore index 25a1df332..01d42c084 100644 --- a/pkgs/term_glyph/.gitignore +++ b/pkgs/term_glyph/.gitignore @@ -1,9 +1,4 @@ -.buildlog -.DS_Store -.idea +.dart_tool/ .pub/ -.settings/ -build/ -packages .packages pubspec.lock diff --git a/pkgs/term_glyph/.travis.yml b/pkgs/term_glyph/.travis.yml new file mode 100644 index 000000000..31cbd43ad --- /dev/null +++ b/pkgs/term_glyph/.travis.yml @@ -0,0 +1,24 @@ +language: dart + +dart: + - dev + - stable + +dart_task: + - test + +matrix: + include: + # Only validate formatting,analyzer using the dev release + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: dartanalyzer + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/term_glyph/analysis_options.yaml @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true From 17ee37f6356a9be86d0b0a7a050305a37343155f Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 26 Mar 2018 01:28:38 -0700 Subject: [PATCH 0391/1215] Add timeout support to test_reflective_loader. To use it, annotate a method with @TestTimeout(t) where t is a const instance of the Timeout class from the `test` package. E.g.: @TestTimeout(const Timeout.factor(2)) --- .../lib/test_reflective_loader.dart | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 9ebaf84e4..4aac7b21d 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -118,7 +118,7 @@ void defineReflectiveTests(Type type) { _hasAnnotationInstance(memberMirror, soloTest); // test_ if (memberName.startsWith('test_')) { - group.addTest(isSolo, memberName, () { + group.addTest(isSolo, memberName, memberMirror, () { if (_hasFailingTestAnnotation(memberMirror) || _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { return _runFailingTest(classMirror, symbol); @@ -130,19 +130,19 @@ void defineReflectiveTests(Type type) { } // solo_test_ if (memberName.startsWith('solo_test_')) { - group.addTest(true, memberName, () { + group.addTest(true, memberName, memberMirror, () { return _runTest(classMirror, symbol); }); } // fail_test_ if (memberName.startsWith('fail_')) { - group.addTest(isSolo, memberName, () { + group.addTest(isSolo, memberName, memberMirror, () { return _runFailingTest(classMirror, symbol); }); } // solo_fail_test_ if (memberName.startsWith('solo_fail_')) { - group.addTest(true, memberName, () { + group.addTest(true, memberName, memberMirror, () { return _runFailingTest(classMirror, symbol); }); } @@ -162,7 +162,8 @@ void _addTestsIfTopLevelSuite() { if (allGroups || group.isSolo) { for (_Test test in group.tests) { if (allTests || test.isSolo) { - test_package.test(test.name, test.function); + test_package.test(test.name, test.function, + timeout: test.timeout); } } } @@ -194,6 +195,15 @@ String _combineNames(String base, String addition) { } } +Object _getAnnotationInstance(DeclarationMirror declaration, Type type) { + for (InstanceMirror annotation in declaration.metadata) { + if (annotation.reflectee.runtimeType == type) { + return annotation.reflectee; + } + } + return null; +} + bool _hasAnnotationInstance(DeclarationMirror declaration, instance) => declaration.metadata.any((InstanceMirror annotation) => identical(annotation.reflectee, instance)); @@ -264,6 +274,16 @@ class ReflectiveTest { const ReflectiveTest(); } +/** + * A marker annotation used to annotate overridden test methods with additional + * timeout information. + */ +class TestTimeout { + final test_package.Timeout timeout; + + const TestTimeout(this.timeout); +} + /** * A marker annotation used to annotate overridden test methods (so we cannot * rename them to `fail_`) which are expected to fail at `assert` in the @@ -293,9 +313,11 @@ class _Group { bool get hasSoloTest => tests.any((test) => test.isSolo); - void addTest(bool isSolo, String name, _TestFunction function) { + void addTest(bool isSolo, String name, MethodMirror memberMirror, + _TestFunction function) { String fullName = _combineNames(this.name, name); - tests.add(new _Test(isSolo, fullName, function)); + TestTimeout timeout = _getAnnotationInstance(memberMirror, TestTimeout); + tests.add(new _Test(isSolo, fullName, function, timeout?.timeout)); } } @@ -313,6 +335,7 @@ class _Test { final bool isSolo; final String name; final _TestFunction function; + final test_package.Timeout timeout; - _Test(this.isSolo, this.name, this.function); + _Test(this.isSolo, this.name, this.function, this.timeout); } From d99ea36acc8c99c5d1bb13145c2e9d92e7fedd75 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 26 Mar 2018 10:18:54 -0700 Subject: [PATCH 0392/1215] Fix comment --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 4aac7b21d..a309948c7 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -275,8 +275,8 @@ class ReflectiveTest { } /** - * A marker annotation used to annotate overridden test methods with additional - * timeout information. + * A marker annotation used to annotate test methods with additional timeout + * information. */ class TestTimeout { final test_package.Timeout timeout; From b96e1fde8c7cac9cb889fe8e883a01e578e1b288 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Mon, 26 Mar 2018 10:25:50 -0700 Subject: [PATCH 0393/1215] Update pubspec version to 0.1.4 in preparation to publish --- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 7e5440438..ae718e8fd 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.3 +version: 0.1.4 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader From b1a5ca68fd6cbe602271012e3154dc674952c2fc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 26 Mar 2018 14:54:01 -0700 Subject: [PATCH 0394/1215] Rename concat as followedBy (dart-lang/stream_transform#43) Matches the naming of `Iterable.followedBy`. Leave concat as a deprecated alias. Add .dart_tool to gitignore --- pkgs/stream_transform/.gitignore | 1 + pkgs/stream_transform/CHANGELOG.md | 5 ++ pkgs/stream_transform/README.md | 8 +- pkgs/stream_transform/lib/src/concat.dart | 85 +----------------- .../stream_transform/lib/src/followed_by.dart | 86 +++++++++++++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- ...{concat_test.dart => followd_by_test.dart} | 0 8 files changed, 102 insertions(+), 86 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/followed_by.dart rename pkgs/stream_transform/test/{concat_test.dart => followd_by_test.dart} (100%) diff --git a/pkgs/stream_transform/.gitignore b/pkgs/stream_transform/.gitignore index 47f11e5fc..bfffcc6c6 100644 --- a/pkgs/stream_transform/.gitignore +++ b/pkgs/stream_transform/.gitignore @@ -1,4 +1,5 @@ .pub/ +.dart_tool/ build/ packages pubspec.lock diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index fe8eaa27b..0e0cfaa6a 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.11 + +- Renamed `concat` as `followedBy` to match the naming of `Iterable.followedBy`. + `concat` is now deprecated. + ## 0.0.10 - Updates to support Dart 2.0 core library changes (wave diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index b504e6cee..5e59fc988 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -19,15 +19,15 @@ the most recent value. Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. -# concat - -Appends the values of a stream after another stream finishes. - # debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. +# followedBy + +Appends the values of a stream after another stream finishes. + # merge, mergeAll Interleaves events from multiple streams into a single stream. diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart index bf0559d43..565a2906c 100644 --- a/pkgs/stream_transform/lib/src/concat.dart +++ b/pkgs/stream_transform/lib/src/concat.dart @@ -1,86 +1,9 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. - import 'dart:async'; -/// Starts emitting values from [next] after the original stream is complete. -/// -/// If the initial stream never finishes, the [next] stream will never be -/// listened to. -/// -/// If a single-subscription is concatted to the end of a broadcast stream it -/// may be listened to and never canceled. -/// -/// If a broadcast stream is concatted to any other stream it will miss any -/// events which occur before the first stream is done. If a broadcast stream is -/// concatted to a single-subscription stream, pausing the stream while it is -/// listening to the second stream will cause events to be dropped rather than -/// buffered. -StreamTransformer concat(Stream next) => new _Concat(next); - -class _Concat extends StreamTransformerBase { - final Stream _next; - - _Concat(this._next); - - @override - Stream bind(Stream first) { - var controller = first.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); - - var next = first.isBroadcast && !_next.isBroadcast - ? _next.asBroadcastStream() - : _next; - - StreamSubscription subscription; - var currentStream = first; - var firstDone = false; - var secondDone = false; - - Function currentDoneHandler; - - listen() { - subscription = currentStream.listen(controller.add, - onError: controller.addError, onDone: () => currentDoneHandler()); - } - - onSecondDone() { - secondDone = true; - controller.close(); - } - - onFirstDone() { - firstDone = true; - currentStream = next; - currentDoneHandler = onSecondDone; - listen(); - } - - currentDoneHandler = onFirstDone; +import 'followed_by.dart'; - controller.onListen = () { - if (subscription != null) return; - listen(); - if (!first.isBroadcast) { - controller.onPause = () { - if (!firstDone || !next.isBroadcast) return subscription.pause(); - subscription.cancel(); - subscription = null; - }; - controller.onResume = () { - if (!firstDone || !next.isBroadcast) return subscription.resume(); - listen(); - }; - } - controller.onCancel = () { - if (secondDone) return null; - var toCancel = subscription; - subscription = null; - return toCancel.cancel(); - }; - }; - return controller.stream; - } -} +@Deprecated('Use followedBy instead') +StreamTransformer concat(Stream next) => followedBy(next); diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart new file mode 100644 index 000000000..22f6945e0 --- /dev/null +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -0,0 +1,86 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Starts emitting values from [next] after the original stream is complete. +/// +/// If the initial stream never finishes, the [next] stream will never be +/// listened to. +/// +/// If a single-subscription follows the a broadcast stream it may be listened +/// to and never canceled. +/// +/// If a broadcast stream follows any other stream it will miss any events which +/// occur before the first stream is done. If a broadcast stream follows a +/// single-subscription stream, pausing the stream while it is listening to the +/// second stream will cause events to be dropped rather than buffered. +StreamTransformer followedBy(Stream next) => + new _FollowedBy(next); + +class _FollowedBy extends StreamTransformerBase { + final Stream _next; + + _FollowedBy(this._next); + + @override + Stream bind(Stream first) { + var controller = first.isBroadcast + ? new StreamController.broadcast(sync: true) + : new StreamController(sync: true); + + var next = first.isBroadcast && !_next.isBroadcast + ? _next.asBroadcastStream() + : _next; + + StreamSubscription subscription; + var currentStream = first; + var firstDone = false; + var secondDone = false; + + Function currentDoneHandler; + + listen() { + subscription = currentStream.listen(controller.add, + onError: controller.addError, onDone: () => currentDoneHandler()); + } + + onSecondDone() { + secondDone = true; + controller.close(); + } + + onFirstDone() { + firstDone = true; + currentStream = next; + currentDoneHandler = onSecondDone; + listen(); + } + + currentDoneHandler = onFirstDone; + + controller.onListen = () { + if (subscription != null) return; + listen(); + if (!first.isBroadcast) { + controller.onPause = () { + if (!firstDone || !next.isBroadcast) return subscription.pause(); + subscription.cancel(); + subscription = null; + }; + controller.onResume = () { + if (!firstDone || !next.isBroadcast) return subscription.resume(); + listen(); + }; + } + controller.onCancel = () { + if (secondDone) return null; + var toCancel = subscription; + subscription = null; + return toCancel.cancel(); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index dced90813..170a5be91 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -8,6 +8,7 @@ export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/concat.dart'; export 'src/debounce.dart'; +export 'src/followed_by.dart'; export 'src/merge.dart'; export 'src/scan.dart'; export 'src/start_with.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 06d650d85..7087b009c 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.10 +version: 0.0.11 environment: sdk: ">=2.0.0-dev.20.0 <2.0.0" diff --git a/pkgs/stream_transform/test/concat_test.dart b/pkgs/stream_transform/test/followd_by_test.dart similarity index 100% rename from pkgs/stream_transform/test/concat_test.dart rename to pkgs/stream_transform/test/followd_by_test.dart From 9d17768f15b60d0a49254ddb9720ec7666682c3f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 26 Mar 2018 15:06:52 -0700 Subject: [PATCH 0395/1215] Clean up internal uses of concat (dart-lang/stream_transform#44) --- pkgs/stream_transform/lib/src/start_with.dart | 4 ++-- pkgs/stream_transform/test/followd_by_test.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart index a98eb6d8a..943474811 100644 --- a/pkgs/stream_transform/lib/src/start_with.dart +++ b/pkgs/stream_transform/lib/src/start_with.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'bind.dart'; -import 'concat.dart'; +import 'followed_by.dart'; /// Emits [initial] before any values from the original stream. /// @@ -31,5 +31,5 @@ StreamTransformer startWithStream(Stream initial) => if (values.isBroadcast && !initial.isBroadcast) { initial = initial.asBroadcastStream(); } - return initial.transform(concat(values)); + return initial.transform(followedBy(values)); }); diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 37a46f700..2bff18c1b 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -14,7 +14,7 @@ void main() { }; for (var firstType in streamTypes.keys) { for (var secondType in streamTypes.keys) { - group('concat [$firstType] with [$secondType]', () { + group('followedBy [$firstType] with [$secondType]', () { StreamController first; StreamController second; @@ -45,7 +45,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = first.stream.transform(concat(second.stream)); + transformed = first.stream.transform(followedBy(second.stream)); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; From 7b0392bef85ec2f8d61ee1221e0b6c774e47cf0f Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 11:57:37 -0700 Subject: [PATCH 0396/1215] make sure the inner sink is properly typed in JsonDocumentTransformer.bind --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 86b9ae71c..40e5155a9 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.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. +import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; @@ -35,9 +36,10 @@ class JsonDocumentTransformer JsonDocumentTransformer._(this._codec); - StreamChannel bind(StreamChannel channel) { + StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers(handleData: (data, sink) { + var sink = new StreamSinkTransformer.fromHandlers( + handleData: (Object data, EventSink sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); return new StreamChannel.withCloseGuarantee(stream, sink); From 4e385426b1e7c144406f515903f093ec2120f83e Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 11:59:09 -0700 Subject: [PATCH 0397/1215] update pubspec/changelog --- pkgs/stream_channel/CHANGELOG.md | 5 +++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 093a2421d..d15b0c032 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.4+1 + +* Fix an issue with `JsonDocumentTransformer.bind` where it created an internal + stream channel which didn't get a properly inferred type for its `sink`. + ## 1.6.4 * Fix a race condition in `MultiChannel` where messages from a remote virtual diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 393e60f3b..5abd523ee 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4 +version: 1.6.4+5 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 3b092fb932e61a7cbcd70f25dfe75b7b1d1fa80a Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 12:11:25 -0700 Subject: [PATCH 0398/1215] fix pubspec version to match changelog --- pkgs/stream_channel/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5abd523ee..09179771c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4+5 +version: 1.6.4+1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From c4dcc8d1a0a39fec7d05346f87531b96c50b4573 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 16 Apr 2018 13:48:36 -0700 Subject: [PATCH 0399/1215] code review updates --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/lib/src/json_document_transformer.dart | 4 ++-- pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index d15b0c032..4813e9a1f 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.6.4+1 +## 1.6.5 * Fix an issue with `JsonDocumentTransformer.bind` where it created an internal stream channel which didn't get a properly inferred type for its `sink`. diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 40e5155a9..533d23823 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -38,8 +38,8 @@ class JsonDocumentTransformer StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers( - handleData: (Object data, EventSink sink) { + var sink = new StreamSinkTransformer.fromHandlers( + handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); return new StreamChannel.withCloseGuarantee(stream, sink); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 09179771c..9221866dc 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.4+1 +version: 1.6.5 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 278de144374bce9c49f16384f6f428d01b02e342 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 17 Apr 2018 14:13:30 -0700 Subject: [PATCH 0400/1215] Upgrade some hints to errors (dart-lang/stream_channel#19) These prevent building internally. Fix an unused import. --- pkgs/stream_channel/analysis_options.yaml | 6 ++++++ pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index a10d4c5a0..743cc902d 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,2 +1,8 @@ analyzer: strong-mode: true + # These are errors when building in Google + errors: + unused_import: error + unused_element: error + unused_local_variable: error + dead_code: error diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 533d23823..6377eeda7 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; From 51947287a3bf2323d86933187c51c203d48ec0d6 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 08:02:29 -0700 Subject: [PATCH 0401/1215] fix tests for dart 2 --- pkgs/stream_channel/lib/src/guarantee_channel.dart | 2 +- pkgs/stream_channel/test/json_document_transformer_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index f18cbb973..ba79ed9bc 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -39,7 +39,7 @@ class GuaranteeChannel extends StreamChannelMixin { // to single-subscription. if (innerStream.isBroadcast) { innerStream = - innerStream.transform(const SingleSubscriptionTransformer()); + innerStream.transform(new SingleSubscriptionTransformer()); } _streamController = new StreamController( diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 22bb83009..b55a11887 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -13,8 +13,8 @@ void main() { var sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); + streamController = new StreamController(); + sinkController = new StreamController(); channel = new StreamChannel(streamController.stream, sinkController.sink); }); From b32ad837ec902416a1846bde58a307e57d3e8fa8 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 08:06:51 -0700 Subject: [PATCH 0402/1215] update changelog/pubspec --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4813e9a1f..a2404d27e 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.6 + +* Fix a Dart2 issue with inner stream transformation in `GuaranteeChannel`. + ## 1.6.5 * Fix an issue with `JsonDocumentTransformer.bind` where it created an internal diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9221866dc..c121f5f13 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.5 +version: 1.6.6 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From 99325e82bfb017f4edd275bdb7a159ef94a638e2 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 1 May 2018 09:58:15 -0700 Subject: [PATCH 0403/1215] fix some stream channel tests --- pkgs/stream_channel/.gitignore | 1 + .../test/stream_channel_test.dart | 43 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pkgs/stream_channel/.gitignore b/pkgs/stream_channel/.gitignore index 25a1df332..1447012ea 100644 --- a/pkgs/stream_channel/.gitignore +++ b/pkgs/stream_channel/.gitignore @@ -1,4 +1,5 @@ .buildlog +.dart_tool/ .DS_Store .idea .pub/ diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index b8ebcbd85..c29002fdf 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -10,9 +10,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var channel; + StreamController streamController; + StreamController sinkController; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); @@ -58,36 +58,35 @@ void main() { }); test("transformStream() transforms only the stream", () async { - var transformed = channel.transformStream(UTF8.decoder); + var transformed = + channel.cast().transformStream(const LineSplitter()); - streamController.add([102, 111, 111, 98, 97, 114]); + streamController.add("hello world"); + streamController.add(" what\nis"); + streamController.add("\nup"); streamController.close(); - expect(await transformed.stream.toList(), equals(["foobar"])); + expect(await transformed.stream.toList(), + equals(["hello world what", "is", "up"])); - transformed.sink.add("fblthp"); + transformed.sink.add("fbl\nthp"); transformed.sink.close(); - expect(sinkController.stream.toList(), completion(equals(["fblthp"]))); + expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); }); test("transformSink() transforms only the sink", () async { - var transformed = channel.transformSink( - new StreamSinkTransformer.fromStreamTransformer(UTF8.encoder)); + var transformed = channel.cast().transformSink( + new StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); - streamController.add([102, 111, 111, 98, 97, 114]); + streamController.add("fbl\nthp"); streamController.close(); - expect( - await transformed.stream.toList(), - equals([ - [102, 111, 111, 98, 97, 114] - ])); + expect(await transformed.stream.toList(), equals(["fbl\nthp"])); - transformed.sink.add("fblthp"); + transformed.sink.add("hello world"); + transformed.sink.add(" what\nis"); + transformed.sink.add("\nup"); transformed.sink.close(); - expect( - sinkController.stream.toList(), - completion(equals([ - [102, 98, 108, 116, 104, 112] - ]))); + expect(sinkController.stream.toList(), + completion(equals(["hello world what", "is", "up"]))); }); test("changeStream() changes the stream", () { From 509e7364b58c6db8b8ecd1e7dd358383d63561f7 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 2 May 2018 12:51:37 -0700 Subject: [PATCH 0404/1215] Fix a remaining Dart 2 issue (dart-lang/stream_channel#23) We had some unnecessary typed wrappers that were interfering with runtime type arguments. Closes dart-lang/stream_channel#22 --- pkgs/stream_channel/CHANGELOG.md | 4 +++- .../stream_channel/lib/src/stream_channel_transformer.dart | 7 ++----- pkgs/stream_channel/test/stream_channel_test.dart | 5 +++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index a2404d27e..014b2fcc3 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,8 @@ ## 1.6.6 -* Fix a Dart2 issue with inner stream transformation in `GuaranteeChannel`. +* Fix a Dart 2 issue with inner stream transformation in `GuaranteeChannel`. + +* Fix a Dart 2 issue with `StreamChannelTransformer.fromCodec()`. ## 1.6.5 diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 1a4afcae2..4fcd3cd69 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -57,11 +57,8 @@ class StreamChannelTransformer { /// All input to the inner channel's sink is encoded using [Codec.encoder], /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) - : this( - typedStreamTransformer(codec.decoder), - StreamSinkTransformer.typed( - new StreamSinkTransformer.fromStreamTransformer( - codec.encoder))); + : this(codec.decoder, + new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); /// Transforms the events sent to and emitted by [channel]. /// diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index c29002fdf..4ec84bc26 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,8 +41,9 @@ void main() { }); test("transform() transforms the channel", () async { - var transformed = - channel.transform(new StreamChannelTransformer.fromCodec(UTF8)); + var transformed = channel + .cast>() + .transform(new StreamChannelTransformer.fromCodec(UTF8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 9a1991971381e2a2ecd7d7285bb5f74f55e52dfe Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Sun, 20 May 2018 13:28:26 +0100 Subject: [PATCH 0405/1215] Stop testing IsolateChannel on browsers (dart-lang/stream_channel#24) --- pkgs/stream_channel/test/isolate_channel_test.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 66834cace..8f3318469 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -2,6 +2,8 @@ // 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. +@TestOn('vm') + import 'dart:async'; import 'dart:isolate'; From f147ac8d3021fbc81ad977aeabf8be167c47dd1c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 23 May 2018 12:47:58 -0700 Subject: [PATCH 0406/1215] Add types required in Dart2 and prepare for release (dart-lang/watcher#56) Fixes https://github.com/dart-lang/watcher/issues/55 --- pkgs/watcher/CHANGELOG.md | 4 ++++ .../lib/src/directory_watcher/mac_os.dart | 17 +++++++++-------- .../lib/src/directory_watcher/windows.dart | 17 +++++++++-------- pkgs/watcher/lib/src/utils.dart | 4 ++-- pkgs/watcher/pubspec.yaml | 2 +- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 8f1ffc387..fe30bc6cb 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+8 + +* Fix Dart 2.0 type issues on Mac and Windows. + # 0.9.7+7 * Updates to support Dart 2.0 core library changes (wave 2.2). diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 759765f72..5ad99847d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -171,7 +171,7 @@ class _MacOSDirectoryWatcher /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it /// contain any events relating to [path]. Map> _sortEvents(List batch) { - var eventsForPaths = {}; + var eventsForPaths = >{}; // FSEvents can report past events, including events on the root directory // such as it being created. We want to ignore these. If the directory is @@ -182,20 +182,21 @@ class _MacOSDirectoryWatcher // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return new Set(); + if (!event.isDirectory) return new Set(); if (event is FileSystemMoveEvent) { - return new Set.from([event.path, event.destination]); + return new Set.from([event.path, event.destination]); } - return new Set.from([event.path]); + return new Set.from([event.path]); })); - isInModifiedDirectory(path) => + isInModifiedDirectory(String path) => directories.any((dir) => path != dir && path.startsWith(dir)); - addEvent(path, event) { + addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - var set = eventsForPaths.putIfAbsent(path, () => new Set()); - set.add(event); + eventsForPaths + .putIfAbsent(path, () => new Set()) + .add(event); } for (var event in batch) { diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 3352b68fe..db9ca8328 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -216,26 +216,27 @@ class _WindowsDirectoryWatcher /// The returned events won't contain any [FileSystemMoveEvent]s, nor will it /// contain any events relating to [path]. Map> _sortEvents(List batch) { - var eventsForPaths = {}; + var eventsForPaths = >{}; // Events within directories that already have events are superfluous; the // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return new Set(); + if (!event.isDirectory) return new Set(); if (event is FileSystemMoveEvent) { - return new Set.from([event.path, event.destination]); + return new Set.from([event.path, event.destination]); } - return new Set.from([event.path]); + return new Set.from([event.path]); })); - isInModifiedDirectory(path) => + isInModifiedDirectory(String path) => directories.any((dir) => path != dir && path.startsWith(dir)); - addEvent(path, event) { + addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - var set = eventsForPaths.putIfAbsent(path, () => new Set()); - set.add(event); + eventsForPaths + .putIfAbsent(path, () => new Set()) + .add(event); } for (var event in batch) { diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 0b2f79961..62d8e0ff8 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -19,8 +19,8 @@ bool isDirectoryNotFoundException(error) { } /// Returns the union of all elements in each set in [sets]. -Set unionAll(Iterable sets) => - sets.fold(new Set(), (union, set) => union.union(set)); +Set unionAll(Iterable> sets) => + sets.fold(new Set(), (union, set) => union.union(set)); /// Returns a buffered stream that will emit the same values as the stream /// returned by [future] once [future] completes. diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index daea75b00..3cb964370 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+7 +version: 0.9.7+8 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > From 3d01b6e0703832511cfb97d8a9646aed58281cd8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 23 May 2018 16:08:06 -0700 Subject: [PATCH 0407/1215] Update .travis.yml for branch change (dart-lang/watcher#57) --- pkgs/watcher/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index c9774304b..254764448 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -8,7 +8,7 @@ dart_task: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, 0.9.7+x] + only: [master] cache: directories: From 83e552b13deb0fcc8b06f36f38147a3a1200812a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 24 May 2018 11:12:09 -0700 Subject: [PATCH 0408/1215] Explicitly handle null callback for tap (dart-lang/stream_transform#45) This does not change visible behavior since a null callback would have previously been an ignored exception. Rename the argument to `onValue` for consistency and expand the doc comment. --- pkgs/stream_transform/lib/src/tap.dart | 21 +++++++++++++++------ pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/tap_test.dart | 5 +++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 804664004..bfed97ceb 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -8,16 +8,25 @@ import 'from_handlers.dart'; /// Taps into a Stream to allow additional handling on a single-subscriber /// stream without first wrapping as a broadcast stream. /// -/// The callback will be called with every value from the stream before it is -/// forwarded to listeners on the stream. Errors from the callbacks are ignored. +/// The [onValue] callback will be called with every value from the original +/// stream before it is forwarded to listeners on the resulting stream. May be +/// null if only [onError] or [onDone] callbacks are needed. /// -/// The tapped stream may not emit any values until the result stream has a -/// listener, and may be canceled only by the listener. -StreamTransformer tap(void fn(T value), +/// The [onError] callback will be called with every error from the original +/// stream before it is forwarded to listeners on the resulting stream. +/// +/// The [onDone] callback will be called after the original stream closes and +/// before the resulting stream is closed. +/// +/// Errors from any of the callbacks are ignored. +/// +/// The callbacks may not be called until the tapped stream has a listener, and +/// may not be called after the listener has canceled the subscription. +StreamTransformer tap(void onValue(T value), {void onError(error, stackTrace), void onDone()}) => fromHandlers(handleData: (value, sink) { try { - fn(value); + onValue?.call(value); } catch (_) {/*Ignore*/} sink.add(value); }, handleError: (error, stackTrace, sink) { diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 7087b009c..dc4525b2b 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.11 +version: 0.0.12-dev environment: sdk: ">=2.0.0-dev.20.0 <2.0.0" diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index f3ef8e32c..ffdabba2b 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -113,4 +113,9 @@ void main() { expect(emittedValues1, [1]); expect(emittedValues2, [1]); }); + + test('allows null callback', () async { + var stream = new Stream.fromIterable([1, 2, 3]); + await stream.transform(tap(null)).last; + }); } From 2e9888bc2d3cdf749077e3c3e596c6497666eb58 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 24 May 2018 11:16:42 -0700 Subject: [PATCH 0409/1215] Use latest conventions for Travis (dart-lang/stream_transform#46) - Only test on master - Remove sudo option since it's default --- pkgs/stream_transform/.travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 65c7fc39e..70dd97752 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -1,5 +1,6 @@ language: dart -sudo: false +branches: + only: [master] dart: - dev cache: From c6badcd94f96893e13be3f3dcff9c866780d99cb Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 31 May 2018 14:00:40 -0700 Subject: [PATCH 0410/1215] Initial commit --- pkgs/pubspec_parse/.gitignore | 4 ++ pkgs/pubspec_parse/README.md | 5 ++ pkgs/pubspec_parse/analysis_options.yaml | 76 ++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 pkgs/pubspec_parse/.gitignore create mode 100644 pkgs/pubspec_parse/README.md create mode 100644 pkgs/pubspec_parse/analysis_options.yaml diff --git a/pkgs/pubspec_parse/.gitignore b/pkgs/pubspec_parse/.gitignore new file mode 100644 index 000000000..ec8eae3f1 --- /dev/null +++ b/pkgs/pubspec_parse/.gitignore @@ -0,0 +1,4 @@ +# Don’t commit the following directories created by pub. +.dart_tool/ +.packages +pubspec.lock diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md new file mode 100644 index 000000000..b355cef76 --- /dev/null +++ b/pkgs/pubspec_parse/README.md @@ -0,0 +1,5 @@ +## Features and bugs + +Please file feature requests and bugs at the [issue tracker]. + +[issue tracker]: https://github.com/dart-lang/pubspec_parse/issues diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml new file mode 100644 index 000000000..8521d7b7d --- /dev/null +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -0,0 +1,76 @@ +analyzer: + strong-mode: + implicit-casts: false + errors: + dead_code: error + override_on_non_overriding_method: error + unused_element: error + unused_import: error + unused_local_variable: error +linter: + rules: + - annotate_overrides + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_types_as_parameter_names + - avoid_unused_constructor_parameters + - await_only_futures + - camel_case_types + - cancel_subscriptions + #- cascade_invocations + - comment_references + - constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - library_names + - library_prefixes + - list_remove_unrelated_type + - no_adjacent_strings_in_list + - no_duplicate_case_values + - non_constant_identifier_names + - omit_local_variable_types + - only_throw_errors + - overridden_fields + #- package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_contains + - prefer_final_fields + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_single_quotes + - prefer_typing_uninitialized_variables + - recursive_getters + - slash_for_doc_comments + - super_goes_last + - test_types_in_equals + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unawaited_futures + - unnecessary_brace_in_string_interps + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_null_aware_assignments + - unnecessary_statements + - unnecessary_this + - unrelated_type_equality_checks + - valid_regexps From dbe4ec143efd91a28d76a89f845669adc8ec7095 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Fri, 1 Jun 2018 14:57:12 +0200 Subject: [PATCH 0411/1215] Remove upper case constants (dart-lang/stream_channel#17) * Remove usage of upper-case constants. * update SDK version * remove stable from Travis config --- pkgs/stream_channel/.travis.yml | 2 -- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- pkgs/stream_channel/test/json_document_transformer_test.dart | 2 +- pkgs/stream_channel/test/stream_channel_test.dart | 2 +- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index a9510326d..45359fb40 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -2,8 +2,6 @@ language: dart dart: - dev - - stable - dart_task: - test: --platform vm - test: --platform firefox -j 1 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 014b2fcc3..eafdb8122 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.7 + +* Update SDK version to 2.0.0-dev.17.0. + ## 1.6.6 * Fix a Dart 2 issue with inner stream transformation in `GuaranteeChannel`. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c121f5f13..47e24c2f7 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,10 @@ name: stream_channel -version: 1.6.6 +version: 1.6.7-dev description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=1.21.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: async: '>=1.11.0 <3.0.0' stack_trace: '^1.0.0' diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index b55a11887..d6fd72b96 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -29,7 +29,7 @@ void main() { var transformed = channel.transform(jsonDocument); transformed.sink.add({"foo": "bar"}); expect(sinkController.stream.first, - completion(equals(JSON.encode({"foo": "bar"})))); + completion(equals(jsonEncode({"foo": "bar"})))); }); test("supports the reviver function", () { diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 4ec84bc26..dbe421195 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -43,7 +43,7 @@ void main() { test("transform() transforms the channel", () async { var transformed = channel .cast>() - .transform(new StreamChannelTransformer.fromCodec(UTF8)); + .transform(new StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); From 541969ec35ad2e3f86bb0bda260723d9a8801a4d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 09:22:24 -0700 Subject: [PATCH 0412/1215] Add initial package implementation (dart-lang/pubspec_parse#3) - Pubspec class - Dependency classes - top-level parsePubspec function --- pkgs/pubspec_parse/.travis.yml | 18 +++ pkgs/pubspec_parse/CHANGELOG.md | 4 + pkgs/pubspec_parse/build.yaml | 17 +++ pkgs/pubspec_parse/dart_test.yaml | 3 + pkgs/pubspec_parse/lib/pubspec_parse.dart | 14 ++ pkgs/pubspec_parse/lib/src/dependency.dart | 144 ++++++++++++++++++ pkgs/pubspec_parse/lib/src/errors.dart | 87 +++++++++++ pkgs/pubspec_parse/lib/src/functions.dart | 34 +++++ pkgs/pubspec_parse/lib/src/pubspec.dart | 103 +++++++++++++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 38 +++++ pkgs/pubspec_parse/pubspec.yaml | 20 +++ pkgs/pubspec_parse/test/dependency_test.dart | 128 ++++++++++++++++ .../pubspec_parse/test/ensure_build_test.dart | 63 ++++++++ pkgs/pubspec_parse/test/parse_test.dart | 95 ++++++++++++ pkgs/pubspec_parse/test/test_utils.dart | 74 +++++++++ 15 files changed, 842 insertions(+) create mode 100644 pkgs/pubspec_parse/.travis.yml create mode 100644 pkgs/pubspec_parse/CHANGELOG.md create mode 100644 pkgs/pubspec_parse/build.yaml create mode 100644 pkgs/pubspec_parse/dart_test.yaml create mode 100644 pkgs/pubspec_parse/lib/pubspec_parse.dart create mode 100644 pkgs/pubspec_parse/lib/src/dependency.dart create mode 100644 pkgs/pubspec_parse/lib/src/errors.dart create mode 100644 pkgs/pubspec_parse/lib/src/functions.dart create mode 100644 pkgs/pubspec_parse/lib/src/pubspec.dart create mode 100644 pkgs/pubspec_parse/lib/src/pubspec.g.dart create mode 100644 pkgs/pubspec_parse/pubspec.yaml create mode 100644 pkgs/pubspec_parse/test/dependency_test.dart create mode 100644 pkgs/pubspec_parse/test/ensure_build_test.dart create mode 100644 pkgs/pubspec_parse/test/parse_test.dart create mode 100644 pkgs/pubspec_parse/test/test_utils.dart diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml new file mode 100644 index 000000000..ea5469401 --- /dev/null +++ b/pkgs/pubspec_parse/.travis.yml @@ -0,0 +1,18 @@ +language: dart + +dart: + - dev + +dart_task: + - test: -x presubmit-only + - test: --run-skipped -t presubmit-only + - dartfmt + - dartanalyzer: --fatal-infos --fatal-warnings . + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md new file mode 100644 index 000000000..39d51431c --- /dev/null +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -0,0 +1,4 @@ +## 0.1.0 + +- Initial release including the `Pubspec` class and a top-level `parsePubspec` + function. diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml new file mode 100644 index 000000000..ec706e421 --- /dev/null +++ b/pkgs/pubspec_parse/build.yaml @@ -0,0 +1,17 @@ +# Read about `build.yaml` at https://pub.dartlang.org/packages/build_config +# To update generated code, run `pub run build_runner build` +targets: + $default: + builders: + json_serializable: + generate_for: + - lib/src/pubspec.dart + options: + any_map: true + checked: true + header: |+ + // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file + // 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. + + // GENERATED CODE - DO NOT MODIFY BY HAND diff --git a/pkgs/pubspec_parse/dart_test.yaml b/pkgs/pubspec_parse/dart_test.yaml new file mode 100644 index 000000000..1d7ac69cc --- /dev/null +++ b/pkgs/pubspec_parse/dart_test.yaml @@ -0,0 +1,3 @@ +tags: + presubmit-only: + skip: "Should only be run during presubmit" diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart new file mode 100644 index 000000000..3339982b1 --- /dev/null +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -0,0 +1,14 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +export 'src/dependency.dart' + show + Dependency, + HostedDependency, + GitDependency, + SdkDependency, + PathDependency; +export 'src/errors.dart' show ParsedYamlException; +export 'src/functions.dart' show parsePubspec; +export 'src/pubspec.dart' show Pubspec; diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart new file mode 100644 index 000000000..8c9ab15b5 --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -0,0 +1,144 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:json_annotation/json_annotation.dart'; +import 'package:pub_semver/pub_semver.dart'; + +abstract class Dependency { + Dependency._(); + + /// Returns `null` if the data could not be parsed. + factory Dependency.fromJson(dynamic data) { + if (data == null) { + return new HostedDependency(VersionConstraint.any); + } else if (data is String) { + return new HostedDependency(new VersionConstraint.parse(data)); + } else if (data is Map) { + try { + return new Dependency._fromMap(data); + } on ArgumentError catch (e) { + throw new CheckedFromJsonException( + data, e.name, 'Dependency', e.message.toString()); + } + } + + return null; + } + + factory Dependency._fromMap(Map data) { + if (data.entries.isEmpty) { + // TODO: provide list of supported keys? + throw new CheckedFromJsonException( + data, null, 'Dependency', 'Must provide at least one key.'); + } + + if (data.containsKey('sdk')) { + return new SdkDependency.fromData(data); + } + + if (data.entries.length > 1) { + throw new CheckedFromJsonException( + data, + data.keys.skip(1).first as String, + 'Dependency', + 'Expected only one key.'); + } + + var entry = data.entries.single; + var key = entry.key as String; + + if (entry.value == null) { + throw new CheckedFromJsonException( + data, key, 'Dependency', 'Cannot be null.'); + } + + switch (key) { + case 'path': + return new PathDependency.fromData(entry.value); + case 'git': + return new GitDependency.fromData(entry.value); + } + + return null; + } + + String get _info; + + @override + String toString() => '$runtimeType: $_info'; +} + +class SdkDependency extends Dependency { + final String name; + final VersionConstraint version; + + SdkDependency(this.name, {this.version}) : super._(); + + factory SdkDependency.fromData(Map data) { + VersionConstraint version; + if (data.containsKey('version')) { + version = new VersionConstraint.parse(data['version'] as String); + } + return new SdkDependency(data['sdk'] as String, version: version); + } + + @override + String get _info => name; +} + +class GitDependency extends Dependency { + final Uri url; + final String ref; + final String path; + + GitDependency(this.url, this.ref, this.path) : super._(); + + factory GitDependency.fromData(Object data) { + String url; + String path; + String ref; + + if (data is String) { + url = data; + } else if (data is Map) { + url = data['url'] as String; + path = data['path'] as String; + ref = data['ref'] as String; + } else { + throw new ArgumentError.value(data, 'git', 'Must be a String or a Map.'); + } + + // TODO: validate `url` is a valid URI + return new GitDependency(Uri.parse(url), ref, path); + } + + @override + String get _info => 'url@$url'; +} + +class PathDependency extends Dependency { + final String path; + + PathDependency(this.path) : super._(); + + factory PathDependency.fromData(Object data) { + if (data is String) { + return new PathDependency(data); + } + throw new ArgumentError.value(data, 'path', 'Must be a String.'); + } + + @override + String get _info => 'path@$path'; +} + +// TODO: support explicit host? +class HostedDependency extends Dependency { + final VersionConstraint constraint; + + HostedDependency(this.constraint) : super._(); + + @override + String get _info => constraint.toString(); +} diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart new file mode 100644 index 000000000..9b1489cf4 --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -0,0 +1,87 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:json_annotation/json_annotation.dart'; +import 'package:yaml/yaml.dart'; + +ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => + new ParsedYamlException._(message, yamlNode); + +ParsedYamlException parsedYamlExceptionFromError( + CheckedFromJsonException error, StackTrace stack) { + var innerError = error.innerError; + if (innerError is BadKeyException) { + var map = innerError.map; + if (map is YamlMap) { + var key = map.nodes.keys.singleWhere((key) { + return (key as YamlScalar).value == innerError.key; + }, orElse: () => null); + + if (key is YamlScalar) { + return new ParsedYamlException._(innerError.message, key, + innerError: error, innerStack: stack); + } + } + } else if (innerError is ParsedYamlException) { + return innerError; + } + + var yamlMap = error.map as YamlMap; + var yamlNode = yamlMap.nodes[error.key]; + + String message; + if (yamlNode == null) { + assert(error.message != null); + message = error.message; + yamlNode = yamlMap; + } else { + if (error.message == null) { + message = 'Unsupported value for `${error.key}`.'; + } else { + message = error.message.toString(); + } + } + + return new ParsedYamlException._(message, yamlNode, + innerError: error, innerStack: stack); +} + +/// Thrown when parsing a YAML document fails. +class ParsedYamlException implements Exception { + /// Describes the nature of the parse failure. + final String message; + + /// The [YamlNode] that corresponds to the exception. + final YamlNode yamlNode; + + /// If this exception was thrown as a result of another error, + /// contains the source error object. + final Object innerError; + + /// If this exception was thrown as a result of another error, + /// contains the corresponding [StackTrace]. + final StackTrace innerStack; + + ParsedYamlException._(this.message, this.yamlNode, + {this.innerError, this.innerStack}); + + /// Returns [message] formatted with source information provided by + /// [yamlNode]. + String get formatMessage => yamlNode.span.message(message); + + @override + String toString() => message; +} + +/// Package-private class representing an invalid key. +/// +/// Used instead of [CheckedFromJsonException] when highlighting a bad [key] +/// is desired, instead of the associated value. +class BadKeyException implements Exception { + final Map map; + final String key; + final String message; + + BadKeyException(this.map, this.key, this.message); +} diff --git a/pkgs/pubspec_parse/lib/src/functions.dart b/pkgs/pubspec_parse/lib/src/functions.dart new file mode 100644 index 000000000..84ef35cc0 --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/functions.dart @@ -0,0 +1,34 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:json_annotation/json_annotation.dart'; +import 'package:yaml/yaml.dart'; + +import 'errors.dart'; +import 'pubspec.dart'; + +/// If [sourceUrl] is passed, it's used as the URL from which the YAML +/// originated for error reporting. It can be a [String], a [Uri], or `null`. +Pubspec parsePubspec(String yaml, {sourceUrl}) { + var item = loadYaml(yaml, sourceUrl: sourceUrl); + + if (item == null) { + throw new ArgumentError.notNull('yaml'); + } + + if (item is! YamlMap) { + if (item is YamlNode) { + throw parsedYamlException('Does not represent a YAML map.', item); + } + + throw new ArgumentError.value( + yaml, 'yaml', 'Does not represent a YAML map.'); + } + + try { + return new Pubspec.fromJson(item as YamlMap); + } on CheckedFromJsonException catch (error, stack) { + throw parsedYamlExceptionFromError(error, stack); + } +} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart new file mode 100644 index 000000000..6a5c3a6ad --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -0,0 +1,103 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:json_annotation/json_annotation.dart'; +import 'package:pub_semver/pub_semver.dart'; + +import 'dependency.dart'; +import 'errors.dart'; + +part 'pubspec.g.dart'; + +@JsonSerializable(createToJson: false) +class Pubspec { + final String name; + final String homepage; + final String documentation; + final String description; + final String author; + final List authors; + + @JsonKey(fromJson: _environmentMap) + final Map environment; + + List get allAuthors { + var values = []; + if (author != null) { + values.add(author); + } + values.addAll(authors); + return values; + } + + @JsonKey(fromJson: _versionFromString) + final Version version; + + @JsonKey(fromJson: _getDeps, nullable: false) + final Map dependencies; + + @JsonKey(name: 'dev_dependencies', fromJson: _getDeps, nullable: false) + final Map devDependencies; + + @JsonKey(name: 'dependency_overrides', fromJson: _getDeps, nullable: false) + final Map dependencyOverrides; + + Pubspec( + this.name, { + this.version, + this.author, + this.environment, + List authors, + this.homepage, + this.documentation, + this.description, + Map dependencies, + Map devDependencies, + Map dependencyOverrides, + }) : this.authors = authors ?? const [], + this.dependencies = dependencies ?? const {}, + this.devDependencies = devDependencies ?? const {}, + this.dependencyOverrides = dependencyOverrides ?? const {} { + if (name == null || name.isEmpty) { + throw new ArgumentError.value(name, 'name', '"name" cannot be empty.'); + } + } + + factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); +} + +// TODO: maybe move this to `dependencies.dart`? +Map _getDeps(Map source) => + source?.map((k, v) { + var key = k as String; + var value = new Dependency.fromJson(v); + if (value == null) { + throw new CheckedFromJsonException( + source, key, 'Pubspec', 'Not a valid dependency value.'); + } + return new MapEntry(key, value); + }) ?? + {}; + +Version _versionFromString(String input) => new Version.parse(input); + +Map _environmentMap(Map source) => + source.map((key, value) { + if (key == 'dart') { + // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 + // 'dart' is not allowed as a key! + throw new BadKeyException( + source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); + } + + VersionConstraint constraint; + try { + constraint = new VersionConstraint.parse(value as String); + } on FormatException catch (e) { + throw new CheckedFromJsonException( + source, key as String, 'Pubspec', e.message); + } + + return new MapEntry(key as String, constraint); + }); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart new file mode 100644 index 000000000..b98d76654 --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -0,0 +1,38 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'pubspec.dart'; + +// ************************************************************************** +// Generator: JsonSerializableGenerator +// ************************************************************************** + +Pubspec _$PubspecFromJson(Map json) => $checkedNew( + 'Pubspec', + json, + () => new Pubspec($checkedConvert(json, 'name', (v) => v as String), + version: $checkedConvert(json, 'version', + (v) => v == null ? null : _versionFromString(v as String)), + author: $checkedConvert(json, 'author', (v) => v as String), + environment: $checkedConvert(json, 'environment', + (v) => v == null ? null : _environmentMap(v as Map)), + authors: $checkedConvert(json, 'authors', + (v) => (v as List)?.map((e) => e as String)?.toList()), + homepage: $checkedConvert(json, 'homepage', (v) => v as String), + documentation: + $checkedConvert(json, 'documentation', (v) => v as String), + description: + $checkedConvert(json, 'description', (v) => v as String), + dependencies: $checkedConvert( + json, 'dependencies', (v) => _getDeps(v as Map)), + devDependencies: $checkedConvert( + json, 'dev_dependencies', (v) => _getDeps(v as Map)), + dependencyOverrides: $checkedConvert( + json, 'dependency_overrides', (v) => _getDeps(v as Map))), + fieldKeyMap: const { + 'devDependencies': 'dev_dependencies', + 'dependencyOverrides': 'dependency_overrides' + }); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml new file mode 100644 index 000000000..ae1a617a0 --- /dev/null +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -0,0 +1,20 @@ +name: pubspec_parse +description: >- + Simple package for parsing pubspec.yaml files with a type-safe API and rich + error reporting. +version: 0.1.0-dev +homepage: https://github.com/dart-lang/pubspec_parse +author: Dart Team + +environment: + sdk: '>=2.0.0-dev.54 <2.0.0' + +dependencies: + json_annotation: ^0.2.6 + pub_semver: ^1.3.2 + yaml: ^2.1.12 + +dev_dependencies: + build_runner: ^0.8.0 + json_serializable: ^0.5.5 + test: ^0.12.0 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart new file mode 100644 index 000000000..21c621dbf --- /dev/null +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -0,0 +1,128 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:pubspec_parse/pubspec_parse.dart'; +import 'package:test/test.dart'; + +import 'test_utils.dart'; + +void main() { + test('HostedDepedency', () { + var dep = _dependency('^1.0.0'); + expect(dep.constraint.toString(), '^1.0.0'); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + + test('SdkDependency without version', () { + var dep = _dependency({'sdk': 'flutter'}); + expect(dep.name, 'flutter'); + expect(dep.version, isNull); + expect(dep.toString(), 'SdkDependency: flutter'); + }); + + test('SdkDependency with version', () { + var dep = _dependency( + {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}); + expect(dep.name, 'flutter'); + expect(dep.version.toString(), '>=1.2.3 <2.0.0'); + expect(dep.toString(), 'SdkDependency: flutter'); + }); + + test('GitDependency', () { + var dep = _dependency({'git': 'bob'}); + expect(dep.url.toString(), 'bob'); + expect(dep.toString(), 'GitDependency: url@bob'); + }); + + test('HostedDepedency', () { + var dep = _dependency('^1.0.0'); + expect(dep.constraint.toString(), '^1.0.0'); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + + test('PathDependency', () { + var dep = _dependency({'path': '../path'}); + expect(dep.path, '../path'); + expect(dep.toString(), 'PathDependency: path@../path'); + }); + + group('errors', () { + test('List', () { + _expectThrows([], r''' +line 4, column 10: Not a valid dependency value. + "dep": [] + ^^'''); + }); + + test('int', () { + _expectThrows(42, r''' +line 4, column 10: Not a valid dependency value. + "dep": 42 + ^^^'''); + }); + + test('empty map', () { + _expectThrows({}, r''' +line 4, column 10: Must provide at least one key. + "dep": {} + ^^'''); + }); + + test('map with too many keys', () { + _expectThrows({'path': 'a', 'git': 'b'}, r''' +line 5, column 12: Expected only one key. + "path": "a", + ^^^'''); + }); + + test('git - null content', () { + _expectThrows({'git': null}, r''' +line 5, column 11: Cannot be null. + "git": null + ^^^^^'''); + }); + + test('git - int content', () { + _expectThrows({'git': 42}, r''' +line 5, column 11: Must be a String or a Map. + "git": 42 + ^^^'''); + }); + + test('path - null content', () { + _expectThrows({'path': null}, r''' +line 5, column 12: Cannot be null. + "path": null + ^^^^^'''); + }); + + test('path - int content', () { + _expectThrows({'path': 42}, r''' +line 5, column 12: Must be a String. + "path": 42 + ^^^'''); + }); + }); +} + +void _expectThrows(Object content, String expectedError) { + expectParseThrows({ + 'name': 'sample', + 'dependencies': {'dep': content} + }, expectedError); +} + +T _dependency(Object content) { + var value = parse({ + 'name': 'sample', + 'dependencies': {'dep': content} + }); + expect(value.name, 'sample'); + expect(value.dependencies, hasLength(1)); + + var entry = value.dependencies.entries.single; + expect(entry.key, 'dep'); + + return entry.value as T; +} diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart new file mode 100644 index 000000000..2842c5a06 --- /dev/null +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('vm') +@Tags(const ['presubmit-only']) + +import 'dart:convert'; +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +void main() { + // TODO(kevmoo): replace with a common utility + // https://github.com/dart-lang/build/issues/716 + test('ensure local build succeeds with no changes', () { + var pkgRoot = _runProc('git', ['rev-parse', '--show-toplevel']); + var currentDir = Directory.current.resolveSymbolicLinksSync(); + + if (!p.equals(p.join(pkgRoot), currentDir)) { + throw new StateError('Expected the git root ($pkgRoot) ' + 'to match the current directory ($currentDir).'); + } + + // 1 - get a list of modified `.g.dart` files - should be empty + expect(_changedGeneratedFiles(), isEmpty); + + // 2 - run build - should be no output, since nothing should change + var result = _runProc('pub', + ['run', 'build_runner', 'build', '--delete-conflicting-outputs']); + + print(result); + expect(result, + contains(new RegExp(r'\[INFO\] Succeeded after \S+ with \d+ outputs'))); + + // 3 - get a list of modified `.g.dart` files - should still be empty + expect(_changedGeneratedFiles(), isEmpty); + }); +} + +final _whitespace = new RegExp(r'\s'); + +Set _changedGeneratedFiles() { + var output = _runProc('git', ['status', '--porcelain']); + + return LineSplitter + .split(output) + .map((line) => line.split(_whitespace).last) + .where((path) => path.endsWith('.dart')) + .toSet(); +} + +String _runProc(String proc, List args) { + var result = Process.runSync(proc, args); + + if (result.exitCode != 0) { + throw new ProcessException( + proc, args, result.stderr as String, result.exitCode); + } + + return (result.stdout as String).trim(); +} diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart new file mode 100644 index 000000000..7a4af7625 --- /dev/null +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -0,0 +1,95 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:test/test.dart'; + +import 'test_utils.dart'; + +void main() { + test('trival', () { + var value = parse({'name': 'sample'}); + expect(value.name, 'sample'); + expect(value.authors, isEmpty); + expect(value.dependencies, isEmpty); + }); + + test('one author', () { + var value = parse({'name': 'sample', 'author': 'name@example.com'}); + expect(value.allAuthors, ['name@example.com']); + }); + + test('one author, via authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com'] + }); + expect(value.authors, ['name@example.com']); + }); + + test('many authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com', 'name2@example.com'] + }); + expect(value.authors, ['name@example.com', 'name2@example.com']); + }); + + test('author and authors', () { + var value = parse({ + 'name': 'sample', + 'author': 'name@example.com', + 'authors': ['name2@example.com'] + }); + expect(value.allAuthors, ['name@example.com', 'name2@example.com']); + }); + + group('invalid', () { + test('null', () { + expect(() => parse(null), throwsArgumentError); + }); + test('empty string', () { + expect(() => parse(''), throwsArgumentError); + }); + test('array', () { + expectParseThrows([], r''' +line 1, column 1: Does not represent a YAML map. +[] +^^'''); + }); + + test('missing name', () { + expectParseThrows({}, r''' +line 1, column 1: "name" cannot be empty. +{} +^^'''); + }); + + test('"dart" is an invalid environment key', () { + expectParseThrows({ + 'name': 'sample', + 'environment': {'dart': 'cool'} + }, r''' +line 4, column 3: Use "sdk" to for Dart SDK constraints. + "dart": "cool" + ^^^^^^'''); + }); + + test('invalid version', () { + expectParseThrows({'name': 'sample', 'version': 'invalid'}, r''' +line 3, column 13: Unsupported value for `version`. + "version": "invalid" + ^^^^^^^^^'''); + }); + + test('invalid environment value', () { + expectParseThrows({ + 'name': 'sample', + 'environment': {'sdk': 'silly'} + }, r''' +line 4, column 10: Could not parse version "silly". Unknown text at "silly". + "sdk": "silly" + ^^^^^^^'''); + }); + }); +} diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart new file mode 100644 index 000000000..69102bf08 --- /dev/null +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -0,0 +1,74 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:convert'; + +import 'package:json_annotation/json_annotation.dart'; +import 'package:pubspec_parse/pubspec_parse.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; + +String _encodeJson(Object input) => + const JsonEncoder.withIndent(' ').convert(input); + +Matcher _throwsParsedYamlException(String prettyValue) => throwsA(allOf( + const isInstanceOf(), + new FeatureMatcher('formatMessage', (e) { + var message = e.formatMessage; + printOnFailure("Actual error format:\nr'''\n$message'''"); + _printDebugParsedYamlException(e); + return message; + }, prettyValue))); + +void _printDebugParsedYamlException(ParsedYamlException e) { + var innerError = e.innerError; + var innerStack = e.innerStack; + + if (e.innerError is CheckedFromJsonException) { + var cfje = e.innerError as CheckedFromJsonException; + if (cfje.innerError != null) { + innerError = cfje.innerError; + innerStack = cfje.innerStack; + } + } + + if (innerError != null) { + var items = [innerError]; + if (innerStack != null) { + items.add(Trace.format(innerStack, terse: true)); + } + + var content = + LineSplitter.split(items.join('\n')).map((e) => ' $e').join('\n'); + + printOnFailure('Inner error details:\n$content'); + } +} + +Pubspec parse(Object content, {bool quietOnError: false}) { + quietOnError ??= false; + try { + return parsePubspec(_encodeJson(content)); + } on ParsedYamlException catch (e) { + if (!quietOnError) { + _printDebugParsedYamlException(e); + } + rethrow; + } +} + +void expectParseThrows(Object content, String expectedError) => expect( + () => parse(content, quietOnError: true), + _throwsParsedYamlException(expectedError)); + +// TODO(kevmoo) add this to pkg/matcher – is nice! +class FeatureMatcher extends CustomMatcher { + final dynamic Function(T value) _feature; + + FeatureMatcher(String name, this._feature, matcher) + : super('`$name`', '`$name`', matcher); + + @override + featureValueOf(covariant T actual) => _feature(actual); +} From 0736e275fa1735a4e8c9bc201aac6ac54f2e068a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 09:53:25 -0700 Subject: [PATCH 0413/1215] Handle author and authors in a more sane way There is at least one published package with both author & authors set https://pub.dartlang.org/packages/crclib/versions/1.0.0 So we do normalization if both are set, eliminating duplicates and providing reasonable values from both author and authors properties Fixes https://github.com/dart-lang/pubspec_parse/issues/2 --- pkgs/pubspec_parse/lib/src/pubspec.dart | 42 +++++++++----- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 4 +- pkgs/pubspec_parse/test/parse_test.dart | 67 +++++++++++++++-------- 3 files changed, 76 insertions(+), 37 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 6a5c3a6ad..90efa1cb9 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -16,21 +16,24 @@ class Pubspec { final String homepage; final String documentation; final String description; - final String author; + + /// If there is exactly 1 value in [authors], returns it. + /// + /// If there are 0 or more than 1, returns `null`. + @Deprecated( + 'Here for completeness, but not recommended. Use `authors` instead.') + String get author { + if (authors.length == 1) { + return authors.single; + } + return null; + } + final List authors; @JsonKey(fromJson: _environmentMap) final Map environment; - List get allAuthors { - var values = []; - if (author != null) { - values.add(author); - } - values.addAll(authors); - return values; - } - @JsonKey(fromJson: _versionFromString) final Version version; @@ -43,19 +46,21 @@ class Pubspec { @JsonKey(name: 'dependency_overrides', fromJson: _getDeps, nullable: false) final Map dependencyOverrides; + /// If [author] and [authors] are both provided, their values are combined + /// with duplicates eliminated. Pubspec( this.name, { this.version, - this.author, - this.environment, + String author, List authors, + this.environment, this.homepage, this.documentation, this.description, Map dependencies, Map devDependencies, Map dependencyOverrides, - }) : this.authors = authors ?? const [], + }) : this.authors = _normalizeAuthors(author, authors), this.dependencies = dependencies ?? const {}, this.devDependencies = devDependencies ?? const {}, this.dependencyOverrides = dependencyOverrides ?? const {} { @@ -65,6 +70,17 @@ class Pubspec { } factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); + + static List _normalizeAuthors(String author, List authors) { + var value = new Set(); + if (author != null) { + value.add(author); + } + if (authors != null) { + value.addAll(authors); + } + return value.toList(); + } } // TODO: maybe move this to `dependencies.dart`? diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index b98d76654..4f040fffc 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -17,10 +17,10 @@ Pubspec _$PubspecFromJson(Map json) => $checkedNew( version: $checkedConvert(json, 'version', (v) => v == null ? null : _versionFromString(v as String)), author: $checkedConvert(json, 'author', (v) => v as String), - environment: $checkedConvert(json, 'environment', - (v) => v == null ? null : _environmentMap(v as Map)), authors: $checkedConvert(json, 'authors', (v) => (v as List)?.map((e) => e as String)?.toList()), + environment: $checkedConvert(json, 'environment', + (v) => v == null ? null : _environmentMap(v as Map)), homepage: $checkedConvert(json, 'homepage', (v) => v as String), documentation: $checkedConvert(json, 'documentation', (v) => v as String), diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 7a4af7625..bfe20f0a9 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -10,38 +10,61 @@ void main() { test('trival', () { var value = parse({'name': 'sample'}); expect(value.name, 'sample'); + // ignore: deprecated_member_use + expect(value.author, isNull); expect(value.authors, isEmpty); expect(value.dependencies, isEmpty); }); - test('one author', () { - var value = parse({'name': 'sample', 'author': 'name@example.com'}); - expect(value.allAuthors, ['name@example.com']); - }); + group('author, authors', () { + test('one author', () { + var value = parse({'name': 'sample', 'author': 'name@example.com'}); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); + }); - test('one author, via authors', () { - var value = parse({ - 'name': 'sample', - 'authors': ['name@example.com'] + test('one author, via authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); + }); + + test('many authors', () { + var value = parse({ + 'name': 'sample', + 'authors': ['name@example.com', 'name2@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, isNull); + expect(value.authors, ['name@example.com', 'name2@example.com']); }); - expect(value.authors, ['name@example.com']); - }); - test('many authors', () { - var value = parse({ - 'name': 'sample', - 'authors': ['name@example.com', 'name2@example.com'] + test('author and authors', () { + var value = parse({ + 'name': 'sample', + 'author': 'name@example.com', + 'authors': ['name2@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, isNull); + expect(value.authors, ['name@example.com', 'name2@example.com']); }); - expect(value.authors, ['name@example.com', 'name2@example.com']); - }); - test('author and authors', () { - var value = parse({ - 'name': 'sample', - 'author': 'name@example.com', - 'authors': ['name2@example.com'] + test('duplicate author values', () { + var value = parse({ + 'name': 'sample', + 'author': 'name@example.com', + 'authors': ['name@example.com', 'name@example.com'] + }); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); }); - expect(value.allAuthors, ['name@example.com', 'name2@example.com']); }); group('invalid', () { From c136a5ad38a35f66477e7c410bfce9035eb80d29 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 10:01:08 -0700 Subject: [PATCH 0414/1215] Test all trivial fields --- pkgs/pubspec_parse/lib/src/pubspec.dart | 11 ++++----- pkgs/pubspec_parse/test/parse_test.dart | 30 ++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 90efa1cb9..06d358a47 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -13,9 +13,12 @@ part 'pubspec.g.dart'; @JsonSerializable(createToJson: false) class Pubspec { final String name; - final String homepage; - final String documentation; + + @JsonKey(fromJson: _versionFromString) + final Version version; + final String description; + final String homepage; /// If there is exactly 1 value in [authors], returns it. /// @@ -30,13 +33,11 @@ class Pubspec { } final List authors; + final String documentation; @JsonKey(fromJson: _environmentMap) final Map environment; - @JsonKey(fromJson: _versionFromString) - final Version version; - @JsonKey(fromJson: _getDeps, nullable: false) final Map dependencies; diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index bfe20f0a9..d163e5a39 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -7,13 +7,41 @@ import 'package:test/test.dart'; import 'test_utils.dart'; void main() { - test('trival', () { + test('minimal set values', () { var value = parse({'name': 'sample'}); expect(value.name, 'sample'); + expect(value.version, isNull); + expect(value.description, isNull); + expect(value.homepage, isNull); // ignore: deprecated_member_use expect(value.author, isNull); expect(value.authors, isEmpty); + expect(value.documentation, isNull); expect(value.dependencies, isEmpty); + expect(value.devDependencies, isEmpty); + expect(value.dependencyOverrides, isEmpty); + }); + + test('all fields set', () { + var value = parse({ + 'name': 'sample', + 'version': '1.2.3', + 'author': 'name@example.com', + 'description': 'description', + 'homepage': 'homepage', + 'documentation': 'documentation' + }); + expect(value.name, 'sample'); + expect(value.version.toString(), '1.2.3'); + expect(value.description, 'description'); + expect(value.homepage, 'homepage'); + // ignore: deprecated_member_use + expect(value.author, 'name@example.com'); + expect(value.authors, ['name@example.com']); + expect(value.documentation, 'documentation'); + expect(value.dependencies, isEmpty); + expect(value.devDependencies, isEmpty); + expect(value.dependencyOverrides, isEmpty); }); group('author, authors', () { From 21f602ab29333157a6a96c67929f95128eacd1f7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 10:10:11 -0700 Subject: [PATCH 0415/1215] Move _getDeps to dependencies.dart - renamed to parseDeps Removed public Dependency.fromJson ctor --- pkgs/pubspec_parse/lib/src/dependency.dart | 99 ++++++++++++---------- pkgs/pubspec_parse/lib/src/pubspec.dart | 19 +---- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 6 +- 3 files changed, 60 insertions(+), 64 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 8c9ab15b5..935325004 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -5,64 +5,73 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; -abstract class Dependency { - Dependency._(); - - /// Returns `null` if the data could not be parsed. - factory Dependency.fromJson(dynamic data) { - if (data == null) { - return new HostedDependency(VersionConstraint.any); - } else if (data is String) { - return new HostedDependency(new VersionConstraint.parse(data)); - } else if (data is Map) { - try { - return new Dependency._fromMap(data); - } on ArgumentError catch (e) { +Map parseDeps(Map source) => + source?.map((k, v) { + var key = k as String; + var value = _fromJson(v); + if (value == null) { throw new CheckedFromJsonException( - data, e.name, 'Dependency', e.message.toString()); + source, key, 'Pubspec', 'Not a valid dependency value.'); } + return new MapEntry(key, value); + }) ?? + {}; + +/// Returns `null` if the data could not be parsed. +Dependency _fromJson(dynamic data) { + if (data == null) { + return new HostedDependency(VersionConstraint.any); + } else if (data is String) { + return new HostedDependency(new VersionConstraint.parse(data)); + } else if (data is Map) { + try { + return _fromMap(data); + } on ArgumentError catch (e) { + throw new CheckedFromJsonException( + data, e.name, 'Dependency', e.message.toString()); } - - return null; } - factory Dependency._fromMap(Map data) { - if (data.entries.isEmpty) { - // TODO: provide list of supported keys? - throw new CheckedFromJsonException( - data, null, 'Dependency', 'Must provide at least one key.'); - } + return null; +} - if (data.containsKey('sdk')) { - return new SdkDependency.fromData(data); - } +Dependency _fromMap(Map data) { + if (data.entries.isEmpty) { +// TODO: provide list of supported keys? + throw new CheckedFromJsonException( + data, null, 'Dependency', 'Must provide at least one key.'); + } - if (data.entries.length > 1) { - throw new CheckedFromJsonException( - data, - data.keys.skip(1).first as String, - 'Dependency', - 'Expected only one key.'); - } + if (data.containsKey('sdk')) { + return new SdkDependency.fromData(data); + } - var entry = data.entries.single; - var key = entry.key as String; + if (data.entries.length > 1) { + throw new CheckedFromJsonException(data, data.keys.skip(1).first as String, + 'Dependency', 'Expected only one key.'); + } - if (entry.value == null) { - throw new CheckedFromJsonException( - data, key, 'Dependency', 'Cannot be null.'); - } + var entry = data.entries.single; + var key = entry.key as String; - switch (key) { - case 'path': - return new PathDependency.fromData(entry.value); - case 'git': - return new GitDependency.fromData(entry.value); - } + if (entry.value == null) { + throw new CheckedFromJsonException( + data, key, 'Dependency', 'Cannot be null.'); + } - return null; + switch (key) { + case 'path': + return new PathDependency.fromData(entry.value); + case 'git': + return new GitDependency.fromData(entry.value); } + return null; +} + +abstract class Dependency { + Dependency._(); + String get _info; @override diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 06d358a47..3c9c045d4 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -38,13 +38,13 @@ class Pubspec { @JsonKey(fromJson: _environmentMap) final Map environment; - @JsonKey(fromJson: _getDeps, nullable: false) + @JsonKey(fromJson: parseDeps, nullable: false) final Map dependencies; - @JsonKey(name: 'dev_dependencies', fromJson: _getDeps, nullable: false) + @JsonKey(name: 'dev_dependencies', fromJson: parseDeps, nullable: false) final Map devDependencies; - @JsonKey(name: 'dependency_overrides', fromJson: _getDeps, nullable: false) + @JsonKey(name: 'dependency_overrides', fromJson: parseDeps, nullable: false) final Map dependencyOverrides; /// If [author] and [authors] are both provided, their values are combined @@ -84,19 +84,6 @@ class Pubspec { } } -// TODO: maybe move this to `dependencies.dart`? -Map _getDeps(Map source) => - source?.map((k, v) { - var key = k as String; - var value = new Dependency.fromJson(v); - if (value == null) { - throw new CheckedFromJsonException( - source, key, 'Pubspec', 'Not a valid dependency value.'); - } - return new MapEntry(key, value); - }) ?? - {}; - Version _versionFromString(String input) => new Version.parse(input); Map _environmentMap(Map source) => diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 4f040fffc..c32db09ff 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -27,11 +27,11 @@ Pubspec _$PubspecFromJson(Map json) => $checkedNew( description: $checkedConvert(json, 'description', (v) => v as String), dependencies: $checkedConvert( - json, 'dependencies', (v) => _getDeps(v as Map)), + json, 'dependencies', (v) => parseDeps(v as Map)), devDependencies: $checkedConvert( - json, 'dev_dependencies', (v) => _getDeps(v as Map)), + json, 'dev_dependencies', (v) => parseDeps(v as Map)), dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => _getDeps(v as Map))), + json, 'dependency_overrides', (v) => parseDeps(v as Map))), fieldKeyMap: const { 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' From ad586155548f05942812c4ca0da09faf22440fdd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 10:43:36 -0700 Subject: [PATCH 0416/1215] Improve handling of git dependencies and improve associated tests --- pkgs/pubspec_parse/build.yaml | 1 + pkgs/pubspec_parse/lib/src/dependency.dart | 38 +++++++++++------ pkgs/pubspec_parse/lib/src/dependency.g.dart | 20 +++++++++ pkgs/pubspec_parse/lib/src/errors.dart | 16 +++---- pkgs/pubspec_parse/test/dependency_test.dart | 45 ++++++++++++++++++-- 5 files changed, 94 insertions(+), 26 deletions(-) create mode 100644 pkgs/pubspec_parse/lib/src/dependency.g.dart diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index ec706e421..930aad181 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -6,6 +6,7 @@ targets: json_serializable: generate_for: - lib/src/pubspec.dart + - lib/src/dependency.dart options: any_map: true checked: true diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 935325004..526023984 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -4,6 +4,9 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; +import 'package:pubspec_parse/src/errors.dart'; + +part 'dependency.g.dart'; Map parseDeps(Map source) => source?.map((k, v) { @@ -96,36 +99,43 @@ class SdkDependency extends Dependency { String get _info => name; } +@JsonSerializable(createToJson: false) class GitDependency extends Dependency { + @JsonKey(fromJson: _parseUri) final Uri url; final String ref; final String path; - GitDependency(this.url, this.ref, this.path) : super._(); + GitDependency(this.url, this.ref, this.path) : super._() { + if (url == null) { + throw new ArgumentError.value(url, 'url', '"url" cannot be null.'); + } + } factory GitDependency.fromData(Object data) { - String url; - String path; - String ref; - if (data is String) { - url = data; - } else if (data is Map) { - url = data['url'] as String; - path = data['path'] as String; - ref = data['ref'] as String; - } else { - throw new ArgumentError.value(data, 'git', 'Must be a String or a Map.'); + data = {'url': data}; } - // TODO: validate `url` is a valid URI - return new GitDependency(Uri.parse(url), ref, path); + if (data is Map) { + // TODO: Need JsonKey.required + // https://github.com/dart-lang/json_serializable/issues/216 + if (!data.containsKey('url')) { + throw new BadKeyException(data, 'url', '"url" is required.'); + } + + return _$GitDependencyFromJson(data); + } + + throw new ArgumentError.value(data, 'git', 'Must be a String or a Map.'); } @override String get _info => 'url@$url'; } +Uri _parseUri(String value) => Uri.parse(value); + class PathDependency extends Dependency { final String path; diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart new file mode 100644 index 000000000..cdb06bbc9 --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'dependency.dart'; + +// ************************************************************************** +// Generator: JsonSerializableGenerator +// ************************************************************************** + +GitDependency _$GitDependencyFromJson(Map json) => $checkedNew( + 'GitDependency', + json, + () => new GitDependency( + $checkedConvert( + json, 'url', (v) => v == null ? null : _parseUri(v as String)), + $checkedConvert(json, 'ref', (v) => v as String), + $checkedConvert(json, 'path', (v) => v as String))); diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index 9b1489cf4..288553c4a 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -14,14 +14,14 @@ ParsedYamlException parsedYamlExceptionFromError( if (innerError is BadKeyException) { var map = innerError.map; if (map is YamlMap) { - var key = map.nodes.keys.singleWhere((key) { - return (key as YamlScalar).value == innerError.key; - }, orElse: () => null); - - if (key is YamlScalar) { - return new ParsedYamlException._(innerError.message, key, - innerError: error, innerStack: stack); - } + // if the associated key exists, use that as the error node, + // otherwise use the map itself + var node = map.nodes.keys.cast().singleWhere((key) { + return key.value == innerError.key; + }, orElse: () => map); + + return new ParsedYamlException._(innerError.message, node, + innerError: error, innerStack: stack); } } else if (innerError is ParsedYamlException) { return innerError; diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 21c621dbf..8ede482cc 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -29,10 +29,22 @@ void main() { expect(dep.toString(), 'SdkDependency: flutter'); }); - test('GitDependency', () { - var dep = _dependency({'git': 'bob'}); - expect(dep.url.toString(), 'bob'); - expect(dep.toString(), 'GitDependency: url@bob'); + test('GitDependency - string', () { + var dep = _dependency({'git': 'url'}); + expect(dep.url.toString(), 'url'); + expect(dep.path, isNull); + expect(dep.ref, isNull); + expect(dep.toString(), 'GitDependency: url@url'); + }); + + test('GitDependency - map', () { + var dep = _dependency({ + 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'} + }); + expect(dep.url.toString(), 'url'); + expect(dep.path, 'path'); + expect(dep.ref, 'ref'); + expect(dep.toString(), 'GitDependency: url@url'); }); test('HostedDepedency', () { @@ -90,6 +102,31 @@ line 5, column 11: Must be a String or a Map. ^^^'''); }); + test('git - empty map', () { + _expectThrows({'git': {}}, r''' +line 5, column 11: "url" is required. + "git": {} + ^^'''); + }); + + test('git - null url', () { + _expectThrows({ + 'git': {'url': null} + }, r''' +line 6, column 12: "url" cannot be null. + "url": null + ^^^^^'''); + }); + + test('git - int url', () { + _expectThrows({ + 'git': {'url': 42} + }, r''' +line 6, column 12: Unsupported value for `url`. + "url": 42 + ^^^'''); + }); + test('path - null content', () { _expectThrows({'path': null}, r''' line 5, column 12: Cannot be null. From d6238b948178f1a8ec3c074e8b4886682d612dca Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 11:21:05 -0700 Subject: [PATCH 0417/1215] Migrate Hosted and Sdk dependency to use generated fromJson Handle HostedDependency with explicit version field --- pkgs/pubspec_parse/lib/src/dependency.dart | 62 +++++++++++++------- pkgs/pubspec_parse/lib/src/dependency.g.dart | 14 +++++ pkgs/pubspec_parse/lib/src/pubspec.dart | 3 + pkgs/pubspec_parse/test/dependency_test.dart | 26 ++++---- 4 files changed, 74 insertions(+), 31 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 526023984..8488fe157 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -22,11 +22,14 @@ Map parseDeps(Map source) => /// Returns `null` if the data could not be parsed. Dependency _fromJson(dynamic data) { - if (data == null) { - return new HostedDependency(VersionConstraint.any); - } else if (data is String) { - return new HostedDependency(new VersionConstraint.parse(data)); - } else if (data is Map) { + var value = + SdkDependency.tryFromData(data) ?? HostedDependency.tryFromData(data); + + if (value != null) { + return value; + } + + if (data is Map) { try { return _fromMap(data); } on ArgumentError catch (e) { @@ -45,10 +48,6 @@ Dependency _fromMap(Map data) { data, null, 'Dependency', 'Must provide at least one key.'); } - if (data.containsKey('sdk')) { - return new SdkDependency.fromData(data); - } - if (data.entries.length > 1) { throw new CheckedFromJsonException(data, data.keys.skip(1).first as String, 'Dependency', 'Expected only one key.'); @@ -81,22 +80,23 @@ abstract class Dependency { String toString() => '$runtimeType: $_info'; } +@JsonSerializable(createToJson: false) class SdkDependency extends Dependency { - final String name; + final String sdk; + @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; - SdkDependency(this.name, {this.version}) : super._(); + SdkDependency(this.sdk, {this.version}) : super._(); - factory SdkDependency.fromData(Map data) { - VersionConstraint version; - if (data.containsKey('version')) { - version = new VersionConstraint.parse(data['version'] as String); + static SdkDependency tryFromData(Object data) { + if (data is Map && data.containsKey('sdk')) { + return _$SdkDependencyFromJson(data); } - return new SdkDependency(data['sdk'] as String, version: version); + return null; } @override - String get _info => name; + String get _info => sdk; } @JsonSerializable(createToJson: false) @@ -152,12 +152,32 @@ class PathDependency extends Dependency { String get _info => 'path@$path'; } -// TODO: support explicit host? +@JsonSerializable(createToJson: false) class HostedDependency extends Dependency { - final VersionConstraint constraint; + // TODO: support explicit host + + @JsonKey(fromJson: _constraintFromString) + final VersionConstraint version; + + HostedDependency({VersionConstraint version}) + : this.version = version ?? VersionConstraint.any, + super._(); + + static HostedDependency tryFromData(Object data) { + if (data == null || data is String) { + data = {'version': data}; + } - HostedDependency(this.constraint) : super._(); + if (data is Map && data.containsKey('version')) { + return _$HostedDependencyFromJson(data); + } + + return null; + } @override - String get _info => constraint.toString(); + String get _info => version.toString(); } + +VersionConstraint _constraintFromString(String input) => + new VersionConstraint.parse(input); diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index cdb06bbc9..7a7d427cd 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -10,6 +10,13 @@ part of 'dependency.dart'; // Generator: JsonSerializableGenerator // ************************************************************************** +SdkDependency _$SdkDependencyFromJson(Map json) => $checkedNew( + 'SdkDependency', + json, + () => new SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), + version: $checkedConvert(json, 'version', + (v) => v == null ? null : _constraintFromString(v as String)))); + GitDependency _$GitDependencyFromJson(Map json) => $checkedNew( 'GitDependency', json, @@ -18,3 +25,10 @@ GitDependency _$GitDependencyFromJson(Map json) => $checkedNew( json, 'url', (v) => v == null ? null : _parseUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), $checkedConvert(json, 'path', (v) => v as String))); + +HostedDependency _$HostedDependencyFromJson(Map json) => $checkedNew( + 'HostedDependency', + json, + () => new HostedDependency( + version: $checkedConvert(json, 'version', + (v) => v == null ? null : _constraintFromString(v as String)))); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 3c9c045d4..163f3f9bf 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -12,6 +12,9 @@ part 'pubspec.g.dart'; @JsonSerializable(createToJson: false) class Pubspec { + // TODO: executables + // TODO: publish_to + final String name; @JsonKey(fromJson: _versionFromString) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 8ede482cc..5c86721f4 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -8,15 +8,27 @@ import 'package:test/test.dart'; import 'test_utils.dart'; void main() { - test('HostedDepedency', () { + test('HostedDepedency - null', () { + var dep = _dependency(null); + expect(dep.version.toString(), 'any'); + expect(dep.toString(), 'HostedDependency: any'); + }); + + test('HostedDepedency - string', () { var dep = _dependency('^1.0.0'); - expect(dep.constraint.toString(), '^1.0.0'); + expect(dep.version.toString(), '^1.0.0'); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + + test('HostedDepedency - map', () { + var dep = _dependency({'version': '^1.0.0'}); + expect(dep.version.toString(), '^1.0.0'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); test('SdkDependency without version', () { var dep = _dependency({'sdk': 'flutter'}); - expect(dep.name, 'flutter'); + expect(dep.sdk, 'flutter'); expect(dep.version, isNull); expect(dep.toString(), 'SdkDependency: flutter'); }); @@ -24,7 +36,7 @@ void main() { test('SdkDependency with version', () { var dep = _dependency( {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}); - expect(dep.name, 'flutter'); + expect(dep.sdk, 'flutter'); expect(dep.version.toString(), '>=1.2.3 <2.0.0'); expect(dep.toString(), 'SdkDependency: flutter'); }); @@ -47,12 +59,6 @@ void main() { expect(dep.toString(), 'GitDependency: url@url'); }); - test('HostedDepedency', () { - var dep = _dependency('^1.0.0'); - expect(dep.constraint.toString(), '^1.0.0'); - expect(dep.toString(), 'HostedDependency: ^1.0.0'); - }); - test('PathDependency', () { var dep = _dependency({'path': '../path'}); expect(dep.path, '../path'); From 7ed87bcaf20190c604b1a45ad1341f7397df3baf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 12:02:50 -0700 Subject: [PATCH 0418/1215] Update to latest json_serializable --- pkgs/pubspec_parse/lib/src/dependency.g.dart | 37 ++++++++------ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 52 ++++++++++---------- pkgs/pubspec_parse/pubspec.yaml | 4 +- 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 7a7d427cd..794200bb9 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -10,25 +10,32 @@ part of 'dependency.dart'; // Generator: JsonSerializableGenerator // ************************************************************************** -SdkDependency _$SdkDependencyFromJson(Map json) => $checkedNew( - 'SdkDependency', - json, - () => new SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), +SdkDependency _$SdkDependencyFromJson(Map json) { + return $checkedNew('SdkDependency', json, () { + var val = new SdkDependency( + $checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert(json, 'version', - (v) => v == null ? null : _constraintFromString(v as String)))); + (v) => v == null ? null : _constraintFromString(v as String))); + return val; + }); +} -GitDependency _$GitDependencyFromJson(Map json) => $checkedNew( - 'GitDependency', - json, - () => new GitDependency( +GitDependency _$GitDependencyFromJson(Map json) { + return $checkedNew('GitDependency', json, () { + var val = new GitDependency( $checkedConvert( json, 'url', (v) => v == null ? null : _parseUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), - $checkedConvert(json, 'path', (v) => v as String))); + $checkedConvert(json, 'path', (v) => v as String)); + return val; + }); +} -HostedDependency _$HostedDependencyFromJson(Map json) => $checkedNew( - 'HostedDependency', - json, - () => new HostedDependency( +HostedDependency _$HostedDependencyFromJson(Map json) { + return $checkedNew('HostedDependency', json, () { + var val = new HostedDependency( version: $checkedConvert(json, 'version', - (v) => v == null ? null : _constraintFromString(v as String)))); + (v) => v == null ? null : _constraintFromString(v as String))); + return val; + }); +} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index c32db09ff..f585b847d 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -10,29 +10,29 @@ part of 'pubspec.dart'; // Generator: JsonSerializableGenerator // ************************************************************************** -Pubspec _$PubspecFromJson(Map json) => $checkedNew( - 'Pubspec', - json, - () => new Pubspec($checkedConvert(json, 'name', (v) => v as String), - version: $checkedConvert(json, 'version', - (v) => v == null ? null : _versionFromString(v as String)), - author: $checkedConvert(json, 'author', (v) => v as String), - authors: $checkedConvert(json, 'authors', - (v) => (v as List)?.map((e) => e as String)?.toList()), - environment: $checkedConvert(json, 'environment', - (v) => v == null ? null : _environmentMap(v as Map)), - homepage: $checkedConvert(json, 'homepage', (v) => v as String), - documentation: - $checkedConvert(json, 'documentation', (v) => v as String), - description: - $checkedConvert(json, 'description', (v) => v as String), - dependencies: $checkedConvert( - json, 'dependencies', (v) => parseDeps(v as Map)), - devDependencies: $checkedConvert( - json, 'dev_dependencies', (v) => parseDeps(v as Map)), - dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => parseDeps(v as Map))), - fieldKeyMap: const { - 'devDependencies': 'dev_dependencies', - 'dependencyOverrides': 'dependency_overrides' - }); +Pubspec _$PubspecFromJson(Map json) { + return $checkedNew('Pubspec', json, () { + var val = new Pubspec($checkedConvert(json, 'name', (v) => v as String), + version: $checkedConvert(json, 'version', + (v) => v == null ? null : _versionFromString(v as String)), + author: $checkedConvert(json, 'author', (v) => v as String), + authors: $checkedConvert(json, 'authors', + (v) => (v as List)?.map((e) => e as String)?.toList()), + environment: $checkedConvert(json, 'environment', + (v) => v == null ? null : _environmentMap(v as Map)), + homepage: $checkedConvert(json, 'homepage', (v) => v as String), + documentation: + $checkedConvert(json, 'documentation', (v) => v as String), + description: $checkedConvert(json, 'description', (v) => v as String), + dependencies: + $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map)), + devDependencies: $checkedConvert( + json, 'dev_dependencies', (v) => parseDeps(v as Map)), + dependencyOverrides: $checkedConvert( + json, 'dependency_overrides', (v) => parseDeps(v as Map))); + return val; + }, fieldKeyMap: const { + 'devDependencies': 'dev_dependencies', + 'dependencyOverrides': 'dependency_overrides' + }); +} diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index ae1a617a0..260681769 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -10,11 +10,11 @@ environment: sdk: '>=2.0.0-dev.54 <2.0.0' dependencies: - json_annotation: ^0.2.6 + json_annotation: ^0.2.7 pub_semver: ^1.3.2 yaml: ^2.1.12 dev_dependencies: build_runner: ^0.8.0 - json_serializable: ^0.5.5 + json_serializable: ^0.5.6 test: ^0.12.0 From 783c4ba45f9745a3ff085b889e8f1cf8b567ef6d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 14:24:33 -0700 Subject: [PATCH 0419/1215] Replace paresPubspec top-level function with Pubspec.parse ctor --- pkgs/pubspec_parse/lib/pubspec_parse.dart | 1 - pkgs/pubspec_parse/lib/src/functions.dart | 34 ----------------------- pkgs/pubspec_parse/lib/src/pubspec.dart | 24 ++++++++++++++++ pkgs/pubspec_parse/test/test_utils.dart | 2 +- 4 files changed, 25 insertions(+), 36 deletions(-) delete mode 100644 pkgs/pubspec_parse/lib/src/functions.dart diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart index 3339982b1..99886c44a 100644 --- a/pkgs/pubspec_parse/lib/pubspec_parse.dart +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -10,5 +10,4 @@ export 'src/dependency.dart' SdkDependency, PathDependency; export 'src/errors.dart' show ParsedYamlException; -export 'src/functions.dart' show parsePubspec; export 'src/pubspec.dart' show Pubspec; diff --git a/pkgs/pubspec_parse/lib/src/functions.dart b/pkgs/pubspec_parse/lib/src/functions.dart deleted file mode 100644 index 84ef35cc0..000000000 --- a/pkgs/pubspec_parse/lib/src/functions.dart +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'package:json_annotation/json_annotation.dart'; -import 'package:yaml/yaml.dart'; - -import 'errors.dart'; -import 'pubspec.dart'; - -/// If [sourceUrl] is passed, it's used as the URL from which the YAML -/// originated for error reporting. It can be a [String], a [Uri], or `null`. -Pubspec parsePubspec(String yaml, {sourceUrl}) { - var item = loadYaml(yaml, sourceUrl: sourceUrl); - - if (item == null) { - throw new ArgumentError.notNull('yaml'); - } - - if (item is! YamlMap) { - if (item is YamlNode) { - throw parsedYamlException('Does not represent a YAML map.', item); - } - - throw new ArgumentError.value( - yaml, 'yaml', 'Does not represent a YAML map.'); - } - - try { - return new Pubspec.fromJson(item as YamlMap); - } on CheckedFromJsonException catch (error, stack) { - throw parsedYamlExceptionFromError(error, stack); - } -} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 163f3f9bf..b57859670 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -4,6 +4,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; +import 'package:yaml/yaml.dart'; import 'dependency.dart'; import 'errors.dart'; @@ -75,6 +76,29 @@ class Pubspec { factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); + factory Pubspec.parse(String yaml, {sourceUrl}) { + var item = loadYaml(yaml, sourceUrl: sourceUrl); + + if (item == null) { + throw new ArgumentError.notNull('yaml'); + } + + if (item is! YamlMap) { + if (item is YamlNode) { + throw parsedYamlException('Does not represent a YAML map.', item); + } + + throw new ArgumentError.value( + yaml, 'yaml', 'Does not represent a YAML map.'); + } + + try { + return new Pubspec.fromJson(item as YamlMap); + } on CheckedFromJsonException catch (error, stack) { + throw parsedYamlExceptionFromError(error, stack); + } + } + static List _normalizeAuthors(String author, List authors) { var value = new Set(); if (author != null) { diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 69102bf08..0924b4138 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -49,7 +49,7 @@ void _printDebugParsedYamlException(ParsedYamlException e) { Pubspec parse(Object content, {bool quietOnError: false}) { quietOnError ??= false; try { - return parsePubspec(_encodeJson(content)); + return new Pubspec.parse(_encodeJson(content)); } on ParsedYamlException catch (e) { if (!quietOnError) { _printDebugParsedYamlException(e); From c12540fe5b34a4744e20dca2d4dc0cf4db8ba372 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 14:25:48 -0700 Subject: [PATCH 0420/1215] Pubspec: Rename formatMessage to formattedMessage --- pkgs/pubspec_parse/lib/src/errors.dart | 2 +- pkgs/pubspec_parse/test/test_utils.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index 288553c4a..528e44ac3 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -68,7 +68,7 @@ class ParsedYamlException implements Exception { /// Returns [message] formatted with source information provided by /// [yamlNode]. - String get formatMessage => yamlNode.span.message(message); + String get formattedMessage => yamlNode.span.message(message); @override String toString() => message; diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 0924b4138..65000afb4 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -14,8 +14,8 @@ String _encodeJson(Object input) => Matcher _throwsParsedYamlException(String prettyValue) => throwsA(allOf( const isInstanceOf(), - new FeatureMatcher('formatMessage', (e) { - var message = e.formatMessage; + new FeatureMatcher('formattedMessage', (e) { + var message = e.formattedMessage; printOnFailure("Actual error format:\nr'''\n$message'''"); _printDebugParsedYamlException(e); return message; From 42621e353f94cbc22f568f10da7d6c52451b3d9a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 14:42:50 -0700 Subject: [PATCH 0421/1215] Organize dependency tests around their type Easier to scan through --- pkgs/pubspec_parse/test/dependency_test.dart | 133 ++++++++++--------- 1 file changed, 73 insertions(+), 60 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 5c86721f4..b8544d8ad 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -8,6 +8,43 @@ import 'package:test/test.dart'; import 'test_utils.dart'; void main() { + group('hosted', _hostedDependency); + group('git', _gitDependency); + group('sdk', _sdkDependency); + group('path', _pathDependency); + + group('errors', () { + test('List', () { + _expectThrows([], r''' +line 4, column 10: Not a valid dependency value. + "dep": [] + ^^'''); + }); + + test('int', () { + _expectThrows(42, r''' +line 4, column 10: Not a valid dependency value. + "dep": 42 + ^^^'''); + }); + + test('empty map', () { + _expectThrows({}, r''' +line 4, column 10: Must provide at least one key. + "dep": {} + ^^'''); + }); + + test('map with too many keys', () { + _expectThrows({'path': 'a', 'git': 'b'}, r''' +line 5, column 12: Expected only one key. + "path": "a", + ^^^'''); + }); + }); +} + +void _hostedDependency() { test('HostedDepedency - null', () { var dep = _dependency(null); expect(dep.version.toString(), 'any'); @@ -25,7 +62,9 @@ void main() { expect(dep.version.toString(), '^1.0.0'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); +} +void _sdkDependency() { test('SdkDependency without version', () { var dep = _dependency({'sdk': 'flutter'}); expect(dep.sdk, 'flutter'); @@ -40,7 +79,9 @@ void main() { expect(dep.version.toString(), '>=1.2.3 <2.0.0'); expect(dep.toString(), 'SdkDependency: flutter'); }); +} +void _gitDependency() { test('GitDependency - string', () { var dep = _dependency({'git': 'url'}); expect(dep.url.toString(), 'url'); @@ -59,93 +100,65 @@ void main() { expect(dep.toString(), 'GitDependency: url@url'); }); - test('PathDependency', () { - var dep = _dependency({'path': '../path'}); - expect(dep.path, '../path'); - expect(dep.toString(), 'PathDependency: path@../path'); - }); - - group('errors', () { - test('List', () { - _expectThrows([], r''' -line 4, column 10: Not a valid dependency value. - "dep": [] - ^^'''); - }); - - test('int', () { - _expectThrows(42, r''' -line 4, column 10: Not a valid dependency value. - "dep": 42 - ^^^'''); - }); - - test('empty map', () { - _expectThrows({}, r''' -line 4, column 10: Must provide at least one key. - "dep": {} - ^^'''); - }); - - test('map with too many keys', () { - _expectThrows({'path': 'a', 'git': 'b'}, r''' -line 5, column 12: Expected only one key. - "path": "a", - ^^^'''); - }); - - test('git - null content', () { - _expectThrows({'git': null}, r''' + test('git - null content', () { + _expectThrows({'git': null}, r''' line 5, column 11: Cannot be null. "git": null ^^^^^'''); - }); + }); - test('git - int content', () { - _expectThrows({'git': 42}, r''' + test('git - int content', () { + _expectThrows({'git': 42}, r''' line 5, column 11: Must be a String or a Map. "git": 42 ^^^'''); - }); + }); - test('git - empty map', () { - _expectThrows({'git': {}}, r''' + test('git - empty map', () { + _expectThrows({'git': {}}, r''' line 5, column 11: "url" is required. "git": {} ^^'''); - }); + }); - test('git - null url', () { - _expectThrows({ - 'git': {'url': null} - }, r''' + test('git - null url', () { + _expectThrows({ + 'git': {'url': null} + }, r''' line 6, column 12: "url" cannot be null. "url": null ^^^^^'''); - }); + }); - test('git - int url', () { - _expectThrows({ - 'git': {'url': 42} - }, r''' + test('git - int url', () { + _expectThrows({ + 'git': {'url': 42} + }, r''' line 6, column 12: Unsupported value for `url`. "url": 42 ^^^'''); - }); + }); +} - test('path - null content', () { - _expectThrows({'path': null}, r''' +void _pathDependency() { + test('PathDependency', () { + var dep = _dependency({'path': '../path'}); + expect(dep.path, '../path'); + expect(dep.toString(), 'PathDependency: path@../path'); + }); + + test('path - null content', () { + _expectThrows({'path': null}, r''' line 5, column 12: Cannot be null. "path": null ^^^^^'''); - }); + }); - test('path - int content', () { - _expectThrows({'path': 42}, r''' + test('path - int content', () { + _expectThrows({'path': 42}, r''' line 5, column 12: Must be a String. "path": 42 ^^^'''); - }); }); } From e50261c0896fc06d09a429e95fc62447c30d1283 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 14:55:16 -0700 Subject: [PATCH 0422/1215] HostedDependency: support host data --- pkgs/pubspec_parse/lib/src/dependency.dart | 25 +++++++++++++++++--- pkgs/pubspec_parse/lib/src/dependency.g.dart | 13 +++++++++- pkgs/pubspec_parse/test/dependency_test.dart | 14 +++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 8488fe157..a66c9c41f 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -154,12 +154,12 @@ class PathDependency extends Dependency { @JsonSerializable(createToJson: false) class HostedDependency extends Dependency { - // TODO: support explicit host - @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; - HostedDependency({VersionConstraint version}) + final HostedDetails hosted; + + HostedDependency({VersionConstraint version, this.hosted}) : this.version = version ?? VersionConstraint.any, super._(); @@ -179,5 +179,24 @@ class HostedDependency extends Dependency { String get _info => version.toString(); } +@JsonSerializable(createToJson: false, nullable: false) +class HostedDetails { + final String name; + + @JsonKey(fromJson: _parseUri) + final Uri url; + + HostedDetails(this.name, this.url) { + if (name == null) { + throw new ArgumentError.value(name, 'name', '"name" cannot be null'); + } + if (url == null) { + throw new ArgumentError.value(url, 'url', '"url" cannot be null'); + } + } + + factory HostedDetails.fromJson(Map json) => _$HostedDetailsFromJson(json); +} + VersionConstraint _constraintFromString(String input) => new VersionConstraint.parse(input); diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 794200bb9..f3dc23d2e 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -35,7 +35,18 @@ HostedDependency _$HostedDependencyFromJson(Map json) { return $checkedNew('HostedDependency', json, () { var val = new HostedDependency( version: $checkedConvert(json, 'version', - (v) => v == null ? null : _constraintFromString(v as String))); + (v) => v == null ? null : _constraintFromString(v as String)), + hosted: $checkedConvert(json, 'hosted', + (v) => v == null ? null : new HostedDetails.fromJson(v as Map))); + return val; + }); +} + +HostedDetails _$HostedDetailsFromJson(Map json) { + return $checkedNew('HostedDetails', json, () { + var val = new HostedDetails( + $checkedConvert(json, 'name', (v) => v as String), + $checkedConvert(json, 'url', (v) => _parseUri(v as String))); return val; }); } diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index b8544d8ad..9a42a64c6 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -48,18 +48,32 @@ void _hostedDependency() { test('HostedDepedency - null', () { var dep = _dependency(null); expect(dep.version.toString(), 'any'); + expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); test('HostedDepedency - string', () { var dep = _dependency('^1.0.0'); expect(dep.version.toString(), '^1.0.0'); + expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); test('HostedDepedency - map', () { var dep = _dependency({'version': '^1.0.0'}); expect(dep.version.toString(), '^1.0.0'); + expect(dep.hosted, isNull); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + + test('HostedDepedency - map', () { + var dep = _dependency({ + 'version': '^1.0.0', + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} + }); + expect(dep.version.toString(), '^1.0.0'); + expect(dep.hosted.name, 'hosted_name'); + expect(dep.hosted.url.toString(), 'hosted_url'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); } From 16e4e6778f45af88b3cdb3c535681c6e30fd2f89 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 1 Jun 2018 14:57:34 -0700 Subject: [PATCH 0423/1215] Remove non-useful doc comment --- pkgs/pubspec_parse/lib/src/errors.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index 528e44ac3..dbdc94763 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -52,7 +52,6 @@ class ParsedYamlException implements Exception { /// Describes the nature of the parse failure. final String message; - /// The [YamlNode] that corresponds to the exception. final YamlNode yamlNode; /// If this exception was thrown as a result of another error, From a05045b806102e670731ad197a822e267cab8437 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 1 Jun 2018 15:52:26 -0700 Subject: [PATCH 0424/1215] Add `chainTransformers` and `map` utilities (dart-lang/stream_transform#47) These are a bit different than others in this package since we would generally not expect to see them directly inlined to a call to `transform`, but are instead useful when dealing with variable or arguments of type `StreamTransformer`, for instance `StreamSinkTransformer.fromStreamTransformer`. --- pkgs/stream_transform/CHANGELOG.md | 5 ++++ .../lib/src/async_map_buffer.dart | 7 +++--- .../lib/src/chain_transformers.dart | 24 +++++++++++++++++++ pkgs/stream_transform/lib/src/map.dart | 22 +++++++++++++++++ pkgs/stream_transform/lib/src/switch.dart | 7 +++--- .../lib/stream_transform.dart | 2 ++ pkgs/stream_transform/pubspec.yaml | 2 +- 7 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/chain_transformers.dart create mode 100644 pkgs/stream_transform/lib/src/map.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 0e0cfaa6a..ca056d405 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.12 + +- Add `chainTransformers` and `map` for use cases where `StreamTransformer` + instances are stored as variables or passed to methods other than `transform`. + ## 0.0.11 - Renamed `concat` as `followedBy` to match the naming of `Iterable.followedBy`. diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index f2fd2a4e1..72190d263 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -4,8 +4,8 @@ import 'dart:async'; -import 'bind.dart'; import 'buffer.dart'; +import 'chain_transformers.dart'; import 'from_handlers.dart'; /// Like [Stream.asyncMap] but events are buffered until previous events have @@ -31,9 +31,8 @@ StreamTransformer asyncMapBuffer( var workFinished = new StreamController(); // Let the first event through. workFinished.add(null); - return fromBind((values) => values - .transform(buffer(workFinished.stream)) - .transform(_asyncMapThen(convert, workFinished.add))); + return chainTransformers( + buffer(workFinished.stream), _asyncMapThen(convert, workFinished.add)); } /// Like [Stream.asyncMap] but the [convert] is only called once per event, diff --git a/pkgs/stream_transform/lib/src/chain_transformers.dart b/pkgs/stream_transform/lib/src/chain_transformers.dart new file mode 100644 index 000000000..50d8be48f --- /dev/null +++ b/pkgs/stream_transform/lib/src/chain_transformers.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'bind.dart'; + +/// Combines two transformers into one. +/// +/// This is most useful to keep a reference to the combination and use it in +/// multiple places or give it a descriptive name. For inline uses the directly +/// chained calls to `.transform` should be preferred. +/// +/// For example: +/// +/// ``` +/// /// values.transform(splitDecoded) is identical to +/// /// values.transform(utf8.decoder).transform(const LineSplitter()) +/// final splitDecoded = chainTransformers(utf8.decoder, const LineSplitter()); +/// ``` +StreamTransformer chainTransformers( + StreamTransformer first, StreamTransformer second) => + fromBind((values) => values.transform(first).transform(second)); diff --git a/pkgs/stream_transform/lib/src/map.dart b/pkgs/stream_transform/lib/src/map.dart new file mode 100644 index 000000000..8bce55016 --- /dev/null +++ b/pkgs/stream_transform/lib/src/map.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'bind.dart'; + +/// Models a [Stream.map] callback as a [StreamTransformer]. +/// +/// This is most useful to pass to functions that take a [StreamTransformer] +/// other than [Stream.transform]. For inline uses [Stream.map] should be +/// preferred. +/// +/// For example: +/// +/// ``` +/// final sinkMapper = new StreamSinkTransformer.fromStreamTransformer( +/// map((v) => '$v')); +/// ``` +StreamTransformer map(T convert(S event)) => + fromBind((stream) => stream.map(convert)); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 1774dd962..bbd40d4bc 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -3,7 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'bind.dart'; +import 'chain_transformers.dart'; +import 'map.dart'; /// Maps events to a Stream and emits values from the most recently created /// Stream. @@ -13,8 +14,8 @@ import 'bind.dart'; /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of the streams produced by [map]. -StreamTransformer switchMap(Stream map(S event)) => - fromBind((stream) => stream.map(map).transform(switchLatest())); +StreamTransformer switchMap(Stream convert(S event)) => + chainTransformers(map(convert), switchLatest()); /// Emits values from the most recently emitted Stream. /// diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 170a5be91..942391b04 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -6,9 +6,11 @@ export 'src/async_map_buffer.dart'; export 'src/async_where.dart'; export 'src/audit.dart'; export 'src/buffer.dart'; +export 'src/chain_transformers.dart'; export 'src/concat.dart'; export 'src/debounce.dart'; export 'src/followed_by.dart'; +export 'src/map.dart'; export 'src/merge.dart'; export 'src/scan.dart'; export 'src/start_with.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index dc4525b2b..6cc3be892 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.12-dev +version: 0.0.12 environment: sdk: ">=2.0.0-dev.20.0 <2.0.0" From d4800de90f45bc2fd56cbe46cc83db91bef86268 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Jun 2018 11:08:41 -0700 Subject: [PATCH 0425/1215] Pubspec.environment: never null, better validation for bad values --- pkgs/pubspec_parse/lib/src/pubspec.dart | 24 ++++++++++++-------- pkgs/pubspec_parse/test/parse_test.dart | 30 +++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index b57859670..169e719d7 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -58,7 +58,7 @@ class Pubspec { this.version, String author, List authors, - this.environment, + Map environment, this.homepage, this.documentation, this.description, @@ -66,6 +66,7 @@ class Pubspec { Map devDependencies, Map dependencyOverrides, }) : this.authors = _normalizeAuthors(author, authors), + this.environment = environment ?? const {}, this.dependencies = dependencies ?? const {}, this.devDependencies = devDependencies ?? const {}, this.dependencyOverrides = dependencyOverrides ?? const {} { @@ -114,7 +115,8 @@ class Pubspec { Version _versionFromString(String input) => new Version.parse(input); Map _environmentMap(Map source) => - source.map((key, value) { + source.map((k, value) { + var key = k as String; if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! @@ -122,13 +124,17 @@ Map _environmentMap(Map source) => source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); } - VersionConstraint constraint; - try { - constraint = new VersionConstraint.parse(value as String); - } on FormatException catch (e) { - throw new CheckedFromJsonException( - source, key as String, 'Pubspec', e.message); + if (value is String) { + VersionConstraint constraint; + try { + constraint = new VersionConstraint.parse(value); + } on FormatException catch (e) { + throw new CheckedFromJsonException(source, key, 'Pubspec', e.message); + } + + return new MapEntry(key, constraint); } - return new MapEntry(key as String, constraint); + throw new CheckedFromJsonException( + source, key, 'VersionConstraint', '`$value` is not a String.'); }); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index d163e5a39..1d7fcd8d5 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.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. +import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; import 'test_utils.dart'; @@ -16,6 +17,7 @@ void main() { // ignore: deprecated_member_use expect(value.author, isNull); expect(value.authors, isEmpty); + expect(value.environment, isEmpty); expect(value.documentation, isNull); expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); @@ -23,21 +25,25 @@ void main() { }); test('all fields set', () { + var constraint = new Version.parse('1.2.3'); var value = parse({ 'name': 'sample', - 'version': '1.2.3', + 'version': constraint.toString(), 'author': 'name@example.com', + 'environment': {'sdk': '1.2.3'}, 'description': 'description', 'homepage': 'homepage', 'documentation': 'documentation' }); expect(value.name, 'sample'); - expect(value.version.toString(), '1.2.3'); + expect(value.version, constraint); expect(value.description, 'description'); expect(value.homepage, 'homepage'); // ignore: deprecated_member_use expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); + expect(value.environment, hasLength(1)); + expect(value.environment, containsPair('sdk', constraint)); expect(value.documentation, 'documentation'); expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); @@ -126,6 +132,26 @@ line 4, column 3: Use "sdk" to for Dart SDK constraints. ^^^^^^'''); }); + test('environment values cannot be null', () { + expectParseThrows({ + 'name': 'sample', + 'environment': {'sdk': null} + }, r''' +line 4, column 10: `null` is not a String. + "sdk": null + ^^^^^'''); + }); + + test('environment values cannot be int', () { + expectParseThrows({ + 'name': 'sample', + 'environment': {'sdk': 42} + }, r''' +line 4, column 10: `42` is not a String. + "sdk": 42 + ^^^'''); + }); + test('invalid version', () { expectParseThrows({'name': 'sample', 'version': 'invalid'}, r''' line 3, column 13: Unsupported value for `version`. From dc34706c1e1e1a0b22847860a3b7d230899f107f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Jun 2018 10:43:26 -0700 Subject: [PATCH 0426/1215] Prepare for v0.1.0 release --- pkgs/pubspec_parse/CHANGELOG.md | 3 +-- pkgs/pubspec_parse/README.md | 8 ++++++++ pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 39d51431c..951a5a3f1 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,4 +1,3 @@ ## 0.1.0 -- Initial release including the `Pubspec` class and a top-level `parsePubspec` - function. +- Initial release. diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index b355cef76..a95459c6f 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,3 +1,11 @@ +[![Build Status](https://travis-ci.org/dart-lang/pubspec_parse.svg?branch=master)](https://travis-ci.org/dart-lang/pubspec_parse) + +Supports parsing `pubspec.yaml` files with robust error reporting and support +for most of the documented features. + +Read more about the +[pubspec format](https://www.dartlang.org/tools/pub/pubspec). + ## Features and bugs Please file feature requests and bugs at the [issue tracker]. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 260681769..e8942bfad 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.0-dev +version: 0.1.0 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team From aefc0e516e2b329202263dd8f0fda7811817c627 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Jun 2018 11:20:02 -0700 Subject: [PATCH 0427/1215] Add LICENSE file and missing stack_trace dependency --- pkgs/pubspec_parse/LICENSE | 26 ++++++++++++++++++++++++++ pkgs/pubspec_parse/pubspec.yaml | 1 + 2 files changed, 27 insertions(+) create mode 100644 pkgs/pubspec_parse/LICENSE diff --git a/pkgs/pubspec_parse/LICENSE b/pkgs/pubspec_parse/LICENSE new file mode 100644 index 000000000..c4dc9ba3c --- /dev/null +++ b/pkgs/pubspec_parse/LICENSE @@ -0,0 +1,26 @@ +Copyright 2018, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index e8942bfad..526c7516b 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,4 +17,5 @@ dependencies: dev_dependencies: build_runner: ^0.8.0 json_serializable: ^0.5.6 + stack_trace: ^1.9.2 test: ^0.12.0 From 94bdc3e17962faddd5eb362eafdeae5fd5ee27ce Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Jun 2018 11:21:27 -0700 Subject: [PATCH 0428/1215] add missing dev_dependency on pkg:path --- pkgs/pubspec_parse/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 526c7516b..4579c9b22 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,5 +17,6 @@ dependencies: dev_dependencies: build_runner: ^0.8.0 json_serializable: ^0.5.6 + path: ^1.5.1 stack_trace: ^1.9.2 test: ^0.12.0 From 15e7dd1692421dc4cd01575a66eff9e11096a154 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 8 Jun 2018 09:59:09 -0700 Subject: [PATCH 0429/1215] Fix name collision with error type in latest `package:json_annotation` Update checks in GitDependency to use new features --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/lib/src/dependency.dart | 15 ++------------- pkgs/pubspec_parse/lib/src/dependency.g.dart | 2 ++ pkgs/pubspec_parse/lib/src/errors.dart | 6 +++--- pkgs/pubspec_parse/lib/src/pubspec.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 6 +++--- pkgs/pubspec_parse/test/dependency_test.dart | 4 ++-- 7 files changed, 17 insertions(+), 22 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 951a5a3f1..4fc410a8a 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1 + +- Fixed name collision with error type in latest `package:json_annotation`. + ## 0.1.0 - Initial release. diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index a66c9c41f..dd66d93e4 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -4,7 +4,6 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; -import 'package:pubspec_parse/src/errors.dart'; part 'dependency.g.dart'; @@ -101,16 +100,12 @@ class SdkDependency extends Dependency { @JsonSerializable(createToJson: false) class GitDependency extends Dependency { - @JsonKey(fromJson: _parseUri) + @JsonKey(fromJson: _parseUri, required: true, disallowNullValue: true) final Uri url; final String ref; final String path; - GitDependency(this.url, this.ref, this.path) : super._() { - if (url == null) { - throw new ArgumentError.value(url, 'url', '"url" cannot be null.'); - } - } + GitDependency(this.url, this.ref, this.path) : super._(); factory GitDependency.fromData(Object data) { if (data is String) { @@ -118,12 +113,6 @@ class GitDependency extends Dependency { } if (data is Map) { - // TODO: Need JsonKey.required - // https://github.com/dart-lang/json_serializable/issues/216 - if (!data.containsKey('url')) { - throw new BadKeyException(data, 'url', '"url" is required.'); - } - return _$GitDependencyFromJson(data); } diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index f3dc23d2e..620bde71b 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -22,6 +22,8 @@ SdkDependency _$SdkDependencyFromJson(Map json) { GitDependency _$GitDependencyFromJson(Map json) { return $checkedNew('GitDependency', json, () { + $checkKeys(json, + requiredKeys: const ['url'], disallowNullValues: const ['url']); var val = new GitDependency( $checkedConvert( json, 'url', (v) => v == null ? null : _parseUri(v as String)), diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index dbdc94763..c9643b885 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -11,7 +11,7 @@ ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => ParsedYamlException parsedYamlExceptionFromError( CheckedFromJsonException error, StackTrace stack) { var innerError = error.innerError; - if (innerError is BadKeyException) { + if (innerError is InvalidKeyException) { var map = innerError.map; if (map is YamlMap) { // if the associated key exists, use that as the error node, @@ -77,10 +77,10 @@ class ParsedYamlException implements Exception { /// /// Used instead of [CheckedFromJsonException] when highlighting a bad [key] /// is desired, instead of the associated value. -class BadKeyException implements Exception { +class InvalidKeyException implements Exception { final Map map; final String key; final String message; - BadKeyException(this.map, this.key, this.message); + InvalidKeyException(this.map, this.key, this.message); } diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 169e719d7..7cc1ee13b 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -120,7 +120,7 @@ Map _environmentMap(Map source) => if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! - throw new BadKeyException( + throw new InvalidKeyException( source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); } diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 4579c9b22..6814fb654 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.0 +version: 0.1.1-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team @@ -10,13 +10,13 @@ environment: sdk: '>=2.0.0-dev.54 <2.0.0' dependencies: - json_annotation: ^0.2.7 + json_annotation: ^0.2.8 pub_semver: ^1.3.2 yaml: ^2.1.12 dev_dependencies: build_runner: ^0.8.0 - json_serializable: ^0.5.6 + json_serializable: ^0.5.7 path: ^1.5.1 stack_trace: ^1.9.2 test: ^0.12.0 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 9a42a64c6..527b310cd 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -130,7 +130,7 @@ line 5, column 11: Must be a String or a Map. test('git - empty map', () { _expectThrows({'git': {}}, r''' -line 5, column 11: "url" is required. +line 5, column 11: Required keys are missing: url. "git": {} ^^'''); }); @@ -139,7 +139,7 @@ line 5, column 11: "url" is required. _expectThrows({ 'git': {'url': null} }, r''' -line 6, column 12: "url" cannot be null. +line 6, column 12: These keys had `null` values, which is not allowed: [url] "url": null ^^^^^'''); }); From de2f9e48bff8b416011c1cbb51084a9284d332fd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 8 Jun 2018 11:28:27 -0700 Subject: [PATCH 0430/1215] Improve parsing of hosted dependencies Use new features from json_serializable Allow `host: String` With the map syntax, require a name, but not a url --- pkgs/pubspec_parse/CHANGELOG.md | 1 + pkgs/pubspec_parse/lib/src/dependency.dart | 51 +++++++++++---- pkgs/pubspec_parse/lib/src/dependency.g.dart | 12 +++- pkgs/pubspec_parse/test/dependency_test.dart | 68 ++++++++++++++++++-- 4 files changed, 114 insertions(+), 18 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 4fc410a8a..c0c94c9e4 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.1.1 - Fixed name collision with error type in latest `package:json_annotation`. +- Improved parsing of hosted dependencies. ## 0.1.0 diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index dd66d93e4..1498740ab 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -4,13 +4,34 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; +import 'package:yaml/yaml.dart'; part 'dependency.g.dart'; Map parseDeps(Map source) => source?.map((k, v) { var key = k as String; - var value = _fromJson(v); + Dependency value; + try { + value = _fromJson(v); + } on CheckedFromJsonException catch (e) { + if (e.map is! YamlMap) { + // This is likely a "synthetic" map created from a String value + // Use `source` to throw this exception with an actual YamlMap and + // extract the associated error information. + + var message = e.message; + var innerError = e.innerError; + // json_annotation should handle FormatException... + // https://github.com/dart-lang/json_serializable/issues/233 + if (innerError is FormatException) { + message = innerError.message; + } + throw new CheckedFromJsonException(source, key, e.className, message); + } + rethrow; + } + if (value == null) { throw new CheckedFromJsonException( source, key, 'Pubspec', 'Not a valid dependency value.'); @@ -141,11 +162,12 @@ class PathDependency extends Dependency { String get _info => 'path@$path'; } -@JsonSerializable(createToJson: false) +@JsonSerializable(createToJson: false, disallowUnrecognizedKeys: true) class HostedDependency extends Dependency { @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; + @JsonKey(disallowNullValue: true) final HostedDetails hosted; HostedDependency({VersionConstraint version, this.hosted}) @@ -157,7 +179,8 @@ class HostedDependency extends Dependency { data = {'version': data}; } - if (data is Map && data.containsKey('version')) { + if (data is Map && + (data.containsKey('version') || data.containsKey('hosted'))) { return _$HostedDependencyFromJson(data); } @@ -168,23 +191,27 @@ class HostedDependency extends Dependency { String get _info => version.toString(); } -@JsonSerializable(createToJson: false, nullable: false) +@JsonSerializable(createToJson: false, disallowUnrecognizedKeys: true) class HostedDetails { + @JsonKey(required: true, disallowNullValue: true) final String name; - @JsonKey(fromJson: _parseUri) + @JsonKey(fromJson: _parseUri, disallowNullValue: true) final Uri url; - HostedDetails(this.name, this.url) { - if (name == null) { - throw new ArgumentError.value(name, 'name', '"name" cannot be null'); + HostedDetails(this.name, this.url); + + factory HostedDetails.fromJson(Object data) { + if (data is String) { + data = {'name': data}; } - if (url == null) { - throw new ArgumentError.value(url, 'url', '"url" cannot be null'); + + if (data is Map) { + return _$HostedDetailsFromJson(data); } - } - factory HostedDetails.fromJson(Map json) => _$HostedDetailsFromJson(json); + throw new ArgumentError.value(data, 'hosted', 'Must be a Map or String.'); + } } VersionConstraint _constraintFromString(String input) => diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 620bde71b..6133cb454 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -35,20 +35,28 @@ GitDependency _$GitDependencyFromJson(Map json) { HostedDependency _$HostedDependencyFromJson(Map json) { return $checkedNew('HostedDependency', json, () { + $checkKeys(json, + allowedKeys: const ['version', 'hosted'], + disallowNullValues: const ['hosted']); var val = new HostedDependency( version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String)), hosted: $checkedConvert(json, 'hosted', - (v) => v == null ? null : new HostedDetails.fromJson(v as Map))); + (v) => v == null ? null : new HostedDetails.fromJson(v))); return val; }); } HostedDetails _$HostedDetailsFromJson(Map json) { return $checkedNew('HostedDetails', json, () { + $checkKeys(json, + allowedKeys: const ['name', 'url'], + requiredKeys: const ['name'], + disallowNullValues: const ['name', 'url']); var val = new HostedDetails( $checkedConvert(json, 'name', (v) => v as String), - $checkedConvert(json, 'url', (v) => _parseUri(v as String))); + $checkedConvert( + json, 'url', (v) => v == null ? null : _parseUri(v as String))); return val; }); } diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 527b310cd..f9fd369d1 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:pubspec_parse/pubspec_parse.dart'; +import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; import 'test_utils.dart'; @@ -45,28 +46,35 @@ line 5, column 12: Expected only one key. } void _hostedDependency() { - test('HostedDepedency - null', () { + test('null', () { var dep = _dependency(null); expect(dep.version.toString(), 'any'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); - test('HostedDepedency - string', () { + test('string version', () { var dep = _dependency('^1.0.0'); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); - test('HostedDepedency - map', () { + test('bad string version', () { + _expectThrows('not a version', r''' +line 4, column 10: Could not parse version "not a version". Unknown text at "not a version". + "dep": "not a version" + ^^^^^^^^^^^^^^^'''); + }); + + test('map w/ just version', () { var dep = _dependency({'version': '^1.0.0'}); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); - test('HostedDepedency - map', () { + test('map w/ version and hosted as Map', () { var dep = _dependency({ 'version': '^1.0.0', 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} @@ -76,6 +84,58 @@ void _hostedDependency() { expect(dep.hosted.url.toString(), 'hosted_url'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); + + test('map w/ bad version value', () { + _expectThrows({ + 'version': 'not a version', + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} + }, r''' +line 5, column 15: Unsupported value for `version`. + "version": "not a version", + ^^^^^^^^^^^^^^^'''); + }); + + test('map w/ unsupported keys', () { + _expectThrows({ + 'version': '^1.0.0', + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, + 'not_supported': null + }, r''' +line 4, column 10: Unrecognized keys: [not_supported]; supported keys: [version, hosted] + "dep": { + ^^'''); + }); + + test('map w/ version and hosted as String', () { + var dep = _dependency( + {'version': '^1.0.0', 'hosted': 'hosted_name'}); + expect(dep.version.toString(), '^1.0.0'); + expect(dep.hosted.name, 'hosted_name'); + expect(dep.hosted.url, isNull); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + + test('map w/ hosted as String', () { + var dep = _dependency({'hosted': 'hosted_name'}); + expect(dep.version, VersionConstraint.any); + expect(dep.hosted.name, 'hosted_name'); + expect(dep.hosted.url, isNull); + expect(dep.toString(), 'HostedDependency: any'); + }); + + test('map w/ null hosted should error', () { + _expectThrows({'hosted': null}, r''' +line 5, column 14: These keys had `null` values, which is not allowed: [hosted] + "hosted": null + ^^^^^'''); + }); + + test('map w/ null version is fine', () { + var dep = _dependency({'version': null}); + expect(dep.version, VersionConstraint.any); + expect(dep.hosted, isNull); + expect(dep.toString(), 'HostedDependency: any'); + }); } void _sdkDependency() { From 408e4d4b5c7261618690880084c8f16b970da627 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 8 Jun 2018 11:28:49 -0700 Subject: [PATCH 0431/1215] Prepare to release v0.1.1 --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 6814fb654..8d305ef82 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.1-dev +version: 0.1.1 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team From fd4b5f400ba76540930390e55b523380fe5da59f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 12:39:56 -0700 Subject: [PATCH 0432/1215] Allow Iterable argument to mergeAll (dart-lang/stream_transform#48) --- pkgs/stream_transform/CHANGELOG.md | 4 ++++ pkgs/stream_transform/lib/src/merge.dart | 4 ++-- pkgs/stream_transform/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index ca056d405..ada1e4b50 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.13 + +- `mergeAll` now accepts an `Iterable` instead of only `List`. + ## 0.0.12 - Add `chainTransformers` and `map` for use cases where `StreamTransformer` diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 06dd9d31d..36d81d3d3 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -18,11 +18,11 @@ StreamTransformer merge(Stream other) => new _Merge([other]); /// well, regardless of the types of streams in [others]. If single /// subscription streams are merged into a broadcast stream they may never be /// canceled. -StreamTransformer mergeAll(List> others) => +StreamTransformer mergeAll(Iterable> others) => new _Merge(others); class _Merge extends StreamTransformerBase { - final List> _others; + final Iterable> _others; _Merge(this._others); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 6cc3be892..53f7bbf39 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.12 +version: 0.0.13 environment: sdk: ">=2.0.0-dev.20.0 <2.0.0" From 533026d8efb58d8c68bcbc977ee69b4aff091ecd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 14:59:31 -0700 Subject: [PATCH 0433/1215] Allow a type on MultiChannel (dart-lang/stream_channel#26) - Add generic type arguments to the classes and relevant fields. - Explicitly indicate which arguments take a `StreamChannel`. - Update the test for MultiChannel to use a consistent type. --- pkgs/stream_channel/CHANGELOG.md | 1 + .../stream_channel/lib/src/multi_channel.dart | 41 +++++++++-------- pkgs/stream_channel/pubspec.yaml | 2 +- .../test/multi_channel_test.dart | 45 +++++++++---------- 4 files changed, 46 insertions(+), 43 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index eafdb8122..b284e5ed8 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.6.7 * Update SDK version to 2.0.0-dev.17.0. +* Add a type argument to `MultiChannel`. ## 1.6.6 diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e54154304..e7e2584aa 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -41,24 +41,25 @@ import '../stream_channel.dart'; /// /// Each virtual channel may be closed individually. When all of them are /// closed, the underlying [StreamSink] is closed automatically. -abstract class MultiChannel implements StreamChannel { +abstract class MultiChannel implements StreamChannel { /// The default input stream. /// /// This connects to the remote [sink]. - Stream get stream; + Stream get stream; /// The default output stream. /// /// This connects to the remote [stream]. If this is closed, the remote /// [stream] will close, but other virtual channels will remain open and new /// virtual channels may be opened. - StreamSink get sink; + StreamSink get sink; /// Creates a new [MultiChannel] that sends and receives messages over /// [inner]. /// /// The inner channel must take JSON-like objects. - factory MultiChannel(StreamChannel inner) => new _MultiChannel(inner); + factory MultiChannel(StreamChannel inner) => + new _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -71,31 +72,32 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([id]); + VirtualChannel virtualChannel([id]); } /// The implementation of [MultiChannel]. /// /// This is private so that [VirtualChannel] can inherit from [MultiChannel] /// without having to implement all the private members. -class _MultiChannel extends StreamChannelMixin implements MultiChannel { +class _MultiChannel extends StreamChannelMixin + implements MultiChannel { /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - StreamChannel _inner; + StreamChannel _inner; /// The subscription to [_inner.stream]. - StreamSubscription _innerStreamSubscription; + StreamSubscription _innerStreamSubscription; - Stream get stream => _mainController.foreign.stream; - StreamSink get sink => _mainController.foreign.sink; + Stream get stream => _mainController.foreign.stream; + StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. - final _mainController = new StreamChannelController(sync: true); + final _mainController = new StreamChannelController(sync: true); /// A map from input IDs to [StreamChannelController]s that should be used to /// communicate over those channels. - final _controllers = {}; + final _controllers = >{}; /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. @@ -164,7 +166,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { onError: _mainController.local.sink.addError); } - VirtualChannel virtualChannel([id]) { + VirtualChannel virtualChannel([id]) { var inputId; var outputId; if (id != null) { @@ -189,7 +191,7 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { this, inputId, new Stream.empty(), new NullStreamSink()); } - StreamChannelController controller; + StreamChannelController controller; if (_pendingIds.remove(inputId)) { // If we've already received messages for this channel, use the controller // where those messages are buffered. @@ -244,9 +246,10 @@ class _MultiChannel extends StreamChannelMixin implements MultiChannel { /// This implements [MultiChannel] for convenience. /// [VirtualChannel.virtualChannel] is semantically identical to the parent's /// [MultiChannel.virtualChannel]. -class VirtualChannel extends StreamChannelMixin implements MultiChannel { +class VirtualChannel extends StreamChannelMixin + implements MultiChannel { /// The [MultiChannel] that created this. - final MultiChannel _parent; + final MultiChannel _parent; /// The identifier for this channel. /// @@ -255,10 +258,10 @@ class VirtualChannel extends StreamChannelMixin implements MultiChannel { /// except that it will be JSON-serializable. final id; - final Stream stream; - final StreamSink sink; + final Stream stream; + final StreamSink sink; VirtualChannel._(this._parent, this.id, this.stream, this.sink); - VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); + VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 47e24c2f7..bbb29d8b7 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.7-dev +version: 1.6.7 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0c9316abb..99a53c328 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -11,8 +11,8 @@ void main() { var channel2; setUp(() { controller = new StreamChannelController(); - channel1 = new MultiChannel(controller.local); - channel2 = new MultiChannel(controller.foreign); + channel1 = new MultiChannel(controller.local); + channel2 = new MultiChannel(controller.foreign); }); group("the default virtual channel", () { @@ -20,15 +20,15 @@ void main() { var first = true; channel2.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); - channel1.sink.add("hello"); - channel1.sink.add("world"); + channel1.sink.add(1); + channel1.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -95,10 +95,10 @@ void main() { var first = true; virtual2.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); @@ -109,8 +109,8 @@ void main() { } channel2.stream.listen(expectAsync1((_) {}, count: 0)); - virtual1.sink.add("hello"); - virtual1.sink.add("world"); + virtual1.sink.add(1); + virtual1.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -174,12 +174,12 @@ void main() { expect(virtual1.id, equals(virtual3.id)); virtual2.stream - .listen(expectAsync1((message) => expect(message, equals("hello")))); - virtual4.stream.listen( - expectAsync1((message) => expect(message, equals("goodbye")))); + .listen(expectAsync1((message) => expect(message, equals(1)))); + virtual4.stream + .listen(expectAsync1((message) => expect(message, equals(2)))); - virtual1.sink.add("hello"); - virtual3.sink.add("goodbye"); + virtual1.sink.add(1); + virtual3.sink.add(2); }); }); @@ -195,10 +195,10 @@ void main() { var first = true; virtual1.stream.listen(expectAsync1((message) { if (first) { - expect(message, equals("hello")); + expect(message, equals(1)); first = false; } else { - expect(message, equals("world")); + expect(message, equals(2)); } }, count: 2)); @@ -209,8 +209,8 @@ void main() { } channel1.stream.listen(expectAsync1((_) {}, count: 0)); - virtual2.sink.add("hello"); - virtual2.sink.add("world"); + virtual2.sink.add(1); + virtual2.sink.add(2); }); test("closes the remote virtual channel when it closes", () { @@ -273,14 +273,13 @@ void main() { () async { virtual1 = channel1.virtualChannel(); - virtual1.sink.add("hello"); + virtual1.sink.add(1); await pumpEventQueue(); - virtual1.sink.add("world"); + virtual1.sink.add(2); await pumpEventQueue(); - expect(channel2.virtualChannel(virtual1.id).stream, - emitsInOrder(["hello", "world"])); + expect(channel2.virtualChannel(virtual1.id).stream, emitsInOrder([1, 2])); }); test( From 58810c95b4898e49b0ee681f8aff4d9fbce4a52b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 14:59:51 -0700 Subject: [PATCH 0434/1215] Drop dependency on StackTrace (dart-lang/stream_channel#27) The extra wrapping of `StackTrace.current` can always be done by the receiver. --- pkgs/stream_channel/lib/src/isolate_channel.dart | 3 +-- pkgs/stream_channel/pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index f1328c03d..290c2ff2c 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:isolate'; import 'package:async/async.dart'; -import 'package:stack_trace/stack_trace.dart'; import '../stream_channel.dart'; @@ -66,7 +65,7 @@ class IsolateChannel extends StreamChannelMixin { streamCompleter.setError( new StateError('Unexpected Isolate response "$message".'), - new Trace.current()); + StackTrace.current); sinkCompleter.setDestinationSink(new NullStreamSink()); subscription.cancel(); }); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bbb29d8b7..ff2209c94 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,6 +7,5 @@ environment: sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: async: '>=1.11.0 <3.0.0' - stack_trace: '^1.0.0' dev_dependencies: test: '^0.12.28' From ff1febd21c1b5e137bd70997a0b54581319fad1e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Jun 2018 15:40:42 -0700 Subject: [PATCH 0435/1215] Fix doc comment references (dart-lang/stream_channel#28) --- pkgs/stream_channel/analysis_options.yaml | 4 +++ .../stream_channel/lib/src/multi_channel.dart | 2 +- .../lib/src/stream_channel_controller.dart | 4 +-- .../lib/src/stream_channel_transformer.dart | 4 +-- pkgs/stream_channel/lib/stream_channel.dart | 30 +++++++++---------- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 743cc902d..107424e55 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -6,3 +6,7 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error + +linter: + rules: + - comment_references diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e7e2584aa..a1ee0574f 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -86,7 +86,7 @@ class _MultiChannel extends StreamChannelMixin /// This will be `null` if the underlying communication channel is closed. StreamChannel _inner; - /// The subscription to [_inner.stream]. + /// The subscription to [_inner].stream. StreamSubscription _innerStreamSubscription; Stream get stream => _mainController.foreign.stream; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 45b2865ed..146e99667 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -50,8 +50,8 @@ class StreamChannelController { /// /// If [allowForeignErrors] is `false`, errors are not allowed to be passed to /// the foreign channel's sink. If any are, the connection will close and the - /// error will be forwarded to the foreign channel's [Sink.done] future. This - /// guarantees that the local stream will never emit errors. + /// error will be forwarded to the foreign channel's [StreamSink.done] future. + /// This guarantees that the local stream will never emit errors. StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { var localToForeignController = new StreamController(sync: sync); var foreignToLocalController = new StreamController(sync: sync); diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 4fcd3cd69..cc9bad881 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -23,8 +23,8 @@ import 'transformer/typed.dart'; /// the stream to close before it emits any more events. This guarantee is /// invalidated when an asynchronous gap is added between the original stream's /// event dispatch and the returned stream's, for example by transforming it -/// with a [StreamTransformer]. The guarantee can be easily preserved using [new -/// StreamChannel.withCloseGuarantee]. +/// with a [StreamTransformer]. The guarantee can be easily preserved using +/// [StreamChannel.withCloseGuarantee]. class StreamChannelTransformer { /// The transformer to use on the channel's stream. final StreamTransformer _streamTransformer; diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 8d0e60421..ce3cf04a7 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -25,8 +25,8 @@ export 'src/stream_channel_transformer.dart'; /// canonical indicator that the channel has closed. If they wish to close the /// channel, they should close the [sink]—canceling the stream subscription is /// not sufficient. Protocol errors may be emitted through the stream or through -/// [Sink.done], depending on their underlying cause. Note that the sink may -/// silently drop events if the channel closes before [Sink.close] is called. +/// [sink].done, depending on their underlying cause. Note that the sink may +/// silently drop events if the channel closes before [sink].close is called. /// /// Implementations are strongly encouraged to mix in or extend /// [StreamChannelMixin] to get default implementations of the various instance @@ -43,7 +43,7 @@ export 'src/stream_channel_transformer.dart'; /// /// * After the stream closes, the sink is automatically closed. If this /// happens, sink methods should silently drop their arguments until -/// [Sink.close] is called. +/// [sink].close is called. /// /// * If the stream closes before it has a listener, the sink should silently /// drop events if possible. @@ -53,7 +53,7 @@ export 'src/stream_channel_transformer.dart'; /// even after the subscription has been canceled. /// /// * The sink *either* forwards errors to the other endpoint *or* closes as -/// soon as an error is added and forwards that error to the [Sink.done] +/// soon as an error is added and forwards that error to the [sink].done /// future. /// /// These guarantees allow users to interact uniformly with all implementations, @@ -69,8 +69,8 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// /// Note that this stream/sink pair must provide the guarantees listed in the - /// [StreamChannel] documentation. If they don't do so natively, [new - /// StreamChannel.withGuarantees] should be used instead. + /// [StreamChannel] documentation. If they don't do so natively, + /// [StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => new _StreamChannel(stream, sink); @@ -83,7 +83,7 @@ abstract class StreamChannel { /// /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to /// [sink]. If any are, the connection will close and the error will be - /// forwarded to [Sink.done]. + /// forwarded to [sink].done. factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, {bool allowSinkErrors: true}) => new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); @@ -101,33 +101,33 @@ abstract class StreamChannel { Stream stream, StreamSink sink) => new CloseGuaranteeChannel(stream, sink); - /// Connects [this] to [other], so that any values emitted by either are sent + /// Connects this to [other], so that any values emitted by either are sent /// directly to the other. void pipe(StreamChannel other); - /// Transforms [this] using [transformer]. + /// Transforms this using [transformer]. /// /// This is identical to calling `transformer.bind(channel)`. StreamChannel transform(StreamChannelTransformer transformer); - /// Transforms only the [stream] component of [this] using [transformer]. + /// Transforms only the [stream] component of this using [transformer]. StreamChannel transformStream(StreamTransformer transformer); - /// Transforms only the [sink] component of [this] using [transformer]. + /// Transforms only the [sink] component of this using [transformer]. StreamChannel transformSink(StreamSinkTransformer transformer); - /// Returns a copy of [this] with [stream] replaced by [change]'s return + /// Returns a copy of this with [stream] replaced by [change]'s return /// value. StreamChannel changeStream(Stream change(Stream stream)); - /// Returns a copy of [this] with [sink] replaced by [change]'s return + /// Returns a copy of this with [sink] replaced by [change]'s return /// value. StreamChannel changeSink(StreamSink change(StreamSink sink)); - /// Returns a copy of [this] with the generic type coerced to [S]. + /// Returns a copy of this with the generic type coerced to [S]. /// /// If any events emitted by [stream] aren't of type [S], they're converted - /// into [CastError] events. Similarly, if any events are added to [sync] that + /// into [CastError] events. Similarly, if any events are added to [sink] that /// aren't of type [S], a [CastError] is thrown. StreamChannel cast(); } From 3439cf13d68aa256d31a762b0874309f4b8510f5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 8 Jun 2018 15:44:39 -0700 Subject: [PATCH 0436/1215] Improve parsing logic to better align with what is supported by pub (dart-lang/pubspec_parse#9) * Allow environment constraint values to be null * Treat dependencies with empty map values like they are empty. * Use an SDK constraint in tests that is compatible with the supported SDK * Update tests to verify behavior of pub client * Failing test cases should cause pub to report a parse error * Successful test cases should be parsed successfully by pub, even if pub get ends up failing for another reason --- pkgs/pubspec_parse/CHANGELOG.md | 2 +- pkgs/pubspec_parse/lib/src/dependency.dart | 16 ++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 12 ++- pkgs/pubspec_parse/pubspec.yaml | 2 + pkgs/pubspec_parse/test/dependency_test.dart | 13 ++- pkgs/pubspec_parse/test/parse_test.dart | 31 +++---- pkgs/pubspec_parse/test/pub_utils.dart | 95 ++++++++++++++++++++ pkgs/pubspec_parse/test/test_utils.dart | 29 +++++- 8 files changed, 160 insertions(+), 40 deletions(-) create mode 100644 pkgs/pubspec_parse/test/pub_utils.dart diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index c0c94c9e4..720f0e723 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.1.1 - Fixed name collision with error type in latest `package:json_annotation`. -- Improved parsing of hosted dependencies. +- Improved parsing of hosted dependencies and environment constraints. ## 0.1.0 diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 1498740ab..c4f7b26ec 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -62,12 +62,7 @@ Dependency _fromJson(dynamic data) { } Dependency _fromMap(Map data) { - if (data.entries.isEmpty) { -// TODO: provide list of supported keys? - throw new CheckedFromJsonException( - data, null, 'Dependency', 'Must provide at least one key.'); - } - + assert(data.entries.isNotEmpty); if (data.entries.length > 1) { throw new CheckedFromJsonException(data, data.keys.skip(1).first as String, 'Dependency', 'Expected only one key.'); @@ -179,9 +174,12 @@ class HostedDependency extends Dependency { data = {'version': data}; } - if (data is Map && - (data.containsKey('version') || data.containsKey('hosted'))) { - return _$HostedDependencyFromJson(data); + if (data is Map) { + if (data.isEmpty || + data.containsKey('version') || + data.containsKey('hosted')) { + return _$HostedDependencyFromJson(data); + } } return null; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 7cc1ee13b..a5cba623e 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -124,8 +124,10 @@ Map _environmentMap(Map source) => source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); } - if (value is String) { - VersionConstraint constraint; + VersionConstraint constraint; + if (value == null) { + constraint = null; + } else if (value is String) { try { constraint = new VersionConstraint.parse(value); } on FormatException catch (e) { @@ -133,8 +135,10 @@ Map _environmentMap(Map source) => } return new MapEntry(key, constraint); + } else { + throw new CheckedFromJsonException( + source, key, 'VersionConstraint', '`$value` is not a String.'); } - throw new CheckedFromJsonException( - source, key, 'VersionConstraint', '`$value` is not a String.'); + return new MapEntry(key, constraint); }); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 8d305ef82..0bf1220b9 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -20,3 +20,5 @@ dev_dependencies: path: ^1.5.1 stack_trace: ^1.9.2 test: ^0.12.0 + test_descriptor: ^1.0.3 + test_process: ^1.0.2 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index f9fd369d1..658e13275 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -29,13 +29,6 @@ line 4, column 10: Not a valid dependency value. ^^^'''); }); - test('empty map', () { - _expectThrows({}, r''' -line 4, column 10: Must provide at least one key. - "dep": {} - ^^'''); - }); - test('map with too many keys', () { _expectThrows({'path': 'a', 'git': 'b'}, r''' line 5, column 12: Expected only one key. @@ -53,6 +46,12 @@ void _hostedDependency() { expect(dep.toString(), 'HostedDependency: any'); }); + test('empty map', () { + var dep = _dependency({}); + expect(dep.hosted, isNull); + expect(dep.toString(), 'HostedDependency: any'); + }); + test('string version', () { var dep = _dependency('^1.0.0'); expect(dep.version.toString(), '^1.0.0'); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 1d7fcd8d5..00a0de97a 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -25,31 +25,42 @@ void main() { }); test('all fields set', () { - var constraint = new Version.parse('1.2.3'); + var version = new Version.parse('1.2.3'); + var sdkConstraint = new VersionConstraint.parse('>=2.0.0-dev.54 <2.0.0'); var value = parse({ 'name': 'sample', - 'version': constraint.toString(), + 'version': version.toString(), 'author': 'name@example.com', - 'environment': {'sdk': '1.2.3'}, + 'environment': {'sdk': sdkConstraint.toString()}, 'description': 'description', 'homepage': 'homepage', 'documentation': 'documentation' }); expect(value.name, 'sample'); - expect(value.version, constraint); + expect(value.version, version); expect(value.description, 'description'); expect(value.homepage, 'homepage'); // ignore: deprecated_member_use expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); expect(value.environment, hasLength(1)); - expect(value.environment, containsPair('sdk', constraint)); + expect(value.environment, containsPair('sdk', sdkConstraint)); expect(value.documentation, 'documentation'); expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); expect(value.dependencyOverrides, isEmpty); }); + test('environment values can be null', () { + var value = parse({ + 'name': 'sample', + 'environment': {'sdk': null} + }); + expect(value.name, 'sample'); + expect(value.environment, hasLength(1)); + expect(value.environment, containsPair('sdk', isNull)); + }); + group('author, authors', () { test('one author', () { var value = parse({'name': 'sample', 'author': 'name@example.com'}); @@ -132,16 +143,6 @@ line 4, column 3: Use "sdk" to for Dart SDK constraints. ^^^^^^'''); }); - test('environment values cannot be null', () { - expectParseThrows({ - 'name': 'sample', - 'environment': {'sdk': null} - }, r''' -line 4, column 10: `null` is not a String. - "sdk": null - ^^^^^'''); - }); - test('environment values cannot be int', () { expectParseThrows({ 'name': 'sample', diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart new file mode 100644 index 000000000..984bb49ae --- /dev/null +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -0,0 +1,95 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:io'; + +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; +import 'package:test_descriptor/test_descriptor.dart' as d; +import 'package:test_process/test_process.dart'; + +Future tryPub(String content) async { + await d.file('pubspec.yaml', content).create(); + + var proc = await TestProcess.start(_pubPath, ['get', '--offline'], + workingDirectory: d.sandbox); + + var result = await ProcResult.fromTestProcess(proc); + + printOnFailure([ + '-----BEGIN pub output-----', + result.toString().trim(), + '-----END pub output-----', + ].join('\n')); + + if (result.exitCode == 0) { + var lockContent = + new File(p.join(d.sandbox, 'pubspec.lock')).readAsStringSync(); + + printOnFailure([ + '-----BEGIN pubspec.lock-----', + lockContent.trim(), + '-----END pubspec.lock-----', + ].join('\n')); + } + + return result; +} + +class ProcResult { + final int exitCode; + final List lines; + + bool get cleanParse => exitCode == 0 || exitCode == 66 || exitCode == 69; + + ProcResult(this.exitCode, this.lines); + + static Future fromTestProcess(TestProcess proc) async { + var items = []; + + var values = await Future.wait([ + proc.exitCode, + proc + .stdoutStream() + .forEach((line) => items.add(new ProcLine(false, line))), + proc + .stderrStream() + .forEach((line) => items.add(new ProcLine(true, line))), + ]); + + return new ProcResult(values[0] as int, items); + } + + @override + String toString() { + var buffer = new StringBuffer('Exit code: $exitCode'); + for (var line in lines) { + buffer.write('\n$line'); + } + return buffer.toString(); + } +} + +class ProcLine { + final bool isError; + final String line; + + ProcLine(this.isError, this.line); + + @override + String toString() => '${isError ? 'err' : 'out'} $line'; +} + +/// The path to the root directory of the SDK. +final String _sdkDir = (() { + // The Dart executable is in "/path/to/sdk/bin/dart", so two levels up is + // "/path/to/sdk". + var aboveExecutable = p.dirname(p.dirname(Platform.resolvedExecutable)); + assert(FileSystemEntity.isFileSync(p.join(aboveExecutable, 'version'))); + return aboveExecutable; +})(); + +final String _pubPath = + p.join(_sdkDir, 'bin', Platform.isWindows ? 'pub.bat' : 'pub'); diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 65000afb4..7180292ff 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.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. +import 'dart:cli'; import 'dart:convert'; import 'package:json_annotation/json_annotation.dart'; @@ -9,6 +10,8 @@ import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; +import 'pub_utils.dart'; + String _encodeJson(Object input) => const JsonEncoder.withIndent(' ').convert(input); @@ -48,11 +51,29 @@ void _printDebugParsedYamlException(ParsedYamlException e) { Pubspec parse(Object content, {bool quietOnError: false}) { quietOnError ??= false; + + var encoded = _encodeJson(content); + + var pubResult = waitFor(tryPub(encoded)); + try { - return new Pubspec.parse(_encodeJson(content)); - } on ParsedYamlException catch (e) { - if (!quietOnError) { - _printDebugParsedYamlException(e); + var value = new Pubspec.parse(encoded); + + addTearDown(() { + expect(pubResult.cleanParse, isTrue, + reason: + 'On success, parsing from the pub client should also succeed.'); + }); + return value; + } catch (e) { + addTearDown(() { + expect(pubResult.cleanParse, isFalse, + reason: 'On failure, parsing from the pub client should also fail.'); + }); + if (e is ParsedYamlException) { + if (!quietOnError) { + _printDebugParsedYamlException(e); + } } rethrow; } From 8e6c600ad84e43cf5724de2f84763e21d80c8868 Mon Sep 17 00:00:00 2001 From: BC Ko Date: Fri, 8 Jun 2018 16:50:37 -0700 Subject: [PATCH 0437/1215] Update .gitignore to new `dart_tool` pub cache (dart-lang/stack_trace#40) See dart-lang/sdkdart-lang/stack_trace#32030 --- pkgs/stack_trace/.gitignore | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/pkgs/stack_trace/.gitignore b/pkgs/stack_trace/.gitignore index 7dbf0350d..34595d725 100644 --- a/pkgs/stack_trace/.gitignore +++ b/pkgs/stack_trace/.gitignore @@ -1,15 +1,6 @@ +# See https://www.dartlang.org/guides/libraries/private-files # Don’t commit the following directories created by pub. -.buildlog -.pub/ -build/ -packages +.dart_tool/ .packages - -# Or the files created by dart2js. -*.dart.js -*.js_ -*.js.deps -*.js.map - -# Include when developing application packages. -pubspec.lock \ No newline at end of file +.pub/ +pubspec.lock From b0dc30207fa6f5c617f0618ed3edc22b75f1da74 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Jun 2018 09:27:35 -0700 Subject: [PATCH 0438/1215] Enable prefer_typing_unitialized_varables lint (dart-lang/stream_channel#30) Work towards dart-lang/stream_channel#29 Using the lint catches a bug were an uninitialized variable was causing an instantiation to pick up a reified type of `dynamic` instead of a useful type. --- pkgs/stream_channel/analysis_options.yaml | 1 + .../lib/src/isolate_channel.dart | 2 +- .../stream_channel/lib/src/multi_channel.dart | 12 +++++----- .../test/disconnector_test.dart | 8 +++---- .../test/isolate_channel_test.dart | 8 +++---- .../test/json_document_transformer_test.dart | 4 ++-- .../test/multi_channel_test.dart | 22 +++++++++---------- .../test/stream_channel_completer_test.dart | 8 +++---- .../test/stream_channel_controller_test.dart | 4 ++-- .../test/with_close_guarantee_test.dart | 4 ++-- .../test/with_guarantees_test.dart | 6 ++--- 11 files changed, 40 insertions(+), 39 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 107424e55..bf7c331dd 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -10,3 +10,4 @@ analyzer: linter: rules: - comment_references + - prefer_typing_uninitialized_variables diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 290c2ff2c..4a1717df1 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -49,7 +49,7 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - var subscription; + StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = new StreamChannelController( diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a1ee0574f..a6d684a13 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -72,7 +72,7 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([id]); + VirtualChannel virtualChannel([int id]); } /// The implementation of [MultiChannel]. @@ -166,15 +166,15 @@ class _MultiChannel extends StreamChannelMixin onError: _mainController.local.sink.addError); } - VirtualChannel virtualChannel([id]) { - var inputId; - var outputId; + VirtualChannel virtualChannel([int id]) { + int inputId; + int outputId; if (id != null) { // Since the user is passing in an id, we're connected to a remote // VirtualChannel. This means messages they send over this channel will // have the original odd id, but our replies will have an even id. inputId = id; - outputId = (id as int) + 1; + outputId = id + 1; } else { // Since we're generating an id, we originated this VirtualChannel. This // means messages we send over this channel will have the original odd id, @@ -256,7 +256,7 @@ class VirtualChannel extends StreamChannelMixin /// This can be sent across the [MultiChannel] to provide the remote endpoint /// a means to connect to this channel. Nothing about this is guaranteed /// except that it will be JSON-serializable. - final id; + final int id; final Stream stream; final StreamSink sink; diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 5b725740c..62ef78b54 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -9,10 +9,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var disconnector; - var channel; + StreamController streamController; + StreamController sinkController; + Disconnector disconnector; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 8f3318469..00f45844c 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -11,9 +11,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var receivePort; - var sendPort; - var channel; + ReceivePort receivePort; + SendPort sendPort; + StreamChannel channel; setUp(() { receivePort = new ReceivePort(); var receivePortForSend = new ReceivePort(); @@ -126,7 +126,7 @@ void main() { }); group("connect constructors", () { - var connectPort; + ReceivePort connectPort; setUp(() { connectPort = new ReceivePort(); }); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index d6fd72b96..3c6d11c91 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -9,8 +9,8 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; + StreamController streamController; + StreamController sinkController; StreamChannel channel; setUp(() { streamController = new StreamController(); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 99a53c328..ddc4150bb 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -6,9 +6,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var controller; - var channel1; - var channel2; + StreamChannelController controller; + MultiChannel channel1; + MultiChannel channel2; setUp(() { controller = new StreamChannelController(); channel1 = new MultiChannel(controller.local); @@ -84,8 +84,8 @@ void main() { }); group("a locally-created virtual channel", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -184,8 +184,8 @@ void main() { }); group("a remotely-created virtual channel", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -296,8 +296,8 @@ void main() { }); group("when the underlying stream", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -405,8 +405,8 @@ void main() { }); group("for a virtual channel:", () { - var virtual1; - var virtual2; + VirtualChannel virtual1; + VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 8d830058a..666efe9ed 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -8,10 +8,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var completer; - var streamController; - var sinkController; - var innerChannel; + StreamChannelCompleter completer; + StreamController streamController; + StreamController sinkController; + StreamChannel innerChannel; setUp(() { completer = new StreamChannelCompleter(); streamController = new StreamController(); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index c092570f5..483b7f6f1 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -7,7 +7,7 @@ import 'package:test/test.dart'; void main() { group("asynchronously", () { - var controller; + StreamChannelController controller; setUp(() { controller = new StreamChannelController(); }); @@ -44,7 +44,7 @@ void main() { }); group("synchronously", () { - var controller; + StreamChannelController controller; setUp(() { controller = new StreamChannelController(sync: true); }); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index a6527a716..8e1b63119 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -16,8 +16,8 @@ final _delaySinkTransformer = new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { - var controller; - var channel; + StreamChannelController controller; + StreamChannel channel; setUp(() { controller = new StreamChannelController(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index e1302f64c..dcdffe089 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -8,9 +8,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - var streamController; - var sinkController; - var channel; + StreamController streamController; + StreamController sinkController; + StreamChannel channel; setUp(() { streamController = new StreamController(); sinkController = new StreamController(); From 9ad0a964e1ad06062b0040dfa9177923693b32bd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Jun 2018 10:41:23 -0700 Subject: [PATCH 0439/1215] misc: enable a few more lints (dart-lang/pubspec_parse#10) --- pkgs/pubspec_parse/analysis_options.yaml | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/test_utils.dart | 4 ++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 8521d7b7d..84a5b8d5e 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -9,6 +9,7 @@ analyzer: unused_local_variable: error linter: rules: + - always_declare_return_types - annotate_overrides - avoid_empty_else - avoid_function_literals_in_foreach_calls @@ -37,6 +38,7 @@ linter: - library_names - library_prefixes - list_remove_unrelated_type + - literal_only_boolean_expressions - no_adjacent_strings_in_list - no_duplicate_case_values - non_constant_identifier_names @@ -51,6 +53,7 @@ linter: - prefer_conditional_assignment - prefer_const_constructors - prefer_contains + - prefer_equal_for_default_values - prefer_final_fields - prefer_initializing_formals - prefer_interpolation_to_compose_strings @@ -73,4 +76,5 @@ linter: - unnecessary_statements - unnecessary_this - unrelated_type_equality_checks + - use_rethrow_when_possible - valid_regexps diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 0bf1220b9..e6dbc4c40 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.1 +version: 0.1.2-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 7180292ff..808d7c5e2 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -49,7 +49,7 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } } -Pubspec parse(Object content, {bool quietOnError: false}) { +Pubspec parse(Object content, {bool quietOnError = false}) { quietOnError ??= false; var encoded = _encodeJson(content); @@ -91,5 +91,5 @@ class FeatureMatcher extends CustomMatcher { : super('`$name`', '`$name`', matcher); @override - featureValueOf(covariant T actual) => _feature(actual); + Object featureValueOf(covariant T actual) => _feature(actual); } From 338ee53371ac67e88a094bb4fcb6af73075edfa4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Jun 2018 10:53:40 -0700 Subject: [PATCH 0440/1215] Cast streams to correct types in IsolateChannel (dart-lang/stream_channel#31) Fixes dart-lang/stream_channel#29 - Add a type on the IsolateChannel in one of the tests so that it exhibits the problem when run in Dart 2 mode. - Cast the streams coming from the ReceivePort instances to the appropriate types since ReceivePort is always `Stream`. - Remove the type on the subscription variable since it's a subscription on a dynamic stream and otherwise would never have the correct type. --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 8 +++++--- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 4 ++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index b284e5ed8..3dfbbc6f9 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.7+1 + +* Fix Dart 2 runtime types in `IsolateChannel`. + ## 1.6.7 * Update SDK version to 2.0.0-dev.17.0. diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 4a1717df1..d785ae118 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -49,12 +49,14 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - StreamSubscription subscription; + StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = new StreamChannelController( allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription).pipe(controller.local.sink); + new SubscriptionStream(subscription) + .cast() + .pipe(controller.local.sink); controller.local.stream .listen((data) => message.send(data), onDone: receivePort.close); @@ -93,7 +95,7 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { var controller = new StreamChannelController(allowForeignErrors: false, sync: true); - receivePort.pipe(controller.local.sink); + receivePort.cast().pipe(controller.local.sink); controller.local.stream .listen((data) => sendPort.send(data), onDone: receivePort.close); return new IsolateChannel._( diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index ff2209c94..54bd97217 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.7 +version: 1.6.7+1 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 00f45844c..4c73ab090 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -136,8 +136,8 @@ void main() { }); test("create a connected pair of channels", () { - var channel1 = new IsolateChannel.connectReceive(connectPort); - var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + var channel1 = new IsolateChannel.connectReceive(connectPort); + var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); From b89abe3ec35d8aa1d12d3c1d07ecba26c795a95e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Jun 2018 11:04:01 -0700 Subject: [PATCH 0441/1215] Remove dupe test_types_in_equals (dart-lang/pubspec_parse#11) --- pkgs/pubspec_parse/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 84a5b8d5e..8cd2a0f6d 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -65,7 +65,6 @@ linter: - slash_for_doc_comments - super_goes_last - test_types_in_equals - - test_types_in_equals - throw_in_finally - type_init_formals - unawaited_futures From c03db609d42d0b4512363c07f0ffd9df5d7e6542 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 13 Jun 2018 12:31:17 -0700 Subject: [PATCH 0442/1215] Loosen the expectations in a test case (dart-lang/stack_trace#44) Dart 2 runtime semantics changed the traces we were tracking somehow, but not in a way that matters for user experience. --- pkgs/stack_trace/test/chain/vm_test.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index a47cbf7e5..f84d1d2c7 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -467,14 +467,12 @@ void main() { } }); - expect(chain.traces, hasLength(2)); + expect(chain.traces, hasLength(greaterThan(1))); // Assert that we've trimmed the VM's stack chains here to avoid // duplication. expect(chain.traces.first.toString(), equals(new Chain.parse(trace.toString()).traces.first.toString())); - expect( - chain.traces.last.frames, contains(frameMember(startsWith('main')))); }); }); From 55d124cc58294e11c02d551e6a1180e6f7ff9c95 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Jun 2018 15:12:12 -0700 Subject: [PATCH 0443/1215] Forward errors thrown during `asyncWhere` (dart-lang/stream_transform#49) - Add a try/catch and a test for the new behavior. - Update the Doc comment with more details on the behavior. --- pkgs/stream_transform/CHANGELOG.md | 5 +++++ .../stream_transform/lib/src/async_where.dart | 20 ++++++++++++++++++- .../test/async_where_test.dart | 16 +++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index ada1e4b50..2ad693c01 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.14 + +- `asyncWhere` will now forward exceptions thrown by the callback through the + result Stream. + ## 0.0.13 - `mergeAll` now accepts an `Iterable` instead of only `List`. diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/async_where.dart index 6a4fc329f..734f65f9e 100644 --- a/pkgs/stream_transform/lib/src/async_where.dart +++ b/pkgs/stream_transform/lib/src/async_where.dart @@ -6,13 +6,31 @@ import 'dart:async'; import 'from_handlers.dart'; /// Like [Stream.where] but allows the [test] to return a [Future]. +/// +/// Events on the result stream will be emitted in the order that [test] +/// completes which may not match the order of the original stream. +/// +/// If the source stream is a broadcast stream the result will be as well. When +/// used with a broadcast stream behavior also differs from [Stream.where] in +/// that the [test] function is only called once per event, rather than once +/// per listener per event. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// Errors during the conversion are also forwarded to the result stream. +/// +/// The result stream will not close until the source stream closes and all +/// pending [test] calls have finished. StreamTransformer asyncWhere(FutureOr test(T element)) { var valuesWaiting = 0; var sourceDone = false; return fromHandlers(handleData: (element, sink) { valuesWaiting++; () async { - if (await test(element)) sink.add(element); + try { + if (await test(element)) sink.add(element); + } catch (e, st) { + sink.addError(e, st); + } valuesWaiting--; if (valuesWaiting <= 0 && sourceDone) sink.close(); }(); diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 4cf8af6f6..9c6650666 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -66,4 +66,20 @@ void main() { expect(firstDone, true); expect(secondDone, true); }); + + test('forwards errors emitted by the test callback', () async { + var errors = []; + var emitted = []; + var values = new Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(asyncWhere((e) async { + await new Future(() {}); + if (e.isEven) throw new Exception('$e'); + return true; + })); + var done = new Completer(); + filtered.listen(emitted.add, onError: errors.add, onDone: done.complete); + await done.future; + expect(emitted, [1, 3]); + expect(errors.map((e) => '$e'), ['Exception: 2', 'Exception: 4']); + }); } From 3c2c0cacbba1eefb65acc994d5cb6f2a0a4334c9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Jun 2018 16:11:44 -0700 Subject: [PATCH 0444/1215] Add `concurrentAsyncMap` (dart-lang/stream_transform#50) The `Stream.asyncMap` call is always serial and preserves ordering. --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/README.md | 9 +- .../lib/src/concurrent_async_map.dart | 44 +++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- .../test/concurrent_async_map_test.dart | 160 ++++++++++++++++++ 6 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/concurrent_async_map.dart create mode 100644 pkgs/stream_transform/test/concurrent_async_map_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 2ad693c01..a7c0a7e3f 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -2,6 +2,7 @@ - `asyncWhere` will now forward exceptions thrown by the callback through the result Stream. +- Added `concurrentAsyncMap`. ## 0.0.13 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 5e59fc988..5e5445746 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -2,8 +2,8 @@ Utility methods to create `StreamTransfomer` instances to manipulate Streams. # asyncMapBuffer -Like `asyncMap` but events are buffered until previous events have been -processed. +Like `asyncMap` but events are buffered in a List until previous events have +been processed rather than being called for each element individually. # asyncWhere @@ -24,6 +24,11 @@ collected values are emitted. Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. +# concurrentAsyncMap + +Like `asyncMap` but the convert callback can be called with subsequent values +before it has finished for previous values. + # followedBy Appends the values of a stream after another stream finishes. diff --git a/pkgs/stream_transform/lib/src/concurrent_async_map.dart b/pkgs/stream_transform/lib/src/concurrent_async_map.dart new file mode 100644 index 000000000..791c84c82 --- /dev/null +++ b/pkgs/stream_transform/lib/src/concurrent_async_map.dart @@ -0,0 +1,44 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'from_handlers.dart'; + +/// Like [Stream.asyncMap] but the [convert] callback may be called for an +/// element before processing for the previous element is finished. +/// +/// Events on the result stream will be emitted in the order that [convert] +/// completed which may not match the order of the original stream. +/// +/// If the source stream is a broadcast stream the result will be as well. When +/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in +/// that the [convert] function is only called once per event, rather than once +/// per listener per event. The [convert] callback won't be called for events +/// while a broadcast stream has no listener. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// Errors during the conversion are also forwarded to the result stream. +/// +/// The result stream will not close until the source stream closes and all +/// pending conversions have finished. +StreamTransformer concurrentAsyncMap(FutureOr convert(S event)) { + var valuesWaiting = 0; + var sourceDone = false; + return fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + try { + sink.add(await convert(element)); + } catch (e, st) { + sink.addError(e, st); + } + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + }); +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 942391b04..13b80a463 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -8,6 +8,7 @@ export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/chain_transformers.dart'; export 'src/concat.dart'; +export 'src/concurrent_async_map.dart'; export 'src/debounce.dart'; export 'src/followed_by.dart'; export 'src/map.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 53f7bbf39..6d1d5378b 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.13 +version: 0.0.14 environment: sdk: ">=2.0.0-dev.20.0 <2.0.0" diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart new file mode 100644 index 000000000..9ea11a5bc --- /dev/null +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -0,0 +1,160 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var streamTypes = { + 'single subscription': () => new StreamController(), + 'broadcast': () => new StreamController.broadcast() + }; + StreamController streamController; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + List finishWork; + List values; + + Future convert(dynamic value) { + values.add(value); + var completer = new Completer(); + finishWork.add(completer); + return completer.future; + } + + for (var streamType in streamTypes.keys) { + group('concurrentAsyncMap for stream type: [$streamType]', () { + setUp(() { + valuesCanceled = false; + streamController = streamTypes[streamType]() + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + finishWork = []; + values = []; + transformed = + streamController.stream.transform(concurrentAsyncMap(convert)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('does not emit before convert finishes', () async { + streamController.add(1); + await new Future(() {}); + expect(emittedValues, isEmpty); + expect(values, [1]); + finishWork.first.complete(1); + await new Future(() {}); + expect(emittedValues, [1]); + }); + + test('allows calls to convert before the last one finished', () async { + streamController.add(1); + streamController.add(2); + streamController.add(3); + await new Future(() {}); + expect(values, [1, 2, 3]); + }); + + test('forwards errors directly without waiting for previous convert', + () async { + streamController.add(1); + await new Future(() {}); + streamController.addError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors which occur during the convert', () async { + streamController.add(1); + await new Future(() {}); + finishWork.first.completeError('error'); + await new Future(() {}); + expect(errors, ['error']); + }); + + test('can continue handling events after an error', () async { + streamController.add(1); + await new Future(() {}); + finishWork[0].completeError('error'); + streamController.add(2); + await new Future(() {}); + expect(values, [1, 2]); + finishWork[1].completeError('another'); + await new Future(() {}); + expect(errors, ['error', 'another']); + }); + + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('closes when values end if no conversion is pending', () async { + expect(isDone, false); + await streamController.close(); + await new Future(() {}); + expect(isDone, true); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + streamController.add(1); + await new Future(() {}); + finishWork.first.complete('result'); + await new Future(() {}); + expect(emittedValues, ['result']); + expect(otherValues, ['result']); + }); + + test('multiple listeners get done when values end', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + streamController.add(1); + await new Future(() {}); + await streamController.close(); + expect(isDone, false); + expect(otherDone, false); + finishWork.first.complete(); + await new Future(() {}); + expect(isDone, true); + expect(otherDone, true); + }); + + test('can cancel and relisten', () async { + streamController.add(1); + await new Future(() {}); + finishWork.first.complete('first'); + await new Future(() {}); + await subscription.cancel(); + streamController.add(2); + await new Future(() {}); + subscription = transformed.listen(emittedValues.add); + streamController.add(3); + await new Future(() {}); + expect(values, [1, 3]); + finishWork[1].complete('second'); + await new Future(() {}); + expect(emittedValues, ['first', 'second']); + }); + } + }); + } +} From afcb6224619a36cf2307b9101fc557ccee13b2f8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 15 Jun 2018 13:57:52 -0700 Subject: [PATCH 0445/1215] fix: update generated output for latest source_gen (dart-lang/pubspec_parse#12) Also updated test code to use new TypeMatcher --- pkgs/pubspec_parse/lib/src/dependency.g.dart | 2 +- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/test_utils.dart | 18 +++--------------- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 6133cb454..ed384a994 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -7,7 +7,7 @@ part of 'dependency.dart'; // ************************************************************************** -// Generator: JsonSerializableGenerator +// JsonSerializableGenerator // ************************************************************************** SdkDependency _$SdkDependencyFromJson(Map json) { diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index f585b847d..921b7e435 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -7,7 +7,7 @@ part of 'pubspec.dart'; // ************************************************************************** -// Generator: JsonSerializableGenerator +// JsonSerializableGenerator // ************************************************************************** Pubspec _$PubspecFromJson(Map json) { diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index e6dbc4c40..78dba00e9 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -19,6 +19,6 @@ dev_dependencies: json_serializable: ^0.5.7 path: ^1.5.1 stack_trace: ^1.9.2 - test: ^0.12.0 + test: ^0.12.42 test_descriptor: ^1.0.3 test_process: ^1.0.2 diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 808d7c5e2..37cd3e96b 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -15,14 +15,13 @@ import 'pub_utils.dart'; String _encodeJson(Object input) => const JsonEncoder.withIndent(' ').convert(input); -Matcher _throwsParsedYamlException(String prettyValue) => throwsA(allOf( - const isInstanceOf(), - new FeatureMatcher('formattedMessage', (e) { +Matcher _throwsParsedYamlException(String prettyValue) => + throwsA(const TypeMatcher().having((e) { var message = e.formattedMessage; printOnFailure("Actual error format:\nr'''\n$message'''"); _printDebugParsedYamlException(e); return message; - }, prettyValue))); + }, 'formattedMessage', prettyValue)); void _printDebugParsedYamlException(ParsedYamlException e) { var innerError = e.innerError; @@ -82,14 +81,3 @@ Pubspec parse(Object content, {bool quietOnError = false}) { void expectParseThrows(Object content, String expectedError) => expect( () => parse(content, quietOnError: true), _throwsParsedYamlException(expectedError)); - -// TODO(kevmoo) add this to pkg/matcher – is nice! -class FeatureMatcher extends CustomMatcher { - final dynamic Function(T value) _feature; - - FeatureMatcher(String name, this._feature, matcher) - : super('`$name`', '`$name`', matcher); - - @override - Object featureValueOf(covariant T actual) => _feature(actual); -} From 62162ccf747b5c0b5beef4c3ffd86368ea687953 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 19 Jun 2018 17:03:26 -0700 Subject: [PATCH 0446/1215] fix(Dependency) ignore extra `version` key with path and git deps (dart-lang/pubspec_parse#14) Streamline the handling of all dependencies Improve errors when unsupported keys are provided in dependencies Better handling (and testing) for invalid `sdk:` values Handle scp-like URIs for git dependencies - See https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a Fixes https://github.com/dart-lang/pubspec_parse/issues/13 Prepare for release --- pkgs/pubspec_parse/CHANGELOG.md | 8 ++ pkgs/pubspec_parse/lib/src/dependency.dart | 137 +++++++++++-------- pkgs/pubspec_parse/lib/src/dependency.g.dart | 6 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/dependency_test.dart | 87 ++++++++++-- pkgs/pubspec_parse/test/git_uri_test.dart | 25 ++++ 6 files changed, 188 insertions(+), 77 deletions(-) create mode 100644 pkgs/pubspec_parse/test/git_uri_test.dart diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 720f0e723..30551e713 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.1.2 + +- Allow superfluous `version` keys with `git` and `path` dependencies. +- Improve errors when unsupported keys are provided in dependencies. +- Provide better errors with invalid `sdk` dependency values. +- Support "scp-like syntax" for Git SSH URIs in the form + `[user@]host.xz:path/to/repo.git/`. + ## 0.1.1 - Fixed name collision with error type in latest `package:json_annotation`. diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index c4f7b26ec..07d08b57b 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -6,6 +6,8 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; +import 'errors.dart'; + part 'dependency.g.dart'; Map parseDeps(Map source) => @@ -40,49 +42,55 @@ Map parseDeps(Map source) => }) ?? {}; +const _sourceKeys = const ['sdk', 'git', 'path', 'hosted']; + /// Returns `null` if the data could not be parsed. Dependency _fromJson(dynamic data) { - var value = - SdkDependency.tryFromData(data) ?? HostedDependency.tryFromData(data); - - if (value != null) { - return value; + if (data is String || data == null) { + return _$HostedDependencyFromJson({'version': data}); } if (data is Map) { - try { - return _fromMap(data); - } on ArgumentError catch (e) { - throw new CheckedFromJsonException( - data, e.name, 'Dependency', e.message.toString()); - } - } - - return null; -} - -Dependency _fromMap(Map data) { - assert(data.entries.isNotEmpty); - if (data.entries.length > 1) { - throw new CheckedFromJsonException(data, data.keys.skip(1).first as String, - 'Dependency', 'Expected only one key.'); - } - - var entry = data.entries.single; - var key = entry.key as String; + var matchedKeys = + data.keys.cast().where((key) => key != 'version').toList(); + + if (data.isEmpty || (matchedKeys.isEmpty && data.containsKey('version'))) { + return _$HostedDependencyFromJson(data); + } else { + var weirdKey = matchedKeys.firstWhere((k) => !_sourceKeys.contains(k), + orElse: () => null); + + if (weirdKey != null) { + throw new InvalidKeyException( + data, weirdKey, 'Unsupported dependency key.'); + } + if (matchedKeys.length > 1) { + throw new CheckedFromJsonException(data, matchedKeys[1], 'Dependency', + 'A dependency may only have one source.'); + } - if (entry.value == null) { - throw new CheckedFromJsonException( - data, key, 'Dependency', 'Cannot be null.'); - } + var key = matchedKeys.single; - switch (key) { - case 'path': - return new PathDependency.fromData(entry.value); - case 'git': - return new GitDependency.fromData(entry.value); + try { + switch (key) { + case 'git': + return new GitDependency.fromData(data[key]); + case 'path': + return new PathDependency.fromData(data[key]); + case 'sdk': + return _$SdkDependencyFromJson(data); + case 'hosted': + return _$HostedDependencyFromJson(data); + } + throw new StateError('There is a bug in pubspec_parse.'); + } on ArgumentError catch (e) { + throw new CheckedFromJsonException( + data, e.name, 'Dependency', e.message.toString()); + } + } } + // Not a String or a Map – return null so parent logic can throw proper error return null; } @@ -97,26 +105,20 @@ abstract class Dependency { @JsonSerializable(createToJson: false) class SdkDependency extends Dependency { + @JsonKey(nullable: false, disallowNullValue: true, required: true) final String sdk; @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; SdkDependency(this.sdk, {this.version}) : super._(); - static SdkDependency tryFromData(Object data) { - if (data is Map && data.containsKey('sdk')) { - return _$SdkDependencyFromJson(data); - } - return null; - } - @override String get _info => sdk; } @JsonSerializable(createToJson: false) class GitDependency extends Dependency { - @JsonKey(fromJson: _parseUri, required: true, disallowNullValue: true) + @JsonKey(fromJson: parseGitUri, required: true, disallowNullValue: true) final Uri url; final String ref; final String path; @@ -139,7 +141,38 @@ class GitDependency extends Dependency { String get _info => 'url@$url'; } -Uri _parseUri(String value) => Uri.parse(value); +Uri parseGitUri(String value) => _tryParseScpUri(value) ?? Uri.parse(value); + +/// Supports URIs like `[user@]host.xz:path/to/repo.git/` +/// See https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a +Uri _tryParseScpUri(String value) { + var colonIndex = value.indexOf(':'); + + if (colonIndex < 0) { + return null; + } else if (colonIndex == value.indexOf('://')) { + // If the first colon is part of a scheme, it's not an scp-like URI + return null; + } + var slashIndex = value.indexOf('/'); + + if (slashIndex >= 0 && slashIndex < colonIndex) { + // Per docs: This syntax is only recognized if there are no slashes before + // the first colon. This helps differentiate a local path that contains a + // colon. For example the local path foo:bar could be specified as an + // absolute path or ./foo:bar to avoid being misinterpreted as an ssh url. + return null; + } + + var atIndex = value.indexOf('@'); + if (colonIndex > atIndex) { + var user = atIndex >= 0 ? value.substring(0, atIndex) : null; + var host = value.substring(atIndex + 1, colonIndex); + var path = value.substring(colonIndex + 1); + return new Uri(scheme: 'ssh', userInfo: user, host: host, path: path); + } + return null; +} class PathDependency extends Dependency { final String path; @@ -169,22 +202,6 @@ class HostedDependency extends Dependency { : this.version = version ?? VersionConstraint.any, super._(); - static HostedDependency tryFromData(Object data) { - if (data == null || data is String) { - data = {'version': data}; - } - - if (data is Map) { - if (data.isEmpty || - data.containsKey('version') || - data.containsKey('hosted')) { - return _$HostedDependencyFromJson(data); - } - } - - return null; - } - @override String get _info => version.toString(); } @@ -194,7 +211,7 @@ class HostedDetails { @JsonKey(required: true, disallowNullValue: true) final String name; - @JsonKey(fromJson: _parseUri, disallowNullValue: true) + @JsonKey(fromJson: parseGitUri, disallowNullValue: true) final Uri url; HostedDetails(this.name, this.url); diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index ed384a994..e4bca581e 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -12,6 +12,8 @@ part of 'dependency.dart'; SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { + $checkKeys(json, + requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); var val = new SdkDependency( $checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert(json, 'version', @@ -26,7 +28,7 @@ GitDependency _$GitDependencyFromJson(Map json) { requiredKeys: const ['url'], disallowNullValues: const ['url']); var val = new GitDependency( $checkedConvert( - json, 'url', (v) => v == null ? null : _parseUri(v as String)), + json, 'url', (v) => v == null ? null : parseGitUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), $checkedConvert(json, 'path', (v) => v as String)); return val; @@ -56,7 +58,7 @@ HostedDetails _$HostedDetailsFromJson(Map json) { var val = new HostedDetails( $checkedConvert(json, 'name', (v) => v as String), $checkedConvert( - json, 'url', (v) => v == null ? null : _parseUri(v as String))); + json, 'url', (v) => v == null ? null : parseGitUri(v as String))); return val; }); } diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 78dba00e9..e21906084 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.2-dev +version: 0.1.2 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 658e13275..def243d10 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -31,10 +31,17 @@ line 4, column 10: Not a valid dependency value. test('map with too many keys', () { _expectThrows({'path': 'a', 'git': 'b'}, r''' -line 5, column 12: Expected only one key. +line 5, column 12: A dependency may only have one source. "path": "a", ^^^'''); }); + + test('map with unsupported keys', () { + _expectThrows({'bob': 'a', 'jones': 'b'}, r''' +line 6, column 4: Unsupported dependency key. + "jones": "b" + ^^^^^^^'''); + }); }); } @@ -94,15 +101,15 @@ line 5, column 15: Unsupported value for `version`. ^^^^^^^^^^^^^^^'''); }); - test('map w/ unsupported keys', () { + test('map w/ extra keys should fail', () { _expectThrows({ 'version': '^1.0.0', 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, 'not_supported': null }, r''' -line 4, column 10: Unrecognized keys: [not_supported]; supported keys: [version, hosted] - "dep": { - ^^'''); +line 10, column 4: Unsupported dependency key. + "not_supported": null + ^^^^^^^^^^^^^^^'''); }); test('map w/ version and hosted as String', () { @@ -138,24 +145,38 @@ line 5, column 14: These keys had `null` values, which is not allowed: [hosted] } void _sdkDependency() { - test('SdkDependency without version', () { + test('without version', () { var dep = _dependency({'sdk': 'flutter'}); expect(dep.sdk, 'flutter'); expect(dep.version, isNull); expect(dep.toString(), 'SdkDependency: flutter'); }); - test('SdkDependency with version', () { + test('with version', () { var dep = _dependency( {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}); expect(dep.sdk, 'flutter'); expect(dep.version.toString(), '>=1.2.3 <2.0.0'); expect(dep.toString(), 'SdkDependency: flutter'); }); + + test('null content', () { + _expectThrows({'sdk': null}, r''' +line 5, column 11: These keys had `null` values, which is not allowed: [sdk] + "sdk": null + ^^^^^'''); + }); + + test('number content', () { + _expectThrows({'sdk': 42}, r''' +line 5, column 11: Unsupported value for `sdk`. + "sdk": 42 + ^^^'''); + }); } void _gitDependency() { - test('GitDependency - string', () { + test('string', () { var dep = _dependency({'git': 'url'}); expect(dep.url.toString(), 'url'); expect(dep.path, isNull); @@ -163,7 +184,31 @@ void _gitDependency() { expect(dep.toString(), 'GitDependency: url@url'); }); - test('GitDependency - map', () { + test('string with version key is ignored', () { + // Regression test for https://github.com/dart-lang/pubspec_parse/issues/13 + var dep = _dependency({'git': 'url', 'version': '^1.2.3'}); + expect(dep.url.toString(), 'url'); + expect(dep.path, isNull); + expect(dep.ref, isNull); + expect(dep.toString(), 'GitDependency: url@url'); + }); + + test('string with user@ URL', () { + var dep = _dependency({'git': 'git@localhost:dep.git'}); + expect(dep.url.toString(), 'ssh://git@localhost/dep.git'); + expect(dep.path, isNull); + expect(dep.ref, isNull); + expect(dep.toString(), 'GitDependency: url@ssh://git@localhost/dep.git'); + }); + + test('string with random extra key fails', () { + _expectThrows({'git': 'url', 'bob': '^1.2.3'}, r''' +line 6, column 4: Unsupported dependency key. + "bob": "^1.2.3" + ^^^^^'''); + }); + + test('map', () { var dep = _dependency({ 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'} }); @@ -175,7 +220,7 @@ void _gitDependency() { test('git - null content', () { _expectThrows({'git': null}, r''' -line 5, column 11: Cannot be null. +line 5, column 11: Must be a String or a Map. "git": null ^^^^^'''); }); @@ -214,20 +259,34 @@ line 6, column 12: Unsupported value for `url`. } void _pathDependency() { - test('PathDependency', () { + test('valid', () { var dep = _dependency({'path': '../path'}); expect(dep.path, '../path'); expect(dep.toString(), 'PathDependency: path@../path'); }); - test('path - null content', () { + test('valid with version key is ignored', () { + var dep = + _dependency({'path': '../path', 'version': '^1.2.3'}); + expect(dep.path, '../path'); + expect(dep.toString(), 'PathDependency: path@../path'); + }); + + test('valid with random extra key fails', () { + _expectThrows({'path': '../path', 'bob': '^1.2.3'}, r''' +line 6, column 4: Unsupported dependency key. + "bob": "^1.2.3" + ^^^^^'''); + }); + + test('null content', () { _expectThrows({'path': null}, r''' -line 5, column 12: Cannot be null. +line 5, column 12: Must be a String. "path": null ^^^^^'''); }); - test('path - int content', () { + test('int content', () { _expectThrows({'path': 42}, r''' line 5, column 12: Must be a String. "path": 42 diff --git a/pkgs/pubspec_parse/test/git_uri_test.dart b/pkgs/pubspec_parse/test/git_uri_test.dart new file mode 100644 index 000000000..a1cfdf9cb --- /dev/null +++ b/pkgs/pubspec_parse/test/git_uri_test.dart @@ -0,0 +1,25 @@ +import 'package:test/test.dart'; + +import 'package:pubspec_parse/src/dependency.dart'; + +void main() { + for (var item in { + 'git@github.com:google/grinder.dart.git': + 'ssh://git@github.com/google/grinder.dart.git', + 'host.xz:path/to/repo.git/': 'ssh://host.xz/path/to/repo.git/', + 'http:path/to/repo.git/': 'ssh://http/path/to/repo.git/', + 'file:path/to/repo.git/': 'ssh://file/path/to/repo.git/', + './foo:bar': 'foo%3Abar', + '/path/to/repo.git/': '/path/to/repo.git/', + 'file:///path/to/repo.git/': 'file:///path/to/repo.git/', + }.entries) { + test(item.key, () { + var uri = parseGitUri(item.key); + + printOnFailure( + [uri.scheme, uri.userInfo, uri.host, uri.port, uri.path].join('\n')); + + expect(uri, Uri.parse(item.value)); + }); + } +} From 5bd79f1a2d98141a4ccc8eae4c97558e48994f93 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 21 Jun 2018 12:38:21 -0700 Subject: [PATCH 0447/1215] Cast Stream of Streams (dart-lang/stream_transform#52) --- pkgs/stream_transform/test/switch_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index dda658ca2..f5ac19a6e 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -43,6 +43,7 @@ void main() { errors = []; isDone = false; subscription = outer.stream + .cast() .transform(switchLatest()) .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; From 40f6dadc913eee417d4a79919609960281030787 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 21 Jun 2018 12:45:53 -0700 Subject: [PATCH 0448/1215] Stop running --no-strong analyzer (dart-lang/stream_transform#53) With Dart 2 Strong mode is the only analysis we care about. Also stop running extra tests on firefox. --- pkgs/stream_transform/.travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 70dd97752..326d6cfb8 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -9,7 +9,5 @@ cache: dart_task: - test - test -p chrome - - test -p firefox - dartfmt - dartanalyzer - - dartanalyzer: --no-strong . From e0e79c8cee4044d67a5f415c41c3b84b950ad38b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 21 Jun 2018 14:54:41 -0700 Subject: [PATCH 0449/1215] test: update error tests for latest pkg:json_serializable (dart-lang/pubspec_parse#15) --- pkgs/pubspec_parse/pubspec.yaml | 6 +++--- pkgs/pubspec_parse/test/dependency_test.dart | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index e21906084..ae60a284e 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.2 +version: 0.1.3-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team @@ -10,13 +10,13 @@ environment: sdk: '>=2.0.0-dev.54 <2.0.0' dependencies: - json_annotation: ^0.2.8 + json_annotation: ^0.2.9 pub_semver: ^1.3.2 yaml: ^2.1.12 dev_dependencies: build_runner: ^0.8.0 - json_serializable: ^0.5.7 + json_serializable: ^0.5.8 path: ^1.5.1 stack_trace: ^1.9.2 test: ^0.12.42 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index def243d10..2a8b49132 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -96,7 +96,7 @@ line 4, column 10: Could not parse version "not a version". Unknown text at "not 'version': 'not a version', 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} }, r''' -line 5, column 15: Unsupported value for `version`. +line 5, column 15: Could not parse version "not a version". Unknown text at "not a version". "version": "not a version", ^^^^^^^^^^^^^^^'''); }); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 00a0de97a..b3db0b0e9 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -153,9 +153,9 @@ line 4, column 10: `42` is not a String. ^^^'''); }); - test('invalid version', () { + test('version', () { expectParseThrows({'name': 'sample', 'version': 'invalid'}, r''' -line 3, column 13: Unsupported value for `version`. +line 3, column 13: Could not parse "invalid". "version": "invalid" ^^^^^^^^^'''); }); From 6813e42ff097e885cd1dbe3cdeef975d6cce78a8 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Mon, 25 Jun 2018 13:26:44 -0700 Subject: [PATCH 0450/1215] Use Dart 2 constants (dart-lang/watcher#60) --- pkgs/watcher/CHANGELOG.md | 4 ++++ .../src/constructable_file_system_event.dart | 8 ++++---- .../lib/src/directory_watcher/mac_os.dart | 14 +++++++------- .../lib/src/directory_watcher/windows.dart | 18 +++++++++--------- pkgs/watcher/lib/src/file_watcher/native.dart | 2 +- pkgs/watcher/pubspec.yaml | 4 ++-- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index fe30bc6cb..d8f2d5f99 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+9 + +* Internal changes only. + # 0.9.7+8 * Fix Dart 2.0 type issues on Mac and Windows. diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index a0f153e53..29b7c8ded 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -14,7 +14,7 @@ abstract class _ConstructableFileSystemEvent implements FileSystemEvent { class ConstructableFileSystemCreateEvent extends _ConstructableFileSystemEvent implements FileSystemCreateEvent { - final type = FileSystemEvent.CREATE; + final type = FileSystemEvent.create; ConstructableFileSystemCreateEvent(String path, bool isDirectory) : super(path, isDirectory); @@ -24,7 +24,7 @@ class ConstructableFileSystemCreateEvent extends _ConstructableFileSystemEvent class ConstructableFileSystemDeleteEvent extends _ConstructableFileSystemEvent implements FileSystemDeleteEvent { - final type = FileSystemEvent.DELETE; + final type = FileSystemEvent.delete; ConstructableFileSystemDeleteEvent(String path, bool isDirectory) : super(path, isDirectory); @@ -35,7 +35,7 @@ class ConstructableFileSystemDeleteEvent extends _ConstructableFileSystemEvent class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent implements FileSystemModifyEvent { final bool contentChanged; - final type = FileSystemEvent.MODIFY; + final type = FileSystemEvent.modify; ConstructableFileSystemModifyEvent( String path, bool isDirectory, this.contentChanged) @@ -48,7 +48,7 @@ class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent implements FileSystemMoveEvent { final String destination; - final type = FileSystemEvent.MOVE; + final type = FileSystemEvent.move; ConstructableFileSystemMoveEvent( String path, bool isDirectory, this.destination) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 5ad99847d..9da413a62 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -244,13 +244,13 @@ class _MacOSDirectoryWatcher // If we previously thought this was a MODIFY, we now consider it to be a // CREATE or REMOVE event. This is safe for the same reason as above. - if (type == FileSystemEvent.MODIFY) { + if (type == FileSystemEvent.modify) { type = event.type; continue; } // A CREATE event contradicts a REMOVE event and vice versa. - assert(type == FileSystemEvent.CREATE || type == FileSystemEvent.DELETE); + assert(type == FileSystemEvent.create || type == FileSystemEvent.delete); if (type != event.type) return null; } @@ -258,23 +258,23 @@ class _MacOSDirectoryWatcher // from FSEvents reporting an add that happened prior to the watch // beginning. If we also received a MODIFY event, we want to report that, // but not the CREATE. - if (type == FileSystemEvent.CREATE && + if (type == FileSystemEvent.create && hadModifyEvent && _files.contains(batch.first.path)) { - type = FileSystemEvent.MODIFY; + type = FileSystemEvent.modify; } switch (type) { - case FileSystemEvent.CREATE: + case FileSystemEvent.create: // Issue 16003 means that a CREATE event for a directory can indicate // that the directory was moved and then re-created. // [_eventsBasedOnFileSystem] will handle this correctly by producing a // DELETE event followed by a CREATE event if the directory exists. if (isDir) return null; return new ConstructableFileSystemCreateEvent(batch.first.path, false); - case FileSystemEvent.DELETE: + case FileSystemEvent.delete: return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); - case FileSystemEvent.MODIFY: + case FileSystemEvent.modify: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); default: diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index db9ca8328..0e550aecc 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -132,7 +132,7 @@ class _WindowsDirectoryWatcher // the directory is now gone. if (event is FileSystemMoveEvent || event is FileSystemDeleteEvent || - (FileSystemEntity.typeSync(path) == FileSystemEntityType.NOT_FOUND)) { + (FileSystemEntity.typeSync(path) == FileSystemEntityType.notFound)) { for (var path in _files.paths) { _emitEvent(ChangeType.REMOVE, path); } @@ -283,27 +283,27 @@ class _WindowsDirectoryWatcher // If we previously thought this was a MODIFY, we now consider it to be a // CREATE or REMOVE event. This is safe for the same reason as above. - if (type == FileSystemEvent.MODIFY) { + if (type == FileSystemEvent.modify) { type = event.type; continue; } // A CREATE event contradicts a REMOVE event and vice versa. - assert(type == FileSystemEvent.CREATE || - type == FileSystemEvent.DELETE || - type == FileSystemEvent.MOVE); + assert(type == FileSystemEvent.create || + type == FileSystemEvent.delete || + type == FileSystemEvent.move); if (type != event.type) return null; } switch (type) { - case FileSystemEvent.CREATE: + case FileSystemEvent.create: return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); - case FileSystemEvent.DELETE: + case FileSystemEvent.delete: return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); - case FileSystemEvent.MODIFY: + case FileSystemEvent.modify: return new ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); - case FileSystemEvent.MOVE: + case FileSystemEvent.move: return null; default: throw 'unreachable'; diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 8e7dd0981..5f56f739f 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -49,7 +49,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { } void _onBatch(List batch) { - if (batch.any((event) => event.type == FileSystemEvent.DELETE)) { + if (batch.any((event) => event.type == FileSystemEvent.delete)) { // If the file is deleted, the underlying stream will close. We handle // emitting our own REMOVE event in [_onDone]. return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 3cb964370..2f449ff75 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,12 +1,12 @@ name: watcher -version: 0.9.7+8 +version: 0.9.7+9 author: Dart Team homepage: https://github.com/dart-lang/watcher description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. environment: - sdk: '>=2.0.0-dev.20.0 <2.0.0' + sdk: '>=2.0.0-dev.61.0 <2.0.0' dependencies: async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' From 7ab24840647d244b1b9db2a68eb2ade9b5a26809 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 26 Jun 2018 10:08:21 -0700 Subject: [PATCH 0451/1215] misc: update dev_dependencies to support latest SDK (dart-lang/term_glyph#4) --- pkgs/term_glyph/pubspec.yaml | 6 +++--- pkgs/term_glyph/tool/generate.dart | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 4ba1efbe6..02a5b2aa9 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.0.0 +version: 1.0.1-dev description: Useful glyphs and Windows-safe equivalents. author: Dart Team homepage: https://github.com/dart-lang/term_glyph @@ -9,5 +9,5 @@ environment: dev_dependencies: csv: '^3.0.0' - dart_style: '^0.2.0' - test: '^0.12.0' + dart_style: '>=0.2.0 <2.0.0' + test: '>=0.12.0 <2.0.0' diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 2e94b4ca1..aa05c13fa 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -8,12 +8,12 @@ import 'package:csv/csv.dart'; void main() { var csv = new CsvCodec(eol: "\n"); - var data = csv.decode(new File("data.csv").readAsStringSync()); + var data = csv.decoder.convert(new File("data.csv").readAsStringSync()); // Remove comments and empty lines. data.removeWhere((row) => row.length < 3); - var file = new File("lib/src/generated.dart").openSync(mode: FileMode.WRITE); + var file = new File("lib/src/generated.dart").openSync(mode: FileMode.write); file.writeStringSync(""" // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a From 472a9fe13f11f92c099e8ee5a2f87e74425caea2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Jun 2018 09:44:24 -0700 Subject: [PATCH 0452/1215] misc: require a minimum of build_runner 0.9.0, update pkg:test dep --- pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index ae60a284e..2ec796f9b 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -15,10 +15,10 @@ dependencies: yaml: ^2.1.12 dev_dependencies: - build_runner: ^0.8.0 + build_runner: ^0.9.0 json_serializable: ^0.5.8 path: ^1.5.1 stack_trace: ^1.9.2 - test: ^0.12.42 + test: ^1.0.0 test_descriptor: ^1.0.3 test_process: ^1.0.2 From c4eb5c0784fc391119887559757a1790f882edd7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 27 Jun 2018 17:36:13 -0700 Subject: [PATCH 0453/1215] update dartfmt --- pkgs/pubspec_parse/test/ensure_build_test.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index 2842c5a06..854dd2493 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -44,8 +44,7 @@ final _whitespace = new RegExp(r'\s'); Set _changedGeneratedFiles() { var output = _runProc('git', ['status', '--porcelain']); - return LineSplitter - .split(output) + return LineSplitter.split(output) .map((line) => line.split(_whitespace).last) .where((path) => path.endsWith('.dart')) .toSet(); From a81b4a1b220c46dd5b632fadedb1c0a499283559 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 10 Jul 2018 11:23:33 -0700 Subject: [PATCH 0454/1215] dartfmt --- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 9da413a62..b0e3326fe 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -81,8 +81,8 @@ class _MacOSDirectoryWatcher // // If we do receive a batch of events, [_onBatch] will ensure that these // futures don't fire and that the directory is re-listed. - Future.wait([_listDir(), _waitForBogusEvents()]).then( - (_) => _readyCompleter.complete()); + Future.wait([_listDir(), _waitForBogusEvents()]) + .then((_) => _readyCompleter.complete()); } void close() { From fc2e3929c120944b4c24e4d7f828225a4af1fdbb Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 16 Jul 2018 10:43:48 -0400 Subject: [PATCH 0455/1215] chore: set max SDK version to <3.0.0 --- pkgs/test_reflective_loader/.gitignore | 1 + pkgs/test_reflective_loader/.travis.yml | 1 + pkgs/test_reflective_loader/CHANGELOG.md | 4 +++- pkgs/test_reflective_loader/analysis_options.yaml | 2 +- pkgs/test_reflective_loader/pubspec.yaml | 7 ++++--- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/pkgs/test_reflective_loader/.gitignore b/pkgs/test_reflective_loader/.gitignore index 67a390f24..2a2c2612b 100644 --- a/pkgs/test_reflective_loader/.gitignore +++ b/pkgs/test_reflective_loader/.gitignore @@ -1,6 +1,7 @@ .buildlog .DS_Store .idea +.dart_tool/ .pub/ .project .settings/ diff --git a/pkgs/test_reflective_loader/.travis.yml b/pkgs/test_reflective_loader/.travis.yml index 9c3a39f97..99c700e11 100644 --- a/pkgs/test_reflective_loader/.travis.yml +++ b/pkgs/test_reflective_loader/.travis.yml @@ -1,2 +1,3 @@ language: dart +dart: [dev, stable, 1.24.3] script: ./tool/travis.sh diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 6e5b8519c..ade68b1a3 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,4 +1,6 @@ -# Changelog +## 0.1.5 + +- Set max SDK version to `<3.0.0`, and adjust other dependencies. ## 0.1.3 diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml index 5f425e0e1..180004e7c 100644 --- a/pkgs/test_reflective_loader/analysis_options.yaml +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -1,5 +1,5 @@ analyzer: - strong-mode: true + linter: rules: - always_declare_return_types diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index ae718e8fd..392e498b6 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,11 +1,12 @@ name: test_reflective_loader -version: 0.1.4 +version: 0.1.5 + description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.8.0 <3.0.0' dependencies: - test: ^0.12.0 + test: '>=0.12.0 <2.0.0' From 033623f8c30b57c25f6176e62ee829de75951529 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Mon, 16 Jul 2018 22:08:17 -0400 Subject: [PATCH 0456/1215] chore: set max SDK version to <3.0.0 (dart-lang/term_glyph#5) --- pkgs/term_glyph/CHANGELOG.md | 4 ++++ pkgs/term_glyph/analysis_options.yaml | 2 -- pkgs/term_glyph/pubspec.yaml | 7 ++++--- 3 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 pkgs/term_glyph/analysis_options.yaml diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 5b26ad30f..6ee5e6f34 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1 + +* Set max SDK version to `<3.0.0`. + ## 1.0.0 * Initial version. diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/term_glyph/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 02a5b2aa9..6ef0c7c62 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,13 +1,14 @@ name: term_glyph -version: 1.0.1-dev +version: 1.0.1 + description: Useful glyphs and Windows-safe equivalents. author: Dart Team homepage: https://github.com/dart-lang/term_glyph environment: - sdk: '>=1.8.0 <2.0.0' + sdk: '>=1.8.0 <3.0.0' dev_dependencies: - csv: '^3.0.0' + csv: ^3.0.0 dart_style: '>=0.2.0 <2.0.0' test: '>=0.12.0 <2.0.0' From 72e6065f216f7bb90a22a5c439ceb38a30890fa8 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 17 Jul 2018 17:47:30 -0400 Subject: [PATCH 0457/1215] chore: set max SDK version to <3.0.0 (dart-lang/watcher#61) --- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/analysis_options.yaml | 2 -- pkgs/watcher/pubspec.yaml | 18 +++++++++++------- .../test/directory_watcher/linux_test.dart | 3 +-- .../test/directory_watcher/mac_os_test.dart | 3 +-- .../test/directory_watcher/windows_test.dart | 2 +- pkgs/watcher/test/no_subscription/shared.dart | 2 -- 7 files changed, 18 insertions(+), 16 deletions(-) delete mode 100644 pkgs/watcher/analysis_options.yaml diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index d8f2d5f99..7ea1cc1f3 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+10 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + # 0.9.7+9 * Internal changes only. diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/watcher/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 2f449ff75..73ce19b36 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,16 +1,20 @@ name: watcher -version: 0.9.7+9 -author: Dart Team -homepage: https://github.com/dart-lang/watcher +version: 0.9.7+10 + description: > A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. +author: Dart Team +homepage: https://github.com/dart-lang/watcher + environment: - sdk: '>=2.0.0-dev.61.0 <2.0.0' + sdk: '>=2.0.0-dev.61.0 <3.0.0' + dependencies: async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' + dev_dependencies: - benchmark_harness: '^1.0.4' - test: '^0.12.29' - test_descriptor: '^1.0.0' + benchmark_harness: ^1.0.4 + test: '>=0.12.42 <2.0.0' + test_descriptor: ^1.0.0 diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 25c550468..744045fcd 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -17,8 +17,7 @@ void main() { sharedTests(); test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { - expect( - new DirectoryWatcher('.'), new isInstanceOf()); + expect(new DirectoryWatcher('.'), new TypeMatcher()); }); test('emits events for many nested files moved out then immediately back in', diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 8fa76fd2d..689d35318 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -17,8 +17,7 @@ void main() { sharedTests(); test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { - expect( - new DirectoryWatcher('.'), new isInstanceOf()); + expect(new DirectoryWatcher('.'), new TypeMatcher()); }); test( diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 3696f9cb9..875f4ee81 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -22,6 +22,6 @@ void main() { test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { expect( - new DirectoryWatcher('.'), new isInstanceOf()); + new DirectoryWatcher('.'), new TypeMatcher()); }); } diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index c7e050151..ba8468401 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -2,8 +2,6 @@ // 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. -import 'dart:async'; - import 'package:async/async.dart'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; From c464dd53c907e288a7c11d725c5ccb2d46afaafd Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Jul 2018 15:31:10 -0400 Subject: [PATCH 0458/1215] chore: set max SDK version to <3.0.0 (dart-lang/string_scanner#10) --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/analysis_options.yaml | 2 -- pkgs/string_scanner/pubspec.yaml | 22 +++++++++++++--------- pkgs/string_scanner/test/utils.dart | 1 + 4 files changed, 18 insertions(+), 11 deletions(-) delete mode 100644 pkgs/string_scanner/analysis_options.yaml diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 83ca15b3f..2909bea83 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.3 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 1.0.2 * `SpanScanner` no longer crashes when creating a span that contains a UTF-16 diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/string_scanner/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index f0862eeb9..7c87a0d0a 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,13 +1,17 @@ name: string_scanner -version: 1.0.2 -author: "Dart Team " +version: 1.0.3 + +description: A class for parsing strings using a sequence of patterns. +author: Dart Team homepage: https://github.com/dart-lang/string_scanner -description: > - A class for parsing strings using a sequence of patterns. + +environment: + sdk: '>=1.8.0 <3.0.0' + dependencies: - charcode: "^1.1.0" - source_span: "^1.4.0" + charcode: ^1.1.0 + source_span: ^1.4.0 + dev_dependencies: - test: ">=0.12.0 <0.13.0" -environment: - sdk: ">=1.8.0 <2.0.0" + test: '>=0.12.0 <2.0.0' + diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index 471b4c823..7767fbc88 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -9,6 +9,7 @@ import 'package:test/test.dart'; /// with the given [message]. Matcher throwsStringScannerException(String text) { return throwsA(predicate((error) { + // ignore: deprecated_member_use expect(error, new isInstanceOf()); expect(error.span.text, equals(text)); return true; From fde54e7f3c483b689311c32975535e3c74628e54 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Jul 2018 18:18:01 -0400 Subject: [PATCH 0459/1215] chore: set max SDK version to <3.0.0 (dart-lang/stack_trace#45) --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/analysis_options.yaml | 2 -- pkgs/stack_trace/pubspec.yaml | 17 ++++++++++------- 3 files changed, 14 insertions(+), 9 deletions(-) delete mode 100644 pkgs/stack_trace/analysis_options.yaml diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a2a4c4446..d4bfa07ec 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.3 + +* Set max SDK version to `<3.0.0`. + ## 1.9.2 * Fix Dart 2.0 runtime cast failure in test. diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml deleted file mode 100644 index a10d4c5a0..000000000 --- a/pkgs/stack_trace/analysis_options.yaml +++ /dev/null @@ -1,2 +0,0 @@ -analyzer: - strong-mode: true diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3824d641e..6774615c9 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,14 +7,17 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.9.2 -author: "Dart Team " -homepage: https://github.com/dart-lang/stack_trace +version: 1.9.3 + description: A package for manipulating stack traces and printing them readably. +author: 'Dart Team ' +homepage: https://github.com/dart-lang/stack_trace + +environment: + sdk: '>=1.23.0 <3.0.0' + dependencies: - path: "^1.2.0" + path: ^1.2.0 dev_dependencies: - test: '^0.12.17' -environment: - sdk: ">=1.23.0 <2.0.0" + test: '>=0.12.17 <2.0.0' From cc4e21696064d72fd2d98548d4eb448fcc68dc56 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 18 Jul 2018 15:31:52 -0700 Subject: [PATCH 0460/1215] Allow the non-dev Dart 2 SDK (dart-lang/stream_transform#54) --- pkgs/stream_transform/CHANGELOG.md | 4 ++++ pkgs/stream_transform/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index a7c0a7e3f..515f0edc7 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.14+1 + +- Allow using non-dev Dart 2 SDK. + ## 0.0.14 - `asyncWhere` will now forward exceptions thrown by the callback through the diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 6d1d5378b..e10a772e9 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,10 +2,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.14 +version: 0.0.14+1 environment: - sdk: ">=2.0.0-dev.20.0 <2.0.0" + sdk: ">=2.0.0-dev.20.0 <3.0.0" dev_dependencies: test: ^0.12.20+13 From 19ba981cfb19b60437170202d27c18cc2ce98527 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Wed, 18 Jul 2018 19:28:11 -0400 Subject: [PATCH 0461/1215] Allow SDK versions <3.0.0 (dart-lang/stream_channel#32) And update some dependencies. --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/analysis_options.yaml | 1 - pkgs/stream_channel/pubspec.yaml | 10 +++++++--- .../test/json_document_transformer_test.dart | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 3dfbbc6f9..ce98fe038 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.6.8 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 1.6.7+1 * Fix Dart 2 runtime types in `IsolateChannel`. diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index bf7c331dd..d19ee843f 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,5 +1,4 @@ analyzer: - strong-mode: true # These are errors when building in Google errors: unused_import: error diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 54bd97217..6b1ace36f 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,11 +1,15 @@ name: stream_channel -version: 1.6.7+1 +version: 1.6.8 + description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel + environment: - sdk: '>=2.0.0-dev.17.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <3.0.0' + dependencies: async: '>=1.11.0 <3.0.0' + dev_dependencies: - test: '^0.12.28' + test: ^1.2.0 diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 3c6d11c91..6cb97f945 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -55,6 +55,6 @@ void main() { test("synchronously throws if an unencodable object is added", () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(new Object()), - throwsA(new isInstanceOf())); + throwsA(new TypeMatcher())); }); } From 787021153824348c19b559ac0f6e534b659e3c63 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 20 Jul 2018 14:47:22 -0700 Subject: [PATCH 0462/1215] Make FailingTest public. --- pkgs/test_reflective_loader/CHANGELOG.md | 5 ++++ .../lib/test_reflective_loader.dart | 26 +++++++++---------- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index ade68b1a3..843021950 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.6 + +- Make `FailingTest` public, with the URI of the issue that causes + the test to break. + ## 0.1.5 - Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 9f2478f77..efefaa638 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -21,7 +21,7 @@ const _AssertFailingTest assertFailingTest = const _AssertFailingTest(); * A marker annotation used to annotate overridden test methods (so we cannot * rename them to `fail_`) which are expected to fail. */ -const _FailingTest failingTest = const _FailingTest(); +const FailingTest failingTest = const FailingTest(null); /** * A marker annotation used to instruct dart2js to keep reflection information @@ -267,11 +267,11 @@ Future _runTest(ClassMirror classMirror, Symbol symbol) { typedef dynamic _TestFunction(); /** - * A marker annotation used to instruct dart2js to keep reflection information - * for the annotated classes. + * A marker annotation used to annotate overridden test methods (so we cannot + * rename them to `fail_`) which are expected to fail. */ -class _ReflectiveTest { - const _ReflectiveTest(); +class FailingTest { + const FailingTest(String issueUri); } /** @@ -293,14 +293,6 @@ class _AssertFailingTest { const _AssertFailingTest(); } -/** - * A marker annotation used to annotate overridden test methods (so we cannot - * rename them to `fail_`) which are expected to fail. - */ -class _FailingTest { - const _FailingTest(); -} - /** * Information about a type based test group. */ @@ -321,6 +313,14 @@ class _Group { } } +/** + * A marker annotation used to instruct dart2js to keep reflection information + * for the annotated classes. + */ +class _ReflectiveTest { + const _ReflectiveTest(); +} + /** * A marker annotation used to annotate "solo" groups and tests. */ diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 392e498b6..dd6090ebb 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.5 +version: 0.1.6 description: Support for discovering tests and test suites using reflection. author: Dart Team From 870ad666f7ced0de2bebf387a132c3f1833ffeab Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Fri, 20 Jul 2018 18:27:45 -0700 Subject: [PATCH 0463/1215] Update comments (dart-lang/test_reflective_loader#20) --- pkgs/test_reflective_loader/CHANGELOG.md | 5 ++++ .../lib/test_reflective_loader.dart | 29 ++++++++++--------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 843021950..e9a5ee6ec 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.1.7 + +- Update documentation comments. +- Remove `@MirrorsUsed` annotation on `dart:mirrors`. + ## 0.1.6 - Make `FailingTest` public, with the URI of the issue that causes diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index efefaa638..5667fe342 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -5,21 +5,18 @@ library test_reflective_loader; import 'dart:async'; -@MirrorsUsed(metaTargets: 'ReflectiveTest') import 'dart:mirrors'; import 'package:test/test.dart' as test_package; /** - * A marker annotation used to annotate overridden test methods (so we cannot - * rename them to `fail_`) which are expected to fail at `assert` in the - * checked mode. + * A marker annotation used to annotate test methods which are expected to fail + * when asserts are enabled. */ const _AssertFailingTest assertFailingTest = const _AssertFailingTest(); /** - * A marker annotation used to annotate overridden test methods (so we cannot - * rename them to `fail_`) which are expected to fail. + * A marker annotation used to annotate test methods which are expected to fail. */ const FailingTest failingTest = const FailingTest(null); @@ -267,10 +264,12 @@ Future _runTest(ClassMirror classMirror, Symbol symbol) { typedef dynamic _TestFunction(); /** - * A marker annotation used to annotate overridden test methods (so we cannot - * rename them to `fail_`) which are expected to fail. + * A marker annotation used to annotate test methods which are expected to fail. */ class FailingTest { + /** + * Initialize this annotation with the given issue URI. + */ const FailingTest(String issueUri); } @@ -279,15 +278,17 @@ class FailingTest { * information. */ class TestTimeout { - final test_package.Timeout timeout; + final test_package.Timeout _timeout; - const TestTimeout(this.timeout); + /** + * Initialize this annotation with the given timeout. + */ + const TestTimeout(test_package.Timeout timeout) : _timeout = timeout; } /** - * A marker annotation used to annotate overridden test methods (so we cannot - * rename them to `fail_`) which are expected to fail at `assert` in the - * checked mode. + * A marker annotation used to annotate test methods which are expected to fail + * when asserts are enabled. */ class _AssertFailingTest { const _AssertFailingTest(); @@ -309,7 +310,7 @@ class _Group { _TestFunction function) { String fullName = _combineNames(this.name, name); TestTimeout timeout = _getAnnotationInstance(memberMirror, TestTimeout); - tests.add(new _Test(isSolo, fullName, function, timeout?.timeout)); + tests.add(new _Test(isSolo, fullName, function, timeout?._timeout)); } } From 8f4e1944c5c37e6bded0bf75eddcd2fd2d9a575c Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Fri, 20 Jul 2018 18:36:09 -0700 Subject: [PATCH 0464/1215] Update pubspec.yaml version. (dart-lang/test_reflective_loader#21) --- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index dd6090ebb..b4f1781ed 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.6 +version: 0.1.7 description: Support for discovering tests and test suites using reflection. author: Dart Team From 54df806f2e00fcf07c8f385fc0903eee35335949 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 23 Jul 2018 08:26:24 -0700 Subject: [PATCH 0465/1215] misc: support the Dart 2 stable release (dart-lang/pubspec_parse#18) --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 30551e713..2447adb30 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2+1 + +- Support the Dart 2 stable release. + ## 0.1.2 - Allow superfluous `version` keys with `git` and `path` dependencies. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 2ec796f9b..eaedffbc1 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,12 +2,12 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.3-dev +version: 0.1.2+1 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team environment: - sdk: '>=2.0.0-dev.54 <2.0.0' + sdk: '>=2.0.0-dev.54 <3.0.0' dependencies: json_annotation: ^0.2.9 From 8697c47de770762195ab9165c9af074180d89312 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 24 Jul 2018 16:03:42 -0700 Subject: [PATCH 0466/1215] misc: support v1 json_annotation Verified that v1 changes don't affect runtime behavior --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 2447adb30..d114b8c36 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2+2 + +- Support `package:json_annotation` v1. + ## 0.1.2+1 - Support the Dart 2 stable release. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index eaedffbc1..17ff7d323 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.2+1 +version: 0.1.2+2 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team @@ -10,7 +10,7 @@ environment: sdk: '>=2.0.0-dev.54 <3.0.0' dependencies: - json_annotation: ^0.2.9 + json_annotation: '>=0.2.9 <2.0.0' pub_semver: ^1.3.2 yaml: ^2.1.12 From 6f98f8aa573e974885a03767917d21c24793a9ec Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Thu, 26 Jul 2018 12:05:37 -0700 Subject: [PATCH 0467/1215] Add 'issue' and 'reason' parameters to FailingTest. (dart-lang/test_reflective_loader#23) --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ .../lib/test_reflective_loader.dart | 9 ++++++--- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index e9a5ee6ec..b6121a198 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8 + +- Update `FailingTest` to add named parameters `issue` and `reason`. + ## 0.1.7 - Update documentation comments. diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 5667fe342..25868d9ca 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -18,7 +18,7 @@ const _AssertFailingTest assertFailingTest = const _AssertFailingTest(); /** * A marker annotation used to annotate test methods which are expected to fail. */ -const FailingTest failingTest = const FailingTest(null); +const FailingTest failingTest = const FailingTest(); /** * A marker annotation used to instruct dart2js to keep reflection information @@ -268,9 +268,12 @@ typedef dynamic _TestFunction(); */ class FailingTest { /** - * Initialize this annotation with the given issue URI. + * Initialize this annotation with the given arguments. + * + * [issue] is a full URI describing the failure and used for tracking. + * [reason] is a free form textual description. */ - const FailingTest(String issueUri); + const FailingTest({String issue, String reason}); } /** diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index b4f1781ed..3f399eab0 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.7 +version: 0.1.8 description: Support for discovering tests and test suites using reflection. author: Dart Team From aca34f65a3cd0623db9882251aff99f1e9653d03 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Fri, 3 Aug 2018 13:56:30 -0700 Subject: [PATCH 0468/1215] Annotate method error with alwaysThrows annotation. (dart-lang/string_scanner#11) --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/lib/src/string_scanner.dart | 2 ++ pkgs/string_scanner/pubspec.yaml | 3 ++- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 2909bea83..3602fb326 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0 + +* Add @alwaysThrows annotation to error method. + ## 1.0.3 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index ea3d6d60e..d32dc38ad 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:charcode/charcode.dart'; +import 'package:meta/meta.dart'; import 'package:source_span/source_span.dart'; import 'exception.dart'; @@ -197,6 +198,7 @@ class StringScanner { /// position; if only [position] is passed, [length] defaults to 0. /// /// It's an error to pass [match] at the same time as [position] or [length]. + @alwaysThrows void error(String message, {Match match, int position, int length}) { validateErrorArgs(string, match, position, length); diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 7c87a0d0a..769199054 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.0.3 +version: 1.0.4 description: A class for parsing strings using a sequence of patterns. author: Dart Team @@ -10,6 +10,7 @@ environment: dependencies: charcode: ^1.1.0 + meta: ^1.1.0 source_span: ^1.4.0 dev_dependencies: From b579a49a247a42b2d833d2120d8f24395bac0967 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy Date: Fri, 3 Aug 2018 16:26:02 -0700 Subject: [PATCH 0469/1215] Add missing return to fix analysis (dart-lang/watcher#62) * Add missing return to fix analysis * address comment * Update async_queue.dart --- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/lib/src/async_queue.dart | 5 +++-- pkgs/watcher/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 7ea1cc1f3..cd34d904e 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+11 + +* Fix an analysis hint. + # 0.9.7+10 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 1895c804e..1904192b4 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -59,12 +59,13 @@ class AsyncQueue { /// the process was cancelled. Future _processNextItem() { var item = _items.removeFirst(); - return _processor(item).then((_) { - if (_items.isNotEmpty) return _processNextItem(); + return _processor(item).then((_) async { + if (_items.isNotEmpty) return await _processNextItem(); // We have drained the queue, stop processing and wait until something // has been enqueued. _isProcessing = false; + return null; }); } } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 73ce19b36..8f38a49f6 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+10 +version: 0.9.7+11 description: > A file system watcher. It monitors changes to contents of directories and From 1ef7d9ae7d51d4bb9627f7090e4f06e0c4454821 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 7 Aug 2018 10:21:29 -0700 Subject: [PATCH 0470/1215] Run dartfmt --fix to drop optional `new` (dart-lang/stream_transform#55) - Require 2.0 stable SDK. - Test with stable SDK on Travis. - Update `package:test` dependency. --- pkgs/stream_transform/.travis.yml | 1 + .../lib/src/async_map_buffer.dart | 2 +- pkgs/stream_transform/lib/src/audit.dart | 2 +- pkgs/stream_transform/lib/src/bind.dart | 2 +- pkgs/stream_transform/lib/src/buffer.dart | 7 +-- pkgs/stream_transform/lib/src/debounce.dart | 2 +- .../stream_transform/lib/src/followed_by.dart | 7 +-- .../lib/src/from_handlers.dart | 6 +- pkgs/stream_transform/lib/src/merge.dart | 8 +-- pkgs/stream_transform/lib/src/start_with.dart | 4 +- pkgs/stream_transform/lib/src/switch.dart | 7 +-- pkgs/stream_transform/lib/src/take_until.dart | 6 +- pkgs/stream_transform/lib/src/throttle.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 6 +- .../test/async_map_buffer_test.dart | 62 +++++++++---------- .../test/async_where_test.dart | 28 ++++----- pkgs/stream_transform/test/audit_test.dart | 8 +-- pkgs/stream_transform/test/buffer_test.dart | 52 ++++++++-------- .../test/concurrent_async_map_test.dart | 46 +++++++------- pkgs/stream_transform/test/debounce_test.dart | 8 +-- .../test/followd_by_test.dart | 26 ++++---- .../test/from_handlers_test.dart | 22 +++---- pkgs/stream_transform/test/merge_test.dart | 38 ++++++------ pkgs/stream_transform/test/scan_test.dart | 4 +- .../test/start_with_test.dart | 30 ++++----- pkgs/stream_transform/test/switch_test.dart | 42 ++++++------- .../test/take_until_test.dart | 24 +++---- pkgs/stream_transform/test/tap_test.dart | 30 ++++----- pkgs/stream_transform/test/throttle_test.dart | 6 +- pkgs/stream_transform/test/utils.dart | 4 +- 30 files changed, 245 insertions(+), 247 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 326d6cfb8..e6d16f66a 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,6 +3,7 @@ branches: only: [master] dart: - dev + - stable cache: directories: - $HOME/.pub-cache diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index 72190d263..f8046668e 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -28,7 +28,7 @@ import 'from_handlers.dart'; /// pending conversions have finished. StreamTransformer asyncMapBuffer( Future convert(List collected)) { - var workFinished = new StreamController(); + var workFinished = StreamController(); // Let the first event through. workFinished.add(null); return chainTransformers( diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart index 2463ee631..7b4d7676e 100644 --- a/pkgs/stream_transform/lib/src/audit.dart +++ b/pkgs/stream_transform/lib/src/audit.dart @@ -23,7 +23,7 @@ StreamTransformer audit(Duration duration) { return fromHandlers(handleData: (T data, EventSink sink) { recentData = data; - timer ??= new Timer(duration, () { + timer ??= Timer(duration, () { sink.add(recentData); timer = null; if (shouldClose) { diff --git a/pkgs/stream_transform/lib/src/bind.dart b/pkgs/stream_transform/lib/src/bind.dart index 169653f4a..eefdc60e4 100644 --- a/pkgs/stream_transform/lib/src/bind.dart +++ b/pkgs/stream_transform/lib/src/bind.dart @@ -10,7 +10,7 @@ typedef Stream Bind(Stream values); /// Creates a [StreamTransformer] which overrides [StreamTransformer.bind] to /// [bindFn]. StreamTransformer fromBind(Bind bindFn) => - new _StreamTransformer(bindFn); + _StreamTransformer(bindFn); class _StreamTransformer extends StreamTransformerBase { final Bind _bind; diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index 0d9b87fc0..c05e79ab0 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -12,8 +12,7 @@ import 'dart:async'; /// /// Errors from the source stream or the trigger are immediately forwarded to /// the output. -StreamTransformer> buffer(Stream trigger) => - new _Buffer(trigger); +StreamTransformer> buffer(Stream trigger) => _Buffer(trigger); /// A StreamTransformer which aggregates values and emits when it sees a value /// on [_trigger]. @@ -32,8 +31,8 @@ class _Buffer extends StreamTransformerBase> { @override Stream> bind(Stream values) { var controller = values.isBroadcast - ? new StreamController>.broadcast(sync: true) - : new StreamController>(sync: true); + ? StreamController>.broadcast(sync: true) + : StreamController>(sync: true); List currentResults; var waitingForTrigger = true; diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart index 1ff91deb1..ff3f21ff2 100644 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -39,7 +39,7 @@ StreamTransformer _debounceAggregate( var shouldClose = false; return fromHandlers(handleData: (T value, EventSink sink) { timer?.cancel(); - timer = new Timer(duration, () { + timer = Timer(duration, () { sink.add(soFar); if (shouldClose) { sink.close(); diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart index 22f6945e0..df506f3a8 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -16,8 +16,7 @@ import 'dart:async'; /// occur before the first stream is done. If a broadcast stream follows a /// single-subscription stream, pausing the stream while it is listening to the /// second stream will cause events to be dropped rather than buffered. -StreamTransformer followedBy(Stream next) => - new _FollowedBy(next); +StreamTransformer followedBy(Stream next) => _FollowedBy(next); class _FollowedBy extends StreamTransformerBase { final Stream _next; @@ -27,8 +26,8 @@ class _FollowedBy extends StreamTransformerBase { @override Stream bind(Stream first) { var controller = first.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); var next = first.isBroadcast && !_next.isBroadcast ? _next.asBroadcastStream() diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 36a0417f3..6096c4c02 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -15,7 +15,7 @@ StreamTransformer fromHandlers( {HandleData handleData, HandleError handleError, HandleDone handleDone}) => - new _StreamTransformer( + _StreamTransformer( handleData: handleData, handleError: handleError, handleDone: handleDone); @@ -49,8 +49,8 @@ class _StreamTransformer extends StreamTransformerBase { @override Stream bind(Stream values) { var controller = values.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); StreamSubscription subscription; controller.onListen = () { diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 36d81d3d3..ead8bc6d9 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -9,7 +9,7 @@ import 'dart:async'; /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of [other]'s type. If a single subscription stream is /// merged into a broadcast stream it may never be canceled. -StreamTransformer merge(Stream other) => new _Merge([other]); +StreamTransformer merge(Stream other) => _Merge([other]); /// Emits values from the source stream and all streams in [others] in any order /// as they arrive. @@ -19,7 +19,7 @@ StreamTransformer merge(Stream other) => new _Merge([other]); /// subscription streams are merged into a broadcast stream they may never be /// canceled. StreamTransformer mergeAll(Iterable> others) => - new _Merge(others); + _Merge(others); class _Merge extends StreamTransformerBase { final Iterable> _others; @@ -29,8 +29,8 @@ class _Merge extends StreamTransformerBase { @override Stream bind(Stream first) { var controller = first.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); var allStreams = [first]..addAll(_others); if (first.isBroadcast) { diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart index 943474811..1ddde0cfe 100644 --- a/pkgs/stream_transform/lib/src/start_with.dart +++ b/pkgs/stream_transform/lib/src/start_with.dart @@ -11,7 +11,7 @@ import 'followed_by.dart'; /// /// If the original stream is a broadcast stream the result will be as well. StreamTransformer startWith(T initial) => - startWithStream(new Future.value(initial).asStream()); + startWithStream(Future.value(initial).asStream()); /// Emits all values in [initial] before any values from the original stream. /// @@ -19,7 +19,7 @@ StreamTransformer startWith(T initial) => /// the original stream is a broadcast stream it will miss any events which /// occur before the initial values are all emitted. StreamTransformer startWithMany(Iterable initial) => - startWithStream(new Stream.fromIterable(initial)); + startWithStream(Stream.fromIterable(initial)); /// Emits all values in [initial] before any values from the original stream. /// diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index bbd40d4bc..87ae4ffed 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -24,8 +24,7 @@ StreamTransformer switchMap(Stream convert(S event)) => /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of streams emitted. -StreamTransformer, T> switchLatest() => - new _SwitchTransformer(); +StreamTransformer, T> switchLatest() => _SwitchTransformer(); class _SwitchTransformer extends StreamTransformerBase, T> { const _SwitchTransformer(); @@ -33,8 +32,8 @@ class _SwitchTransformer extends StreamTransformerBase, T> { @override Stream bind(Stream> outer) { var controller = outer.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); StreamSubscription> outerSubscription; diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 0c10856eb..522ef30c4 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -10,7 +10,7 @@ import 'dart:async'; /// which are emitted before the trigger, but have further asynchronous delays /// in transformations following the takeUtil, will still go through. Cancelling /// a subscription immediately stops values. -StreamTransformer takeUntil(Future trigger) => new _TakeUntil(trigger); +StreamTransformer takeUntil(Future trigger) => _TakeUntil(trigger); class _TakeUntil extends StreamTransformerBase { final Future _trigger; @@ -20,8 +20,8 @@ class _TakeUntil extends StreamTransformerBase { @override Stream bind(Stream values) { var controller = values.isBroadcast - ? new StreamController.broadcast(sync: true) - : new StreamController(sync: true); + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); StreamSubscription subscription; var isDone = false; diff --git a/pkgs/stream_transform/lib/src/throttle.dart b/pkgs/stream_transform/lib/src/throttle.dart index b8faa25aa..475ad92cb 100644 --- a/pkgs/stream_transform/lib/src/throttle.dart +++ b/pkgs/stream_transform/lib/src/throttle.dart @@ -13,7 +13,7 @@ StreamTransformer throttle(Duration duration) { return fromHandlers(handleData: (data, sink) { if (timer == null) { sink.add(data); - timer = new Timer(duration, () { + timer = Timer(duration, () { timer = null; }); } diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index e10a772e9..81c10434d 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,10 +2,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.14+1 +version: 0.0.15-dev environment: - sdk: ">=2.0.0-dev.20.0 <3.0.0" + sdk: ">=2.0.0 <3.0.0" dev_dependencies: - test: ^0.12.20+13 + test: ^1.0.0 diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index f8b73a7a2..f96092aae 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -10,8 +10,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; StreamController values; List emittedValues; @@ -30,7 +30,7 @@ void main() { expect(finishWork, isNull, reason: 'See $values befor previous work is complete'); workArgument = values; - finishWork = new Completer(); + finishWork = Completer(); finishWork.future.then((_) { workArgument = null; finishWork = null; @@ -63,11 +63,11 @@ void main() { test('does not emit before work finishes', () async { values.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, isEmpty); expect(workArgument, [1]); finishWork.complete(workArgument); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -75,50 +75,50 @@ void main() { test('buffers values while work is ongoing', () async { values.add(1); - await new Future(() {}); + await Future(() {}); values.add(2); values.add(3); - await new Future(() {}); + await Future(() {}); finishWork.complete(); - await new Future(() {}); + await Future(() {}); expect(workArgument, [2, 3]); }); test('forwards errors without waiting for work', () async { values.add(1); - await new Future(() {}); + await Future(() {}); values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('forwards errors which occur during the work', () async { values.add(1); - await new Future(() {}); + await Future(() {}); finishWork.completeError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('can continue handling events after an error', () async { values.add(1); - await new Future(() {}); + await Future(() {}); finishWork.completeError('error'); values.add(2); - await new Future(() {}); + await Future(() {}); expect(workArgument, [2]); finishWork.completeError('another'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error', 'another']); }); test('does not start next work early due to an error in values', () async { values.add(1); - await new Future(() {}); + await Future(() {}); values.addError('error'); values.add(2); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); // [work] will assert that the second iteration is not called because // the first has not completed. @@ -133,29 +133,29 @@ void main() { test('closes when values end if no work is pending', () async { expect(isDone, false); await values.close(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); test('waits for pending work when values close', () async { values.add(1); - await new Future(() {}); + await Future(() {}); expect(isDone, false); values.add(2); await values.close(); expect(isDone, false); finishWork.complete(null); - await new Future(() {}); + await Future(() {}); // Still a pending value expect(isDone, false); finishWork.complete(null); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); test('forwards errors from values', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); @@ -164,9 +164,9 @@ void main() { var otherValues = []; transformed.listen(otherValues.add); values.add(1); - await new Future(() {}); + await Future(() {}); finishWork.complete('result'); - await new Future(() {}); + await Future(() {}); expect(emittedValues, ['result']); expect(otherValues, ['result']); }); @@ -175,30 +175,30 @@ void main() { var otherDone = false; transformed.listen(null, onDone: () => otherDone = true); values.add(1); - await new Future(() {}); + await Future(() {}); await values.close(); expect(isDone, false); expect(otherDone, false); finishWork.complete(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); expect(otherDone, true); }); test('can cancel and relisten', () async { values.add(1); - await new Future(() {}); + await Future(() {}); finishWork.complete('first'); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); values.add(2); - await new Future(() {}); + await Future(() {}); subscription = transformed.listen(emittedValues.add); values.add(3); - await new Future(() {}); + await Future(() {}); expect(workArgument, [3]); finishWork.complete('second'); - await new Future(() {}); + await Future(() {}); expect(emittedValues, ['first', 'second']); }); } diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 9c6650666..9d0c9f201 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -9,47 +9,47 @@ import 'package:stream_transform/stream_transform.dart'; void main() { test('forwards only events that pass the predicate', () async { - var values = new Stream.fromIterable([1, 2, 3, 4]); + var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.transform(asyncWhere((e) async => e > 2)); expect(await filtered.toList(), [3, 4]); }); test('allows predicates that go through event loop', () async { - var values = new Stream.fromIterable([1, 2, 3, 4]); + var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.transform(asyncWhere((e) async { - await new Future(() {}); + await Future(() {}); return e > 2; })); expect(await filtered.toList(), [3, 4]); }); test('allows synchronous predicate', () async { - var values = new Stream.fromIterable([1, 2, 3, 4]); + var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.transform(asyncWhere((e) => e > 2)); expect(await filtered.toList(), [3, 4]); }); test('can result in empty stream', () async { - var values = new Stream.fromIterable([1, 2, 3, 4]); + var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.transform(asyncWhere((e) => e > 4)); expect(await filtered.isEmpty, true); }); test('forwards values to multiple listeners', () async { - var values = new StreamController.broadcast(); + var values = StreamController.broadcast(); var filtered = values.stream.transform(asyncWhere((e) async => e > 2)); var firstValues = []; var secondValues = []; filtered..listen(firstValues.add)..listen(secondValues.add); values..add(1)..add(2)..add(3)..add(4); - await new Future(() {}); + await Future(() {}); expect(firstValues, [3, 4]); expect(secondValues, [3, 4]); }); test('closes streams with multiple listeners', () async { - var values = new StreamController.broadcast(); - var predicate = new Completer(); + var values = StreamController.broadcast(); + var predicate = Completer(); var filtered = values.stream.transform(asyncWhere((_) => predicate.future)); var firstDone = false; var secondDone = false; @@ -62,7 +62,7 @@ void main() { expect(secondDone, false); predicate.complete(true); - await new Future(() {}); + await Future(() {}); expect(firstDone, true); expect(secondDone, true); }); @@ -70,13 +70,13 @@ void main() { test('forwards errors emitted by the test callback', () async { var errors = []; var emitted = []; - var values = new Stream.fromIterable([1, 2, 3, 4]); + var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.transform(asyncWhere((e) async { - await new Future(() {}); - if (e.isEven) throw new Exception('$e'); + await Future(() {}); + if (e.isEven) throw Exception('$e'); return true; })); - var done = new Completer(); + var done = Completer(); filtered.listen(emitted.add, onError: errors.add, onDone: done.complete); await done.future; expect(emitted, [1, 3]); diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index b61a8dbc8..55a327e3f 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -11,8 +11,8 @@ import 'utils.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var streamType in streamTypes.keys) { group('Stream type [$streamType]', () { @@ -87,9 +87,9 @@ void main() { test('does not starve output if many values come closer than duration', () async { values.add(1); - await new Future.delayed(const Duration(milliseconds: 3)); + await Future.delayed(const Duration(milliseconds: 3)); values.add(2); - await new Future.delayed(const Duration(milliseconds: 3)); + await Future.delayed(const Duration(milliseconds: 3)); values.add(3); await waitForTimer(5); expect(emittedValues, [2, 3]); diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 4d3a2b65c..835a7ebf7 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -9,8 +9,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; StreamController trigger; StreamController values; @@ -59,10 +59,10 @@ void main() { test('does not emit before `trigger`', () async { values.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, isEmpty); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -70,10 +70,10 @@ void main() { test('emits immediately if trigger emits before a value', () async { trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, isEmpty); values.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -82,12 +82,12 @@ void main() { test('two triggers in a row - emit then emit next value', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); trigger.add(null); trigger.add(null); - await new Future(() {}); + await Future(() {}); values.add(3); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1, 2], [3] @@ -96,12 +96,12 @@ void main() { test('pre-emptive trigger then trigger after values', () async { trigger.add(null); - await new Future(() {}); + await Future(() {}); values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1], [2] @@ -111,10 +111,10 @@ void main() { test('multiple pre-emptive triggers, only emits first value', () async { trigger.add(null); trigger.add(null); - await new Future(() {}); + await Future(() {}); values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -123,13 +123,13 @@ void main() { test('groups values between trigger', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); trigger.add(null); values.add(3); values.add(4); - await new Future(() {}); + await Future(() {}); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1, 2], [3, 4] @@ -145,7 +145,7 @@ void main() { test('closes when trigger ends', () async { expect(isDone, false); await trigger.close(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); @@ -156,7 +156,7 @@ void main() { await values.close(); expect(isDone, false); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -169,7 +169,7 @@ void main() { values.add(1); trigger.add(null); await values.close(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); @@ -179,7 +179,7 @@ void main() { await trigger.close(); expect(isDone, false); values.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); @@ -188,13 +188,13 @@ void main() { test('forwards errors from trigger', () async { trigger.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('forwards errors from values', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); }); @@ -234,18 +234,18 @@ void main() { setUpForStreamTypes(triggerType, 'broadcast'); values.add(1); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1] ]); await subscription.cancel(); values.add(2); trigger.add(null); - await new Future(() {}); + await Future(() {}); subscription = transformed.listen(emittedValues.add); values.add(3); trigger.add(null); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [ [1], [3] diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index 9ea11a5bc..531e94128 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -10,8 +10,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; StreamController streamController; List emittedValues; @@ -26,7 +26,7 @@ void main() { Future convert(dynamic value) { values.add(value); - var completer = new Completer(); + var completer = Completer(); finishWork.add(completer); return completer.future; } @@ -54,11 +54,11 @@ void main() { test('does not emit before convert finishes', () async { streamController.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, isEmpty); expect(values, [1]); finishWork.first.complete(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1]); }); @@ -66,36 +66,36 @@ void main() { streamController.add(1); streamController.add(2); streamController.add(3); - await new Future(() {}); + await Future(() {}); expect(values, [1, 2, 3]); }); test('forwards errors directly without waiting for previous convert', () async { streamController.add(1); - await new Future(() {}); + await Future(() {}); streamController.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('forwards errors which occur during the convert', () async { streamController.add(1); - await new Future(() {}); + await Future(() {}); finishWork.first.completeError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('can continue handling events after an error', () async { streamController.add(1); - await new Future(() {}); + await Future(() {}); finishWork[0].completeError('error'); streamController.add(2); - await new Future(() {}); + await Future(() {}); expect(values, [1, 2]); finishWork[1].completeError('another'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error', 'another']); }); @@ -108,7 +108,7 @@ void main() { test('closes when values end if no conversion is pending', () async { expect(isDone, false); await streamController.close(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); @@ -117,9 +117,9 @@ void main() { var otherValues = []; transformed.listen(otherValues.add); streamController.add(1); - await new Future(() {}); + await Future(() {}); finishWork.first.complete('result'); - await new Future(() {}); + await Future(() {}); expect(emittedValues, ['result']); expect(otherValues, ['result']); }); @@ -128,30 +128,30 @@ void main() { var otherDone = false; transformed.listen(null, onDone: () => otherDone = true); streamController.add(1); - await new Future(() {}); + await Future(() {}); await streamController.close(); expect(isDone, false); expect(otherDone, false); finishWork.first.complete(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); expect(otherDone, true); }); test('can cancel and relisten', () async { streamController.add(1); - await new Future(() {}); + await Future(() {}); finishWork.first.complete('first'); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); streamController.add(2); - await new Future(() {}); + await Future(() {}); subscription = transformed.listen(emittedValues.add); streamController.add(3); - await new Future(() {}); + await Future(() {}); expect(values, [1, 3]); finishWork[1].complete('second'); - await new Future(() {}); + await Future(() {}); expect(emittedValues, ['first', 'second']); }); } diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index 59cb809fe..a5dc4b6fb 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -11,8 +11,8 @@ import 'utils.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var streamType in streamTypes.keys) { group('Stream type [$streamType]', () { @@ -70,7 +70,7 @@ void main() { values.add(1); await waitForTimer(5); await values.close(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); @@ -78,7 +78,7 @@ void main() { values.add(1); await waitForTimer(5); values.add(2); - await new Future(() {}); + await Future(() {}); await values.close(); expect(isDone, false); await waitForTimer(5); diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 2bff18c1b..956bf23a2 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -9,8 +9,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var firstType in streamTypes.keys) { for (var secondType in streamTypes.keys) { @@ -55,9 +55,9 @@ void main() { test('adds all values from both streams', () async { first..add(1)..add(2); await first.close(); - await new Future(() {}); + await Future(() {}); second..add(3)..add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -94,10 +94,10 @@ void main() { await first.close(); subscription.pause(); second.add(1); - await new Future(() {}); + await Future(() {}); subscription.resume(); second.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [2]); }); } else { @@ -106,10 +106,10 @@ void main() { await first.close(); subscription.pause(); second.add(1); - await new Future(() {}); + await Future(() {}); subscription.resume(); second.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2]); }); } @@ -121,7 +121,7 @@ void main() { first.add(1); subscription = transformed.listen(emittedValues.add); first.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [2]); }); @@ -129,10 +129,10 @@ void main() { await first.close(); await subscription.cancel(); second.add(2); - await new Future(() {}); + await Future(() {}); subscription = transformed.listen(emittedValues.add); second.add(3); - await new Future((() {})); + await Future((() {})); expect(emittedValues, [3]); }); @@ -142,11 +142,11 @@ void main() { first.add(1); await first.close(); second.add(2); - await new Future(() {}); + await Future(() {}); var thirdValues = []; transformed.listen(thirdValues.add); second.add(3); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3]); expect(otherValues, [1, 2, 3]); expect(thirdValues, [3]); diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 8240b1c0c..d77f676cb 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -37,7 +37,7 @@ void main() { group('default from_handlers', () { group('Single subscription stream', () { setUp(() { - setUpForController(new StreamController(), fromHandlers()); + setUpForController(StreamController(), fromHandlers()); }); test('has correct stream type', () { @@ -47,13 +47,13 @@ void main() { test('forwards values', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2]); }); test('forwards errors', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); @@ -75,7 +75,7 @@ void main() { StreamSubscription subscription2; setUp(() { - setUpForController(new StreamController.broadcast(), fromHandlers()); + setUpForController(StreamController.broadcast(), fromHandlers()); emittedValues2 = []; errors2 = []; isDone2 = false; @@ -92,14 +92,14 @@ void main() { test('forwards values', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2]); expect(emittedValues2, [1, 2]); }); test('forwards errors', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); expect(errors2, ['error']); }); @@ -122,7 +122,7 @@ void main() { group('custom handlers', () { group('single subscription', () { setUp(() async { - setUpForController(new StreamController(), + setUpForController(StreamController(), fromHandlers(handleData: (value, sink) { sink.add(value + 1); })); @@ -130,7 +130,7 @@ void main() { test('uses transform from handleData', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [2, 3]); }); }); @@ -145,7 +145,7 @@ void main() { doneCallCount = 0; errorCallCount = 0; setUpForController( - new StreamController.broadcast(), + StreamController.broadcast(), fromHandlers(handleData: (value, sink) { dataCallCount++; }, handleError: (error, stackTrace, sink) { @@ -159,7 +159,7 @@ void main() { test('handles data once', () async { values.add(1); - await new Future(() {}); + await Future(() {}); expect(dataCallCount, 1); }); @@ -170,7 +170,7 @@ void main() { test('handles errors once', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errorCallCount, 1); }); }); diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 75df0e81e..cf576ac7a 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -11,8 +11,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { group('merge', () { test('includes all values', () async { - var first = new Stream.fromIterable([1, 2, 3]); - var second = new Stream.fromIterable([4, 5, 6]); + var first = Stream.fromIterable([1, 2, 3]); + var second = Stream.fromIterable([4, 5, 6]); var allValues = await first.transform(merge(second)).toList(); expect(allValues, containsAllInOrder([1, 2, 3])); expect(allValues, containsAllInOrder([4, 5, 6])); @@ -21,12 +21,12 @@ void main() { test('cancels both sources', () async { var firstCanceled = false; - var first = new StreamController() + var first = StreamController() ..onCancel = () { firstCanceled = true; }; var secondCanceled = false; - var second = new StreamController() + var second = StreamController() ..onCancel = () { secondCanceled = true; }; @@ -38,8 +38,8 @@ void main() { }); test('completes when both sources complete', () async { - var first = new StreamController(); - var second = new StreamController(); + var first = StreamController(); + var second = StreamController(); var isDone = false; first.stream.transform(merge(second.stream)).listen((_) {}, onDone: () { isDone = true; @@ -51,14 +51,14 @@ void main() { }); test('can cancel and relisten to broadcast stream', () async { - var first = new StreamController.broadcast(); - var second = new StreamController(); + var first = StreamController.broadcast(); + var second = StreamController(); var emittedValues = []; var transformed = first.stream.transform((merge(second.stream))); var subscription = transformed.listen(emittedValues.add); first.add(1); second.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, contains(1)); expect(emittedValues, contains(2)); await subscription.cancel(); @@ -66,7 +66,7 @@ void main() { subscription = transformed.listen(emittedValues.add); first.add(3); second.add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, contains(3)); expect(emittedValues, contains(4)); }); @@ -74,9 +74,9 @@ void main() { group('mergeAll', () { test('includes all values', () async { - var first = new Stream.fromIterable([1, 2, 3]); - var second = new Stream.fromIterable([4, 5, 6]); - var third = new Stream.fromIterable([7, 8, 9]); + var first = Stream.fromIterable([1, 2, 3]); + var second = Stream.fromIterable([4, 5, 6]); + var third = Stream.fromIterable([7, 8, 9]); var allValues = await first.transform(mergeAll([second, third])).toList(); expect(allValues, containsAllInOrder([1, 2, 3])); expect(allValues, containsAllInOrder([4, 5, 6])); @@ -86,17 +86,17 @@ void main() { test('handles mix of broadcast and single-subscription', () async { var firstCanceled = false; - var first = new StreamController.broadcast() + var first = StreamController.broadcast() ..onCancel = () { firstCanceled = true; }; var secondBroadcastCanceled = false; - var secondBroadcast = new StreamController.broadcast() + var secondBroadcast = StreamController.broadcast() ..onCancel = () { secondBroadcastCanceled = true; }; var secondSingleCanceled = false; - var secondSingle = new StreamController() + var secondSingle = StreamController() ..onCancel = () { secondSingleCanceled = true; }; @@ -114,7 +114,7 @@ void main() { secondBroadcast.add(2); secondSingle.add(3); - await new Future(() {}); + await Future(() {}); await firstSubscription.cancel(); expect(firstCanceled, false); @@ -125,10 +125,10 @@ void main() { secondBroadcast.add(5); secondSingle.add(6); - await new Future(() {}); + await Future(() {}); await secondSubscription.cancel(); - await new Future(() {}); + await Future(() {}); expect(firstCanceled, true); expect(secondBroadcastCanceled, true); expect(secondSingleCanceled, false, diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index b2b976050..db958850e 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -11,7 +11,7 @@ import 'package:stream_transform/stream_transform.dart'; void main() { group('Scan', () { test('produces intermediate values', () async { - var source = new Stream.fromIterable([1, 2, 3, 4]); + var source = Stream.fromIterable([1, 2, 3, 4]); var sum = (int x, int y) => x + y; var result = await source.transform(scan(0, sum)).toList(); @@ -19,7 +19,7 @@ void main() { }); test('can create a broadcast stream', () async { - var source = new StreamController.broadcast(); + var source = StreamController.broadcast(); var transformed = source.stream.transform(scan(null, null)); diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 97f0529b6..c02e2a3b6 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -10,8 +10,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; StreamController values; Stream transformed; @@ -35,7 +35,7 @@ void main() { test('outputs all values', () async { values..add(2)..add(3); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3]); }); @@ -53,12 +53,12 @@ void main() { if (streamType == 'broadcast') { test('can cancel and relisten', () async { values.add(2); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); subscription = transformed.listen(emittedValues.add); values.add(3); - await new Future(() {}); - await new Future(() {}); + await Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3]); }); } @@ -68,12 +68,12 @@ void main() { setUp(() async { setupForStreamType(streamType, startWithMany([1, 2])); // Ensure all initial values go through - await new Future(() {}); + await Future(() {}); }); test('outputs all values', () async { values..add(3)..add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -91,11 +91,11 @@ void main() { if (streamType == 'broadcast') { test('can cancel and relisten', () async { values.add(3); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); subscription = transformed.listen(emittedValues.add); values.add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); } @@ -113,7 +113,7 @@ void main() { starting..add(1)..add(2); await starting.close(); values..add(3)..add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -128,13 +128,13 @@ void main() { if (streamType == 'broadcast') { test('can cancel and relisten during starting', () async { starting.add(1); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); subscription = transformed.listen(emittedValues.add); starting.add(2); await starting.close(); values..add(3)..add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -142,11 +142,11 @@ void main() { starting..add(1)..add(2); await starting.close(); values.add(3); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); subscription = transformed.listen(emittedValues.add); values.add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); } diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index f5ac19a6e..8fb190df1 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -10,8 +10,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var outerType in streamTypes.keys) { for (var innerType in streamTypes.keys) { @@ -52,40 +52,40 @@ void main() { test('forwards events', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); first.add(1); first.add(2); - await new Future(() {}); + await Future(() {}); outer.add(second.stream); - await new Future(() {}); + await Future(() {}); second.add(3); second.add(4); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); test('forwards errors from outer Stream', () async { outer.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('forwards errors from inner Stream', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); first.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); test('closes when final stream is done', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); outer.add(second.stream); - await new Future(() {}); + await Future(() {}); await outer.close(); expect(isDone, false); @@ -98,7 +98,7 @@ void main() { 'closes when outer stream closes if latest inner stream already ' 'closed', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); await first.close(); expect(isDone, false); @@ -108,20 +108,20 @@ void main() { test('cancels listeners on previous streams', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); outer.add(second.stream); - await new Future(() {}); + await Future(() {}); expect(firstCanceled, true); }); test('cancels listener on current and outer stream on cancel', () async { outer.add(first.stream); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); - await new Future(() {}); + await Future(() {}); expect(outerCanceled, true); expect(firstCanceled, true); }); @@ -131,22 +131,22 @@ void main() { group('switchMap', () { test('uses map function', () async { - var outer = new StreamController(); + var outer = StreamController(); var values = []; outer.stream - .transform(switchMap((l) => new Stream.fromIterable(l))) + .transform(switchMap((l) => Stream.fromIterable(l))) .listen(values.add); outer.add([1, 2, 3]); - await new Future(() {}); + await Future(() {}); outer.add([4, 5, 6]); - await new Future(() {}); + await Future(() {}); expect(values, [1, 2, 3, 4, 5, 6]); }); test('can create a broadcast stream', () async { - var outer = new StreamController.broadcast(); + var outer = StreamController.broadcast(); var transformed = outer.stream.transform(switchMap(null)); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 1ed2f7999..3c7bb1bef 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -10,8 +10,8 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var streamType in streamTypes.keys) { group('takeUntil on Stream type [$streamType]', () { @@ -33,7 +33,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - closeTrigger = new Completer(); + closeTrigger = Completer(); transformed = values.stream.transform(takeUntil(closeTrigger.future)); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { @@ -49,13 +49,13 @@ void main() { test('lets values through before trigger', () async { values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2]); }); test('forwards errors', () async { values.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errors, ['error']); }); @@ -66,13 +66,13 @@ void main() { test('sends done when trigger fires', () async { closeTrigger.complete(); - await new Future(() {}); + await Future(() {}); expect(isDone, true); }); test('cancels value subscription when trigger fires', () async { closeTrigger.complete(); - await new Future(() {}); + await Future(() {}); expect(valuesCanceled, true); }); @@ -82,7 +82,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); values.add(2); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 2]); expect(otherValues, [1, 2]); }); @@ -91,7 +91,7 @@ void main() { var otherDone = false; transformed.listen(null, onDone: () => otherDone = true); closeTrigger.complete(); - await new Future(() {}); + await Future(() {}); expect(otherDone, true); expect(isDone, true); }); @@ -106,13 +106,13 @@ void main() { test('can cancel and relisten before trigger fires', () async { values.add(1); - await new Future(() {}); + await Future(() {}); await subscription.cancel(); values.add(2); - await new Future(() {}); + await Future(() {}); subscription = transformed.listen(emittedValues.add); values.add(3); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1, 3]); }); } diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index ffdabba2b..989c3423e 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -11,45 +11,45 @@ import 'package:stream_transform/stream_transform.dart'; void main() { test('calls function for values', () async { var valuesSeen = []; - var stream = new Stream.fromIterable([1, 2, 3]); + var stream = Stream.fromIterable([1, 2, 3]); await stream.transform(tap(valuesSeen.add)).last; expect(valuesSeen, [1, 2, 3]); }); test('forwards values', () async { - var stream = new Stream.fromIterable([1, 2, 3]); + var stream = Stream.fromIterable([1, 2, 3]); var values = await stream.transform(tap((_) {})).toList(); expect(values, [1, 2, 3]); }); test('calls function for errors', () async { var error; - var source = new StreamController(); + var source = StreamController(); source.stream .transform(tap((_) {}, onError: (e, st) { error = e; })) .listen((_) {}, onError: (_) {}); source.addError('error'); - await new Future(() {}); + await Future(() {}); expect(error, 'error'); }); test('forwards errors', () async { var error; - var source = new StreamController(); + var source = StreamController(); source.stream.transform(tap((_) {}, onError: (e, st) {})).listen((_) {}, onError: (e) { error = e; }); source.addError('error'); - await new Future(() {}); + await Future(() {}); expect(error, 'error'); }); test('calls function on done', () async { var doneCalled = false; - var source = new StreamController(); + var source = StreamController(); source.stream .transform((tap((_) {}, onDone: () { doneCalled = true; @@ -62,14 +62,14 @@ void main() { test('forwards only once with multiple listeners on a broadcast stream', () async { var dataCallCount = 0; - var source = new StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.transform(tap((_) { dataCallCount++; })) ..listen((_) {}) ..listen((_) {}); source.add(1); - await new Future(() {}); + await Future(() {}); expect(dataCallCount, 1); }); @@ -77,21 +77,21 @@ void main() { 'forwards errors only once with multiple listeners on a broadcast stream', () async { var errorCallCount = 0; - var source = new StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.transform(tap((_) {}, onError: (_, __) { errorCallCount++; })) ..listen((_) {}, onError: (_, __) {}) ..listen((_) {}, onError: (_, __) {}); source.addError('error'); - await new Future(() {}); + await Future(() {}); expect(errorCallCount, 1); }); test('calls onDone only once with multiple listeners on a broadcast stream', () async { var doneCallCount = 0; - var source = new StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.transform(tap((_) {}, onDone: () { doneCallCount++; })) @@ -102,20 +102,20 @@ void main() { }); test('forwards values to multiple listeners', () async { - var source = new StreamController.broadcast(); + var source = StreamController.broadcast(); var emittedValues1 = []; var emittedValues2 = []; source.stream.transform(tap((_) {})) ..listen(emittedValues1.add) ..listen(emittedValues2.add); source.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues1, [1]); expect(emittedValues2, [1]); }); test('allows null callback', () async { - var stream = new Stream.fromIterable([1, 2, 3]); + var stream = Stream.fromIterable([1, 2, 3]); await stream.transform(tap(null)).last; }); } diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 94e1851eb..b0b839d7f 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -11,8 +11,8 @@ import 'utils.dart'; void main() { var streamTypes = { - 'single subscription': () => new StreamController(), - 'broadcast': () => new StreamController.broadcast() + 'single subscription': () => StreamController(), + 'broadcast': () => StreamController.broadcast() }; for (var streamType in streamTypes.keys) { group('Stream type [$streamType]', () { @@ -79,7 +79,7 @@ void main() { var otherValues = []; transformed.listen(otherValues.add); values.add(1); - await new Future(() {}); + await Future(() {}); expect(emittedValues, [1]); expect(otherValues, [1]); }); diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart index 4e38ef7f7..2bb76795f 100644 --- a/pkgs/stream_transform/test/utils.dart +++ b/pkgs/stream_transform/test/utils.dart @@ -7,5 +7,5 @@ import 'dart:async'; /// Cycle the event loop to ensure timers are started, then wait for a delay /// longer than [milliseconds] to allow for the timer to fire. Future waitForTimer(int milliseconds) => - new Future(() {/* ensure Timer is started*/}).then((_) => - new Future.delayed(new Duration(milliseconds: milliseconds + 1))); + Future(() {/* ensure Timer is started*/}) + .then((_) => Future.delayed(Duration(milliseconds: milliseconds + 1))); From 584b8552bb46de126a04cadc40de9b5c3609358f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 8 Aug 2018 14:10:08 -0700 Subject: [PATCH 0471/1215] Skip tests on dev channel (dart-lang/stream_transform#56) --- pkgs/stream_transform/.travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index e6d16f66a..d18b3db46 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -2,7 +2,8 @@ language: dart branches: only: [master] dart: - - dev + # Skipping dev until Dart 2.1.0-dev is out + #- dev - stable cache: directories: From d797569a99947570bb8b6abe65a81adb3711894e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 9 Aug 2018 14:40:12 -0700 Subject: [PATCH 0472/1215] misc: upgraded to json_serializable v1 (dart-lang/pubspec_parse#20) - Updated generated output - Use latest build_runner - Update test to pass with Dart 2 stable - Test on the stable SDK, too --- pkgs/pubspec_parse/.travis.yml | 1 + pkgs/pubspec_parse/build.yaml | 6 ---- pkgs/pubspec_parse/lib/src/dependency.g.dart | 30 +++++++------------- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 8 ++---- pkgs/pubspec_parse/pubspec.yaml | 7 +++-- pkgs/pubspec_parse/test/parse_test.dart | 2 +- 6 files changed, 19 insertions(+), 35 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index ea5469401..8c6a4b8c3 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -2,6 +2,7 @@ language: dart dart: - dev + - stable dart_task: - test: -x presubmit-only diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 930aad181..69bcb1f43 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -10,9 +10,3 @@ targets: options: any_map: true checked: true - header: |+ - // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file - // 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. - - // GENERATED CODE - DO NOT MODIFY BY HAND diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index e4bca581e..cba3364b2 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -1,7 +1,3 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - // GENERATED CODE - DO NOT MODIFY BY HAND part of 'dependency.dart'; @@ -12,10 +8,8 @@ part of 'dependency.dart'; SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { - $checkKeys(json, - requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); - var val = new SdkDependency( - $checkedConvert(json, 'sdk', (v) => v as String), + $checkKeys(json, requiredKeys: ['sdk'], disallowNullValues: ['sdk']); + var val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String))); return val; @@ -24,9 +18,8 @@ SdkDependency _$SdkDependencyFromJson(Map json) { GitDependency _$GitDependencyFromJson(Map json) { return $checkedNew('GitDependency', json, () { - $checkKeys(json, - requiredKeys: const ['url'], disallowNullValues: const ['url']); - var val = new GitDependency( + $checkKeys(json, requiredKeys: ['url'], disallowNullValues: ['url']); + var val = GitDependency( $checkedConvert( json, 'url', (v) => v == null ? null : parseGitUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), @@ -38,13 +31,12 @@ GitDependency _$GitDependencyFromJson(Map json) { HostedDependency _$HostedDependencyFromJson(Map json) { return $checkedNew('HostedDependency', json, () { $checkKeys(json, - allowedKeys: const ['version', 'hosted'], - disallowNullValues: const ['hosted']); - var val = new HostedDependency( + allowedKeys: ['version', 'hosted'], disallowNullValues: ['hosted']); + var val = HostedDependency( version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String)), hosted: $checkedConvert(json, 'hosted', - (v) => v == null ? null : new HostedDetails.fromJson(v))); + (v) => v == null ? null : HostedDetails.fromJson(v))); return val; }); } @@ -52,10 +44,10 @@ HostedDependency _$HostedDependencyFromJson(Map json) { HostedDetails _$HostedDetailsFromJson(Map json) { return $checkedNew('HostedDetails', json, () { $checkKeys(json, - allowedKeys: const ['name', 'url'], - requiredKeys: const ['name'], - disallowNullValues: const ['name', 'url']); - var val = new HostedDetails( + allowedKeys: ['name', 'url'], + requiredKeys: ['name'], + disallowNullValues: ['name', 'url']); + var val = HostedDetails( $checkedConvert(json, 'name', (v) => v as String), $checkedConvert( json, 'url', (v) => v == null ? null : parseGitUri(v as String))); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 921b7e435..dfb0bcf12 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -1,7 +1,3 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - // GENERATED CODE - DO NOT MODIFY BY HAND part of 'pubspec.dart'; @@ -12,7 +8,7 @@ part of 'pubspec.dart'; Pubspec _$PubspecFromJson(Map json) { return $checkedNew('Pubspec', json, () { - var val = new Pubspec($checkedConvert(json, 'name', (v) => v as String), + var val = Pubspec($checkedConvert(json, 'name', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _versionFromString(v as String)), author: $checkedConvert(json, 'author', (v) => v as String), @@ -31,7 +27,7 @@ Pubspec _$PubspecFromJson(Map json) { dependencyOverrides: $checkedConvert( json, 'dependency_overrides', (v) => parseDeps(v as Map))); return val; - }, fieldKeyMap: const { + }, fieldKeyMap: { 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' }); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 17ff7d323..490a6b254 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.2+2 +version: 0.1.3-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team @@ -10,13 +10,14 @@ environment: sdk: '>=2.0.0-dev.54 <3.0.0' dependencies: + # Verified that no new features since 0.2.9 are used - be careful! json_annotation: '>=0.2.9 <2.0.0' pub_semver: ^1.3.2 yaml: ^2.1.12 dev_dependencies: - build_runner: ^0.9.0 - json_serializable: ^0.5.8 + build_runner: ^0.10.0 + json_serializable: ^1.0.0 path: ^1.5.1 stack_trace: ^1.9.2 test: ^1.0.0 diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index b3db0b0e9..71c0a58ed 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -26,7 +26,7 @@ void main() { test('all fields set', () { var version = new Version.parse('1.2.3'); - var sdkConstraint = new VersionConstraint.parse('>=2.0.0-dev.54 <2.0.0'); + var sdkConstraint = new VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); var value = parse({ 'name': 'sample', 'version': version.toString(), From bcf5a0aee713052206e0362d4742d2102c3c30e2 Mon Sep 17 00:00:00 2001 From: BC Ko Date: Mon, 13 Aug 2018 12:14:41 -0700 Subject: [PATCH 0473/1215] Update .gitignore to new `dart_tool` pub cache (dart-lang/string_scanner#8) RE dart-lang/sdkdart-lang/string_scanner#32030 --- pkgs/string_scanner/.gitignore | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pkgs/string_scanner/.gitignore b/pkgs/string_scanner/.gitignore index 7dbf0350d..fb97bdebd 100644 --- a/pkgs/string_scanner/.gitignore +++ b/pkgs/string_scanner/.gitignore @@ -1,15 +1,5 @@ # Don’t commit the following directories created by pub. -.buildlog +.dart_tool/ .pub/ -build/ -packages .packages - -# Or the files created by dart2js. -*.dart.js -*.js_ -*.js.deps -*.js.map - -# Include when developing application packages. -pubspec.lock \ No newline at end of file +pubspec.lock From 15977bbbf14222f8263d7e3228e414d1f0799c07 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 13 Aug 2018 12:34:32 -0700 Subject: [PATCH 0474/1215] Fix changelog for release (dart-lang/string_scanner#13) Fixes https://github.com/dart-lang/string_scanner/issues/12 --- pkgs/string_scanner/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 3602fb326..43b94535a 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.1.0 +## 1.0.4 * Add @alwaysThrows annotation to error method. From fcf673efd9c1f769ae79a5ea04ebe9215cee403a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 30 Aug 2018 15:44:27 -0700 Subject: [PATCH 0475/1215] Regenerate files with json_serializable v1.2.1 (dart-lang/pubspec_parse#22) --- pkgs/pubspec_parse/lib/src/dependency.g.dart | 15 +++++++++------ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index cba3364b2..7aee20614 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -8,7 +8,8 @@ part of 'dependency.dart'; SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { - $checkKeys(json, requiredKeys: ['sdk'], disallowNullValues: ['sdk']); + $checkKeys(json, + requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); var val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String))); @@ -18,7 +19,8 @@ SdkDependency _$SdkDependencyFromJson(Map json) { GitDependency _$GitDependencyFromJson(Map json) { return $checkedNew('GitDependency', json, () { - $checkKeys(json, requiredKeys: ['url'], disallowNullValues: ['url']); + $checkKeys(json, + requiredKeys: const ['url'], disallowNullValues: const ['url']); var val = GitDependency( $checkedConvert( json, 'url', (v) => v == null ? null : parseGitUri(v as String)), @@ -31,7 +33,8 @@ GitDependency _$GitDependencyFromJson(Map json) { HostedDependency _$HostedDependencyFromJson(Map json) { return $checkedNew('HostedDependency', json, () { $checkKeys(json, - allowedKeys: ['version', 'hosted'], disallowNullValues: ['hosted']); + allowedKeys: const ['version', 'hosted'], + disallowNullValues: const ['hosted']); var val = HostedDependency( version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String)), @@ -44,9 +47,9 @@ HostedDependency _$HostedDependencyFromJson(Map json) { HostedDetails _$HostedDetailsFromJson(Map json) { return $checkedNew('HostedDetails', json, () { $checkKeys(json, - allowedKeys: ['name', 'url'], - requiredKeys: ['name'], - disallowNullValues: ['name', 'url']); + allowedKeys: const ['name', 'url'], + requiredKeys: const ['name'], + disallowNullValues: const ['name', 'url']); var val = HostedDetails( $checkedConvert(json, 'name', (v) => v as String), $checkedConvert( diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index dfb0bcf12..7ac66f708 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -27,7 +27,7 @@ Pubspec _$PubspecFromJson(Map json) { dependencyOverrides: $checkedConvert( json, 'dependency_overrides', (v) => parseDeps(v as Map))); return val; - }, fieldKeyMap: { + }, fieldKeyMap: const { 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' }); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 490a6b254..2db643df0 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: dev_dependencies: build_runner: ^0.10.0 - json_serializable: ^1.0.0 + json_serializable: ^1.2.1 path: ^1.5.1 stack_trace: ^1.9.2 test: ^1.0.0 From 7bd71140bd08005151926d7efc5b3d6daadd271b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 4 Sep 2018 15:14:31 -0700 Subject: [PATCH 0476/1215] Use pkg:pedantic lints (dart-lang/pubspec_parse#23) --- pkgs/pubspec_parse/analysis_options.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 8cd2a0f6d..918f5deed 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -15,6 +15,7 @@ linter: - avoid_function_literals_in_foreach_calls - avoid_init_to_null - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports - avoid_renaming_method_parameters - avoid_return_types_on_setters - avoid_returning_null From 6ab1113902f054e606943f8db8de564640538e8c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 4 Sep 2018 21:38:19 -0700 Subject: [PATCH 0477/1215] Add more lints used in package:pedantic (dart-lang/stream_transform#58) Closes dart-lang/stream_transform#57 --- pkgs/stream_transform/analysis_options.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 5741706ca..dcfc23987 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -12,7 +12,9 @@ linter: - annotate_overrides - avoid_empty_else - avoid_init_to_null + - avoid_relative_lib_imports - avoid_return_types_on_setters + - avoid_types_as_parameter_names - await_only_futures - camel_case_types - comment_references @@ -25,16 +27,21 @@ linter: - implementation_imports - library_names - library_prefixes + - no_duplicate_case_values - non_constant_identifier_names - omit_local_variable_types - only_throw_errors + - prefer_contains + - prefer_equal_for_default_values - prefer_final_fields - prefer_is_not_empty - prefer_single_quotes + - recursive_getters - slash_for_doc_comments - test_types_in_equals - test_types_in_equals - throw_in_finally - type_init_formals - unrelated_type_equality_checks + - use_rethrow_when_possible - valid_regexps From a330c4daf61128b2129aa9fcf87215e8fe5ad370 Mon Sep 17 00:00:00 2001 From: Ivan Naydonov Date: Wed, 5 Sep 2018 16:01:02 -0700 Subject: [PATCH 0478/1215] Starting timing package repo From c5d255a80b961c3fa3c0898b2bb93e1fa3c78575 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Sep 2018 17:38:18 -0700 Subject: [PATCH 0479/1215] Add some stricter analysis (dart-lang/watcher#64) - Enable errors that would fail internally - Add `comment_references` lint - this makes DartDocs output more usable and there isn't any reason to have unclickable references. - Add `prefer_typing_uninitialized_variables` lint - this prevents some unintentionally dynamic behavior. - Disable implicit casts. - Use function type syntax for the ManuallyClosedWatcher factory. - Remove some unused utilities. --- pkgs/watcher/analysis_options.yaml | 14 ++ pkgs/watcher/benchmark/path_set.dart | 2 +- .../lib/src/directory_watcher/linux.dart | 12 +- .../lib/src/directory_watcher/mac_os.dart | 8 +- .../lib/src/directory_watcher/polling.dart | 12 +- .../lib/src/directory_watcher/windows.dart | 6 +- pkgs/watcher/lib/src/file_watcher.dart | 2 +- .../watcher/lib/src/file_watcher/polling.dart | 2 +- pkgs/watcher/lib/src/path_set.dart | 16 +- pkgs/watcher/lib/src/resubscribable.dart | 8 +- pkgs/watcher/lib/src/utils.dart | 51 ------ pkgs/watcher/test/path_set_test.dart | 171 +++++++++--------- pkgs/watcher/test/utils.dart | 12 +- 13 files changed, 137 insertions(+), 179 deletions(-) create mode 100644 pkgs/watcher/analysis_options.yaml diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml new file mode 100644 index 000000000..4c9f8113a --- /dev/null +++ b/pkgs/watcher/analysis_options.yaml @@ -0,0 +1,14 @@ +analyzer: + strong-mode: + implicit-casts: false + errors: + todo: ignore + unused_import: error + unused_element: error + unused_local_variable: error + dead_code: error + +linter: + rules: + - comment_references + - prefer_typing_uninitialized_variables diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index aba3ed750..bf9f5fc7c 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -31,7 +31,7 @@ abstract class PathSetBenchmark extends BenchmarkBase { /// Each virtual directory contains ten entries: either subdirectories or /// files. void walkTree(int depth, callback(String path)) { - recurse(path, remainingDepth) { + recurse(String path, remainingDepth) { for (var i = 0; i < 10; i++) { var padded = i.toString().padLeft(2, '0'); if (remainingDepth == 0) { diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 354ddc020..5eeed2327 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -79,13 +79,14 @@ class _LinuxDirectoryWatcher .transform(new BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError); - _listen(new Directory(path).list(recursive: true), (entity) { + _listen(new Directory(path).list(recursive: true), + (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); } else { _files.add(entity.path); } - }, onError: (error, stackTrace) { + }, onError: (error, StackTrace stackTrace) { _eventsController.addError(error, stackTrace); close(); }, onDone: () { @@ -207,14 +208,15 @@ class _LinuxDirectoryWatcher /// Emits [ChangeType.ADD] events for the recursive contents of [path]. void _addSubdir(String path) { - _listen(new Directory(path).list(recursive: true), (entity) { + _listen(new Directory(path).list(recursive: true), + (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); } else { _files.add(entity.path); _emit(ChangeType.ADD, entity.path); } - }, onError: (error, stackTrace) { + }, onError: (error, StackTrace stackTrace) { // Ignore an exception caused by the dir not existing. It's fine if it // was added and then quickly removed. if (error is FileSystemException) return; @@ -252,7 +254,7 @@ class _LinuxDirectoryWatcher /// [_subscriptions] so that it can be canceled when [close] is called. void _listen(Stream stream, void onData(T event), {Function onError, void onDone(), bool cancelOnError}) { - var subscription; + StreamSubscription subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); if (onDone != null) onDone(); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index b0e3326fe..61531c5d9 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -54,8 +54,8 @@ class _MacOSDirectoryWatcher /// The subscription to the stream returned by [Directory.watch]. /// - /// This is separate from [_subscriptions] because this stream occasionally - /// needs to be resubscribed in order to work around issue 14849. + /// This is separate from [_listSubscriptions] because this stream + /// occasionally needs to be resubscribed in order to work around issue 14849. StreamSubscription> _watchSubscription; /// The subscription to the [Directory.list] call for the initial listing of @@ -143,7 +143,7 @@ class _MacOSDirectoryWatcher _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (e, stackTrace) { + }, onError: (e, StackTrace stackTrace) { _emitError(e, stackTrace); }, onDone: () { _listSubscriptions.remove(subscription); @@ -212,7 +212,7 @@ class _MacOSDirectoryWatcher /// one exists. /// /// If [batch] doesn't contain any contradictory events (e.g. DELETE and - /// CREATE, or events with different values for [isDirectory]), this returns a + /// CREATE, or events with different values for `isDirectory`), this returns a /// single event that describes what happened to the path in question. /// /// If [batch] does contain contradictory events, this returns `null` to diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index fa72a2f54..790d0b982 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -19,7 +19,7 @@ class PollingDirectoryWatcher extends ResubscribableWatcher /// Creates a new polling watcher monitoring [directory]. /// - /// If [_pollingDelay] is passed, it specifies the amount of time the watcher + /// If [pollingDelay] is passed, it specifies the amount of time the watcher /// will pause between successive polls of the directory contents. Making this /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. @@ -68,13 +68,13 @@ class _PollingDirectoryWatcher /// The set of files that have been seen in the current directory listing. /// - /// Used to tell which files have been removed: files that are in [_statuses] - /// but not in here when a poll completes have been removed. + /// Used to tell which files have been removed: files that are in + /// [_lastModifieds] but not in here when a poll completes have been removed. final _polledFiles = new Set(); _PollingDirectoryWatcher(this.path, this._pollingDelay) { - _filesToProcess = - new AsyncQueue(_processFile, onError: (e, stackTrace) { + _filesToProcess = new AsyncQueue(_processFile, + onError: (e, StackTrace stackTrace) { if (!_events.isClosed) _events.addError(e, stackTrace); }); @@ -113,7 +113,7 @@ class _PollingDirectoryWatcher if (entity is! File) return; _filesToProcess.add(entity.path); - }, onError: (error, stackTrace) { + }, onError: (error, StackTrace stackTrace) { if (!isDirectoryNotFoundException(error)) { // It's some unknown error. Pipe it over to the event stream so the // user can see it. diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 0e550aecc..baeaf233a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -188,7 +188,7 @@ class _WindowsDirectoryWatcher _files.add(entity.path); }, onDone: () { _listSubscriptions.remove(subscription); - }, onError: (e, stackTrace) { + }, onError: (e, StackTrace stackTrace) { _listSubscriptions.remove(subscription); _emitError(e, stackTrace); }, cancelOnError: true); @@ -253,7 +253,7 @@ class _WindowsDirectoryWatcher /// one exists. /// /// If [batch] doesn't contain any contradictory events (e.g. DELETE and - /// CREATE, or events with different values for [isDirectory]), this returns a + /// CREATE, or events with different values for `isDirectory`), this returns a /// single event that describes what happened to the path in question. /// /// If [batch] does contain contradictory events, this returns `null` to @@ -382,7 +382,7 @@ class _WindowsDirectoryWatcher _files.clear(); var completer = new Completer(); var stream = new Directory(path).list(recursive: true); - void handleEntity(entity) { + void handleEntity(FileSystemEntity entity) { if (entity is! Directory) _files.add(entity.path); } diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index 17c5f2efb..09065bc8b 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -15,7 +15,7 @@ import 'file_watcher/polling.dart'; /// it will emit a single [ChangeType.REMOVE] event and then close the stream. /// /// If the file is deleted and quickly replaced (when a new file is moved in its -/// place, for example) this will emit a [ChangeTime.MODIFY] event. +/// place, for example) this will emit a [ChangeType.MODIFY] event. abstract class FileWatcher implements Watcher { /// Creates a new [FileWatcher] monitoring [file]. /// diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 97a4f9533..960b11b9b 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -58,7 +58,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { return; } - var modified; + DateTime modified; try { try { modified = await getModificationTime(path); diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 3726e1fd8..77737f82e 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -49,13 +49,13 @@ class PathSet { /// empty set. Set remove(String path) { path = _normalize(path); - var parts = new Queue.from(p.split(path)); + var parts = new Queue.of(p.split(path)); // Remove the children of [dir], as well as [dir] itself if necessary. // // [partialPath] is the path to [dir], and a prefix of [path]; the remaining // components of [path] are in [parts]. - Set recurse(dir, partialPath) { + Set recurse(_Entry dir, String partialPath) { if (parts.length > 1) { // If there's more than one component left in [path], recurse down to // the next level. @@ -97,7 +97,7 @@ class PathSet { /// [dirPath] should be the path to [dir]. Set _explicitPathsWithin(_Entry dir, String dirPath) { var paths = new Set(); - recurse(dir, path) { + recurse(_Entry dir, String path) { dir.contents.forEach((name, entry) { var entryPath = p.join(path, name); if (entry.isExplicit) paths.add(p.join(root, entryPath)); @@ -110,9 +110,9 @@ class PathSet { return paths; } - /// Returns whether [this] contains [path]. + /// Returns whether this set contains [path]. /// - /// This only returns true for paths explicitly added to [this]. + /// This only returns true for paths explicitly added to this set. /// Implicitly-added directories can be inspected using [containsDir]. bool contains(String path) { path = _normalize(path); @@ -126,7 +126,7 @@ class PathSet { return entry.isExplicit; } - /// Returns whether [this] contains paths beneath [path]. + /// Returns whether this set contains paths beneath [path]. bool containsDir(String path) { path = _normalize(path); var entry = _entries; @@ -143,7 +143,7 @@ class PathSet { List get paths { var result = []; - recurse(dir, path) { + recurse(_Entry dir, String path) { for (var name in dir.contents.keys) { var entry = dir.contents[name]; var entryPath = p.join(path, name); @@ -156,7 +156,7 @@ class PathSet { return result; } - /// Removes all paths from [this]. + /// Removes all paths from this set. void clear() { _entries.contents.clear(); } diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 28c425ff4..e96b918dc 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -7,8 +7,6 @@ import 'dart:async'; import '../watcher.dart'; import 'watch_event.dart'; -typedef ManuallyClosedWatcher WatcherFactory(); - /// A wrapper for [ManuallyClosedWatcher] that encapsulates support for closing /// the watcher when it has no subscribers and re-opening it when it's /// re-subscribed. @@ -24,7 +22,7 @@ typedef ManuallyClosedWatcher WatcherFactory(); /// takes a factory function that produces instances of the inner class. abstract class ResubscribableWatcher implements Watcher { /// The factory function that produces instances of the inner class. - final WatcherFactory _factory; + final ManuallyClosedWatcher Function() _factory; final String path; @@ -39,8 +37,8 @@ abstract class ResubscribableWatcher implements Watcher { /// Creates a new [ResubscribableWatcher] wrapping the watchers /// emitted by [_factory]. ResubscribableWatcher(this.path, this._factory) { - var watcher; - var subscription; + ManuallyClosedWatcher watcher; + StreamSubscription subscription; _eventsController = new StreamController.broadcast( onListen: () { diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 62d8e0ff8..30fbaae21 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -6,8 +6,6 @@ import 'dart:async'; import 'dart:io'; import 'dart:collection'; -import 'package:async/async.dart'; - /// Returns `true` if [error] is a [FileSystemException] for a missing /// directory. bool isDirectoryNotFoundException(error) { @@ -22,55 +20,6 @@ bool isDirectoryNotFoundException(error) { Set unionAll(Iterable> sets) => sets.fold(new Set(), (union, set) => union.union(set)); -/// Returns a buffered stream that will emit the same values as the stream -/// returned by [future] once [future] completes. -/// -/// If [future] completes to an error, the return value will emit that error and -/// then close. -/// -/// If [broadcast] is true, a broadcast stream is returned. This assumes that -/// the stream returned by [future] will be a broadcast stream as well. -/// [broadcast] defaults to false. -Stream futureStream(Future> future, {bool broadcast: false}) { - var subscription; - StreamController controller; - - future = DelegatingFuture.typed(future.catchError((e, stackTrace) { - // Since [controller] is synchronous, it's likely that emitting an error - // will cause it to be cancelled before we call close. - if (controller != null) controller.addError(e, stackTrace); - if (controller != null) controller.close(); - controller = null; - })); - - onListen() { - future.then((stream) { - if (controller == null) return; - subscription = stream.listen(controller.add, - onError: controller.addError, onDone: controller.close); - }); - } - - onCancel() { - if (subscription != null) subscription.cancel(); - subscription = null; - controller = null; - } - - if (broadcast) { - controller = new StreamController.broadcast( - sync: true, onListen: onListen, onCancel: onCancel); - } else { - controller = new StreamController( - sync: true, onListen: onListen, onCancel: onCancel); - } - return controller.stream; -} - -/// Like [new Future], but avoids around issue 11911 by using [new Future.value] -/// under the covers. -Future newFuture(callback()) => new Future.value().then((_) => callback()); - /// A stream transformer that batches all events that are sent at the same time. /// /// When multiple events are synchronously added to a stream controller, the diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index be15c77c4..fe91d417f 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -7,83 +7,84 @@ import 'package:test/test.dart'; import 'package:watcher/src/path_set.dart'; Matcher containsPath(String path) => predicate( - (set) => set is PathSet && set.contains(path), 'set contains "$path"'); + (paths) => paths is PathSet && paths.contains(path), + 'set contains "$path"'); Matcher containsDir(String path) => predicate( - (set) => set is PathSet && set.containsDir(path), + (paths) => paths is PathSet && paths.containsDir(path), 'set contains directory "$path"'); void main() { - var set; - setUp(() => set = new PathSet("root")); + PathSet paths; + setUp(() => paths = new PathSet("root")); group("adding a path", () { test("stores the path in the set", () { - set.add("root/path/to/file"); - expect(set, containsPath("root/path/to/file")); + paths.add("root/path/to/file"); + expect(paths, containsPath("root/path/to/file")); }); test("that's a subdir of another path keeps both in the set", () { - set.add("root/path"); - set.add("root/path/to/file"); - expect(set, containsPath("root/path")); - expect(set, containsPath("root/path/to/file")); + paths.add("root/path"); + paths.add("root/path/to/file"); + expect(paths, containsPath("root/path")); + expect(paths, containsPath("root/path/to/file")); }); test("that's not normalized normalizes the path before storing it", () { - set.add("root/../root/path/to/../to/././file"); - expect(set, containsPath("root/path/to/file")); + paths.add("root/../root/path/to/../to/././file"); + expect(paths, containsPath("root/path/to/file")); }); test("that's absolute normalizes the path before storing it", () { - set.add(p.absolute("root/path/to/file")); - expect(set, containsPath("root/path/to/file")); + paths.add(p.absolute("root/path/to/file")); + expect(paths, containsPath("root/path/to/file")); }); }); group("removing a path", () { test("that's in the set removes and returns that path", () { - set.add("root/path/to/file"); - expect(set.remove("root/path/to/file"), + paths.add("root/path/to/file"); + expect(paths.remove("root/path/to/file"), unorderedEquals([p.normalize("root/path/to/file")])); - expect(set, isNot(containsPath("root/path/to/file"))); + expect(paths, isNot(containsPath("root/path/to/file"))); }); test("that's not in the set returns an empty set", () { - set.add("root/path/to/file"); - expect(set.remove("root/path/to/nothing"), isEmpty); + paths.add("root/path/to/file"); + expect(paths.remove("root/path/to/nothing"), isEmpty); }); test("that's a directory removes and returns all files beneath it", () { - set.add("root/outside"); - set.add("root/path/to/one"); - set.add("root/path/to/two"); - set.add("root/path/to/sub/three"); + paths.add("root/outside"); + paths.add("root/path/to/one"); + paths.add("root/path/to/two"); + paths.add("root/path/to/sub/three"); expect( - set.remove("root/path"), + paths.remove("root/path"), unorderedEquals([ "root/path/to/one", "root/path/to/two", "root/path/to/sub/three" ].map(p.normalize))); - expect(set, containsPath("root/outside")); - expect(set, isNot(containsPath("root/path/to/one"))); - expect(set, isNot(containsPath("root/path/to/two"))); - expect(set, isNot(containsPath("root/path/to/sub/three"))); + expect(paths, containsPath("root/outside")); + expect(paths, isNot(containsPath("root/path/to/one"))); + expect(paths, isNot(containsPath("root/path/to/two"))); + expect(paths, isNot(containsPath("root/path/to/sub/three"))); }); test( "that's a directory in the set removes and returns it and all files " "beneath it", () { - set.add("root/path"); - set.add("root/path/to/one"); - set.add("root/path/to/two"); - set.add("root/path/to/sub/three"); + paths.add("root/path"); + paths.add("root/path/to/one"); + paths.add("root/path/to/two"); + paths.add("root/path/to/sub/three"); expect( - set.remove("root/path"), + paths.remove("root/path"), unorderedEquals([ "root/path", "root/path/to/one", @@ -91,113 +92,113 @@ void main() { "root/path/to/sub/three" ].map(p.normalize))); - expect(set, isNot(containsPath("root/path"))); - expect(set, isNot(containsPath("root/path/to/one"))); - expect(set, isNot(containsPath("root/path/to/two"))); - expect(set, isNot(containsPath("root/path/to/sub/three"))); + expect(paths, isNot(containsPath("root/path"))); + expect(paths, isNot(containsPath("root/path/to/one"))); + expect(paths, isNot(containsPath("root/path/to/two"))); + expect(paths, isNot(containsPath("root/path/to/sub/three"))); }); test("that's not normalized removes and returns the normalized path", () { - set.add("root/path/to/file"); - expect(set.remove("root/../root/path/to/../to/./file"), + paths.add("root/path/to/file"); + expect(paths.remove("root/../root/path/to/../to/./file"), unorderedEquals([p.normalize("root/path/to/file")])); }); test("that's absolute removes and returns the normalized path", () { - set.add("root/path/to/file"); - expect(set.remove(p.absolute("root/path/to/file")), + paths.add("root/path/to/file"); + expect(paths.remove(p.absolute("root/path/to/file")), unorderedEquals([p.normalize("root/path/to/file")])); }); }); group("containsPath()", () { test("returns false for a non-existent path", () { - set.add("root/path/to/file"); - expect(set, isNot(containsPath("root/path/to/nothing"))); + paths.add("root/path/to/file"); + expect(paths, isNot(containsPath("root/path/to/nothing"))); }); test("returns false for a directory that wasn't added explicitly", () { - set.add("root/path/to/file"); - expect(set, isNot(containsPath("root/path"))); + paths.add("root/path/to/file"); + expect(paths, isNot(containsPath("root/path"))); }); test("returns true for a directory that was added explicitly", () { - set.add("root/path"); - set.add("root/path/to/file"); - expect(set, containsPath("root/path")); + paths.add("root/path"); + paths.add("root/path/to/file"); + expect(paths, containsPath("root/path")); }); test("with a non-normalized path normalizes the path before looking it up", () { - set.add("root/path/to/file"); - expect(set, containsPath("root/../root/path/to/../to/././file")); + paths.add("root/path/to/file"); + expect(paths, containsPath("root/../root/path/to/../to/././file")); }); test("with an absolute path normalizes the path before looking it up", () { - set.add("root/path/to/file"); - expect(set, containsPath(p.absolute("root/path/to/file"))); + paths.add("root/path/to/file"); + expect(paths, containsPath(p.absolute("root/path/to/file"))); }); }); group("containsDir()", () { test("returns true for a directory that was added implicitly", () { - set.add("root/path/to/file"); - expect(set, containsDir("root/path")); - expect(set, containsDir("root/path/to")); + paths.add("root/path/to/file"); + expect(paths, containsDir("root/path")); + expect(paths, containsDir("root/path/to")); }); test("returns true for a directory that was added explicitly", () { - set.add("root/path"); - set.add("root/path/to/file"); - expect(set, containsDir("root/path")); + paths.add("root/path"); + paths.add("root/path/to/file"); + expect(paths, containsDir("root/path")); }); test("returns false for a directory that wasn't added", () { - expect(set, isNot(containsDir("root/nothing"))); + expect(paths, isNot(containsDir("root/nothing"))); }); test("returns false for a non-directory path that was added", () { - set.add("root/path/to/file"); - expect(set, isNot(containsDir("root/path/to/file"))); + paths.add("root/path/to/file"); + expect(paths, isNot(containsDir("root/path/to/file"))); }); test( "returns false for a directory that was added implicitly and then " "removed implicitly", () { - set.add("root/path/to/file"); - set.remove("root/path/to/file"); - expect(set, isNot(containsDir("root/path"))); + paths.add("root/path/to/file"); + paths.remove("root/path/to/file"); + expect(paths, isNot(containsDir("root/path"))); }); test( "returns false for a directory that was added explicitly whose " "children were then removed", () { - set.add("root/path"); - set.add("root/path/to/file"); - set.remove("root/path/to/file"); - expect(set, isNot(containsDir("root/path"))); + paths.add("root/path"); + paths.add("root/path/to/file"); + paths.remove("root/path/to/file"); + expect(paths, isNot(containsDir("root/path"))); }); test("with a non-normalized path normalizes the path before looking it up", () { - set.add("root/path/to/file"); - expect(set, containsDir("root/../root/path/to/../to/.")); + paths.add("root/path/to/file"); + expect(paths, containsDir("root/../root/path/to/../to/.")); }); test("with an absolute path normalizes the path before looking it up", () { - set.add("root/path/to/file"); - expect(set, containsDir(p.absolute("root/path"))); + paths.add("root/path/to/file"); + expect(paths, containsDir(p.absolute("root/path"))); }); }); group("paths", () { test("returns paths added to the set", () { - set.add("root/path"); - set.add("root/path/to/one"); - set.add("root/path/to/two"); + paths.add("root/path"); + paths.add("root/path/to/one"); + paths.add("root/path/to/two"); expect( - set.paths, + paths.paths, unorderedEquals([ "root/path", "root/path/to/one", @@ -206,22 +207,22 @@ void main() { }); test("doesn't return paths removed from the set", () { - set.add("root/path/to/one"); - set.add("root/path/to/two"); - set.remove("root/path/to/two"); + paths.add("root/path/to/one"); + paths.add("root/path/to/two"); + paths.remove("root/path/to/two"); - expect(set.paths, unorderedEquals([p.normalize("root/path/to/one")])); + expect(paths.paths, unorderedEquals([p.normalize("root/path/to/one")])); }); }); group("clear", () { test("removes all paths from the set", () { - set.add("root/path"); - set.add("root/path/to/one"); - set.add("root/path/to/two"); + paths.add("root/path"); + paths.add("root/path/to/one"); + paths.add("root/path/to/two"); - set.clear(); - expect(set.paths, isEmpty); + paths.clear(); + expect(paths.paths, isEmpty); }); }); } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 637eacff7..7462c991a 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -35,10 +35,6 @@ WatcherFactory _watcherFactory; /// Creates a new [Watcher] that watches a temporary file or directory. /// -/// Normally, this will pause the schedule until the watcher is done scanning -/// and is polling for changes. If you pass `false` for [waitForReady], it will -/// not schedule this delay. -/// /// If [path] is provided, watches a subdirectory in the sandbox with that name. Watcher createWatcher({String path}) { if (path == null) { @@ -202,7 +198,7 @@ Future allowRemoveEvent(String path) => /// Schedules writing a file in the sandbox at [path] with [contents]. /// -/// If [contents] is omitted, creates an empty file. If [updatedModified] is +/// If [contents] is omitted, creates an empty file. If [updateModified] is /// `false`, the mock file modification time is not changed. void writeFile(String path, {String contents, bool updateModified}) { if (contents == null) contents = ""; @@ -232,8 +228,6 @@ void deleteFile(String path) { } /// Schedules renaming a file in the sandbox from [from] to [to]. -/// -/// If [contents] is omitted, creates an empty file. void renameFile(String from, String to) { new File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); @@ -259,8 +253,8 @@ void deleteDir(String path) { new Directory(p.join(d.sandbox, path)).deleteSync(recursive: true); } -/// Runs [callback] with every permutation of non-negative [i], [j], and [k] -/// less than [limit]. +/// Runs [callback] with every permutation of non-negative numbers for each +/// argument less than [limit]. /// /// Returns a set of all values returns by [callback]. /// From e9823fa18490b3bdddff667cadd3f91aa5017137 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 10 Sep 2018 17:46:46 -0700 Subject: [PATCH 0480/1215] Run dartfmt --fix (dart-lang/watcher#65) Drops optional `new` and `const` Bump SDK constraint to `2.0.0` to ensure compatibility with omitted `new`. --- pkgs/watcher/benchmark/path_set.dart | 12 ++-- pkgs/watcher/example/watch.dart | 2 +- pkgs/watcher/lib/src/async_queue.dart | 2 +- pkgs/watcher/lib/src/directory_watcher.dart | 8 +-- .../lib/src/directory_watcher/linux.dart | 34 +++++----- .../lib/src/directory_watcher/mac_os.dart | 64 +++++++++---------- .../lib/src/directory_watcher/polling.dart | 24 +++---- .../lib/src/directory_watcher/windows.dart | 64 +++++++++---------- pkgs/watcher/lib/src/file_watcher.dart | 4 +- pkgs/watcher/lib/src/file_watcher/native.dart | 19 +++--- .../watcher/lib/src/file_watcher/polling.dart | 16 ++--- pkgs/watcher/lib/src/path_set.dart | 14 ++-- pkgs/watcher/lib/src/resubscribable.dart | 6 +- pkgs/watcher/lib/src/stat.dart | 2 +- pkgs/watcher/lib/src/utils.dart | 6 +- pkgs/watcher/lib/src/watch_event.dart | 6 +- pkgs/watcher/lib/watcher.dart | 6 +- pkgs/watcher/pubspec.yaml | 2 +- .../test/directory_watcher/linux_test.dart | 4 +- .../test/directory_watcher/mac_os_test.dart | 4 +- .../test/directory_watcher/polling_test.dart | 4 +- .../test/directory_watcher/shared.dart | 4 +- .../test/directory_watcher/windows_test.dart | 5 +- .../test/file_watcher/native_test.dart | 2 +- .../test/file_watcher/polling_test.dart | 4 +- pkgs/watcher/test/file_watcher/shared.dart | 2 +- .../test/no_subscription/linux_test.dart | 2 +- .../test/no_subscription/mac_os_test.dart | 2 +- .../test/no_subscription/polling_test.dart | 2 +- pkgs/watcher/test/no_subscription/shared.dart | 4 +- pkgs/watcher/test/path_set_test.dart | 2 +- pkgs/watcher/test/ready/linux_test.dart | 2 +- pkgs/watcher/test/ready/mac_os_test.dart | 2 +- pkgs/watcher/test/ready/polling_test.dart | 2 +- pkgs/watcher/test/ready/shared.dart | 2 +- pkgs/watcher/test/utils.dart | 22 +++---- 36 files changed, 176 insertions(+), 186 deletions(-) diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index bf9f5fc7c..8a5b843ef 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -19,11 +19,11 @@ final String root = Platform.isWindows ? r"C:\root" : "/root"; abstract class PathSetBenchmark extends BenchmarkBase { PathSetBenchmark(String method) : super("PathSet.$method"); - final PathSet pathSet = new PathSet(root); + final PathSet pathSet = PathSet(root); /// Use a fixed [Random] with a constant seed to ensure the tests are /// deterministic. - final math.Random random = new math.Random(1234); + final math.Random random = math.Random(1234); /// Walks over a virtual directory [depth] levels deep invoking [callback] /// for each "file". @@ -140,8 +140,8 @@ class RemoveBenchmark extends PathSetBenchmark { } main() { - new AddBenchmark().report(); - new ContainsBenchmark().report(); - new PathsBenchmark().report(); - new RemoveBenchmark().report(); + AddBenchmark().report(); + ContainsBenchmark().report(); + PathsBenchmark().report(); + RemoveBenchmark().report(); } diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index da3c2633c..1477e4282 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -14,7 +14,7 @@ main(List arguments) { return; } - var watcher = new DirectoryWatcher(p.absolute(arguments[0])); + var watcher = DirectoryWatcher(p.absolute(arguments[0])); watcher.events.listen((event) { print(event); }); diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 1904192b4..de7b7188a 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -17,7 +17,7 @@ typedef Future ItemProcessor(T item); /// needed. When all items are processed, it stops processing until more items /// are added. class AsyncQueue { - final _items = new Queue(); + final _items = Queue(); /// Whether or not the queue is currently waiting on a processing future to /// complete. diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 6beebd0a4..8c52ed97a 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -29,10 +29,10 @@ abstract class DirectoryWatcher implements Watcher { /// watchers. factory DirectoryWatcher(String directory, {Duration pollingDelay}) { if (FileSystemEntity.isWatchSupported) { - if (Platform.isLinux) return new LinuxDirectoryWatcher(directory); - if (Platform.isMacOS) return new MacOSDirectoryWatcher(directory); - if (Platform.isWindows) return new WindowsDirectoryWatcher(directory); + if (Platform.isLinux) return LinuxDirectoryWatcher(directory); + if (Platform.isMacOS) return MacOSDirectoryWatcher(directory); + if (Platform.isWindows) return WindowsDirectoryWatcher(directory); } - return new PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); + return PollingDirectoryWatcher(directory, pollingDelay: pollingDelay); } } diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 5eeed2327..f3866c6c6 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -28,7 +28,7 @@ class LinuxDirectoryWatcher extends ResubscribableWatcher String get directory => path; LinuxDirectoryWatcher(String directory) - : super(directory, () => new _LinuxDirectoryWatcher(directory)); + : super(directory, () => _LinuxDirectoryWatcher(directory)); } class _LinuxDirectoryWatcher @@ -37,16 +37,16 @@ class _LinuxDirectoryWatcher String get path => _files.root; Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); + final _eventsController = StreamController.broadcast(); bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); + final _readyCompleter = Completer(); /// A stream group for the [Directory.watch] events of [path] and all its /// subdirectories. - var _nativeEvents = new StreamGroup(); + var _nativeEvents = StreamGroup(); /// All known files recursively within [path]. final PathSet _files; @@ -60,12 +60,12 @@ class _LinuxDirectoryWatcher /// /// These are gathered together so that they may all be canceled when the /// watcher is closed. - final _subscriptions = new Set(); + final _subscriptions = Set(); - _LinuxDirectoryWatcher(String path) : _files = new PathSet(path) { - _nativeEvents.add(new Directory(path) + _LinuxDirectoryWatcher(String path) : _files = PathSet(path) { + _nativeEvents.add(Directory(path) .watch() - .transform(new StreamTransformer.fromHandlers(handleDone: (sink) { + .transform(StreamTransformer.fromHandlers(handleDone: (sink) { // Handle the done event here rather than in the call to [_listen] because // [innerStream] won't close until we close the [StreamGroup]. However, if // we close the [StreamGroup] here, we run the risk of new-directory @@ -76,11 +76,10 @@ class _LinuxDirectoryWatcher // Batch the inotify changes together so that we can dedup events. var innerStream = _nativeEvents.stream - .transform(new BatchedStreamTransformer()); + .transform(BatchedStreamTransformer()); _listen(innerStream, _onBatch, onError: _eventsController.addError); - _listen(new Directory(path).list(recursive: true), - (FileSystemEntity entity) { + _listen(Directory(path).list(recursive: true), (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); } else { @@ -122,16 +121,16 @@ class _LinuxDirectoryWatcher // TODO(nweiz): Catch any errors here that indicate that the directory in // question doesn't exist and silently stop watching it instead of // propagating the errors. - var stream = new Directory(path).watch(); + var stream = Directory(path).watch(); _subdirStreams[path] = stream; _nativeEvents.add(stream); } /// The callback that's run when a batch of changes comes in. void _onBatch(List batch) { - var files = new Set(); - var dirs = new Set(); - var changed = new Set(); + var files = Set(); + var dirs = Set(); + var changed = Set(); // inotify event batches are ordered by occurrence, so we treat them as a // log of what happened to a file. We only emit events based on the @@ -208,8 +207,7 @@ class _LinuxDirectoryWatcher /// Emits [ChangeType.ADD] events for the recursive contents of [path]. void _addSubdir(String path) { - _listen(new Directory(path).list(recursive: true), - (FileSystemEntity entity) { + _listen(Directory(path).list(recursive: true), (FileSystemEntity entity) { if (entity is Directory) { _watchSubdir(entity.path); } else { @@ -247,7 +245,7 @@ class _LinuxDirectoryWatcher void _emit(ChangeType type, String path) { if (!isReady) return; if (_eventsController.isClosed) return; - _eventsController.add(new WatchEvent(type, path)); + _eventsController.add(WatchEvent(type, path)); } /// Like [Stream.listen], but automatically adds the subscription to diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 61531c5d9..f593fbd51 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -27,7 +27,7 @@ class MacOSDirectoryWatcher extends ResubscribableWatcher String get directory => path; MacOSDirectoryWatcher(String directory) - : super(directory, () => new _MacOSDirectoryWatcher(directory)); + : super(directory, () => _MacOSDirectoryWatcher(directory)); } class _MacOSDirectoryWatcher @@ -36,12 +36,12 @@ class _MacOSDirectoryWatcher final String path; Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); + final _eventsController = StreamController.broadcast(); bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); + final _readyCompleter = Completer(); /// The set of files that are known to exist recursively within the watched /// directory. @@ -64,7 +64,7 @@ class _MacOSDirectoryWatcher /// The subscriptions to [Directory.list] calls for listing the contents of a /// subdirectory that was moved into the watched directory. - final _listSubscriptions = new Set>(); + final _listSubscriptions = Set>(); /// The timer for tracking how long we wait for an initial batch of bogus /// events (see issue 14373). @@ -72,7 +72,7 @@ class _MacOSDirectoryWatcher _MacOSDirectoryWatcher(String path) : path = path, - _files = new PathSet(path) { + _files = PathSet(path) { _startWatch(); // Before we're ready to emit events, wait for [_listDir] to complete and @@ -136,8 +136,7 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; StreamSubscription subscription; - subscription = - new Directory(path).list(recursive: true).listen((entity) { + subscription = Directory(path).list(recursive: true).listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -182,11 +181,11 @@ class _MacOSDirectoryWatcher // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return new Set(); + if (!event.isDirectory) return Set(); if (event is FileSystemMoveEvent) { - return new Set.from([event.path, event.destination]); + return Set.from([event.path, event.destination]); } - return new Set.from([event.path]); + return Set.from([event.path]); })); isInModifiedDirectory(String path) => @@ -194,9 +193,7 @@ class _MacOSDirectoryWatcher addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - eventsForPaths - .putIfAbsent(path, () => new Set()) - .add(event); + eventsForPaths.putIfAbsent(path, () => Set()).add(event); } for (var event in batch) { @@ -271,11 +268,11 @@ class _MacOSDirectoryWatcher // [_eventsBasedOnFileSystem] will handle this correctly by producing a // DELETE event followed by a CREATE event if the directory exists. if (isDir) return null; - return new ConstructableFileSystemCreateEvent(batch.first.path, false); + return ConstructableFileSystemCreateEvent(batch.first.path, false); case FileSystemEvent.delete: - return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + return ConstructableFileSystemDeleteEvent(batch.first.path, isDir); case FileSystemEvent.modify: - return new ConstructableFileSystemModifyEvent( + return ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); default: throw 'unreachable'; @@ -292,32 +289,32 @@ class _MacOSDirectoryWatcher List _eventsBasedOnFileSystem(String path) { var fileExisted = _files.contains(path); var dirExisted = _files.containsDir(path); - var fileExists = new File(path).existsSync(); - var dirExists = new Directory(path).existsSync(); + var fileExists = File(path).existsSync(); + var dirExists = Directory(path).existsSync(); var events = []; if (fileExisted) { if (fileExists) { - events.add(new ConstructableFileSystemModifyEvent(path, false, false)); + events.add(ConstructableFileSystemModifyEvent(path, false, false)); } else { - events.add(new ConstructableFileSystemDeleteEvent(path, false)); + events.add(ConstructableFileSystemDeleteEvent(path, false)); } } else if (dirExisted) { if (dirExists) { // If we got contradictory events for a directory that used to exist and // still exists, we need to rescan the whole thing in case it was // replaced with a different directory. - events.add(new ConstructableFileSystemDeleteEvent(path, true)); - events.add(new ConstructableFileSystemCreateEvent(path, true)); + events.add(ConstructableFileSystemDeleteEvent(path, true)); + events.add(ConstructableFileSystemCreateEvent(path, true)); } else { - events.add(new ConstructableFileSystemDeleteEvent(path, true)); + events.add(ConstructableFileSystemDeleteEvent(path, true)); } } if (!fileExisted && fileExists) { - events.add(new ConstructableFileSystemCreateEvent(path, false)); + events.add(ConstructableFileSystemCreateEvent(path, false)); } else if (!dirExisted && dirExists) { - events.add(new ConstructableFileSystemCreateEvent(path, true)); + events.add(ConstructableFileSystemCreateEvent(path, true)); } return events; @@ -330,7 +327,7 @@ class _MacOSDirectoryWatcher // If the directory still exists and we're still expecting bogus events, // this is probably issue 14849 rather than a real close event. We should // just restart the watcher. - if (!isReady && new Directory(path).existsSync()) { + if (!isReady && Directory(path).existsSync()) { _startWatch(); return; } @@ -348,9 +345,9 @@ class _MacOSDirectoryWatcher /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = new Directory(path) + var innerStream = Directory(path) .watch(recursive: true) - .transform(new BatchedStreamTransformer()); + .transform(BatchedStreamTransformer()); _watchSubscription = innerStream.listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); } @@ -362,8 +359,8 @@ class _MacOSDirectoryWatcher if (_initialListSubscription != null) _initialListSubscription.cancel(); _files.clear(); - var completer = new Completer(); - var stream = new Directory(path).list(recursive: true); + var completer = Completer(); + var stream = Directory(path).list(recursive: true); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); }, onError: _emitError, onDone: completer.complete, cancelOnError: true); @@ -376,16 +373,15 @@ class _MacOSDirectoryWatcher /// watcher tests take on the bots, so it should be safe to assume that any /// bogus events will be signaled in that time frame. Future _waitForBogusEvents() { - var completer = new Completer(); - _bogusEventTimer = - new Timer(new Duration(milliseconds: 200), completer.complete); + var completer = Completer(); + _bogusEventTimer = Timer(Duration(milliseconds: 200), completer.complete); return completer.future; } /// Emit an event with the given [type] and [path]. void _emitEvent(ChangeType type, String path) { if (!isReady) return; - _eventsController.add(new WatchEvent(type, path)); + _eventsController.add(WatchEvent(type, path)); } /// Emit an error, then close the watcher. diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 790d0b982..735a80722 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -25,8 +25,8 @@ class PollingDirectoryWatcher extends ResubscribableWatcher /// and higher CPU usage. Defaults to one second. PollingDirectoryWatcher(String directory, {Duration pollingDelay}) : super(directory, () { - return new _PollingDirectoryWatcher(directory, - pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + return _PollingDirectoryWatcher(directory, + pollingDelay != null ? pollingDelay : Duration(seconds: 1)); }); } @@ -36,12 +36,12 @@ class _PollingDirectoryWatcher final String path; Stream get events => _events.stream; - final _events = new StreamController.broadcast(); + final _events = StreamController.broadcast(); bool get isReady => _ready.isCompleted; Future get ready => _ready.future; - final _ready = new Completer(); + final _ready = Completer(); /// The amount of time the watcher pauses between successive polls of the /// directory contents. @@ -50,7 +50,7 @@ class _PollingDirectoryWatcher /// The previous modification times of the files in the directory. /// /// Used to tell which files have been modified. - final _lastModifieds = new Map(); + final _lastModifieds = Map(); /// The subscription used while [directory] is being listed. /// @@ -70,11 +70,11 @@ class _PollingDirectoryWatcher /// /// Used to tell which files have been removed: files that are in /// [_lastModifieds] but not in here when a poll completes have been removed. - final _polledFiles = new Set(); + final _polledFiles = Set(); _PollingDirectoryWatcher(this.path, this._pollingDelay) { - _filesToProcess = new AsyncQueue(_processFile, - onError: (e, StackTrace stackTrace) { + _filesToProcess = + AsyncQueue(_processFile, onError: (e, StackTrace stackTrace) { if (!_events.isClosed) _events.addError(e, stackTrace); }); @@ -107,7 +107,7 @@ class _PollingDirectoryWatcher _filesToProcess.add(null); } - var stream = new Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true); _listSubscription = stream.listen((entity) { assert(!_events.isClosed); @@ -154,7 +154,7 @@ class _PollingDirectoryWatcher if (!isReady) return null; var type = lastModified == null ? ChangeType.ADD : ChangeType.MODIFY; - _events.add(new WatchEvent(type, file)); + _events.add(WatchEvent(type, file)); }); } @@ -165,14 +165,14 @@ class _PollingDirectoryWatcher // status for must have been removed. var removedFiles = _lastModifieds.keys.toSet().difference(_polledFiles); for (var removed in removedFiles) { - if (isReady) _events.add(new WatchEvent(ChangeType.REMOVE, removed)); + if (isReady) _events.add(WatchEvent(ChangeType.REMOVE, removed)); _lastModifieds.remove(removed); } if (!isReady) _ready.complete(); // Wait and then poll again. - return new Future.delayed(_pollingDelay).then((_) { + return Future.delayed(_pollingDelay).then((_) { if (_events.isClosed) return; _poll(); }); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index baeaf233a..021493995 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -21,11 +21,11 @@ class WindowsDirectoryWatcher extends ResubscribableWatcher String get directory => path; WindowsDirectoryWatcher(String directory) - : super(directory, () => new _WindowsDirectoryWatcher(directory)); + : super(directory, () => _WindowsDirectoryWatcher(directory)); } class _EventBatcher { - static const Duration _BATCH_DELAY = const Duration(milliseconds: 100); + static const Duration _BATCH_DELAY = Duration(milliseconds: 100); final List events = []; Timer timer; @@ -34,7 +34,7 @@ class _EventBatcher { if (timer != null) { timer.cancel(); } - timer = new Timer(_BATCH_DELAY, callback); + timer = Timer(_BATCH_DELAY, callback); } void cancelTimer() { @@ -48,15 +48,15 @@ class _WindowsDirectoryWatcher final String path; Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); + final _eventsController = StreamController.broadcast(); bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); + final _readyCompleter = Completer(); final Map _eventBatchers = - new HashMap(); + HashMap(); /// The set of files that are known to exist recursively within the watched /// directory. @@ -81,11 +81,11 @@ class _WindowsDirectoryWatcher /// The subscriptions to the [Directory.list] calls for listing the contents /// of subdirectories that were moved into the watched directory. final Set> _listSubscriptions = - new HashSet>(); + HashSet>(); _WindowsDirectoryWatcher(String path) : path = path, - _files = new PathSet(path) { + _files = PathSet(path) { // Before we're ready to emit events, wait for [_listDir] to complete. _listDir().then((_) { _startWatch(); @@ -121,7 +121,7 @@ class _WindowsDirectoryWatcher var parent = p.dirname(absoluteDir); // Check if [path] is already the root directory. if (FileSystemEntity.identicalSync(parent, path)) return; - var parentStream = new Directory(parent).watch(recursive: false); + var parentStream = Directory(parent).watch(recursive: false); _parentWatchSubscription = parentStream.listen((event) { // Only look at events for 'directory'. if (p.basename(event.path) != p.basename(absoluteDir)) return; @@ -151,7 +151,7 @@ class _WindowsDirectoryWatcher void _onEvent(FileSystemEvent event) { assert(isReady); final batcher = - _eventBatchers.putIfAbsent(event.path, () => new _EventBatcher()); + _eventBatchers.putIfAbsent(event.path, () => _EventBatcher()); batcher.addEvent(event, () { _eventBatchers.remove(event.path); _onBatch(batcher.events); @@ -178,7 +178,7 @@ class _WindowsDirectoryWatcher if (_files.containsDir(path)) continue; - var stream = new Directory(path).list(recursive: true); + var stream = Directory(path).list(recursive: true); StreamSubscription subscription; subscription = stream.listen((entity) { if (entity is Directory) return; @@ -222,11 +222,11 @@ class _WindowsDirectoryWatcher // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return new Set(); + if (!event.isDirectory) return Set(); if (event is FileSystemMoveEvent) { - return new Set.from([event.path, event.destination]); + return Set.from([event.path, event.destination]); } - return new Set.from([event.path]); + return Set.from([event.path]); })); isInModifiedDirectory(String path) => @@ -234,9 +234,7 @@ class _WindowsDirectoryWatcher addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - eventsForPaths - .putIfAbsent(path, () => new Set()) - .add(event); + eventsForPaths.putIfAbsent(path, () => Set()).add(event); } for (var event in batch) { @@ -297,11 +295,11 @@ class _WindowsDirectoryWatcher switch (type) { case FileSystemEvent.create: - return new ConstructableFileSystemCreateEvent(batch.first.path, isDir); + return ConstructableFileSystemCreateEvent(batch.first.path, isDir); case FileSystemEvent.delete: - return new ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + return ConstructableFileSystemDeleteEvent(batch.first.path, isDir); case FileSystemEvent.modify: - return new ConstructableFileSystemModifyEvent( + return ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); case FileSystemEvent.move: return null; @@ -320,32 +318,32 @@ class _WindowsDirectoryWatcher List _eventsBasedOnFileSystem(String path) { var fileExisted = _files.contains(path); var dirExisted = _files.containsDir(path); - var fileExists = new File(path).existsSync(); - var dirExists = new Directory(path).existsSync(); + var fileExists = File(path).existsSync(); + var dirExists = Directory(path).existsSync(); var events = []; if (fileExisted) { if (fileExists) { - events.add(new ConstructableFileSystemModifyEvent(path, false, false)); + events.add(ConstructableFileSystemModifyEvent(path, false, false)); } else { - events.add(new ConstructableFileSystemDeleteEvent(path, false)); + events.add(ConstructableFileSystemDeleteEvent(path, false)); } } else if (dirExisted) { if (dirExists) { // If we got contradictory events for a directory that used to exist and // still exists, we need to rescan the whole thing in case it was // replaced with a different directory. - events.add(new ConstructableFileSystemDeleteEvent(path, true)); - events.add(new ConstructableFileSystemCreateEvent(path, true)); + events.add(ConstructableFileSystemDeleteEvent(path, true)); + events.add(ConstructableFileSystemCreateEvent(path, true)); } else { - events.add(new ConstructableFileSystemDeleteEvent(path, true)); + events.add(ConstructableFileSystemDeleteEvent(path, true)); } } if (!fileExisted && fileExists) { - events.add(new ConstructableFileSystemCreateEvent(path, false)); + events.add(ConstructableFileSystemCreateEvent(path, false)); } else if (!dirExisted && dirExists) { - events.add(new ConstructableFileSystemCreateEvent(path, true)); + events.add(ConstructableFileSystemCreateEvent(path, true)); } return events; @@ -368,7 +366,7 @@ class _WindowsDirectoryWatcher /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the events together so that we can dedup events. - var innerStream = new Directory(path).watch(recursive: true); + var innerStream = Directory(path).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, onError: _eventsController.addError, onDone: _onDone); } @@ -380,8 +378,8 @@ class _WindowsDirectoryWatcher if (_initialListSubscription != null) _initialListSubscription.cancel(); _files.clear(); - var completer = new Completer(); - var stream = new Directory(path).list(recursive: true); + var completer = Completer(); + var stream = Directory(path).list(recursive: true); void handleEntity(FileSystemEntity entity) { if (entity is! Directory) _files.add(entity.path); } @@ -395,7 +393,7 @@ class _WindowsDirectoryWatcher void _emitEvent(ChangeType type, String path) { if (!isReady) return; - _eventsController.add(new WatchEvent(type, path)); + _eventsController.add(WatchEvent(type, path)); } /// Emit an error, then close the watcher. diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index 09065bc8b..c4abddd6c 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -33,8 +33,8 @@ abstract class FileWatcher implements Watcher { // [FileSystemEntity.isWatchSupported] is still true because directory // watching does work. if (FileSystemEntity.isWatchSupported && !Platform.isWindows) { - return new NativeFileWatcher(file); + return NativeFileWatcher(file); } - return new PollingFileWatcher(file, pollingDelay: pollingDelay); + return PollingFileWatcher(file, pollingDelay: pollingDelay); } } diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 5f56f739f..ff25eb74e 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -15,20 +15,19 @@ import '../watch_event.dart'; /// Single-file notifications are much simpler than those for multiple files, so /// this doesn't need to be split out into multiple OS-specific classes. class NativeFileWatcher extends ResubscribableWatcher implements FileWatcher { - NativeFileWatcher(String path) - : super(path, () => new _NativeFileWatcher(path)); + NativeFileWatcher(String path) : super(path, () => _NativeFileWatcher(path)); } class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { final String path; Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); + final _eventsController = StreamController.broadcast(); bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); + final _readyCompleter = Completer(); StreamSubscription _subscription; @@ -42,9 +41,9 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { void _listen() { // Batch the events together so that we can dedup them. - _subscription = new File(path) + _subscription = File(path) .watch() - .transform(new BatchedStreamTransformer()) + .transform(BatchedStreamTransformer()) .listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); } @@ -55,11 +54,11 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { return; } - _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); } _onDone() async { - var fileExists = await new File(path).exists(); + var fileExists = await File(path).exists(); // Check for this after checking whether the file exists because it's // possible that [close] was called between [File.exists] being called and @@ -70,10 +69,10 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { // If the file exists now, it was probably removed and quickly replaced; // this can happen for example when another file is moved on top of it. // Re-subscribe and report a modify event. - _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); _listen(); } else { - _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + _eventsController.add(WatchEvent(ChangeType.REMOVE, path)); close(); } } diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 960b11b9b..777038fdf 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -14,8 +14,8 @@ import '../watch_event.dart'; class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { PollingFileWatcher(String path, {Duration pollingDelay}) : super(path, () { - return new _PollingFileWatcher(path, - pollingDelay != null ? pollingDelay : new Duration(seconds: 1)); + return _PollingFileWatcher( + path, pollingDelay != null ? pollingDelay : Duration(seconds: 1)); }); } @@ -23,12 +23,12 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { final String path; Stream get events => _eventsController.stream; - final _eventsController = new StreamController.broadcast(); + final _eventsController = StreamController.broadcast(); bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - final _readyCompleter = new Completer(); + final _readyCompleter = Completer(); /// The timer that controls polling. Timer _timer; @@ -40,7 +40,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { DateTime _lastModified; _PollingFileWatcher(this.path, Duration pollingDelay) { - _timer = new Timer.periodic(pollingDelay, (_) => _poll()); + _timer = Timer.periodic(pollingDelay, (_) => _poll()); _poll(); } @@ -49,11 +49,11 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { // We don't mark the file as removed if this is the first poll (indicated by // [_lastModified] being null). Instead, below we forward the dart:io error // that comes from trying to read the mtime below. - var pathExists = await new File(path).exists(); + var pathExists = await File(path).exists(); if (_eventsController.isClosed) return; if (_lastModified != null && !pathExists) { - _eventsController.add(new WatchEvent(ChangeType.REMOVE, path)); + _eventsController.add(WatchEvent(ChangeType.REMOVE, path)); close(); return; } @@ -80,7 +80,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { _readyCompleter.complete(); } else { _lastModified = modified; - _eventsController.add(new WatchEvent(ChangeType.MODIFY, path)); + _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); } } diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 77737f82e..9a2c03cc1 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -22,7 +22,7 @@ class PathSet { /// Each entry represents a directory or file. It may be a file or directory /// that was explicitly added, or a parent directory that was implicitly /// added in order to add a child. - final _Entry _entries = new _Entry(); + final _Entry _entries = _Entry(); PathSet(this.root); @@ -33,7 +33,7 @@ class PathSet { var parts = p.split(path); var entry = _entries; for (var part in parts) { - entry = entry.contents.putIfAbsent(part, () => new _Entry()); + entry = entry.contents.putIfAbsent(part, () => _Entry()); } entry.isExplicit = true; @@ -49,7 +49,7 @@ class PathSet { /// empty set. Set remove(String path) { path = _normalize(path); - var parts = new Queue.of(p.split(path)); + var parts = Queue.of(p.split(path)); // Remove the children of [dir], as well as [dir] itself if necessary. // @@ -61,7 +61,7 @@ class PathSet { // the next level. var part = parts.removeFirst(); var entry = dir.contents[part]; - if (entry == null || entry.contents.isEmpty) return new Set(); + if (entry == null || entry.contents.isEmpty) return Set(); partialPath = p.join(partialPath, part); var paths = recurse(entry, partialPath); @@ -75,10 +75,10 @@ class PathSet { // If there's only one component left in [path], we should remove it. var entry = dir.contents.remove(parts.first); - if (entry == null) return new Set(); + if (entry == null) return Set(); if (entry.contents.isEmpty) { - return new Set.from([p.join(root, path)]); + return Set.from([p.join(root, path)]); } var set = _explicitPathsWithin(entry, path); @@ -96,7 +96,7 @@ class PathSet { /// /// [dirPath] should be the path to [dir]. Set _explicitPathsWithin(_Entry dir, String dirPath) { - var paths = new Set(); + var paths = Set(); recurse(_Entry dir, String path) { dir.contents.forEach((name, entry) { var entryPath = p.join(path, name); diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index e96b918dc..e00ebb0d1 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -32,7 +32,7 @@ abstract class ResubscribableWatcher implements Watcher { bool get isReady => _readyCompleter.isCompleted; Future get ready => _readyCompleter.future; - var _readyCompleter = new Completer(); + var _readyCompleter = Completer(); /// Creates a new [ResubscribableWatcher] wrapping the watchers /// emitted by [_factory]. @@ -40,7 +40,7 @@ abstract class ResubscribableWatcher implements Watcher { ManuallyClosedWatcher watcher; StreamSubscription subscription; - _eventsController = new StreamController.broadcast( + _eventsController = StreamController.broadcast( onListen: () { watcher = _factory(); subscription = watcher.events.listen(_eventsController.add, @@ -57,7 +57,7 @@ abstract class ResubscribableWatcher implements Watcher { // watcher's `onDone` event doesn't close [events]. subscription.cancel(); watcher.close(); - _readyCompleter = new Completer(); + _readyCompleter = Completer(); }, sync: true); } diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 05ee9ba0a..59a5eb6f0 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -24,7 +24,7 @@ void mockGetModificationTime(MockTimeCallback callback) { /// Gets the modification time for the file at [path]. Future getModificationTime(String path) { if (_mockTimeCallback != null) { - return new Future.value(_mockTimeCallback(path)); + return Future.value(_mockTimeCallback(path)); } return FileStat.stat(path).then((stat) => stat.modified); diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 30fbaae21..676ae281b 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -18,7 +18,7 @@ bool isDirectoryNotFoundException(error) { /// Returns the union of all elements in each set in [sets]. Set unionAll(Iterable> sets) => - sets.fold(new Set(), (union, set) => union.union(set)); + sets.fold(Set(), (union, set) => union.union(set)); /// A stream transformer that batches all events that are sent at the same time. /// @@ -29,8 +29,8 @@ Set unionAll(Iterable> sets) => /// microtasks. class BatchedStreamTransformer extends StreamTransformerBase> { Stream> bind(Stream input) { - var batch = new Queue(); - return new StreamTransformer>.fromHandlers( + var batch = Queue(); + return StreamTransformer>.fromHandlers( handleData: (event, sink) { batch.add(event); diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart index 54093a5d7..94ee5cb89 100644 --- a/pkgs/watcher/lib/src/watch_event.dart +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -18,13 +18,13 @@ class WatchEvent { /// Enum for what kind of change has happened to a file. class ChangeType { /// A new file has been added. - static const ADD = const ChangeType("add"); + static const ADD = ChangeType("add"); /// A file has been removed. - static const REMOVE = const ChangeType("remove"); + static const REMOVE = ChangeType("remove"); /// The contents of a file have changed. - static const MODIFY = const ChangeType("modify"); + static const MODIFY = ChangeType("modify"); final String _name; const ChangeType(this._name); diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index b3cebe665..107ac8fae 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -58,10 +58,10 @@ abstract class Watcher { /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. factory Watcher(String path, {Duration pollingDelay}) { - if (new File(path).existsSync()) { - return new FileWatcher(path, pollingDelay: pollingDelay); + if (File(path).existsSync()) { + return FileWatcher(path, pollingDelay: pollingDelay); } else { - return new DirectoryWatcher(path, pollingDelay: pollingDelay); + return DirectoryWatcher(path, pollingDelay: pollingDelay); } } } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 8f38a49f6..552b13a9d 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -8,7 +8,7 @@ author: Dart Team homepage: https://github.com/dart-lang/watcher environment: - sdk: '>=2.0.0-dev.61.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: async: '>=1.10.0 <3.0.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 744045fcd..0b81919a2 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -12,12 +12,12 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + watcherFactory = (dir) => LinuxDirectoryWatcher(dir); sharedTests(); test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { - expect(new DirectoryWatcher('.'), new TypeMatcher()); + expect(DirectoryWatcher('.'), TypeMatcher()); }); test('emits events for many nested files moved out then immediately back in', diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 689d35318..1470f71dc 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -12,12 +12,12 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + watcherFactory = (dir) => MacOSDirectoryWatcher(dir); sharedTests(); test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { - expect(new DirectoryWatcher('.'), new TypeMatcher()); + expect(DirectoryWatcher('.'), TypeMatcher()); }); test( diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 39bbbef0b..d64eb0706 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -10,8 +10,8 @@ import '../utils.dart'; void main() { // Use a short delay to make the tests run quickly. - watcherFactory = (dir) => new PollingDirectoryWatcher(dir, - pollingDelay: new Duration(milliseconds: 100)); + watcherFactory = (dir) => + PollingDirectoryWatcher(dir, pollingDelay: Duration(milliseconds: 100)); sharedTests(); diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 2c0f44116..f6e451cbc 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -276,7 +276,7 @@ void sharedTests() { isAddEvent("new") ]); }, onPlatform: { - "mac-os": new Skip("https://github.com/dart-lang/watcher/issues/21") + "mac-os": Skip("https://github.com/dart-lang/watcher/issues/21") }); test('emits events for many nested files added at once', () async { @@ -316,7 +316,7 @@ void sharedTests() { renameDir("dir/old", "dir/new"); await inAnyOrder(unionAll(withPermutations((i, j, k) { - return new Set.from([ + return Set.from([ isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"), isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt") ]); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 875f4ee81..7931fa819 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -12,7 +12,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new WindowsDirectoryWatcher(dir); + watcherFactory = (dir) => WindowsDirectoryWatcher(dir); // TODO(grouma) - renable when https://github.com/dart-lang/sdk/issues/31760 // is resolved. @@ -21,7 +21,6 @@ void main() { }, skip: "SDK issue see - https://github.com/dart-lang/sdk/issues/31760"); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { - expect( - new DirectoryWatcher('.'), new TypeMatcher()); + expect(DirectoryWatcher('.'), TypeMatcher()); }); } diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart index b6ed901bc..2417dae60 100644 --- a/pkgs/watcher/test/file_watcher/native_test.dart +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -11,7 +11,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (file) => new NativeFileWatcher(file); + watcherFactory = (file) => NativeFileWatcher(file); setUp(() { writeFile("file.txt"); diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index 01d579a9f..9492f658e 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -11,8 +11,8 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (file) => new PollingFileWatcher(file, - pollingDelay: new Duration(milliseconds: 100)); + watcherFactory = (file) => + PollingFileWatcher(file, pollingDelay: Duration(milliseconds: 100)); setUp(() { writeFile("file.txt"); diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 286a04210..eefe5dfc4 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -64,7 +64,7 @@ void sharedTests() { var sub = watcher.events.listen(null); deleteFile("file.txt"); - await new Future.delayed(new Duration(milliseconds: 10)); + await Future.delayed(Duration(milliseconds: 10)); await sub.cancel(); }); } diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart index e9bfd69ca..aa5763772 100644 --- a/pkgs/watcher/test/no_subscription/linux_test.dart +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -11,7 +11,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + watcherFactory = (dir) => LinuxDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index fc14ebf10..5ffb11738 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -12,7 +12,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + watcherFactory = (dir) => MacOSDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart index 75fa3a7a0..633ca2eb4 100644 --- a/pkgs/watcher/test/no_subscription/polling_test.dart +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -8,7 +8,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new PollingDirectoryWatcher(dir); + watcherFactory = (dir) => PollingDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index ba8468401..2fa3353e0 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -14,7 +14,7 @@ void sharedTests() { // utils.dart because it needs to be very explicit about when the event // stream is and is not subscribed. var watcher = createWatcher(); - var queue = new StreamQueue(watcher.events); + var queue = StreamQueue(watcher.events); queue.hasNext; var future = @@ -33,7 +33,7 @@ void sharedTests() { // Now write a file while we aren't listening. writeFile("unwatched.txt"); - queue = new StreamQueue(watcher.events); + queue = StreamQueue(watcher.events); future = expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "added.txt"))); expect(queue, neverEmits(isWatchEvent(ChangeType.ADD, "unwatched.txt"))); diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index fe91d417f..9ca418180 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -16,7 +16,7 @@ Matcher containsDir(String path) => predicate( void main() { PathSet paths; - setUp(() => paths = new PathSet("root")); + setUp(() => paths = PathSet("root")); group("adding a path", () { test("stores the path in the set", () { diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart index e9bfd69ca..aa5763772 100644 --- a/pkgs/watcher/test/ready/linux_test.dart +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -11,7 +11,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new LinuxDirectoryWatcher(dir); + watcherFactory = (dir) => LinuxDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart index 9533cc818..4bfdc8d3e 100644 --- a/pkgs/watcher/test/ready/mac_os_test.dart +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -11,7 +11,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new MacOSDirectoryWatcher(dir); + watcherFactory = (dir) => MacOSDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart index 75fa3a7a0..633ca2eb4 100644 --- a/pkgs/watcher/test/ready/polling_test.dart +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -8,7 +8,7 @@ import 'shared.dart'; import '../utils.dart'; void main() { - watcherFactory = (dir) => new PollingDirectoryWatcher(dir); + watcherFactory = (dir) => PollingDirectoryWatcher(dir); sharedTests(); } diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index 730d57953..76089e25e 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -38,7 +38,7 @@ void sharedTests() { // Ensure ready completes immediately expect( - watcher.ready.timeout(new Duration(milliseconds: 0), + watcher.ready.timeout(Duration(milliseconds: 0), onTimeout: () => throw 'Does not complete immedately'), completes); }); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 7462c991a..95f594d8a 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -61,13 +61,13 @@ Future startWatcher({String path}) async { assert(p.isRelative(path) && !path.startsWith("..")); var mtime = _mockFileModificationTimes[path]; - return new DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); + return DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); }); // We want to wait until we're ready *after* we subscribe to the watcher's // events. var watcher = createWatcher(path: path); - _watcherEvents = new StreamQueue(watcher.events); + _watcherEvents = StreamQueue(watcher.events); // Forces a subscription to the underlying stream. _watcherEvents.hasNext; await watcher.ready; @@ -93,7 +93,7 @@ List _collectedStreamMatchers; /// The returned matcher will match each of the collected matchers in order. StreamMatcher _collectStreamMatcher(block()) { var oldStreamMatchers = _collectedStreamMatchers; - _collectedStreamMatchers = new List(); + _collectedStreamMatchers = List(); try { block(); return emitsInOrder(_collectedStreamMatchers); @@ -207,12 +207,12 @@ void writeFile(String path, {String contents, bool updateModified}) { var fullPath = p.join(d.sandbox, path); // Create any needed subdirectories. - var dir = new Directory(p.dirname(fullPath)); + var dir = Directory(p.dirname(fullPath)); if (!dir.existsSync()) { dir.createSync(recursive: true); } - new File(fullPath).writeAsStringSync(contents); + File(fullPath).writeAsStringSync(contents); if (updateModified) { path = p.normalize(path); @@ -224,12 +224,12 @@ void writeFile(String path, {String contents, bool updateModified}) { /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { - new File(p.join(d.sandbox, path)).deleteSync(); + File(p.join(d.sandbox, path)).deleteSync(); } /// Schedules renaming a file in the sandbox from [from] to [to]. void renameFile(String from, String to) { - new File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); + File(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); // Make sure we always use the same separator on Windows. to = p.normalize(to); @@ -240,17 +240,17 @@ void renameFile(String from, String to) { /// Schedules creating a directory in the sandbox at [path]. void createDir(String path) { - new Directory(p.join(d.sandbox, path)).createSync(); + Directory(p.join(d.sandbox, path)).createSync(); } /// Schedules renaming a directory in the sandbox from [from] to [to]. void renameDir(String from, String to) { - new Directory(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); + Directory(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); } /// Schedules deleting a directory in the sandbox at [path]. void deleteDir(String path) { - new Directory(p.join(d.sandbox, path)).deleteSync(recursive: true); + Directory(p.join(d.sandbox, path)).deleteSync(recursive: true); } /// Runs [callback] with every permutation of non-negative numbers for each @@ -261,7 +261,7 @@ void deleteDir(String path) { /// [limit] defaults to 3. Set withPermutations(S callback(int i, int j, int k), {int limit}) { if (limit == null) limit = 3; - var results = new Set(); + var results = Set(); for (var i = 0; i < limit; i++) { for (var j = 0; j < limit; j++) { for (var k = 0; k < limit; k++) { From d6bad1fdf2d8cd35f572982260b919f510aab1f1 Mon Sep 17 00:00:00 2001 From: samogot Date: Tue, 11 Sep 2018 12:03:57 -0700 Subject: [PATCH 0481/1215] Create timing package (dart-lang/timing#1) --- pkgs/timing/.gitignore | 7 + pkgs/timing/.travis.yml | 17 ++ pkgs/timing/CHANGELOG.md | 3 + pkgs/timing/LICENSE | 26 ++ pkgs/timing/README.md | 13 + pkgs/timing/lib/src/clock.dart | 20 ++ pkgs/timing/lib/src/timing.dart | 309 ++++++++++++++++++++++ pkgs/timing/lib/timing.dart | 13 + pkgs/timing/pubspec.yaml | 11 + pkgs/timing/test/timing_test.dart | 413 ++++++++++++++++++++++++++++++ 10 files changed, 832 insertions(+) create mode 100644 pkgs/timing/.gitignore create mode 100644 pkgs/timing/.travis.yml create mode 100644 pkgs/timing/CHANGELOG.md create mode 100644 pkgs/timing/LICENSE create mode 100644 pkgs/timing/README.md create mode 100644 pkgs/timing/lib/src/clock.dart create mode 100644 pkgs/timing/lib/src/timing.dart create mode 100644 pkgs/timing/lib/timing.dart create mode 100644 pkgs/timing/pubspec.yaml create mode 100644 pkgs/timing/test/timing_test.dart diff --git a/pkgs/timing/.gitignore b/pkgs/timing/.gitignore new file mode 100644 index 000000000..1ddf798b7 --- /dev/null +++ b/pkgs/timing/.gitignore @@ -0,0 +1,7 @@ +.packages +/build/ +pubspec.lock + +# Files generated by dart tools +.dart_tool +doc/ diff --git a/pkgs/timing/.travis.yml b/pkgs/timing/.travis.yml new file mode 100644 index 000000000..77141bf1a --- /dev/null +++ b/pkgs/timing/.travis.yml @@ -0,0 +1,17 @@ +language: dart + +dart: + - dev + +dart_task: +- dartfmt +- dartanalyzer: --fatal-infos --fatal-warnings . +- test + +branches: + only: + - master + +cache: + directories: + - $HOME/.pub-cache diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md new file mode 100644 index 000000000..090fc3659 --- /dev/null +++ b/pkgs/timing/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.1.0 + +- Initial release diff --git a/pkgs/timing/LICENSE b/pkgs/timing/LICENSE new file mode 100644 index 000000000..c4dc9ba3c --- /dev/null +++ b/pkgs/timing/LICENSE @@ -0,0 +1,26 @@ +Copyright 2018, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md new file mode 100644 index 000000000..a1518ea97 --- /dev/null +++ b/pkgs/timing/README.md @@ -0,0 +1,13 @@ +# [![Build Status](https://travis-ci.org/dart-lang/timing.svg?branch=master)](https://travis-ci.org/dart-lang/timing) + +Timing is a simple package for tracking performance of both async and sync actions + +```dart +var tracker = AsyncTimeTracker(); +await tracker.track(() async { + // some async code here +}); + +// Use results +print('${tracker.duration} ${tracker.innerDuration} ${tracker.slices}'); +``` \ No newline at end of file diff --git a/pkgs/timing/lib/src/clock.dart b/pkgs/timing/lib/src/clock.dart new file mode 100644 index 000000000..1974c4a79 --- /dev/null +++ b/pkgs/timing/lib/src/clock.dart @@ -0,0 +1,20 @@ +// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// A function that returns the current [DateTime]. +typedef DateTime _Clock(); +DateTime _defaultClock() => DateTime.now(); + +const _ZoneKey = #timing_Clock; + +/// Returns the current [DateTime]. +/// +/// May be overridden for tests using [scopeClock]. +DateTime now() => (Zone.current[_ZoneKey] as _Clock ?? _defaultClock)(); + +/// Runs [f], with [clock] scoped whenever [now] is called. +T scopeClock(DateTime clock(), T f()) => + runZoned(f, zoneValues: {_ZoneKey: clock}); diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart new file mode 100644 index 000000000..a1d5a85ec --- /dev/null +++ b/pkgs/timing/lib/src/timing.dart @@ -0,0 +1,309 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'clock.dart'; + +/// The timings of an operation, including its [startTime], [stopTime], and +/// [duration]. +class TimeSlice { + /// The total duration of this operation, equivalent to taking the difference + /// between [stopTime] and [startTime]. + Duration get duration => stopTime.difference(startTime); + + final DateTime startTime; + + final DateTime stopTime; + + TimeSlice(this.startTime, this.stopTime); + + @override + String toString() => '($startTime + $duration)'; +} + +/// The timings of an async operation, consist of several sync [slices] and +/// includes total [startTime], [stopTime], and [duration]. +class TimeSliceGroup implements TimeSlice { + final List slices; + + @override + DateTime get startTime => slices.first.startTime; + + @override + DateTime get stopTime => slices.last.stopTime; + + /// The total duration of this operation, equivalent to taking the difference + /// between [stopTime] and [startTime]. + @override + Duration get duration => stopTime.difference(startTime); + + /// Sum of [duration]s of all [slices]. + /// + /// If some of slices implements [TimeSliceGroup] [innerDuration] will be used + /// to compute sum. + Duration get innerDuration => slices.fold( + Duration.zero, + (duration, slice) => + duration + + (slice is TimeSliceGroup ? slice.innerDuration : slice.duration)); + + TimeSliceGroup(List this.slices); + + @override + String toString() => slices.toString(); +} + +abstract class TimeTracker implements TimeSlice { + /// Whether tracking is active. + /// + /// Tracking is only active after `isStarted` and before `isFinished`. + bool get isTracking; + + /// Whether tracking is finished. + /// + /// Tracker can't be used as [TimeSlice] before it is finished + bool get isFinished; + + /// Whether tracking was started. + /// + /// Equivalent of `isTracking || isFinished` + bool get isStarted; + + T track(T Function() action); +} + +/// Tracks only sync actions +class SyncTimeTracker implements TimeTracker { + /// When this operation started, call [_start] to set this. + @override + DateTime get startTime => _startTime; + DateTime _startTime; + + /// When this operation stopped, call [_stop] to set this. + @override + DateTime get stopTime => _stopTime; + DateTime _stopTime; + + /// Start tracking this operation, must only be called once, before [_stop]. + void _start() { + assert(_startTime == null && _stopTime == null); + _startTime = now(); + } + + /// Stop tracking this operation, must only be called once, after [_start]. + void _stop() { + assert(_startTime != null && _stopTime == null); + _stopTime = now(); + } + + /// Splits tracker into two slices + /// + /// Returns new [TimeSlice] started on [startTime] and ended now. + /// Modifies [startTime] of tracker to current time point + /// + /// Don't change state of tracker. Can be called only while [isTracking], and + /// tracker will sill be tracking after call. + TimeSlice _split() { + if (!isTracking) { + throw StateError('Can be only called while tracking'); + } + var _now = now(); + var prevSlice = TimeSlice(_startTime, _now); + _startTime = _now; + return prevSlice; + } + + @override + T track(T Function() action) { + if (isStarted) { + throw StateError('Can not be tracked twice'); + } + _start(); + try { + return action(); + } finally { + _stop(); + } + } + + @override + bool get isStarted => startTime != null; + + @override + bool get isTracking => startTime != null && stopTime == null; + + @override + bool get isFinished => startTime != null && stopTime != null; + + @override + Duration get duration => stopTime?.difference(startTime); +} + +/// Async actions returning [Future] will be tracked as single sync time span +/// from the beginning of execution till completion of future +class SimpleAsyncTimeTracker extends SyncTimeTracker { + @override + T track(T Function() action) { + if (isStarted) { + throw StateError('Can not be tracked twice'); + } + T result; + _start(); + try { + result = action(); + } catch (_) { + _stop(); + rethrow; + } + if (result is Future) { + return result.whenComplete(_stop) as T; + } else { + _stop(); + return result; + } + } +} + +/// No-op implementation of [SyncTimeTracker] that does nothing. +class NoOpTimeTracker implements TimeTracker { + static final sharedInstance = NoOpTimeTracker(); + + @override + Duration get duration => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + DateTime get startTime => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + DateTime get stopTime => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + bool get isStarted => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + bool get isTracking => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + bool get isFinished => + throw UnsupportedError('Unsupported in no-op implementation'); + + @override + T track(T Function() action) => action(); +} + +/// Track all async execution as disjoint time [slices] in ascending order. +/// +/// Can [track] both async and sync actions. +/// Can exclude time of tested trackers. +/// +/// If tracked action spawns some dangled async executions behavior is't +/// defined. Tracked might or might not track time of such executions +class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { + final bool trackNested; + + static const _ZoneKey = #timing_AsyncTimeTracker; + + AsyncTimeTracker({this.trackNested = true}) : super([]); + + T _trackSyncSlice(ZoneDelegate parent, Zone zone, T Function() action) { + // Ignore dangling runs after tracker completes + if (isFinished) { + return action(); + } + + var isNestedRun = slices.isNotEmpty && + slices.last is SyncTimeTracker && + (slices.last as SyncTimeTracker).isTracking; + var isExcludedNestedTrack = !trackNested && zone[_ZoneKey] != this; + + // Exclude nested sync tracks + if (isNestedRun && isExcludedNestedTrack) { + var timer = slices.last as SyncTimeTracker; + // Split already tracked time into new slice. + // Replace tracker in slices.last with splitted slice, to indicate for + // recursive calls that we not tracking. + slices.last = parent.run(zone, timer._split); + try { + return action(); + } finally { + // Split tracker again and discard slice that was spend in nested tracker + parent.run(zone, timer._split); + // Add tracker back to list of slices and continue tracking + slices.add(timer); + } + } + + // Exclude nested async tracks + if (isExcludedNestedTrack) { + return action(); + } + + // Split time slices in nested sync runs + if (isNestedRun) { + return action(); + } + + var timer = SyncTimeTracker(); + slices.add(timer); + + // Pass to parent zone, in case of overwritten clock + return parent.runUnary(zone, timer.track, action); + } + + static final asyncTimeTrackerZoneSpecification = ZoneSpecification( + run: (Zone self, ZoneDelegate parent, Zone zone, R Function() f) { + var tracker = self[_ZoneKey] as AsyncTimeTracker; + return tracker._trackSyncSlice(parent, zone, () => parent.run(zone, f)); + }, + runUnary: (Zone self, ZoneDelegate parent, Zone zone, R Function(T) f, + T arg) { + var tracker = self[_ZoneKey] as AsyncTimeTracker; + return tracker._trackSyncSlice( + parent, zone, () => parent.runUnary(zone, f, arg)); + }, + runBinary: (Zone self, ZoneDelegate parent, Zone zone, + R Function(T1, T2) f, T1 arg1, T2 arg2) { + var tracker = self[_ZoneKey] as AsyncTimeTracker; + return tracker._trackSyncSlice( + parent, zone, () => parent.runBinary(zone, f, arg1, arg2)); + }, + ); + + @override + T track(T Function() action) { + if (isStarted) { + throw StateError('Can not be tracked twice'); + } + _tracking = true; + var result = runZoned(action, + zoneSpecification: asyncTimeTrackerZoneSpecification, + zoneValues: {_ZoneKey: this}); + if (result is Future) { + return result + // Break possible sync processing of future completion, so slice trackers can be finished + .whenComplete(() => Future.value()) + .whenComplete(() => _tracking = false) as T; + } else { + _tracking = false; + return result; + } + } + + bool _tracking; + + @override + bool get isStarted => _tracking != null; + + @override + bool get isFinished => _tracking == false; + + @override + bool get isTracking => _tracking == true; +} diff --git a/pkgs/timing/lib/timing.dart b/pkgs/timing/lib/timing.dart new file mode 100644 index 000000000..0163e8d86 --- /dev/null +++ b/pkgs/timing/lib/timing.dart @@ -0,0 +1,13 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +export 'src/timing.dart' + show + TimeSlice, + TimeSliceGroup, + TimeTracker, + SyncTimeTracker, + SimpleAsyncTimeTracker, + AsyncTimeTracker, + NoOpTimeTracker; diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml new file mode 100644 index 000000000..984052655 --- /dev/null +++ b/pkgs/timing/pubspec.yaml @@ -0,0 +1,11 @@ +name: timing +version: 0.1.0-dev +description: +author: Dart Team +homepage: https://github.com/dart-lang/timing + +environment: + sdk: ">=2.0.0 <3.0.0" + +dev_dependencies: + test: ^1.0.0 diff --git a/pkgs/timing/test/timing_test.dart b/pkgs/timing/test/timing_test.dart new file mode 100644 index 000000000..9f3f3acff --- /dev/null +++ b/pkgs/timing/test/timing_test.dart @@ -0,0 +1,413 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; +import 'package:timing/src/clock.dart'; +import 'package:timing/src/timing.dart'; + +_noop() {} + +main() { + DateTime time; + final startTime = DateTime(2017); + DateTime fakeClock() => time; + + TimeTracker tracker; + TimeTracker nestedTracker; + + T scopedTrack(T f()) => scopeClock(fakeClock, () => tracker.track(f)); + + setUp(() { + time = startTime; + }); + + canHandleSync([additionalExpects() = _noop]) { + test('Can track sync code', () { + expect(tracker.isStarted, false); + expect(tracker.isTracking, false); + expect(tracker.isFinished, false); + scopedTrack(() { + expect(tracker.isStarted, true); + expect(tracker.isTracking, true); + expect(tracker.isFinished, false); + time = time.add(const Duration(seconds: 5)); + }); + expect(tracker.isStarted, true); + expect(tracker.isTracking, false); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 5)); + additionalExpects(); + }); + + test('Can track handled sync exceptions', () async { + scopedTrack(() { + try { + time = time.add(const Duration(seconds: 4)); + throw 'error'; + } on String { + time = time.add(const Duration(seconds: 1)); + } + }); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 5)); + additionalExpects(); + }); + + test('Can track in case of unhandled sync exceptions', () async { + expect( + () => scopedTrack(() { + time = time.add(const Duration(seconds: 5)); + throw 'error'; + }), + throwsA(TypeMatcher())); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 5)); + additionalExpects(); + }); + + test('Can be nested sync', () { + scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + nestedTracker.track(() { + time = time.add(const Duration(seconds: 2)); + }); + time = time.add(const Duration(seconds: 4)); + }); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 7)); + expect(nestedTracker.startTime.isAfter(startTime), true); + expect(nestedTracker.stopTime.isBefore(time), true); + expect(nestedTracker.duration, const Duration(seconds: 2)); + additionalExpects(); + }); + } + + canHandleAsync([additionalExpects() = _noop]) { + test('Can track async code', () async { + expect(tracker.isStarted, false); + expect(tracker.isTracking, false); + expect(tracker.isFinished, false); + await scopedTrack(() => Future(() { + expect(tracker.isStarted, true); + expect(tracker.isTracking, true); + expect(tracker.isFinished, false); + time = time.add(const Duration(seconds: 5)); + })); + expect(tracker.isStarted, true); + expect(tracker.isTracking, false); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 5)); + additionalExpects(); + }); + + test('Can track handled async exceptions', () async { + await scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + return Future(() { + time = time.add(const Duration(seconds: 2)); + throw 'error'; + }).then((_) { + time = time.add(const Duration(seconds: 4)); + }).catchError((error, stack) { + time = time.add(const Duration(seconds: 8)); + }); + }); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 11)); + additionalExpects(); + }); + + test('Can track in case of unhandled async exceptions', () async { + var future = scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + return Future(() { + time = time.add(const Duration(seconds: 2)); + throw 'error'; + }).then((_) { + time = time.add(const Duration(seconds: 4)); + }); + }); + await expectLater(future, throwsA(TypeMatcher())); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 3)); + additionalExpects(); + }); + + test('Can be nested async', () async { + await scopedTrack(() async { + time = time.add(const Duration(milliseconds: 1)); + await Future.value(); + time = time.add(const Duration(milliseconds: 2)); + await nestedTracker.track(() async { + time = time.add(const Duration(milliseconds: 4)); + await Future.value(); + time = time.add(const Duration(milliseconds: 8)); + await Future.value(); + time = time.add(const Duration(milliseconds: 16)); + }); + time = time.add(const Duration(milliseconds: 32)); + await Future.value(); + time = time.add(const Duration(milliseconds: 64)); + }); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(milliseconds: 127)); + expect(nestedTracker.startTime.isAfter(startTime), true); + expect(nestedTracker.stopTime.isBefore(time), true); + expect(nestedTracker.duration, const Duration(milliseconds: 28)); + additionalExpects(); + }); + } + + group('SyncTimeTracker', () { + setUp(() { + tracker = SyncTimeTracker(); + nestedTracker = SyncTimeTracker(); + }); + + canHandleSync(); + + test('Can not track async code', () async { + await scopedTrack(() => Future(() { + time = time.add(const Duration(seconds: 5)); + })); + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, startTime); + expect(tracker.duration, const Duration(seconds: 0)); + }); + }); + + group('AsyncTimeTracker.simple', () { + setUp(() { + tracker = SimpleAsyncTimeTracker(); + nestedTracker = SimpleAsyncTimeTracker(); + }); + + canHandleSync(); + + canHandleAsync(); + + test('Can not distinguish own async code', () async { + var future = scopedTrack(() => Future(() { + time = time.add(const Duration(seconds: 5)); + })); + time = time.add(const Duration(seconds: 10)); + await future; + expect(tracker.isFinished, true); + expect(tracker.startTime, startTime); + expect(tracker.stopTime, time); + expect(tracker.duration, const Duration(seconds: 15)); + }); + }); + + group('AsyncTimeTracker', () { + AsyncTimeTracker asyncTracker; + AsyncTimeTracker nestedAsyncTracker; + setUp(() { + tracker = asyncTracker = AsyncTimeTracker(); + nestedTracker = nestedAsyncTracker = AsyncTimeTracker(); + }); + + canHandleSync(() { + expect(asyncTracker.innerDuration, asyncTracker.duration); + expect(asyncTracker.slices.length, 1); + }); + + canHandleAsync(() { + expect(asyncTracker.innerDuration, asyncTracker.duration); + expect(asyncTracker.slices.length, greaterThan(1)); + }); + + test('Can track complex async innerDuration', () async { + var completer = Completer(); + var future = scopedTrack(() async { + time = time.add(const Duration(seconds: 1)); // Tracked sync + await Future.value(); + time = time.add(const Duration(seconds: 2)); // Tracked async + await completer.future; + time = time.add(const Duration(seconds: 4)); // Tracked async, delayed + }).then((_) { + time = time.add(const Duration(seconds: 8)); // Async, after tracking + }); + time = time.add(const Duration(seconds: 16)); // Sync, between slices + + await Future(() { + // Async, between slices + time = time.add(const Duration(seconds: 32)); + completer.complete(); + }); + await future; + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime.isBefore(time), true); + expect(asyncTracker.duration, const Duration(seconds: 55)); + expect(asyncTracker.innerDuration, const Duration(seconds: 7)); + expect(asyncTracker.slices.length, greaterThan(1)); + }); + + test('Can exclude nested sync', () { + tracker = asyncTracker = AsyncTimeTracker(trackNested: false); + scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + nestedAsyncTracker.track(() { + time = time.add(const Duration(seconds: 2)); + }); + time = time.add(const Duration(seconds: 4)); + }); + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime, time); + expect(asyncTracker.duration, const Duration(seconds: 7)); + expect(asyncTracker.innerDuration, const Duration(seconds: 5)); + expect(asyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker.stopTime.isBefore(time), true); + expect(nestedAsyncTracker.duration, const Duration(seconds: 2)); + expect(nestedAsyncTracker.innerDuration, const Duration(seconds: 2)); + expect(nestedAsyncTracker.slices.length, 1); + }); + + test('Can exclude complex nested sync', () { + tracker = asyncTracker = AsyncTimeTracker(trackNested: false); + nestedAsyncTracker = AsyncTimeTracker(trackNested: false); + var nestedAsyncTracker2 = AsyncTimeTracker(trackNested: false); + scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + nestedAsyncTracker.track(() { + time = time.add(const Duration(seconds: 2)); + nestedAsyncTracker2.track(() { + time = time.add(const Duration(seconds: 4)); + }); + time = time.add(const Duration(seconds: 8)); + }); + time = time.add(const Duration(seconds: 16)); + }); + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime, time); + expect(asyncTracker.duration, const Duration(seconds: 31)); + expect(asyncTracker.innerDuration, const Duration(seconds: 17)); + expect(asyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker.stopTime.isBefore(time), true); + expect(nestedAsyncTracker.duration, const Duration(seconds: 14)); + expect(nestedAsyncTracker.innerDuration, const Duration(seconds: 10)); + expect(nestedAsyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker2.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker2.stopTime.isBefore(time), true); + expect(nestedAsyncTracker2.duration, const Duration(seconds: 4)); + expect(nestedAsyncTracker2.innerDuration, const Duration(seconds: 4)); + expect(nestedAsyncTracker2.slices.length, 1); + }); + + test( + 'Can track all on grand-parent level and ' + 'exclude grand-childrens from parent', () { + tracker = asyncTracker = AsyncTimeTracker(trackNested: true); + nestedAsyncTracker = AsyncTimeTracker(trackNested: false); + var nestedAsyncTracker2 = AsyncTimeTracker(); + scopedTrack(() { + time = time.add(const Duration(seconds: 1)); + nestedAsyncTracker.track(() { + time = time.add(const Duration(seconds: 2)); + nestedAsyncTracker2.track(() { + time = time.add(const Duration(seconds: 4)); + }); + time = time.add(const Duration(seconds: 8)); + }); + time = time.add(const Duration(seconds: 16)); + }); + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime, time); + expect(asyncTracker.duration, const Duration(seconds: 31)); + expect(asyncTracker.innerDuration, const Duration(seconds: 31)); + expect(asyncTracker.slices.length, 1); + expect(nestedAsyncTracker.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker.stopTime.isBefore(time), true); + expect(nestedAsyncTracker.duration, const Duration(seconds: 14)); + expect(nestedAsyncTracker.innerDuration, const Duration(seconds: 10)); + expect(nestedAsyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker2.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker2.stopTime.isBefore(time), true); + expect(nestedAsyncTracker2.duration, const Duration(seconds: 4)); + expect(nestedAsyncTracker2.innerDuration, const Duration(seconds: 4)); + expect(nestedAsyncTracker2.slices.length, 1); + }); + + test('Can exclude nested async', () async { + tracker = asyncTracker = AsyncTimeTracker(trackNested: false); + await scopedTrack(() async { + time = time.add(const Duration(seconds: 1)); + await nestedAsyncTracker.track(() async { + time = time.add(const Duration(seconds: 2)); + await Future.value(); + time = time.add(const Duration(seconds: 4)); + await Future.value(); + time = time.add(const Duration(seconds: 8)); + }); + time = time.add(const Duration(seconds: 16)); + }); + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime, time); + expect(asyncTracker.duration, const Duration(seconds: 31)); + expect(asyncTracker.innerDuration, const Duration(seconds: 17)); + expect(asyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker.stopTime.isBefore(time), true); + expect(nestedAsyncTracker.duration, const Duration(seconds: 14)); + expect(nestedAsyncTracker.innerDuration, const Duration(seconds: 14)); + expect(nestedAsyncTracker.slices.length, greaterThan(1)); + }); + + test('Can handle callbacks in excluded nested async', () async { + tracker = asyncTracker = AsyncTimeTracker(trackNested: false); + await scopedTrack(() async { + time = time.add(const Duration(seconds: 1)); + var completer = Completer(); + var future = completer.future.then((_) { + time = time.add(const Duration(seconds: 2)); + }); + await nestedAsyncTracker.track(() async { + time = time.add(const Duration(seconds: 4)); + await Future.value(); + time = time.add(const Duration(seconds: 8)); + completer.complete(); + await future; + time = time.add(const Duration(seconds: 16)); + }); + time = time.add(const Duration(seconds: 32)); + }); + expect(asyncTracker.isFinished, true); + expect(asyncTracker.startTime, startTime); + expect(asyncTracker.stopTime, time); + expect(asyncTracker.duration, const Duration(seconds: 63)); + expect(asyncTracker.innerDuration, const Duration(seconds: 35)); + expect(asyncTracker.slices.length, greaterThan(1)); + expect(nestedAsyncTracker.startTime.isAfter(startTime), true); + expect(nestedAsyncTracker.stopTime.isBefore(time), true); + expect(nestedAsyncTracker.duration, const Duration(seconds: 30)); + expect(nestedAsyncTracker.innerDuration, const Duration(seconds: 28)); + expect(nestedAsyncTracker.slices.length, greaterThan(1)); + }); + }); +} From a6b1bfba998a10117bf3ff9836007d8c3af9a24c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 11 Sep 2018 12:08:22 -0700 Subject: [PATCH 0482/1215] Add lints from package:pedantic (dart-lang/watcher#66) - Fix a control_flow_in_finally by removing the nested try/catch which was set up for ordering of behavior and instead check for a closed controller in both places. - Fix a prefer_is_not_empty. --- pkgs/watcher/analysis_options.yaml | 1 + pkgs/watcher/lib/src/file_watcher/polling.dart | 18 ++++++++---------- pkgs/watcher/lib/src/path_set.dart | 2 +- pkgs/watcher/pubspec.yaml | 1 + 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index 4c9f8113a..3155c7fc0 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 777038fdf..877031ecb 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -60,16 +60,14 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { DateTime modified; try { - try { - modified = await getModificationTime(path); - } finally { - if (_eventsController.isClosed) return; - } + modified = await getModificationTime(path); } on FileSystemException catch (error, stackTrace) { - _eventsController.addError(error, stackTrace); - close(); - return; + if (!_eventsController.isClosed) { + _eventsController.addError(error, stackTrace); + await close(); + } } + if (_eventsController.isClosed) return; if (_lastModified == modified) return; @@ -84,8 +82,8 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { } } - void close() { + Future close() async { _timer.cancel(); - _eventsController.close(); + await _eventsController.close(); } } diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 9a2c03cc1..d6983ffb1 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -136,7 +136,7 @@ class PathSet { if (entry == null) return false; } - return !entry.contents.isEmpty; + return entry.contents.isNotEmpty; } /// All of the paths explicitly added to this set. diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 552b13a9d..c107856ec 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -16,5 +16,6 @@ dependencies: dev_dependencies: benchmark_harness: ^1.0.4 + pedantic: ^1.1.0 test: '>=0.12.42 <2.0.0' test_descriptor: ^1.0.0 From 96b0b689c1463888e153bb8ec3d5dde2144beb3f Mon Sep 17 00:00:00 2001 From: samogot Date: Tue, 11 Sep 2018 12:08:54 -0700 Subject: [PATCH 0483/1215] Release v0.1.0 (dart-lang/timing#2) --- pkgs/timing/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 984052655..c8c001609 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,6 +1,6 @@ name: timing -version: 0.1.0-dev -description: +version: 0.1.0 +description: Timing is a simple package for tracking performance of both async and sync actions author: Dart Team homepage: https://github.com/dart-lang/timing From 8bd50568438f69b59cf51f6e3665f8ae9ae8fc92 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 11 Sep 2018 13:10:50 -0700 Subject: [PATCH 0484/1215] add analysis_options and pkg:pedantic lints (dart-lang/timing#4) --- pkgs/timing/analysis_options.yaml | 15 +++++++++++++++ pkgs/timing/pubspec.yaml | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 pkgs/timing/analysis_options.yaml diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml new file mode 100644 index 000000000..3155c7fc0 --- /dev/null +++ b/pkgs/timing/analysis_options.yaml @@ -0,0 +1,15 @@ +include: package:pedantic/analysis_options.yaml +analyzer: + strong-mode: + implicit-casts: false + errors: + todo: ignore + unused_import: error + unused_element: error + unused_local_variable: error + dead_code: error + +linter: + rules: + - comment_references + - prefer_typing_uninitialized_variables diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index c8c001609..6b47c472f 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.0 +version: 0.1.1-dev description: Timing is a simple package for tracking performance of both async and sync actions author: Dart Team homepage: https://github.com/dart-lang/timing @@ -8,4 +8,5 @@ environment: sdk: ">=2.0.0 <3.0.0" dev_dependencies: + pedantic: 1.1.0 test: ^1.0.0 From 0579757ce6ce996818a755089cccc5ac097a07ea Mon Sep 17 00:00:00 2001 From: samogot Date: Tue, 18 Sep 2018 00:13:34 +0300 Subject: [PATCH 0485/1215] Add JSON serialization (dart-lang/timing#6) --- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/README.md | 9 +++++++++ pkgs/timing/lib/src/timing.dart | 28 ++++++++++++++++++++++++++++ pkgs/timing/lib/src/timing.g.dart | 26 ++++++++++++++++++++++++++ pkgs/timing/pubspec.yaml | 5 +++++ 5 files changed, 72 insertions(+) create mode 100644 pkgs/timing/lib/src/timing.g.dart diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 090fc3659..7b73c71b8 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1 + +- Add JSON serialization + ## 0.1.0 - Initial release diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md index a1518ea97..400bc4b86 100644 --- a/pkgs/timing/README.md +++ b/pkgs/timing/README.md @@ -10,4 +10,13 @@ await tracker.track(() async { // Use results print('${tracker.duration} ${tracker.innerDuration} ${tracker.slices}'); +``` + + +## Building + +Use the following command to re-generate `lib/src/timing.g.dart` file: + +```bash +pub run build_runner build ``` \ No newline at end of file diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index a1d5a85ec..15e885471 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -4,10 +4,15 @@ import 'dart:async'; +import 'package:json_annotation/json_annotation.dart'; + import 'clock.dart'; +part 'timing.g.dart'; + /// The timings of an operation, including its [startTime], [stopTime], and /// [duration]. +@JsonSerializable(nullable: false) class TimeSlice { /// The total duration of this operation, equivalent to taking the difference /// between [stopTime] and [startTime]. @@ -19,12 +24,18 @@ class TimeSlice { TimeSlice(this.startTime, this.stopTime); + factory TimeSlice.fromJson(Map json) => + _$TimeSliceFromJson(json); + + Map toJson() => _$TimeSliceToJson(this); + @override String toString() => '($startTime + $duration)'; } /// The timings of an async operation, consist of several sync [slices] and /// includes total [startTime], [stopTime], and [duration]. +@JsonSerializable(nullable: false) class TimeSliceGroup implements TimeSlice { final List slices; @@ -51,6 +62,13 @@ class TimeSliceGroup implements TimeSlice { TimeSliceGroup(List this.slices); + /// Constructs TimeSliceGroup from JSON representation + factory TimeSliceGroup.fromJson(Map json) => + _$TimeSliceGroupFromJson(json); + + @override + Map toJson() => _$TimeSliceGroupToJson(this); + @override String toString() => slices.toString(); } @@ -139,6 +157,12 @@ class SyncTimeTracker implements TimeTracker { @override Duration get duration => stopTime?.difference(startTime); + + /// Converts to JSON representation + /// + /// Can't be used before [isFinished] + @override + Map toJson() => _$TimeSliceToJson(this); } /// Async actions returning [Future] will be tracked as single sync time span @@ -196,6 +220,10 @@ class NoOpTimeTracker implements TimeTracker { @override T track(T Function() action) => action(); + + @override + Map toJson() => + throw UnsupportedError('Unsupported in no-op implementation'); } /// Track all async execution as disjoint time [slices] in ascending order. diff --git a/pkgs/timing/lib/src/timing.g.dart b/pkgs/timing/lib/src/timing.g.dart new file mode 100644 index 000000000..214dd82f1 --- /dev/null +++ b/pkgs/timing/lib/src/timing.g.dart @@ -0,0 +1,26 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'timing.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +TimeSlice _$TimeSliceFromJson(Map json) { + return TimeSlice(DateTime.parse(json['startTime'] as String), + DateTime.parse(json['stopTime'] as String)); +} + +Map _$TimeSliceToJson(TimeSlice instance) => { + 'startTime': instance.startTime.toIso8601String(), + 'stopTime': instance.stopTime.toIso8601String() + }; + +TimeSliceGroup _$TimeSliceGroupFromJson(Map json) { + return TimeSliceGroup((json['slices'] as List) + .map((e) => TimeSlice.fromJson(e as Map)) + .toList()); +} + +Map _$TimeSliceGroupToJson(TimeSliceGroup instance) => + {'slices': instance.slices}; diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 6b47c472f..890555dbe 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -7,6 +7,11 @@ homepage: https://github.com/dart-lang/timing environment: sdk: ">=2.0.0 <3.0.0" +dependencies: + json_annotation: ^1.0.0 + dev_dependencies: + build_runner: ^0.10.0 + json_serializable: ^1.0.0 pedantic: 1.1.0 test: ^1.0.0 From f88934075d3b753d9327995be759c8ff8097f868 Mon Sep 17 00:00:00 2001 From: samogot Date: Tue, 18 Sep 2018 21:13:00 +0300 Subject: [PATCH 0486/1215] Release 0.1.1 (dart-lang/timing#7) --- pkgs/timing/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 890555dbe..3e32757f2 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.1-dev +version: 0.1.1 description: Timing is a simple package for tracking performance of both async and sync actions author: Dart Team homepage: https://github.com/dart-lang/timing From b07fdbfb10a6cd24484582bf27c3c6328f5aee01 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Sep 2018 11:01:58 -0700 Subject: [PATCH 0487/1215] Migrate to pkg:build_verify for generated file checks (dart-lang/pubspec_parse#24) Part of https://github.com/kevmoo/build_verify/issues/1 --- pkgs/pubspec_parse/pubspec.yaml | 1 + .../pubspec_parse/test/ensure_build_test.dart | 54 +------------------ 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 2db643df0..4178027d1 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,6 +17,7 @@ dependencies: dev_dependencies: build_runner: ^0.10.0 + build_verify: ^1.0.0 json_serializable: ^1.2.1 path: ^1.5.1 stack_trace: ^1.9.2 diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index 854dd2493..ac67c9ff6 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -4,59 +4,9 @@ @TestOn('vm') @Tags(const ['presubmit-only']) - -import 'dart:convert'; -import 'dart:io'; - -import 'package:path/path.dart' as p; +import 'package:build_verify/build_verify.dart'; import 'package:test/test.dart'; void main() { - // TODO(kevmoo): replace with a common utility - // https://github.com/dart-lang/build/issues/716 - test('ensure local build succeeds with no changes', () { - var pkgRoot = _runProc('git', ['rev-parse', '--show-toplevel']); - var currentDir = Directory.current.resolveSymbolicLinksSync(); - - if (!p.equals(p.join(pkgRoot), currentDir)) { - throw new StateError('Expected the git root ($pkgRoot) ' - 'to match the current directory ($currentDir).'); - } - - // 1 - get a list of modified `.g.dart` files - should be empty - expect(_changedGeneratedFiles(), isEmpty); - - // 2 - run build - should be no output, since nothing should change - var result = _runProc('pub', - ['run', 'build_runner', 'build', '--delete-conflicting-outputs']); - - print(result); - expect(result, - contains(new RegExp(r'\[INFO\] Succeeded after \S+ with \d+ outputs'))); - - // 3 - get a list of modified `.g.dart` files - should still be empty - expect(_changedGeneratedFiles(), isEmpty); - }); -} - -final _whitespace = new RegExp(r'\s'); - -Set _changedGeneratedFiles() { - var output = _runProc('git', ['status', '--porcelain']); - - return LineSplitter.split(output) - .map((line) => line.split(_whitespace).last) - .where((path) => path.endsWith('.dart')) - .toSet(); -} - -String _runProc(String proc, List args) { - var result = Process.runSync(proc, args); - - if (result.exitCode != 0) { - throw new ProcessException( - proc, args, result.stderr as String, result.exitCode); - } - - return (result.stdout as String).trim(); + test('ensure_build', expectBuildClean); } From 4eb18ec65a005acc0ed012191bbd336a41aacb4c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 27 Sep 2018 12:26:52 -0700 Subject: [PATCH 0488/1215] Support latest build_runner and pedantic in dev_dependencies (dart-lang/timing#8) --- pkgs/timing/pubspec.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 3e32757f2..54d619caf 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.1 +version: 0.1.2-dev description: Timing is a simple package for tracking performance of both async and sync actions author: Dart Team homepage: https://github.com/dart-lang/timing @@ -11,7 +11,7 @@ dependencies: json_annotation: ^1.0.0 dev_dependencies: - build_runner: ^0.10.0 + build_runner: ^1.0.0 json_serializable: ^1.0.0 - pedantic: 1.1.0 + pedantic: ^1.1.0 test: ^1.0.0 From cfa6618e75cdc739ed3fd4f81e41f1aeb9d88023 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Oct 2018 13:35:02 -0700 Subject: [PATCH 0489/1215] support latest pkg:build_runner --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 4178027d1..5dcb3dc81 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: yaml: ^2.1.12 dev_dependencies: - build_runner: ^0.10.0 + build_runner: ^1.0.0 build_verify: ^1.0.0 json_serializable: ^1.2.1 path: ^1.5.1 From 5c8a6e4dbe6dd2403b5c88e4f9612cc5a5c48d13 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Oct 2018 13:56:38 -0700 Subject: [PATCH 0490/1215] Avoid running pub w/ user@ git URL on travis Causes a travis-specific failure, it seems --- pkgs/pubspec_parse/test/dependency_test.dart | 13 ++++++-- pkgs/pubspec_parse/test/test_utils.dart | 33 +++++++++++++------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 2a8b49132..3bc890aef 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -2,6 +2,8 @@ // 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. +import 'dart:io'; + import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; @@ -194,7 +196,12 @@ void _gitDependency() { }); test('string with user@ URL', () { - var dep = _dependency({'git': 'git@localhost:dep.git'}); + var skipTryParse = Platform.environment.containsKey('TRAVIS'); + if (skipTryParse) { + print('FYI: not validating git@ URI on travis due to failure'); + } + var dep = _dependency({'git': 'git@localhost:dep.git'}, + skipTryPub: skipTryParse); expect(dep.url.toString(), 'ssh://git@localhost/dep.git'); expect(dep.path, isNull); expect(dep.ref, isNull); @@ -301,11 +308,11 @@ void _expectThrows(Object content, String expectedError) { }, expectedError); } -T _dependency(Object content) { +T _dependency(Object content, {bool skipTryPub = false}) { var value = parse({ 'name': 'sample', 'dependencies': {'dep': content} - }); + }, skipTryPub: skipTryPub); expect(value.name, 'sample'); expect(value.dependencies, hasLength(1)); diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 37cd3e96b..48efdf698 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -48,27 +48,38 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } } -Pubspec parse(Object content, {bool quietOnError = false}) { +Pubspec parse(Object content, + {bool quietOnError = false, bool skipTryPub = false}) { quietOnError ??= false; + skipTryPub ??= false; var encoded = _encodeJson(content); - var pubResult = waitFor(tryPub(encoded)); + ProcResult pubResult; + if (!skipTryPub) { + pubResult = waitFor(tryPub(encoded)); + expect(pubResult, isNotNull); + } try { var value = new Pubspec.parse(encoded); - addTearDown(() { - expect(pubResult.cleanParse, isTrue, - reason: - 'On success, parsing from the pub client should also succeed.'); - }); + if (pubResult != null) { + addTearDown(() { + expect(pubResult.cleanParse, isTrue, + reason: + 'On success, parsing from the pub client should also succeed.'); + }); + } return value; } catch (e) { - addTearDown(() { - expect(pubResult.cleanParse, isFalse, - reason: 'On failure, parsing from the pub client should also fail.'); - }); + if (pubResult != null) { + addTearDown(() { + expect(pubResult.cleanParse, isFalse, + reason: + 'On failure, parsing from the pub client should also fail.'); + }); + } if (e is ParsedYamlException) { if (!quietOnError) { _printDebugParsedYamlException(e); From dc93cbd146040704230ebe6592f0ae6a50442ca9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 11 Oct 2018 15:50:20 -0700 Subject: [PATCH 0491/1215] fix unnecessary_this lint for latest SDK (dart-lang/pubspec_parse#26) --- pkgs/pubspec_parse/lib/src/dependency.dart | 2 +- pkgs/pubspec_parse/lib/src/pubspec.dart | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 07d08b57b..3839e54e8 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -199,7 +199,7 @@ class HostedDependency extends Dependency { final HostedDetails hosted; HostedDependency({VersionConstraint version, this.hosted}) - : this.version = version ?? VersionConstraint.any, + : version = version ?? VersionConstraint.any, super._(); @override diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index a5cba623e..59ee5858b 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -65,11 +65,11 @@ class Pubspec { Map dependencies, Map devDependencies, Map dependencyOverrides, - }) : this.authors = _normalizeAuthors(author, authors), - this.environment = environment ?? const {}, - this.dependencies = dependencies ?? const {}, - this.devDependencies = devDependencies ?? const {}, - this.dependencyOverrides = dependencyOverrides ?? const {} { + }) : authors = _normalizeAuthors(author, authors), + environment = environment ?? const {}, + dependencies = dependencies ?? const {}, + devDependencies = devDependencies ?? const {}, + dependencyOverrides = dependencyOverrides ?? const {} { if (name == null || name.isEmpty) { throw new ArgumentError.value(name, 'name', '"name" cannot be empty.'); } From 09f9ce49ed57908634f11772809e5584f4b55f7b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 23 Oct 2018 14:34:04 -0700 Subject: [PATCH 0492/1215] Support the latest release of pkg:json_annotation (dart-lang/pubspec_parse#28) --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index d114b8c36..26de02e08 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.2+3 + +- Support the latest version of `package:json_annotation`. + ## 0.1.2+2 - Support `package:json_annotation` v1. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 5dcb3dc81..871ae6ea9 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,16 +2,16 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.3-dev +version: 0.1.2+3 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team environment: - sdk: '>=2.0.0-dev.54 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: - # Verified that no new features since 0.2.9 are used - be careful! - json_annotation: '>=0.2.9 <2.0.0' + # Verified that no new features since 1.0.0 are used - be careful! + json_annotation: '>=1.0.0 <3.0.0' pub_semver: ^1.3.2 yaml: ^2.1.12 From 7d7853301aa19870c0db4ba07a0aba7649109c44 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 23 Oct 2018 14:36:11 -0700 Subject: [PATCH 0493/1215] support latest pkg:json_annotation (dart-lang/timing#9) --- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 7b73c71b8..a8ae834de 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1+1 + +- Support the latest version of `package:json_annotation`. + ## 0.1.1 - Add JSON serialization diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 54d619caf..25d81240e 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.2-dev +version: 0.1.1+1 description: Timing is a simple package for tracking performance of both async and sync actions author: Dart Team homepage: https://github.com/dart-lang/timing @@ -8,7 +8,7 @@ environment: sdk: ">=2.0.0 <3.0.0" dependencies: - json_annotation: ^1.0.0 + json_annotation: '>=1.0.0 <3.0.0' dev_dependencies: build_runner: ^1.0.0 From bace2a4a1b27ce170843acc433d04598ae21bad2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 2 Nov 2018 13:09:44 -0700 Subject: [PATCH 0494/1215] Test on Chrome on Travis - less flaky (dart-lang/stack_trace#47) --- pkgs/stack_trace/.travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 1d12365c9..8ddade509 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -1,13 +1,14 @@ language: dart -sudo: false + dart: - dev - stable - - 1.23.0 + dart_task: - test: -p vm - - test: -p firefox + - test: -p chrome - dartanalyzer + matrix: include: # Only validate formatting using the dev release From 85aef339f1458cce2ac8044232cf61edf015d703 Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Wed, 7 Nov 2018 13:12:14 -0800 Subject: [PATCH 0495/1215] Catch FileSystemException during existsSync() on Windows. (dart-lang/watcher#67) --- pkgs/watcher/CHANGELOG.md | 4 ++++ .../lib/src/directory_watcher/windows.dart | 15 +++++++++++---- pkgs/watcher/pubspec.yaml | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index cd34d904e..251c13e96 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.7+12 + +* Catch `FileSystemException` during `existsSync()` on Windows. + # 0.9.7+11 * Fix an analysis hint. diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 021493995..7294c170d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -308,8 +308,8 @@ class _WindowsDirectoryWatcher } } - /// Returns one or more events that describe the change between the last known - /// state of [path] and its current state on the filesystem. + /// Returns zero or more events that describe the change between the last + /// known state of [path] and its current state on the filesystem. /// /// This returns a list whose order should be reflected in the events emitted /// to the user, unlike the batched events from [Directory.watch]. The @@ -318,8 +318,15 @@ class _WindowsDirectoryWatcher List _eventsBasedOnFileSystem(String path) { var fileExisted = _files.contains(path); var dirExisted = _files.containsDir(path); - var fileExists = File(path).existsSync(); - var dirExists = Directory(path).existsSync(); + + bool fileExists; + bool dirExists; + try { + fileExists = File(path).existsSync(); + dirExists = Directory(path).existsSync(); + } on FileSystemException { + return const []; + } var events = []; if (fileExisted) { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index c107856ec..163e70ec1 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+11 +version: 0.9.7+12 description: > A file system watcher. It monitors changes to contents of directories and From 42548114bb67684396dd32604ea3a39bfe55e57b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 15 Nov 2018 19:04:32 -0800 Subject: [PATCH 0496/1215] Drop `fromBind` utility (dart-lang/stream_transform#59) Replace with `StreamTransformer.fromBind` which is now in the SDK. --- pkgs/stream_transform/lib/src/bind.dart | 22 ------------------- .../lib/src/chain_transformers.dart | 5 ++--- pkgs/stream_transform/lib/src/map.dart | 4 +--- pkgs/stream_transform/lib/src/scan.dart | 5 ++--- pkgs/stream_transform/lib/src/start_with.dart | 3 +-- pkgs/stream_transform/pubspec.yaml | 2 +- 6 files changed, 7 insertions(+), 34 deletions(-) delete mode 100644 pkgs/stream_transform/lib/src/bind.dart diff --git a/pkgs/stream_transform/lib/src/bind.dart b/pkgs/stream_transform/lib/src/bind.dart deleted file mode 100644 index eefdc60e4..000000000 --- a/pkgs/stream_transform/lib/src/bind.dart +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// Matches [StreamTransformer.bind]. -typedef Stream Bind(Stream values); - -/// Creates a [StreamTransformer] which overrides [StreamTransformer.bind] to -/// [bindFn]. -StreamTransformer fromBind(Bind bindFn) => - _StreamTransformer(bindFn); - -class _StreamTransformer extends StreamTransformerBase { - final Bind _bind; - - _StreamTransformer(this._bind); - - @override - Stream bind(Stream values) => _bind(values); -} diff --git a/pkgs/stream_transform/lib/src/chain_transformers.dart b/pkgs/stream_transform/lib/src/chain_transformers.dart index 50d8be48f..549befc10 100644 --- a/pkgs/stream_transform/lib/src/chain_transformers.dart +++ b/pkgs/stream_transform/lib/src/chain_transformers.dart @@ -4,8 +4,6 @@ import 'dart:async'; -import 'bind.dart'; - /// Combines two transformers into one. /// /// This is most useful to keep a reference to the combination and use it in @@ -21,4 +19,5 @@ import 'bind.dart'; /// ``` StreamTransformer chainTransformers( StreamTransformer first, StreamTransformer second) => - fromBind((values) => values.transform(first).transform(second)); + StreamTransformer.fromBind( + (values) => values.transform(first).transform(second)); diff --git a/pkgs/stream_transform/lib/src/map.dart b/pkgs/stream_transform/lib/src/map.dart index 8bce55016..09ea0d6f0 100644 --- a/pkgs/stream_transform/lib/src/map.dart +++ b/pkgs/stream_transform/lib/src/map.dart @@ -4,8 +4,6 @@ import 'dart:async'; -import 'bind.dart'; - /// Models a [Stream.map] callback as a [StreamTransformer]. /// /// This is most useful to pass to functions that take a [StreamTransformer] @@ -19,4 +17,4 @@ import 'bind.dart'; /// map((v) => '$v')); /// ``` StreamTransformer map(T convert(S event)) => - fromBind((stream) => stream.map(convert)); + StreamTransformer.fromBind((stream) => stream.map(convert)); diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index fb8c745f2..0936e13e1 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -1,15 +1,14 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. -import 'dart:async'; -import 'bind.dart'; +import 'dart:async'; /// Scan is like fold, but instead of producing a single value it yields /// each intermediate accumulation. StreamTransformer scan( T initialValue, T combine(T previousValue, S element)) => - fromBind((stream) { + StreamTransformer.fromBind((stream) { var accumulated = initialValue; return stream.map((value) => accumulated = combine(accumulated, value)); }); diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart index 1ddde0cfe..fbaf46a7a 100644 --- a/pkgs/stream_transform/lib/src/start_with.dart +++ b/pkgs/stream_transform/lib/src/start_with.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'bind.dart'; import 'followed_by.dart'; /// Emits [initial] before any values from the original stream. @@ -27,7 +26,7 @@ StreamTransformer startWithMany(Iterable initial) => /// the original stream is a broadcast stream it will miss any events which /// occur before [initial] closes. StreamTransformer startWithStream(Stream initial) => - fromBind((values) { + StreamTransformer.fromBind((values) { if (values.isBroadcast && !initial.isBroadcast) { initial = initial.asBroadcastStream(); } diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 81c10434d..b32a050df 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -5,7 +5,7 @@ homepage: https://www.github.com/dart-lang/stream_transform version: 0.0.15-dev environment: - sdk: ">=2.0.0 <3.0.0" + sdk: ">=2.1.0 <3.0.0" dev_dependencies: test: ^1.0.0 From c868e11f58f4ba5f157e66bea036ba41c284628d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 19 Nov 2018 14:54:40 -0800 Subject: [PATCH 0497/1215] Support latest version of pkg:csv (dart-lang/term_glyph#6) --- pkgs/term_glyph/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 6ef0c7c62..4cbaeb4be 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.0.1 +version: 1.0.2-dev description: Useful glyphs and Windows-safe equivalents. author: Dart Team @@ -9,6 +9,6 @@ environment: sdk: '>=1.8.0 <3.0.0' dev_dependencies: - csv: ^3.0.0 + csv: '>=3.0.0 <5.0.0' dart_style: '>=0.2.0 <2.0.0' test: '>=0.12.0 <2.0.0' From cdd1d2e49912371ff2c37086a549cbf4398ea735 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Dec 2018 10:38:34 -0800 Subject: [PATCH 0498/1215] Add pkg:pedantic lints --- pkgs/pubspec_parse/analysis_options.yaml | 1 + pkgs/pubspec_parse/pubspec.yaml | 1 + 2 files changed, 2 insertions(+) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 918f5deed..9602469e0 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 871ae6ea9..842c4d700 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -20,6 +20,7 @@ dev_dependencies: build_verify: ^1.0.0 json_serializable: ^1.2.1 path: ^1.5.1 + pedantic: ^1.4.0 stack_trace: ^1.9.2 test: ^1.0.0 test_descriptor: ^1.0.3 From 788a07258d7a6318803710a7cea4d6fe77d31e27 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Dec 2018 10:40:19 -0800 Subject: [PATCH 0499/1215] Update json_serializable version --- pkgs/pubspec_parse/lib/src/dependency.g.dart | 8 ++++---- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 7aee20614..243a5b3d1 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -10,7 +10,7 @@ SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { $checkKeys(json, requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); - var val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), + final val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String))); return val; @@ -21,7 +21,7 @@ GitDependency _$GitDependencyFromJson(Map json) { return $checkedNew('GitDependency', json, () { $checkKeys(json, requiredKeys: const ['url'], disallowNullValues: const ['url']); - var val = GitDependency( + final val = GitDependency( $checkedConvert( json, 'url', (v) => v == null ? null : parseGitUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), @@ -35,7 +35,7 @@ HostedDependency _$HostedDependencyFromJson(Map json) { $checkKeys(json, allowedKeys: const ['version', 'hosted'], disallowNullValues: const ['hosted']); - var val = HostedDependency( + final val = HostedDependency( version: $checkedConvert(json, 'version', (v) => v == null ? null : _constraintFromString(v as String)), hosted: $checkedConvert(json, 'hosted', @@ -50,7 +50,7 @@ HostedDetails _$HostedDetailsFromJson(Map json) { allowedKeys: const ['name', 'url'], requiredKeys: const ['name'], disallowNullValues: const ['name', 'url']); - var val = HostedDetails( + final val = HostedDetails( $checkedConvert(json, 'name', (v) => v as String), $checkedConvert( json, 'url', (v) => v == null ? null : parseGitUri(v as String))); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 7ac66f708..08ad5460f 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -8,7 +8,7 @@ part of 'pubspec.dart'; Pubspec _$PubspecFromJson(Map json) { return $checkedNew('Pubspec', json, () { - var val = Pubspec($checkedConvert(json, 'name', (v) => v as String), + final val = Pubspec($checkedConvert(json, 'name', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _versionFromString(v as String)), author: $checkedConvert(json, 'author', (v) => v as String), diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 842c4d700..390e60147 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -18,7 +18,7 @@ dependencies: dev_dependencies: build_runner: ^1.0.0 build_verify: ^1.0.0 - json_serializable: ^1.2.1 + json_serializable: ^2.0.0 path: ^1.5.1 pedantic: ^1.4.0 stack_trace: ^1.9.2 From 4986126482769ca4cda8350a5979adbd84f28756 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Dec 2018 12:23:11 -0800 Subject: [PATCH 0500/1215] Use latest pkg:json_serializable --- pkgs/timing/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 25d81240e..efda7ce99 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -12,6 +12,6 @@ dependencies: dev_dependencies: build_runner: ^1.0.0 - json_serializable: ^1.0.0 + json_serializable: ^2.0.0 pedantic: ^1.1.0 test: ^1.0.0 From eaae4fc04db0c7347d616a8adf37f740c7f7cf33 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Dec 2018 10:57:30 -0800 Subject: [PATCH 0501/1215] Remove unnecessary const, new --- pkgs/pubspec_parse/analysis_options.yaml | 2 ++ pkgs/pubspec_parse/lib/src/dependency.dart | 32 +++++++++---------- pkgs/pubspec_parse/lib/src/errors.dart | 6 ++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 25 +++++++-------- .../pubspec_parse/test/ensure_build_test.dart | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 4 +-- pkgs/pubspec_parse/test/pub_utils.dart | 14 +++----- pkgs/pubspec_parse/test/test_utils.dart | 2 +- 8 files changed, 42 insertions(+), 45 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 9602469e0..ed170c1aa 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -71,8 +71,10 @@ linter: - type_init_formals - unawaited_futures - unnecessary_brace_in_string_interps + - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas + - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_statements - unnecessary_this diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 3839e54e8..0fb761c9e 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -29,20 +29,20 @@ Map parseDeps(Map source) => if (innerError is FormatException) { message = innerError.message; } - throw new CheckedFromJsonException(source, key, e.className, message); + throw CheckedFromJsonException(source, key, e.className, message); } rethrow; } if (value == null) { - throw new CheckedFromJsonException( + throw CheckedFromJsonException( source, key, 'Pubspec', 'Not a valid dependency value.'); } - return new MapEntry(key, value); + return MapEntry(key, value); }) ?? {}; -const _sourceKeys = const ['sdk', 'git', 'path', 'hosted']; +const _sourceKeys = ['sdk', 'git', 'path', 'hosted']; /// Returns `null` if the data could not be parsed. Dependency _fromJson(dynamic data) { @@ -61,11 +61,11 @@ Dependency _fromJson(dynamic data) { orElse: () => null); if (weirdKey != null) { - throw new InvalidKeyException( + throw InvalidKeyException( data, weirdKey, 'Unsupported dependency key.'); } if (matchedKeys.length > 1) { - throw new CheckedFromJsonException(data, matchedKeys[1], 'Dependency', + throw CheckedFromJsonException(data, matchedKeys[1], 'Dependency', 'A dependency may only have one source.'); } @@ -74,17 +74,17 @@ Dependency _fromJson(dynamic data) { try { switch (key) { case 'git': - return new GitDependency.fromData(data[key]); + return GitDependency.fromData(data[key]); case 'path': - return new PathDependency.fromData(data[key]); + return PathDependency.fromData(data[key]); case 'sdk': return _$SdkDependencyFromJson(data); case 'hosted': return _$HostedDependencyFromJson(data); } - throw new StateError('There is a bug in pubspec_parse.'); + throw StateError('There is a bug in pubspec_parse.'); } on ArgumentError catch (e) { - throw new CheckedFromJsonException( + throw CheckedFromJsonException( data, e.name, 'Dependency', e.message.toString()); } } @@ -134,7 +134,7 @@ class GitDependency extends Dependency { return _$GitDependencyFromJson(data); } - throw new ArgumentError.value(data, 'git', 'Must be a String or a Map.'); + throw ArgumentError.value(data, 'git', 'Must be a String or a Map.'); } @override @@ -169,7 +169,7 @@ Uri _tryParseScpUri(String value) { var user = atIndex >= 0 ? value.substring(0, atIndex) : null; var host = value.substring(atIndex + 1, colonIndex); var path = value.substring(colonIndex + 1); - return new Uri(scheme: 'ssh', userInfo: user, host: host, path: path); + return Uri(scheme: 'ssh', userInfo: user, host: host, path: path); } return null; } @@ -181,9 +181,9 @@ class PathDependency extends Dependency { factory PathDependency.fromData(Object data) { if (data is String) { - return new PathDependency(data); + return PathDependency(data); } - throw new ArgumentError.value(data, 'path', 'Must be a String.'); + throw ArgumentError.value(data, 'path', 'Must be a String.'); } @override @@ -225,9 +225,9 @@ class HostedDetails { return _$HostedDetailsFromJson(data); } - throw new ArgumentError.value(data, 'hosted', 'Must be a Map or String.'); + throw ArgumentError.value(data, 'hosted', 'Must be a Map or String.'); } } VersionConstraint _constraintFromString(String input) => - new VersionConstraint.parse(input); + VersionConstraint.parse(input); diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index c9643b885..637c5a80b 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -6,7 +6,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:yaml/yaml.dart'; ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => - new ParsedYamlException._(message, yamlNode); + ParsedYamlException._(message, yamlNode); ParsedYamlException parsedYamlExceptionFromError( CheckedFromJsonException error, StackTrace stack) { @@ -20,7 +20,7 @@ ParsedYamlException parsedYamlExceptionFromError( return key.value == innerError.key; }, orElse: () => map); - return new ParsedYamlException._(innerError.message, node, + return ParsedYamlException._(innerError.message, node, innerError: error, innerStack: stack); } } else if (innerError is ParsedYamlException) { @@ -43,7 +43,7 @@ ParsedYamlException parsedYamlExceptionFromError( } } - return new ParsedYamlException._(message, yamlNode, + return ParsedYamlException._(message, yamlNode, innerError: error, innerStack: stack); } diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 59ee5858b..a8ef2fe85 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -71,7 +71,7 @@ class Pubspec { devDependencies = devDependencies ?? const {}, dependencyOverrides = dependencyOverrides ?? const {} { if (name == null || name.isEmpty) { - throw new ArgumentError.value(name, 'name', '"name" cannot be empty.'); + throw ArgumentError.value(name, 'name', '"name" cannot be empty.'); } } @@ -81,7 +81,7 @@ class Pubspec { var item = loadYaml(yaml, sourceUrl: sourceUrl); if (item == null) { - throw new ArgumentError.notNull('yaml'); + throw ArgumentError.notNull('yaml'); } if (item is! YamlMap) { @@ -89,19 +89,18 @@ class Pubspec { throw parsedYamlException('Does not represent a YAML map.', item); } - throw new ArgumentError.value( - yaml, 'yaml', 'Does not represent a YAML map.'); + throw ArgumentError.value(yaml, 'yaml', 'Does not represent a YAML map.'); } try { - return new Pubspec.fromJson(item as YamlMap); + return Pubspec.fromJson(item as YamlMap); } on CheckedFromJsonException catch (error, stack) { throw parsedYamlExceptionFromError(error, stack); } } static List _normalizeAuthors(String author, List authors) { - var value = new Set(); + var value = Set(); if (author != null) { value.add(author); } @@ -112,7 +111,7 @@ class Pubspec { } } -Version _versionFromString(String input) => new Version.parse(input); +Version _versionFromString(String input) => Version.parse(input); Map _environmentMap(Map source) => source.map((k, value) { @@ -120,7 +119,7 @@ Map _environmentMap(Map source) => if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! - throw new InvalidKeyException( + throw InvalidKeyException( source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); } @@ -129,16 +128,16 @@ Map _environmentMap(Map source) => constraint = null; } else if (value is String) { try { - constraint = new VersionConstraint.parse(value); + constraint = VersionConstraint.parse(value); } on FormatException catch (e) { - throw new CheckedFromJsonException(source, key, 'Pubspec', e.message); + throw CheckedFromJsonException(source, key, 'Pubspec', e.message); } - return new MapEntry(key, constraint); + return MapEntry(key, constraint); } else { - throw new CheckedFromJsonException( + throw CheckedFromJsonException( source, key, 'VersionConstraint', '`$value` is not a String.'); } - return new MapEntry(key, constraint); + return MapEntry(key, constraint); }); diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index ac67c9ff6..d64fa4f66 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') -@Tags(const ['presubmit-only']) +@Tags(['presubmit-only']) import 'package:build_verify/build_verify.dart'; import 'package:test/test.dart'; diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 71c0a58ed..3ed73a509 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -25,8 +25,8 @@ void main() { }); test('all fields set', () { - var version = new Version.parse('1.2.3'); - var sdkConstraint = new VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); + var version = Version.parse('1.2.3'); + var sdkConstraint = VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); var value = parse({ 'name': 'sample', 'version': version.toString(), diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart index 984bb49ae..f9e2f0cda 100644 --- a/pkgs/pubspec_parse/test/pub_utils.dart +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -26,7 +26,7 @@ Future tryPub(String content) async { if (result.exitCode == 0) { var lockContent = - new File(p.join(d.sandbox, 'pubspec.lock')).readAsStringSync(); + File(p.join(d.sandbox, 'pubspec.lock')).readAsStringSync(); printOnFailure([ '-----BEGIN pubspec.lock-----', @@ -51,20 +51,16 @@ class ProcResult { var values = await Future.wait([ proc.exitCode, - proc - .stdoutStream() - .forEach((line) => items.add(new ProcLine(false, line))), - proc - .stderrStream() - .forEach((line) => items.add(new ProcLine(true, line))), + proc.stdoutStream().forEach((line) => items.add(ProcLine(false, line))), + proc.stderrStream().forEach((line) => items.add(ProcLine(true, line))), ]); - return new ProcResult(values[0] as int, items); + return ProcResult(values[0] as int, items); } @override String toString() { - var buffer = new StringBuffer('Exit code: $exitCode'); + var buffer = StringBuffer('Exit code: $exitCode'); for (var line in lines) { buffer.write('\n$line'); } diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 48efdf698..d5254db83 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -62,7 +62,7 @@ Pubspec parse(Object content, } try { - var value = new Pubspec.parse(encoded); + var value = Pubspec.parse(encoded); if (pubResult != null) { addTearDown(() { From fe0b7c323ed773cf0d244ed3fcf42950f552a316 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Dec 2018 11:03:13 -0800 Subject: [PATCH 0502/1215] Enable and fix a number of lints --- pkgs/pubspec_parse/analysis_options.yaml | 10 ++++- pkgs/pubspec_parse/lib/src/dependency.dart | 22 +++++------ pkgs/pubspec_parse/lib/src/errors.dart | 8 ++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 6 +-- pkgs/pubspec_parse/test/dependency_test.dart | 40 ++++++++++---------- pkgs/pubspec_parse/test/git_uri_test.dart | 5 +-- pkgs/pubspec_parse/test/parse_test.dart | 20 +++++----- pkgs/pubspec_parse/test/pub_utils.dart | 18 ++++----- pkgs/pubspec_parse/test/test_utils.dart | 12 +++--- 9 files changed, 73 insertions(+), 68 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index ed170c1aa..b95911604 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -20,12 +20,13 @@ linter: - avoid_renaming_method_parameters - avoid_return_types_on_setters - avoid_returning_null + - avoid_returning_null_for_future + - avoid_shadowing_type_parameters - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - await_only_futures - camel_case_types - cancel_subscriptions - #- cascade_invocations - comment_references - constant_identifier_names - control_flow_in_finally @@ -44,10 +45,11 @@ linter: - no_adjacent_strings_in_list - no_duplicate_case_values - non_constant_identifier_names + - null_closures - omit_local_variable_types - only_throw_errors - overridden_fields - #- package_api_docs + - package_api_docs - package_names - package_prefixed_library_names - prefer_adjacent_string_concatenation @@ -57,6 +59,7 @@ linter: - prefer_contains - prefer_equal_for_default_values - prefer_final_fields + - prefer_final_locals - prefer_initializing_formals - prefer_interpolation_to_compose_strings - prefer_is_empty @@ -70,14 +73,17 @@ linter: - throw_in_finally - type_init_formals - unawaited_futures + - unnecessary_await_in_return - unnecessary_brace_in_string_interps - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas - unnecessary_new - unnecessary_null_aware_assignments + - unnecessary_parenthesis - unnecessary_statements - unnecessary_this - unrelated_type_equality_checks + - use_function_type_syntax_for_parameters - use_rethrow_when_possible - valid_regexps diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 0fb761c9e..cba01dc43 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -12,7 +12,7 @@ part 'dependency.g.dart'; Map parseDeps(Map source) => source?.map((k, v) { - var key = k as String; + final key = k as String; Dependency value; try { value = _fromJson(v); @@ -23,7 +23,7 @@ Map parseDeps(Map source) => // extract the associated error information. var message = e.message; - var innerError = e.innerError; + final innerError = e.innerError; // json_annotation should handle FormatException... // https://github.com/dart-lang/json_serializable/issues/233 if (innerError is FormatException) { @@ -51,13 +51,13 @@ Dependency _fromJson(dynamic data) { } if (data is Map) { - var matchedKeys = + final matchedKeys = data.keys.cast().where((key) => key != 'version').toList(); if (data.isEmpty || (matchedKeys.isEmpty && data.containsKey('version'))) { return _$HostedDependencyFromJson(data); } else { - var weirdKey = matchedKeys.firstWhere((k) => !_sourceKeys.contains(k), + final weirdKey = matchedKeys.firstWhere((k) => !_sourceKeys.contains(k), orElse: () => null); if (weirdKey != null) { @@ -69,7 +69,7 @@ Dependency _fromJson(dynamic data) { 'A dependency may only have one source.'); } - var key = matchedKeys.single; + final key = matchedKeys.single; try { switch (key) { @@ -146,7 +146,7 @@ Uri parseGitUri(String value) => _tryParseScpUri(value) ?? Uri.parse(value); /// Supports URIs like `[user@]host.xz:path/to/repo.git/` /// See https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a Uri _tryParseScpUri(String value) { - var colonIndex = value.indexOf(':'); + final colonIndex = value.indexOf(':'); if (colonIndex < 0) { return null; @@ -154,7 +154,7 @@ Uri _tryParseScpUri(String value) { // If the first colon is part of a scheme, it's not an scp-like URI return null; } - var slashIndex = value.indexOf('/'); + final slashIndex = value.indexOf('/'); if (slashIndex >= 0 && slashIndex < colonIndex) { // Per docs: This syntax is only recognized if there are no slashes before @@ -164,11 +164,11 @@ Uri _tryParseScpUri(String value) { return null; } - var atIndex = value.indexOf('@'); + final atIndex = value.indexOf('@'); if (colonIndex > atIndex) { - var user = atIndex >= 0 ? value.substring(0, atIndex) : null; - var host = value.substring(atIndex + 1, colonIndex); - var path = value.substring(colonIndex + 1); + final user = atIndex >= 0 ? value.substring(0, atIndex) : null; + final host = value.substring(atIndex + 1, colonIndex); + final path = value.substring(colonIndex + 1); return Uri(scheme: 'ssh', userInfo: user, host: host, path: path); } return null; diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index 637c5a80b..aba69709b 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -10,13 +10,13 @@ ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => ParsedYamlException parsedYamlExceptionFromError( CheckedFromJsonException error, StackTrace stack) { - var innerError = error.innerError; + final innerError = error.innerError; if (innerError is InvalidKeyException) { - var map = innerError.map; + final map = innerError.map; if (map is YamlMap) { // if the associated key exists, use that as the error node, // otherwise use the map itself - var node = map.nodes.keys.cast().singleWhere((key) { + final node = map.nodes.keys.cast().singleWhere((key) { return key.value == innerError.key; }, orElse: () => map); @@ -27,7 +27,7 @@ ParsedYamlException parsedYamlExceptionFromError( return innerError; } - var yamlMap = error.map as YamlMap; + final yamlMap = error.map as YamlMap; var yamlNode = yamlMap.nodes[error.key]; String message; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index a8ef2fe85..df712625f 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -78,7 +78,7 @@ class Pubspec { factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); factory Pubspec.parse(String yaml, {sourceUrl}) { - var item = loadYaml(yaml, sourceUrl: sourceUrl); + final item = loadYaml(yaml, sourceUrl: sourceUrl); if (item == null) { throw ArgumentError.notNull('yaml'); @@ -100,7 +100,7 @@ class Pubspec { } static List _normalizeAuthors(String author, List authors) { - var value = Set(); + final value = Set(); if (author != null) { value.add(author); } @@ -115,7 +115,7 @@ Version _versionFromString(String input) => Version.parse(input); Map _environmentMap(Map source) => source.map((k, value) { - var key = k as String; + final key = k as String; if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 3bc890aef..6c7d968fe 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -4,8 +4,8 @@ import 'dart:io'; -import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:pub_semver/pub_semver.dart'; +import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:test/test.dart'; import 'test_utils.dart'; @@ -49,20 +49,20 @@ line 6, column 4: Unsupported dependency key. void _hostedDependency() { test('null', () { - var dep = _dependency(null); + final dep = _dependency(null); expect(dep.version.toString(), 'any'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); test('empty map', () { - var dep = _dependency({}); + final dep = _dependency({}); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); test('string version', () { - var dep = _dependency('^1.0.0'); + final dep = _dependency('^1.0.0'); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); @@ -76,14 +76,14 @@ line 4, column 10: Could not parse version "not a version". Unknown text at "not }); test('map w/ just version', () { - var dep = _dependency({'version': '^1.0.0'}); + final dep = _dependency({'version': '^1.0.0'}); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); test('map w/ version and hosted as Map', () { - var dep = _dependency({ + final dep = _dependency({ 'version': '^1.0.0', 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} }); @@ -115,7 +115,7 @@ line 10, column 4: Unsupported dependency key. }); test('map w/ version and hosted as String', () { - var dep = _dependency( + final dep = _dependency( {'version': '^1.0.0', 'hosted': 'hosted_name'}); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted.name, 'hosted_name'); @@ -124,7 +124,7 @@ line 10, column 4: Unsupported dependency key. }); test('map w/ hosted as String', () { - var dep = _dependency({'hosted': 'hosted_name'}); + final dep = _dependency({'hosted': 'hosted_name'}); expect(dep.version, VersionConstraint.any); expect(dep.hosted.name, 'hosted_name'); expect(dep.hosted.url, isNull); @@ -139,7 +139,7 @@ line 5, column 14: These keys had `null` values, which is not allowed: [hosted] }); test('map w/ null version is fine', () { - var dep = _dependency({'version': null}); + final dep = _dependency({'version': null}); expect(dep.version, VersionConstraint.any); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); @@ -148,14 +148,14 @@ line 5, column 14: These keys had `null` values, which is not allowed: [hosted] void _sdkDependency() { test('without version', () { - var dep = _dependency({'sdk': 'flutter'}); + final dep = _dependency({'sdk': 'flutter'}); expect(dep.sdk, 'flutter'); expect(dep.version, isNull); expect(dep.toString(), 'SdkDependency: flutter'); }); test('with version', () { - var dep = _dependency( + final dep = _dependency( {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}); expect(dep.sdk, 'flutter'); expect(dep.version.toString(), '>=1.2.3 <2.0.0'); @@ -179,7 +179,7 @@ line 5, column 11: Unsupported value for `sdk`. void _gitDependency() { test('string', () { - var dep = _dependency({'git': 'url'}); + final dep = _dependency({'git': 'url'}); expect(dep.url.toString(), 'url'); expect(dep.path, isNull); expect(dep.ref, isNull); @@ -188,7 +188,7 @@ void _gitDependency() { test('string with version key is ignored', () { // Regression test for https://github.com/dart-lang/pubspec_parse/issues/13 - var dep = _dependency({'git': 'url', 'version': '^1.2.3'}); + final dep = _dependency({'git': 'url', 'version': '^1.2.3'}); expect(dep.url.toString(), 'url'); expect(dep.path, isNull); expect(dep.ref, isNull); @@ -196,11 +196,11 @@ void _gitDependency() { }); test('string with user@ URL', () { - var skipTryParse = Platform.environment.containsKey('TRAVIS'); + final skipTryParse = Platform.environment.containsKey('TRAVIS'); if (skipTryParse) { print('FYI: not validating git@ URI on travis due to failure'); } - var dep = _dependency({'git': 'git@localhost:dep.git'}, + final dep = _dependency({'git': 'git@localhost:dep.git'}, skipTryPub: skipTryParse); expect(dep.url.toString(), 'ssh://git@localhost/dep.git'); expect(dep.path, isNull); @@ -216,7 +216,7 @@ line 6, column 4: Unsupported dependency key. }); test('map', () { - var dep = _dependency({ + final dep = _dependency({ 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'} }); expect(dep.url.toString(), 'url'); @@ -267,13 +267,13 @@ line 6, column 12: Unsupported value for `url`. void _pathDependency() { test('valid', () { - var dep = _dependency({'path': '../path'}); + final dep = _dependency({'path': '../path'}); expect(dep.path, '../path'); expect(dep.toString(), 'PathDependency: path@../path'); }); test('valid with version key is ignored', () { - var dep = + final dep = _dependency({'path': '../path', 'version': '^1.2.3'}); expect(dep.path, '../path'); expect(dep.toString(), 'PathDependency: path@../path'); @@ -309,14 +309,14 @@ void _expectThrows(Object content, String expectedError) { } T _dependency(Object content, {bool skipTryPub = false}) { - var value = parse({ + final value = parse({ 'name': 'sample', 'dependencies': {'dep': content} }, skipTryPub: skipTryPub); expect(value.name, 'sample'); expect(value.dependencies, hasLength(1)); - var entry = value.dependencies.entries.single; + final entry = value.dependencies.entries.single; expect(entry.key, 'dep'); return entry.value as T; diff --git a/pkgs/pubspec_parse/test/git_uri_test.dart b/pkgs/pubspec_parse/test/git_uri_test.dart index a1cfdf9cb..36e55a84c 100644 --- a/pkgs/pubspec_parse/test/git_uri_test.dart +++ b/pkgs/pubspec_parse/test/git_uri_test.dart @@ -1,6 +1,5 @@ -import 'package:test/test.dart'; - import 'package:pubspec_parse/src/dependency.dart'; +import 'package:test/test.dart'; void main() { for (var item in { @@ -14,7 +13,7 @@ void main() { 'file:///path/to/repo.git/': 'file:///path/to/repo.git/', }.entries) { test(item.key, () { - var uri = parseGitUri(item.key); + final uri = parseGitUri(item.key); printOnFailure( [uri.scheme, uri.userInfo, uri.host, uri.port, uri.path].join('\n')); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 3ed73a509..df2475b88 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -9,7 +9,7 @@ import 'test_utils.dart'; void main() { test('minimal set values', () { - var value = parse({'name': 'sample'}); + final value = parse({'name': 'sample'}); expect(value.name, 'sample'); expect(value.version, isNull); expect(value.description, isNull); @@ -25,9 +25,9 @@ void main() { }); test('all fields set', () { - var version = Version.parse('1.2.3'); - var sdkConstraint = VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); - var value = parse({ + final version = Version.parse('1.2.3'); + final sdkConstraint = VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); + final value = parse({ 'name': 'sample', 'version': version.toString(), 'author': 'name@example.com', @@ -52,7 +52,7 @@ void main() { }); test('environment values can be null', () { - var value = parse({ + final value = parse({ 'name': 'sample', 'environment': {'sdk': null} }); @@ -63,14 +63,14 @@ void main() { group('author, authors', () { test('one author', () { - var value = parse({'name': 'sample', 'author': 'name@example.com'}); + final value = parse({'name': 'sample', 'author': 'name@example.com'}); // ignore: deprecated_member_use expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); test('one author, via authors', () { - var value = parse({ + final value = parse({ 'name': 'sample', 'authors': ['name@example.com'] }); @@ -80,7 +80,7 @@ void main() { }); test('many authors', () { - var value = parse({ + final value = parse({ 'name': 'sample', 'authors': ['name@example.com', 'name2@example.com'] }); @@ -90,7 +90,7 @@ void main() { }); test('author and authors', () { - var value = parse({ + final value = parse({ 'name': 'sample', 'author': 'name@example.com', 'authors': ['name2@example.com'] @@ -101,7 +101,7 @@ void main() { }); test('duplicate author values', () { - var value = parse({ + final value = parse({ 'name': 'sample', 'author': 'name@example.com', 'authors': ['name@example.com', 'name@example.com'] diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart index f9e2f0cda..1ebb9c7ca 100644 --- a/pkgs/pubspec_parse/test/pub_utils.dart +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -13,10 +13,10 @@ import 'package:test_process/test_process.dart'; Future tryPub(String content) async { await d.file('pubspec.yaml', content).create(); - var proc = await TestProcess.start(_pubPath, ['get', '--offline'], + final proc = await TestProcess.start(_pubPath, ['get', '--offline'], workingDirectory: d.sandbox); - var result = await ProcResult.fromTestProcess(proc); + final result = await ProcResult.fromTestProcess(proc); printOnFailure([ '-----BEGIN pub output-----', @@ -25,7 +25,7 @@ Future tryPub(String content) async { ].join('\n')); if (result.exitCode == 0) { - var lockContent = + final lockContent = File(p.join(d.sandbox, 'pubspec.lock')).readAsStringSync(); printOnFailure([ @@ -47,9 +47,9 @@ class ProcResult { ProcResult(this.exitCode, this.lines); static Future fromTestProcess(TestProcess proc) async { - var items = []; + final items = []; - var values = await Future.wait([ + final values = await Future.wait([ proc.exitCode, proc.stdoutStream().forEach((line) => items.add(ProcLine(false, line))), proc.stderrStream().forEach((line) => items.add(ProcLine(true, line))), @@ -60,7 +60,7 @@ class ProcResult { @override String toString() { - var buffer = StringBuffer('Exit code: $exitCode'); + final buffer = StringBuffer('Exit code: $exitCode'); for (var line in lines) { buffer.write('\n$line'); } @@ -79,13 +79,13 @@ class ProcLine { } /// The path to the root directory of the SDK. -final String _sdkDir = (() { +final String _sdkDir = () { // The Dart executable is in "/path/to/sdk/bin/dart", so two levels up is // "/path/to/sdk". - var aboveExecutable = p.dirname(p.dirname(Platform.resolvedExecutable)); + final aboveExecutable = p.dirname(p.dirname(Platform.resolvedExecutable)); assert(FileSystemEntity.isFileSync(p.join(aboveExecutable, 'version'))); return aboveExecutable; -})(); +}(); final String _pubPath = p.join(_sdkDir, 'bin', Platform.isWindows ? 'pub.bat' : 'pub'); diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index d5254db83..9750bfa9b 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -17,7 +17,7 @@ String _encodeJson(Object input) => Matcher _throwsParsedYamlException(String prettyValue) => throwsA(const TypeMatcher().having((e) { - var message = e.formattedMessage; + final message = e.formattedMessage; printOnFailure("Actual error format:\nr'''\n$message'''"); _printDebugParsedYamlException(e); return message; @@ -28,7 +28,7 @@ void _printDebugParsedYamlException(ParsedYamlException e) { var innerStack = e.innerStack; if (e.innerError is CheckedFromJsonException) { - var cfje = e.innerError as CheckedFromJsonException; + final cfje = e.innerError as CheckedFromJsonException; if (cfje.innerError != null) { innerError = cfje.innerError; innerStack = cfje.innerStack; @@ -36,12 +36,12 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } if (innerError != null) { - var items = [innerError]; + final items = [innerError]; if (innerStack != null) { items.add(Trace.format(innerStack, terse: true)); } - var content = + final content = LineSplitter.split(items.join('\n')).map((e) => ' $e').join('\n'); printOnFailure('Inner error details:\n$content'); @@ -53,7 +53,7 @@ Pubspec parse(Object content, quietOnError ??= false; skipTryPub ??= false; - var encoded = _encodeJson(content); + final encoded = _encodeJson(content); ProcResult pubResult; if (!skipTryPub) { @@ -62,7 +62,7 @@ Pubspec parse(Object content, } try { - var value = Pubspec.parse(encoded); + final value = Pubspec.parse(encoded); if (pubResult != null) { addTearDown(() { From 9f42e729850e4ae42e352b13e2879a94e394d81f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 9 Oct 2018 17:52:09 -0700 Subject: [PATCH 0503/1215] Move json_serializable config to build.yaml --- pkgs/pubspec_parse/build.yaml | 1 + pkgs/pubspec_parse/lib/src/dependency.dart | 8 ++++---- pkgs/pubspec_parse/lib/src/pubspec.dart | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 69bcb1f43..90eeb90f6 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -10,3 +10,4 @@ targets: options: any_map: true checked: true + create_to_json: false diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index cba01dc43..d9b3db247 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -103,7 +103,7 @@ abstract class Dependency { String toString() => '$runtimeType: $_info'; } -@JsonSerializable(createToJson: false) +@JsonSerializable() class SdkDependency extends Dependency { @JsonKey(nullable: false, disallowNullValue: true, required: true) final String sdk; @@ -116,7 +116,7 @@ class SdkDependency extends Dependency { String get _info => sdk; } -@JsonSerializable(createToJson: false) +@JsonSerializable() class GitDependency extends Dependency { @JsonKey(fromJson: parseGitUri, required: true, disallowNullValue: true) final Uri url; @@ -190,7 +190,7 @@ class PathDependency extends Dependency { String get _info => 'path@$path'; } -@JsonSerializable(createToJson: false, disallowUnrecognizedKeys: true) +@JsonSerializable(disallowUnrecognizedKeys: true) class HostedDependency extends Dependency { @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; @@ -206,7 +206,7 @@ class HostedDependency extends Dependency { String get _info => version.toString(); } -@JsonSerializable(createToJson: false, disallowUnrecognizedKeys: true) +@JsonSerializable(disallowUnrecognizedKeys: true) class HostedDetails { @JsonKey(required: true, disallowNullValue: true) final String name; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index df712625f..c7fec6b8a 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -11,7 +11,7 @@ import 'errors.dart'; part 'pubspec.g.dart'; -@JsonSerializable(createToJson: false) +@JsonSerializable() class Pubspec { // TODO: executables // TODO: publish_to From 4711ac71da70d85b477d3b65823e4f77833d8dac Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Dec 2018 13:15:44 -0800 Subject: [PATCH 0504/1215] Centralize field rename logic in build.yaml --- pkgs/pubspec_parse/build.yaml | 1 + pkgs/pubspec_parse/lib/src/pubspec.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 90eeb90f6..1525ab832 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -11,3 +11,4 @@ targets: any_map: true checked: true create_to_json: false + field_rename: snake diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index c7fec6b8a..dee92e036 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -45,10 +45,10 @@ class Pubspec { @JsonKey(fromJson: parseDeps, nullable: false) final Map dependencies; - @JsonKey(name: 'dev_dependencies', fromJson: parseDeps, nullable: false) + @JsonKey(fromJson: parseDeps, nullable: false) final Map devDependencies; - @JsonKey(name: 'dependency_overrides', fromJson: parseDeps, nullable: false) + @JsonKey(fromJson: parseDeps, nullable: false) final Map dependencyOverrides; /// If [author] and [authors] are both provided, their values are combined From 9afd4ee4cd600f9632ab51546fe430ccd2914127 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 22 Jun 2018 10:25:05 -0700 Subject: [PATCH 0505/1215] Add support for publish_to field Fixes https://github.com/dart-lang/pubspec_parse/issues/21 --- pkgs/pubspec_parse/CHANGELOG.md | 4 +++ pkgs/pubspec_parse/lib/src/pubspec.dart | 22 +++++++++++- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 ++ pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 44 +++++++++++++++++++++++ pkgs/pubspec_parse/test/test_utils.dart | 10 ++++-- 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 26de02e08..add9737b8 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.3 + +- Add support for `publish_to` field. + ## 0.1.2+3 - Support the latest version of `package:json_annotation`. diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index dee92e036..27ebc640f 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -14,7 +14,6 @@ part 'pubspec.g.dart'; @JsonSerializable() class Pubspec { // TODO: executables - // TODO: publish_to final String name; @@ -24,6 +23,15 @@ class Pubspec { final String description; final String homepage; + /// Specifies where to publish this package. + /// + /// Accepted values: `null`, `'none'` or an `http` or `https` URL. + /// + /// If not specified, the pub client defaults to `https://pub.dartlang.org`. + /// + /// [More information](https://www.dartlang.org/tools/pub/pubspec#publish_to). + final String publishTo; + /// If there is exactly 1 value in [authors], returns it. /// /// If there are 0 or more than 1, returns `null`. @@ -56,6 +64,7 @@ class Pubspec { Pubspec( this.name, { this.version, + this.publishTo, String author, List authors, Map environment, @@ -73,6 +82,17 @@ class Pubspec { if (name == null || name.isEmpty) { throw ArgumentError.value(name, 'name', '"name" cannot be empty.'); } + + if (publishTo != null && publishTo != 'none') { + try { + final targetUri = Uri.parse(publishTo); + if (!(targetUri.isScheme('http') || targetUri.isScheme('https'))) { + throw const FormatException('must be an http or https URL.'); + } + } on FormatException catch (e) { + throw ArgumentError.value(publishTo, 'publishTo', e.message); + } + } } factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 08ad5460f..bf878c2c5 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -11,6 +11,7 @@ Pubspec _$PubspecFromJson(Map json) { final val = Pubspec($checkedConvert(json, 'name', (v) => v as String), version: $checkedConvert(json, 'version', (v) => v == null ? null : _versionFromString(v as String)), + publishTo: $checkedConvert(json, 'publish_to', (v) => v as String), author: $checkedConvert(json, 'author', (v) => v as String), authors: $checkedConvert(json, 'authors', (v) => (v as List)?.map((e) => e as String)?.toList()), @@ -28,6 +29,7 @@ Pubspec _$PubspecFromJson(Map json) { json, 'dependency_overrides', (v) => parseDeps(v as Map))); return val; }, fieldKeyMap: const { + 'publishTo': 'publish_to', 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' }); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 390e60147..fde8f8a76 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.2+3 +version: 0.1.3-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index df2475b88..23d2078de 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -12,6 +12,7 @@ void main() { final value = parse({'name': 'sample'}); expect(value.name, 'sample'); expect(value.version, isNull); + expect(value.publishTo, isNull); expect(value.description, isNull); expect(value.homepage, isNull); // ignore: deprecated_member_use @@ -30,6 +31,7 @@ void main() { final value = parse({ 'name': 'sample', 'version': version.toString(), + 'publish_to': 'none', 'author': 'name@example.com', 'environment': {'sdk': sdkConstraint.toString()}, 'description': 'description', @@ -38,6 +40,7 @@ void main() { }); expect(value.name, 'sample'); expect(value.version, version); + expect(value.publishTo, 'none'); expect(value.description, 'description'); expect(value.homepage, 'homepage'); // ignore: deprecated_member_use @@ -61,6 +64,47 @@ void main() { expect(value.environment, containsPair('sdk', isNull)); }); + group('publish_to', () { + for (var entry in { + 42: r''' +line 3, column 16: Unsupported value for `publish_to`. + "publish_to": 42 + ^^^''', + '##not a uri!': r''' +line 3, column 16: must be an http or https URL. + "publish_to": "##not a uri!" + ^^^^^^^^^^^^^^''', + '/cool/beans': r''' +line 3, column 16: must be an http or https URL. + "publish_to": "/cool/beans" + ^^^^^^^^^^^^^''', + 'file:///Users/kevmoo/': r''' +line 3, column 16: must be an http or https URL. + "publish_to": "file:///Users/kevmoo/" + ^^^^^^^^^^^^^^^^^^^^^^^''' + }.entries) { + test('cannot be `${entry.key}`', () { + expectParseThrows( + {'name': 'sample', 'publish_to': entry.key}, + entry.value, + skipTryPub: true, + ); + }); + } + + for (var entry in { + null: null, + 'http': 'http://example.com', + 'https': 'https://example.com', + 'none': 'none' + }.entries) { + test('can be ${entry.key}', () { + final value = parse({'name': 'sample', 'publish_to': entry.value}); + expect(value.publishTo, entry.value); + }); + } + }); + group('author, authors', () { test('one author', () { final value = parse({'name': 'sample', 'author': 'name@example.com'}); diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 9750bfa9b..491873f34 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -89,6 +89,10 @@ Pubspec parse(Object content, } } -void expectParseThrows(Object content, String expectedError) => expect( - () => parse(content, quietOnError: true), - _throwsParsedYamlException(expectedError)); +void expectParseThrows( + Object content, + String expectedError, { + bool skipTryPub = false, +}) => + expect(() => parse(content, quietOnError: true, skipTryPub: skipTryPub), + _throwsParsedYamlException(expectedError)); From 5c532003292fcef698e1d74ae35799a3022d170f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20So=C3=B3s?= Date: Thu, 20 Dec 2018 00:31:08 +0100 Subject: [PATCH 0506/1215] Support the proposed repository and issue_tracker URLs. (dart-lang/pubspec_parse#30) --- pkgs/pubspec_parse/CHANGELOG.md | 1 + pkgs/pubspec_parse/lib/src/pubspec.dart | 12 ++++++++++++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index add9737b8..066edeb19 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.1.3 - Add support for `publish_to` field. +- Support the proposed `repository` and `issue_tracker` URLs. ## 0.1.2+3 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 27ebc640f..8324e0774 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -21,6 +21,8 @@ class Pubspec { final Version version; final String description; + + /// This should be a URL pointing to the website for the package. final String homepage; /// Specifies where to publish this package. @@ -32,6 +34,14 @@ class Pubspec { /// [More information](https://www.dartlang.org/tools/pub/pubspec#publish_to). final String publishTo; + /// Optional field to specify the source code repository of the package. + /// Useful when a package has both a home page and a repository. + final Uri repository; + + /// Optional field to a web page where developers can report new issues or + /// view existing ones. + final Uri issueTracker; + /// If there is exactly 1 value in [authors], returns it. /// /// If there are 0 or more than 1, returns `null`. @@ -69,6 +79,8 @@ class Pubspec { List authors, Map environment, this.homepage, + this.repository, + this.issueTracker, this.documentation, this.description, Map dependencies, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index bf878c2c5..866438f06 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -18,6 +18,10 @@ Pubspec _$PubspecFromJson(Map json) { environment: $checkedConvert(json, 'environment', (v) => v == null ? null : _environmentMap(v as Map)), homepage: $checkedConvert(json, 'homepage', (v) => v as String), + repository: $checkedConvert(json, 'repository', + (v) => v == null ? null : Uri.parse(v as String)), + issueTracker: $checkedConvert(json, 'issue_tracker', + (v) => v == null ? null : Uri.parse(v as String)), documentation: $checkedConvert(json, 'documentation', (v) => v as String), description: $checkedConvert(json, 'description', (v) => v as String), @@ -30,6 +34,7 @@ Pubspec _$PubspecFromJson(Map json) { return val; }, fieldKeyMap: const { 'publishTo': 'publish_to', + 'issueTracker': 'issue_tracker', 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' }); From ad96ee26306f98308cf1f265d3df7697493d03b5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Dec 2018 08:31:46 -0800 Subject: [PATCH 0507/1215] Add support for the optional `flutter` field --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 9 +++++++++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 4 +++- pkgs/pubspec_parse/test/parse_test.dart | 9 +++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 066edeb19..9df4aca1b 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.1.3 -- Add support for `publish_to` field. -- Support the proposed `repository` and `issue_tracker` URLs. +- Added support for `flutter`, `issue_tracker`, `publish_to`, and `repository` + fields. ## 0.1.2+3 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 8324e0774..b79839d38 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -69,6 +69,14 @@ class Pubspec { @JsonKey(fromJson: parseDeps, nullable: false) final Map dependencyOverrides; + /// Optional configuration specific to [Flutter](https://flutter.io/) + /// packages. + /// + /// May include + /// [assets](https://flutter.io/docs/development/ui/assets-and-images) + /// and other settings. + final Map flutter; + /// If [author] and [authors] are both provided, their values are combined /// with duplicates eliminated. Pubspec( @@ -86,6 +94,7 @@ class Pubspec { Map dependencies, Map devDependencies, Map dependencyOverrides, + this.flutter, }) : authors = _normalizeAuthors(author, authors), environment = environment ?? const {}, dependencies = dependencies ?? const {}, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 866438f06..b68e030fa 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -30,7 +30,9 @@ Pubspec _$PubspecFromJson(Map json) { devDependencies: $checkedConvert( json, 'dev_dependencies', (v) => parseDeps(v as Map)), dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => parseDeps(v as Map))); + json, 'dependency_overrides', (v) => parseDeps(v as Map)), + flutter: $checkedConvert(json, 'flutter', + (v) => (v as Map)?.map((k, e) => MapEntry(k as String, e)))); return val; }, fieldKeyMap: const { 'publishTo': 'publish_to', diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 23d2078de..281f11374 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -23,6 +23,7 @@ void main() { expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); expect(value.dependencyOverrides, isEmpty); + expect(value.flutter, isNull); }); test('all fields set', () { @@ -154,6 +155,14 @@ line 3, column 16: must be an http or https URL. expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); + + test('flutter', () { + final value = parse({ + 'name': 'sample', + 'flutter': {'key': 'value'}, + }); + expect(value.flutter, {'key': 'value'}); + }); }); group('invalid', () { From a073213309664977b4d917f28311512c8e6b5a86 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Dec 2018 08:32:05 -0800 Subject: [PATCH 0508/1215] Prepare to release v0.1.3 --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index fde8f8a76..be7ada51c 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.3-dev +version: 0.1.3 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team From 189d9851e1120da333fdfb6252a5695218217243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20So=C3=B3s?= Date: Tue, 8 Jan 2019 16:35:08 +0100 Subject: [PATCH 0509/1215] Parsing option: lenient. (dart-lang/pubspec_parse#36) Fixes https://github.com/dart-lang/pubspec_parse/issues/35 --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++ pkgs/pubspec_parse/lib/src/pubspec.dart | 32 ++++++++- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 86 +++++++++++++++++++++++++ pkgs/pubspec_parse/test/test_utils.dart | 11 +++- 5 files changed, 128 insertions(+), 7 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 9df4aca1b..d43264920 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4 + +- Added `lenient` named argument to `Pubspec.fromJson` to ignore format and type errors. + ## 0.1.3 - Added support for `flutter`, `issue_tracker`, `publish_to`, and `repository` diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index b79839d38..4052a7017 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -116,9 +116,35 @@ class Pubspec { } } - factory Pubspec.fromJson(Map json) => _$PubspecFromJson(json); + factory Pubspec.fromJson(Map json, {bool lenient = false}) { + lenient ??= false; + + if (lenient) { + while (json.isNotEmpty) { + // Attempting to remove top-level properties that cause parsing errors. + try { + return _$PubspecFromJson(json); + } on CheckedFromJsonException catch (e) { + if (e.map == json && json.containsKey(e.key)) { + json = Map.from(json); + json.remove(e.key); + continue; + } + rethrow; + } + } + } + + return _$PubspecFromJson(json); + } + + /// Parses source [yaml] into [Pubspec]. + /// + /// When [lenient] is set, top-level property-parsing or type cast errors are + /// ignored and `null` values are returned. + factory Pubspec.parse(String yaml, {sourceUrl, bool lenient = false}) { + lenient ??= false; - factory Pubspec.parse(String yaml, {sourceUrl}) { final item = loadYaml(yaml, sourceUrl: sourceUrl); if (item == null) { @@ -134,7 +160,7 @@ class Pubspec { } try { - return Pubspec.fromJson(item as YamlMap); + return Pubspec.fromJson(item as YamlMap, lenient: lenient); } on CheckedFromJsonException catch (error, stack) { throw parsedYamlExceptionFromError(error, stack); } diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index be7ada51c..0b48262e4 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.3 +version: 0.1.4 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 281f11374..ff3ade0a7 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -222,5 +222,91 @@ line 4, column 10: Could not parse version "silly". Unknown text at "silly". "sdk": "silly" ^^^^^^^'''); }); + + test('bad repository url', () { + expectParseThrows({ + 'name': 'foo', + 'repository': {'x': 'y'}, + }, r''' +line 3, column 16: Unsupported value for `repository`. + "repository": { + ^^''', skipTryPub: true); + }); + + test('bad issue_tracker url', () { + expectParseThrows({ + 'name': 'foo', + 'issue_tracker': {'x': 'y'}, + }, r''' +line 3, column 19: Unsupported value for `issue_tracker`. + "issue_tracker": { + ^^''', skipTryPub: true); + }); + }); + + group('lenient', () { + test('null', () { + expect(() => parse(null, lenient: true), throwsArgumentError); + }); + + test('empty string', () { + expect(() => parse('', lenient: true), throwsArgumentError); + }); + + test('name cannot be empty', () { + expect(() => parse({}, lenient: true), throwsException); + }); + + test('bad repository url', () { + final value = parse( + { + 'name': 'foo', + 'repository': {'x': 'y'}, + }, + lenient: true, + ); + expect(value.name, 'foo'); + expect(value.repository, isNull); + }); + + test('bad issue_tracker url', () { + final value = parse( + { + 'name': 'foo', + 'issue_tracker': {'x': 'y'}, + }, + lenient: true, + ); + expect(value.name, 'foo'); + expect(value.issueTracker, isNull); + }); + + test('multiple bad values', () { + final value = parse( + { + 'name': 'foo', + 'repository': {'x': 'y'}, + 'issue_tracker': {'x': 'y'}, + }, + lenient: true, + ); + expect(value.name, 'foo'); + expect(value.repository, isNull); + expect(value.issueTracker, isNull); + }); + + test('deep error throws with lenient', () { + expect( + () => parse({ + 'name': 'foo', + 'dependencies': { + 'foo': { + 'git': {'url': 1} + }, + }, + 'issue_tracker': {'x': 'y'}, + }, skipTryPub: true, lenient: true), + throwsException); + }); }); } diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 491873f34..7f8ae87ae 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -48,10 +48,15 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } } -Pubspec parse(Object content, - {bool quietOnError = false, bool skipTryPub = false}) { +Pubspec parse( + Object content, { + bool quietOnError = false, + bool skipTryPub = false, + bool lenient = false, +}) { quietOnError ??= false; skipTryPub ??= false; + lenient ??= false; final encoded = _encodeJson(content); @@ -62,7 +67,7 @@ Pubspec parse(Object content, } try { - final value = Pubspec.parse(encoded); + final value = Pubspec.parse(encoded, lenient: lenient); if (pubResult != null) { addTearDown(() { From d05aa18de781f3b90bbd0ef532aeee1ddb18ede6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20So=C3=B3s?= Date: Tue, 8 Jan 2019 16:41:57 +0100 Subject: [PATCH 0510/1215] Parse tests for repository and issue_tracker. (dart-lang/pubspec_parse#37) --- pkgs/pubspec_parse/test/parse_test.dart | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index ff3ade0a7..e00f8b0b8 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -24,6 +24,8 @@ void main() { expect(value.devDependencies, isEmpty); expect(value.dependencyOverrides, isEmpty); expect(value.flutter, isNull); + expect(value.repository, isNull); + expect(value.issueTracker, isNull); }); test('all fields set', () { @@ -37,7 +39,9 @@ void main() { 'environment': {'sdk': sdkConstraint.toString()}, 'description': 'description', 'homepage': 'homepage', - 'documentation': 'documentation' + 'documentation': 'documentation', + 'repository': 'https://github.com/example/repo', + 'issue_tracker': 'https://github.com/example/repo/issues', }); expect(value.name, 'sample'); expect(value.version, version); @@ -53,6 +57,9 @@ void main() { expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); expect(value.dependencyOverrides, isEmpty); + expect(value.repository, Uri.parse('https://github.com/example/repo')); + expect(value.issueTracker, + Uri.parse('https://github.com/example/repo/issues')); }); test('environment values can be null', () { From 54aacc45e91f6940b35a7d0724d7ab30962ea29e Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 9 Jan 2019 20:27:22 -0500 Subject: [PATCH 0511/1215] Add a GlyphSet class (dart-lang/term_glyph#7) This makes it easier for a class or function to control whether it individually uses ASCII or Unicode glyphs. --- pkgs/term_glyph/CHANGELOG.md | 8 + pkgs/term_glyph/README.md | 15 +- .../lib/src/generated/ascii_glyph_set.dart | 322 ++++++++++++++++++ .../lib/src/generated/glyph_set.dart | 220 ++++++++++++ .../top_level.dart} | 322 ++++-------------- .../lib/src/generated/unicode_glyph_set.dart | 322 ++++++++++++++++++ pkgs/term_glyph/lib/term_glyph.dart | 31 +- pkgs/term_glyph/pubspec.yaml | 5 +- pkgs/term_glyph/test/symbol_test.dart | 22 +- pkgs/term_glyph/tool/generate.dart | 133 ++++++-- 10 files changed, 1113 insertions(+), 287 deletions(-) create mode 100644 pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart create mode 100644 pkgs/term_glyph/lib/src/generated/glyph_set.dart rename pkgs/term_glyph/lib/src/{generated.dart => generated/top_level.dart} (51%) create mode 100644 pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 6ee5e6f34..7b73fc851 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.1.0 + +* Add a `GlyphSet` class that can be used to easily choose which set of glyphs + to use for a particular chunk of code. + +* Add `asciiGlyphs`, `unicodeGlyphs`, and `glyphs` getters that provide access + to `GlyphSet`s. + ## 1.0.1 * Set max SDK version to `<3.0.0`. diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md index 5459994ad..0d5b78c79 100644 --- a/pkgs/term_glyph/README.md +++ b/pkgs/term_glyph/README.md @@ -1,6 +1,7 @@ This library contains getters for useful Unicode glyphs as well as plain ASCII alternatives. It's intended to be used in command-line applications that may run -on Windows and libraries that may be used by those applications. +in places where Unicode isn't well-supported and libraries that may be used by +those applications. We recommend that you import this library with the prefix "glyph". For example: @@ -14,12 +15,12 @@ String bulletedList(List items) => ## ASCII Mode -The default Windows `cmd.exe` shell is unable to display Unicode characters, so -this package is able to transparently switch its glyphs to ASCII alternatives by -setting [the `ascii` attribute][ascii]. When this attribute is `true`, all -glyphs use ASCII characters instead. It currently defaults to `false`, although -in the future it may default to `true` for applications running on the Dart VM -on Windows. For example: +Some shells are unable to display Unicode characters, so this package is able to +transparently switch its glyphs to ASCII alternatives by setting [the `ascii` +attribute][ascii]. When this attribute is `true`, all glyphs use ASCII +characters instead. It currently defaults to `false`, although in the future it +may default to `true` for applications running on the Dart VM on Windows. For +example: [ascii]: https://www.dartdocs.org/documentation/term_glyph/latest/term_glyph/ascii.html diff --git a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart new file mode 100644 index 000000000..f470fe4a0 --- /dev/null +++ b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart @@ -0,0 +1,322 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +// Don't modify this file by hand! It's generated by tool/generate.dart. + +import 'glyph_set.dart'; + +/// A [GlyphSet] that includes only ASCII glyphs. +class AsciiGlyphSet implements GlyphSet { + const AsciiGlyphSet(); + + /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// otherwise. + String glyphOrAscii(String glyph, String alternative) => alternative; + + /// A bullet point. + /// + /// Always "*" for [this]. + String get bullet => "*"; + + /// A left-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + /// + /// Always "<" for [this]. + String get leftArrow => "<"; + + /// A right-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + /// + /// Always ">" for [this]. + String get rightArrow => ">"; + + /// An upwards-pointing arrow. + /// + /// Always "^" for [this]. + String get upArrow => "^"; + + /// A downwards-pointing arrow. + /// + /// Always "v" for [this]. + String get downArrow => "v"; + + /// A two-character left-pointing arrow. + /// + /// Always "<=" for [this]. + String get longLeftArrow => "<="; + + /// A two-character right-pointing arrow. + /// + /// Always "=>" for [this]. + String get longRightArrow => "=>"; + + /// A horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLine => "-"; + + /// A vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLine => "|"; + + /// The upper left-hand corner of a box. + /// + /// Always "," for [this]. + String get topLeftCorner => ","; + + /// The upper right-hand corner of a box. + /// + /// Always "," for [this]. + String get topRightCorner => ","; + + /// The lower left-hand corner of a box. + /// + /// Always "'" for [this]. + String get bottomLeftCorner => "'"; + + /// The lower right-hand corner of a box. + /// + /// Always "'" for [this]. + String get bottomRightCorner => "'"; + + /// An intersection of vertical and horizontal box lines. + /// + /// Always "+" for [this]. + String get cross => "+"; + + /// A horizontal box line with a vertical line going up from the middle. + /// + /// Always "+" for [this]. + String get teeUp => "+"; + + /// A horizontal box line with a vertical line going down from the middle. + /// + /// Always "+" for [this]. + String get teeDown => "+"; + + /// A vertical box line with a horizontal line going left from the middle. + /// + /// Always "+" for [this]. + String get teeLeft => "+"; + + /// A vertical box line with a horizontal line going right from the middle. + /// + /// Always "+" for [this]. + String get teeRight => "+"; + + /// The top half of a vertical box line. + /// + /// Always "'" for [this]. + String get upEnd => "'"; + + /// The bottom half of a vertical box line. + /// + /// Always "," for [this]. + String get downEnd => ","; + + /// The left half of a horizontal box line. + /// + /// Always "-" for [this]. + String get leftEnd => "-"; + + /// The right half of a horizontal box line. + /// + /// Always "-" for [this]. + String get rightEnd => "-"; + + /// A bold horizontal line that can be used to draw a box. + /// + /// Always "=" for [this]. + String get horizontalLineBold => "="; + + /// A bold vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineBold => "|"; + + /// The bold upper left-hand corner of a box. + /// + /// Always "," for [this]. + String get topLeftCornerBold => ","; + + /// The bold upper right-hand corner of a box. + /// + /// Always "," for [this]. + String get topRightCornerBold => ","; + + /// The bold lower left-hand corner of a box. + /// + /// Always "'" for [this]. + String get bottomLeftCornerBold => "'"; + + /// The bold lower right-hand corner of a box. + /// + /// Always "'" for [this]. + String get bottomRightCornerBold => "'"; + + /// An intersection of bold vertical and horizontal box lines. + /// + /// Always "+" for [this]. + String get crossBold => "+"; + + /// A bold horizontal box line with a vertical line going up from the middle. + /// + /// Always "+" for [this]. + String get teeUpBold => "+"; + + /// A bold horizontal box line with a vertical line going down from the middle. + /// + /// Always "+" for [this]. + String get teeDownBold => "+"; + + /// A bold vertical box line with a horizontal line going left from the middle. + /// + /// Always "+" for [this]. + String get teeLeftBold => "+"; + + /// A bold vertical box line with a horizontal line going right from the middle. + /// + /// Always "+" for [this]. + String get teeRightBold => "+"; + + /// The top half of a bold vertical box line. + /// + /// Always "'" for [this]. + String get upEndBold => "'"; + + /// The bottom half of a bold vertical box line. + /// + /// Always "," for [this]. + String get downEndBold => ","; + + /// The left half of a bold horizontal box line. + /// + /// Always "-" for [this]. + String get leftEndBold => "-"; + + /// The right half of a bold horizontal box line. + /// + /// Always "-" for [this]. + String get rightEndBold => "-"; + + /// A double horizontal line that can be used to draw a box. + /// + /// Always "=" for [this]. + String get horizontalLineDouble => "="; + + /// A double vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineDouble => "|"; + + /// The double upper left-hand corner of a box. + /// + /// Always "," for [this]. + String get topLeftCornerDouble => ","; + + /// The double upper right-hand corner of a box. + /// + /// Always "," for [this]. + String get topRightCornerDouble => ","; + + /// The double lower left-hand corner of a box. + /// + /// Always '"' for [this]. + String get bottomLeftCornerDouble => '"'; + + /// The double lower right-hand corner of a box. + /// + /// Always '"' for [this]. + String get bottomRightCornerDouble => '"'; + + /// An intersection of double vertical and horizontal box lines. + /// + /// Always "+" for [this]. + String get crossDouble => "+"; + + /// A double horizontal box line with a vertical line going up from the middle. + /// + /// Always "+" for [this]. + String get teeUpDouble => "+"; + + /// A double horizontal box line with a vertical line going down from the middle. + /// + /// Always "+" for [this]. + String get teeDownDouble => "+"; + + /// A double vertical box line with a horizontal line going left from the middle. + /// + /// Always "+" for [this]. + String get teeLeftDouble => "+"; + + /// A double vertical box line with a horizontal line going right from the middle. + /// + /// Always "+" for [this]. + String get teeRightDouble => "+"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineDoubleDash => "-"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineDoubleDashBold => "-"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineDoubleDash => "|"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineDoubleDashBold => "|"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineTripleDash => "-"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineTripleDashBold => "-"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineTripleDash => "|"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineTripleDashBold => "|"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineQuadrupleDash => "-"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "-" for [this]. + String get horizontalLineQuadrupleDashBold => "-"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineQuadrupleDash => "|"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "|" for [this]. + String get verticalLineQuadrupleDashBold => "|"; +} diff --git a/pkgs/term_glyph/lib/src/generated/glyph_set.dart b/pkgs/term_glyph/lib/src/generated/glyph_set.dart new file mode 100644 index 000000000..93676db9a --- /dev/null +++ b/pkgs/term_glyph/lib/src/generated/glyph_set.dart @@ -0,0 +1,220 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +// Don't modify this file by hand! It's generated by tool/generate.dart. + +/// A class that provides access to every configurable glyph. +/// +/// This is provided as a class so that individual chunks of code can choose +/// between [ascii] and [unicode] glyphs. For example: +/// +/// ```dart +/// import 'package:term_glyph/term_glyph.dart' as glyph; +/// +/// /// Adds a vertical line to the left of [text]. +/// /// +/// /// If [ascii] is `true`, this uses plain ASCII for the line. If it's +/// /// `false`, this uses Unicode characters. If it's `null`, it defaults +/// /// to [glyph.ascii]. +/// void addVerticalLine(String text, {bool ascii}) { +/// var glyphs = +/// (ascii ?? glyph.ascii) ? glyph.asciiGlyphs : glyph.unicodeGlyphs; +/// +/// return text +/// .split("\n") +/// .map((line) => "${glyphs.verticalLine} $line") +/// .join("\n"); +/// } +/// ``` +abstract class GlyphSet { + /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// otherwise. + String glyphOrAscii(String glyph, String alternative); + + /// A bullet point. + String get bullet; + + /// A left-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + String get leftArrow; + + /// A right-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + String get rightArrow; + + /// An upwards-pointing arrow. + String get upArrow; + + /// A downwards-pointing arrow. + String get downArrow; + + /// A two-character left-pointing arrow. + String get longLeftArrow; + + /// A two-character right-pointing arrow. + String get longRightArrow; + + /// A horizontal line that can be used to draw a box. + String get horizontalLine; + + /// A vertical line that can be used to draw a box. + String get verticalLine; + + /// The upper left-hand corner of a box. + String get topLeftCorner; + + /// The upper right-hand corner of a box. + String get topRightCorner; + + /// The lower left-hand corner of a box. + String get bottomLeftCorner; + + /// The lower right-hand corner of a box. + String get bottomRightCorner; + + /// An intersection of vertical and horizontal box lines. + String get cross; + + /// A horizontal box line with a vertical line going up from the middle. + String get teeUp; + + /// A horizontal box line with a vertical line going down from the middle. + String get teeDown; + + /// A vertical box line with a horizontal line going left from the middle. + String get teeLeft; + + /// A vertical box line with a horizontal line going right from the middle. + String get teeRight; + + /// The top half of a vertical box line. + String get upEnd; + + /// The bottom half of a vertical box line. + String get downEnd; + + /// The left half of a horizontal box line. + String get leftEnd; + + /// The right half of a horizontal box line. + String get rightEnd; + + /// A bold horizontal line that can be used to draw a box. + String get horizontalLineBold; + + /// A bold vertical line that can be used to draw a box. + String get verticalLineBold; + + /// The bold upper left-hand corner of a box. + String get topLeftCornerBold; + + /// The bold upper right-hand corner of a box. + String get topRightCornerBold; + + /// The bold lower left-hand corner of a box. + String get bottomLeftCornerBold; + + /// The bold lower right-hand corner of a box. + String get bottomRightCornerBold; + + /// An intersection of bold vertical and horizontal box lines. + String get crossBold; + + /// A bold horizontal box line with a vertical line going up from the middle. + String get teeUpBold; + + /// A bold horizontal box line with a vertical line going down from the middle. + String get teeDownBold; + + /// A bold vertical box line with a horizontal line going left from the middle. + String get teeLeftBold; + + /// A bold vertical box line with a horizontal line going right from the middle. + String get teeRightBold; + + /// The top half of a bold vertical box line. + String get upEndBold; + + /// The bottom half of a bold vertical box line. + String get downEndBold; + + /// The left half of a bold horizontal box line. + String get leftEndBold; + + /// The right half of a bold horizontal box line. + String get rightEndBold; + + /// A double horizontal line that can be used to draw a box. + String get horizontalLineDouble; + + /// A double vertical line that can be used to draw a box. + String get verticalLineDouble; + + /// The double upper left-hand corner of a box. + String get topLeftCornerDouble; + + /// The double upper right-hand corner of a box. + String get topRightCornerDouble; + + /// The double lower left-hand corner of a box. + String get bottomLeftCornerDouble; + + /// The double lower right-hand corner of a box. + String get bottomRightCornerDouble; + + /// An intersection of double vertical and horizontal box lines. + String get crossDouble; + + /// A double horizontal box line with a vertical line going up from the middle. + String get teeUpDouble; + + /// A double horizontal box line with a vertical line going down from the middle. + String get teeDownDouble; + + /// A double vertical box line with a horizontal line going left from the middle. + String get teeLeftDouble; + + /// A double vertical box line with a horizontal line going right from the middle. + String get teeRightDouble; + + /// A dashed horizontal line that can be used to draw a box. + String get horizontalLineDoubleDash; + + /// A bold dashed horizontal line that can be used to draw a box. + String get horizontalLineDoubleDashBold; + + /// A dashed vertical line that can be used to draw a box. + String get verticalLineDoubleDash; + + /// A bold dashed vertical line that can be used to draw a box. + String get verticalLineDoubleDashBold; + + /// A dashed horizontal line that can be used to draw a box. + String get horizontalLineTripleDash; + + /// A bold dashed horizontal line that can be used to draw a box. + String get horizontalLineTripleDashBold; + + /// A dashed vertical line that can be used to draw a box. + String get verticalLineTripleDash; + + /// A bold dashed vertical line that can be used to draw a box. + String get verticalLineTripleDashBold; + + /// A dashed horizontal line that can be used to draw a box. + String get horizontalLineQuadrupleDash; + + /// A bold dashed horizontal line that can be used to draw a box. + String get horizontalLineQuadrupleDashBold; + + /// A dashed vertical line that can be used to draw a box. + String get verticalLineQuadrupleDash; + + /// A bold dashed vertical line that can be used to draw a box. + String get verticalLineQuadrupleDashBold; +} diff --git a/pkgs/term_glyph/lib/src/generated.dart b/pkgs/term_glyph/lib/src/generated/top_level.dart similarity index 51% rename from pkgs/term_glyph/lib/src/generated.dart rename to pkgs/term_glyph/lib/src/generated/top_level.dart index e1b83d196..9475953ce 100644 --- a/pkgs/term_glyph/lib/src/generated.dart +++ b/pkgs/term_glyph/lib/src/generated/top_level.dart @@ -1,148 +1,16 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. // Don't modify this file by hand! It's generated by tool/generate.dart. -/// Whether the glyph getters return plain ASCII, as opposed to Unicode -/// characters or sequences. -/// -/// Defaults to `false`. -bool get ascii => _ascii; -var _ascii = false; -set ascii(bool value) { - _ascii = value; - if (value) { - _bullet = "*"; - _leftArrow = "<"; - _rightArrow = ">"; - _upArrow = "^"; - _downArrow = "v"; - _longLeftArrow = "<="; - _longRightArrow = "=>"; - _horizontalLine = "-"; - _verticalLine = "|"; - _topLeftCorner = ","; - _topRightCorner = ","; - _bottomLeftCorner = "'"; - _bottomRightCorner = "'"; - _cross = "+"; - _teeUp = "+"; - _teeDown = "+"; - _teeLeft = "+"; - _teeRight = "+"; - _upEnd = "'"; - _downEnd = ","; - _leftEnd = "-"; - _rightEnd = "-"; - _horizontalLineBold = "="; - _verticalLineBold = "|"; - _topLeftCornerBold = ","; - _topRightCornerBold = ","; - _bottomLeftCornerBold = "'"; - _bottomRightCornerBold = "'"; - _crossBold = "+"; - _teeUpBold = "+"; - _teeDownBold = "+"; - _teeLeftBold = "+"; - _teeRightBold = "+"; - _upEndBold = "'"; - _downEndBold = ","; - _leftEndBold = "-"; - _rightEndBold = "-"; - _horizontalLineDouble = "="; - _verticalLineDouble = "|"; - _topLeftCornerDouble = ","; - _topRightCornerDouble = ","; - _bottomLeftCornerDouble = '"'; - _bottomRightCornerDouble = '"'; - _crossDouble = "+"; - _teeUpDouble = "+"; - _teeDownDouble = "+"; - _teeLeftDouble = "+"; - _teeRightDouble = "+"; - _horizontalLineDoubleDash = "-"; - _horizontalLineDoubleDashBold = "-"; - _verticalLineDoubleDash = "|"; - _verticalLineDoubleDashBold = "|"; - _horizontalLineTripleDash = "-"; - _horizontalLineTripleDashBold = "-"; - _verticalLineTripleDash = "|"; - _verticalLineTripleDashBold = "|"; - _horizontalLineQuadrupleDash = "-"; - _horizontalLineQuadrupleDashBold = "-"; - _verticalLineQuadrupleDash = "|"; - _verticalLineQuadrupleDashBold = "|"; - } else { - _bullet = "•"; - _leftArrow = "←"; - _rightArrow = "→"; - _upArrow = "↑"; - _downArrow = "↓"; - _longLeftArrow = "◀━"; - _longRightArrow = "━▶"; - _horizontalLine = "─"; - _verticalLine = "│"; - _topLeftCorner = "┌"; - _topRightCorner = "┐"; - _bottomLeftCorner = "└"; - _bottomRightCorner = "┘"; - _cross = "┼"; - _teeUp = "┴"; - _teeDown = "┬"; - _teeLeft = "┤"; - _teeRight = "├"; - _upEnd = "╵"; - _downEnd = "╷"; - _leftEnd = "╴"; - _rightEnd = "╶"; - _horizontalLineBold = "━"; - _verticalLineBold = "┃"; - _topLeftCornerBold = "┏"; - _topRightCornerBold = "┓"; - _bottomLeftCornerBold = "┗"; - _bottomRightCornerBold = "┛"; - _crossBold = "╋"; - _teeUpBold = "┻"; - _teeDownBold = "┳"; - _teeLeftBold = "┫"; - _teeRightBold = "┣"; - _upEndBold = "╹"; - _downEndBold = "╻"; - _leftEndBold = "╸"; - _rightEndBold = "╺"; - _horizontalLineDouble = "═"; - _verticalLineDouble = "║"; - _topLeftCornerDouble = "╔"; - _topRightCornerDouble = "╗"; - _bottomLeftCornerDouble = "╚"; - _bottomRightCornerDouble = "╝"; - _crossDouble = "╬"; - _teeUpDouble = "╩"; - _teeDownDouble = "╦"; - _teeLeftDouble = "╣"; - _teeRightDouble = "╠"; - _horizontalLineDoubleDash = "╌"; - _horizontalLineDoubleDashBold = "╍"; - _verticalLineDoubleDash = "╎"; - _verticalLineDoubleDashBold = "╏"; - _horizontalLineTripleDash = "┄"; - _horizontalLineTripleDashBold = "┅"; - _verticalLineTripleDash = "┆"; - _verticalLineTripleDashBold = "┇"; - _horizontalLineQuadrupleDash = "┈"; - _horizontalLineQuadrupleDashBold = "┉"; - _verticalLineQuadrupleDash = "┊"; - _verticalLineQuadrupleDashBold = "┋"; - } -} +import '../../term_glyph.dart' as glyph; /// A bullet point. /// /// If [ascii] is `false`, this is "•". If it's `true`, this is /// "*" instead. -String get bullet => _bullet; -var _bullet = "•"; +String get bullet => glyph.glyphs.bullet; /// A left-pointing arrow. /// @@ -151,8 +19,7 @@ var _bullet = "•"; /// /// If [ascii] is `false`, this is "←". If it's `true`, this is /// "<" instead. -String get leftArrow => _leftArrow; -var _leftArrow = "←"; +String get leftArrow => glyph.glyphs.leftArrow; /// A right-pointing arrow. /// @@ -161,404 +28,353 @@ var _leftArrow = "←"; /// /// If [ascii] is `false`, this is "→". If it's `true`, this is /// ">" instead. -String get rightArrow => _rightArrow; -var _rightArrow = "→"; +String get rightArrow => glyph.glyphs.rightArrow; /// An upwards-pointing arrow. /// /// If [ascii] is `false`, this is "↑". If it's `true`, this is /// "^" instead. -String get upArrow => _upArrow; -var _upArrow = "↑"; +String get upArrow => glyph.glyphs.upArrow; /// A downwards-pointing arrow. /// /// If [ascii] is `false`, this is "↓". If it's `true`, this is /// "v" instead. -String get downArrow => _downArrow; -var _downArrow = "↓"; +String get downArrow => glyph.glyphs.downArrow; /// A two-character left-pointing arrow. /// /// If [ascii] is `false`, this is "◀━". If it's `true`, this is /// "<=" instead. -String get longLeftArrow => _longLeftArrow; -var _longLeftArrow = "◀━"; +String get longLeftArrow => glyph.glyphs.longLeftArrow; /// A two-character right-pointing arrow. /// /// If [ascii] is `false`, this is "━▶". If it's `true`, this is /// "=>" instead. -String get longRightArrow => _longRightArrow; -var _longRightArrow = "━▶"; +String get longRightArrow => glyph.glyphs.longRightArrow; /// A horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "─". If it's `true`, this is /// "-" instead. -String get horizontalLine => _horizontalLine; -var _horizontalLine = "─"; +String get horizontalLine => glyph.glyphs.horizontalLine; /// A vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "│". If it's `true`, this is /// "|" instead. -String get verticalLine => _verticalLine; -var _verticalLine = "│"; +String get verticalLine => glyph.glyphs.verticalLine; /// The upper left-hand corner of a box. /// /// If [ascii] is `false`, this is "┌". If it's `true`, this is /// "," instead. -String get topLeftCorner => _topLeftCorner; -var _topLeftCorner = "┌"; +String get topLeftCorner => glyph.glyphs.topLeftCorner; /// The upper right-hand corner of a box. /// /// If [ascii] is `false`, this is "┐". If it's `true`, this is /// "," instead. -String get topRightCorner => _topRightCorner; -var _topRightCorner = "┐"; +String get topRightCorner => glyph.glyphs.topRightCorner; /// The lower left-hand corner of a box. /// /// If [ascii] is `false`, this is "└". If it's `true`, this is /// "'" instead. -String get bottomLeftCorner => _bottomLeftCorner; -var _bottomLeftCorner = "└"; +String get bottomLeftCorner => glyph.glyphs.bottomLeftCorner; /// The lower right-hand corner of a box. /// /// If [ascii] is `false`, this is "┘". If it's `true`, this is /// "'" instead. -String get bottomRightCorner => _bottomRightCorner; -var _bottomRightCorner = "┘"; +String get bottomRightCorner => glyph.glyphs.bottomRightCorner; /// An intersection of vertical and horizontal box lines. /// /// If [ascii] is `false`, this is "┼". If it's `true`, this is /// "+" instead. -String get cross => _cross; -var _cross = "┼"; +String get cross => glyph.glyphs.cross; /// A horizontal box line with a vertical line going up from the middle. /// /// If [ascii] is `false`, this is "┴". If it's `true`, this is /// "+" instead. -String get teeUp => _teeUp; -var _teeUp = "┴"; +String get teeUp => glyph.glyphs.teeUp; /// A horizontal box line with a vertical line going down from the middle. /// /// If [ascii] is `false`, this is "┬". If it's `true`, this is /// "+" instead. -String get teeDown => _teeDown; -var _teeDown = "┬"; +String get teeDown => glyph.glyphs.teeDown; /// A vertical box line with a horizontal line going left from the middle. /// /// If [ascii] is `false`, this is "┤". If it's `true`, this is /// "+" instead. -String get teeLeft => _teeLeft; -var _teeLeft = "┤"; +String get teeLeft => glyph.glyphs.teeLeft; /// A vertical box line with a horizontal line going right from the middle. /// /// If [ascii] is `false`, this is "├". If it's `true`, this is /// "+" instead. -String get teeRight => _teeRight; -var _teeRight = "├"; +String get teeRight => glyph.glyphs.teeRight; /// The top half of a vertical box line. /// /// If [ascii] is `false`, this is "╵". If it's `true`, this is /// "'" instead. -String get upEnd => _upEnd; -var _upEnd = "╵"; +String get upEnd => glyph.glyphs.upEnd; /// The bottom half of a vertical box line. /// /// If [ascii] is `false`, this is "╷". If it's `true`, this is /// "," instead. -String get downEnd => _downEnd; -var _downEnd = "╷"; +String get downEnd => glyph.glyphs.downEnd; /// The left half of a horizontal box line. /// /// If [ascii] is `false`, this is "╴". If it's `true`, this is /// "-" instead. -String get leftEnd => _leftEnd; -var _leftEnd = "╴"; +String get leftEnd => glyph.glyphs.leftEnd; /// The right half of a horizontal box line. /// /// If [ascii] is `false`, this is "╶". If it's `true`, this is /// "-" instead. -String get rightEnd => _rightEnd; -var _rightEnd = "╶"; +String get rightEnd => glyph.glyphs.rightEnd; /// A bold horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "━". If it's `true`, this is /// "=" instead. -String get horizontalLineBold => _horizontalLineBold; -var _horizontalLineBold = "━"; +String get horizontalLineBold => glyph.glyphs.horizontalLineBold; /// A bold vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┃". If it's `true`, this is /// "|" instead. -String get verticalLineBold => _verticalLineBold; -var _verticalLineBold = "┃"; +String get verticalLineBold => glyph.glyphs.verticalLineBold; /// The bold upper left-hand corner of a box. /// /// If [ascii] is `false`, this is "┏". If it's `true`, this is /// "," instead. -String get topLeftCornerBold => _topLeftCornerBold; -var _topLeftCornerBold = "┏"; +String get topLeftCornerBold => glyph.glyphs.topLeftCornerBold; /// The bold upper right-hand corner of a box. /// /// If [ascii] is `false`, this is "┓". If it's `true`, this is /// "," instead. -String get topRightCornerBold => _topRightCornerBold; -var _topRightCornerBold = "┓"; +String get topRightCornerBold => glyph.glyphs.topRightCornerBold; /// The bold lower left-hand corner of a box. /// /// If [ascii] is `false`, this is "┗". If it's `true`, this is /// "'" instead. -String get bottomLeftCornerBold => _bottomLeftCornerBold; -var _bottomLeftCornerBold = "┗"; +String get bottomLeftCornerBold => glyph.glyphs.bottomLeftCornerBold; /// The bold lower right-hand corner of a box. /// /// If [ascii] is `false`, this is "┛". If it's `true`, this is /// "'" instead. -String get bottomRightCornerBold => _bottomRightCornerBold; -var _bottomRightCornerBold = "┛"; +String get bottomRightCornerBold => glyph.glyphs.bottomRightCornerBold; /// An intersection of bold vertical and horizontal box lines. /// /// If [ascii] is `false`, this is "╋". If it's `true`, this is /// "+" instead. -String get crossBold => _crossBold; -var _crossBold = "╋"; +String get crossBold => glyph.glyphs.crossBold; /// A bold horizontal box line with a vertical line going up from the middle. /// /// If [ascii] is `false`, this is "┻". If it's `true`, this is /// "+" instead. -String get teeUpBold => _teeUpBold; -var _teeUpBold = "┻"; +String get teeUpBold => glyph.glyphs.teeUpBold; /// A bold horizontal box line with a vertical line going down from the middle. /// /// If [ascii] is `false`, this is "┳". If it's `true`, this is /// "+" instead. -String get teeDownBold => _teeDownBold; -var _teeDownBold = "┳"; +String get teeDownBold => glyph.glyphs.teeDownBold; /// A bold vertical box line with a horizontal line going left from the middle. /// /// If [ascii] is `false`, this is "┫". If it's `true`, this is /// "+" instead. -String get teeLeftBold => _teeLeftBold; -var _teeLeftBold = "┫"; +String get teeLeftBold => glyph.glyphs.teeLeftBold; /// A bold vertical box line with a horizontal line going right from the middle. /// /// If [ascii] is `false`, this is "┣". If it's `true`, this is /// "+" instead. -String get teeRightBold => _teeRightBold; -var _teeRightBold = "┣"; +String get teeRightBold => glyph.glyphs.teeRightBold; /// The top half of a bold vertical box line. /// /// If [ascii] is `false`, this is "╹". If it's `true`, this is /// "'" instead. -String get upEndBold => _upEndBold; -var _upEndBold = "╹"; +String get upEndBold => glyph.glyphs.upEndBold; /// The bottom half of a bold vertical box line. /// /// If [ascii] is `false`, this is "╻". If it's `true`, this is /// "," instead. -String get downEndBold => _downEndBold; -var _downEndBold = "╻"; +String get downEndBold => glyph.glyphs.downEndBold; /// The left half of a bold horizontal box line. /// /// If [ascii] is `false`, this is "╸". If it's `true`, this is /// "-" instead. -String get leftEndBold => _leftEndBold; -var _leftEndBold = "╸"; +String get leftEndBold => glyph.glyphs.leftEndBold; /// The right half of a bold horizontal box line. /// /// If [ascii] is `false`, this is "╺". If it's `true`, this is /// "-" instead. -String get rightEndBold => _rightEndBold; -var _rightEndBold = "╺"; +String get rightEndBold => glyph.glyphs.rightEndBold; /// A double horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "═". If it's `true`, this is /// "=" instead. -String get horizontalLineDouble => _horizontalLineDouble; -var _horizontalLineDouble = "═"; +String get horizontalLineDouble => glyph.glyphs.horizontalLineDouble; /// A double vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "║". If it's `true`, this is /// "|" instead. -String get verticalLineDouble => _verticalLineDouble; -var _verticalLineDouble = "║"; +String get verticalLineDouble => glyph.glyphs.verticalLineDouble; /// The double upper left-hand corner of a box. /// /// If [ascii] is `false`, this is "╔". If it's `true`, this is /// "," instead. -String get topLeftCornerDouble => _topLeftCornerDouble; -var _topLeftCornerDouble = "╔"; +String get topLeftCornerDouble => glyph.glyphs.topLeftCornerDouble; /// The double upper right-hand corner of a box. /// /// If [ascii] is `false`, this is "╗". If it's `true`, this is /// "," instead. -String get topRightCornerDouble => _topRightCornerDouble; -var _topRightCornerDouble = "╗"; +String get topRightCornerDouble => glyph.glyphs.topRightCornerDouble; /// The double lower left-hand corner of a box. /// /// If [ascii] is `false`, this is "╚". If it's `true`, this is /// """ instead. -String get bottomLeftCornerDouble => _bottomLeftCornerDouble; -var _bottomLeftCornerDouble = "╚"; +String get bottomLeftCornerDouble => glyph.glyphs.bottomLeftCornerDouble; /// The double lower right-hand corner of a box. /// /// If [ascii] is `false`, this is "╝". If it's `true`, this is /// """ instead. -String get bottomRightCornerDouble => _bottomRightCornerDouble; -var _bottomRightCornerDouble = "╝"; +String get bottomRightCornerDouble => glyph.glyphs.bottomRightCornerDouble; /// An intersection of double vertical and horizontal box lines. /// /// If [ascii] is `false`, this is "╬". If it's `true`, this is /// "+" instead. -String get crossDouble => _crossDouble; -var _crossDouble = "╬"; +String get crossDouble => glyph.glyphs.crossDouble; /// A double horizontal box line with a vertical line going up from the middle. /// /// If [ascii] is `false`, this is "╩". If it's `true`, this is /// "+" instead. -String get teeUpDouble => _teeUpDouble; -var _teeUpDouble = "╩"; +String get teeUpDouble => glyph.glyphs.teeUpDouble; /// A double horizontal box line with a vertical line going down from the middle. /// /// If [ascii] is `false`, this is "╦". If it's `true`, this is /// "+" instead. -String get teeDownDouble => _teeDownDouble; -var _teeDownDouble = "╦"; +String get teeDownDouble => glyph.glyphs.teeDownDouble; /// A double vertical box line with a horizontal line going left from the middle. /// /// If [ascii] is `false`, this is "╣". If it's `true`, this is /// "+" instead. -String get teeLeftDouble => _teeLeftDouble; -var _teeLeftDouble = "╣"; +String get teeLeftDouble => glyph.glyphs.teeLeftDouble; /// A double vertical box line with a horizontal line going right from the middle. /// /// If [ascii] is `false`, this is "╠". If it's `true`, this is /// "+" instead. -String get teeRightDouble => _teeRightDouble; -var _teeRightDouble = "╠"; +String get teeRightDouble => glyph.glyphs.teeRightDouble; /// A dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "╌". If it's `true`, this is /// "-" instead. -String get horizontalLineDoubleDash => _horizontalLineDoubleDash; -var _horizontalLineDoubleDash = "╌"; +String get horizontalLineDoubleDash => glyph.glyphs.horizontalLineDoubleDash; /// A bold dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "╍". If it's `true`, this is /// "-" instead. -String get horizontalLineDoubleDashBold => _horizontalLineDoubleDashBold; -var _horizontalLineDoubleDashBold = "╍"; +String get horizontalLineDoubleDashBold => + glyph.glyphs.horizontalLineDoubleDashBold; /// A dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "╎". If it's `true`, this is /// "|" instead. -String get verticalLineDoubleDash => _verticalLineDoubleDash; -var _verticalLineDoubleDash = "╎"; +String get verticalLineDoubleDash => glyph.glyphs.verticalLineDoubleDash; /// A bold dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "╏". If it's `true`, this is /// "|" instead. -String get verticalLineDoubleDashBold => _verticalLineDoubleDashBold; -var _verticalLineDoubleDashBold = "╏"; +String get verticalLineDoubleDashBold => + glyph.glyphs.verticalLineDoubleDashBold; /// A dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┄". If it's `true`, this is /// "-" instead. -String get horizontalLineTripleDash => _horizontalLineTripleDash; -var _horizontalLineTripleDash = "┄"; +String get horizontalLineTripleDash => glyph.glyphs.horizontalLineTripleDash; /// A bold dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┅". If it's `true`, this is /// "-" instead. -String get horizontalLineTripleDashBold => _horizontalLineTripleDashBold; -var _horizontalLineTripleDashBold = "┅"; +String get horizontalLineTripleDashBold => + glyph.glyphs.horizontalLineTripleDashBold; /// A dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┆". If it's `true`, this is /// "|" instead. -String get verticalLineTripleDash => _verticalLineTripleDash; -var _verticalLineTripleDash = "┆"; +String get verticalLineTripleDash => glyph.glyphs.verticalLineTripleDash; /// A bold dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┇". If it's `true`, this is /// "|" instead. -String get verticalLineTripleDashBold => _verticalLineTripleDashBold; -var _verticalLineTripleDashBold = "┇"; +String get verticalLineTripleDashBold => + glyph.glyphs.verticalLineTripleDashBold; /// A dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┈". If it's `true`, this is /// "-" instead. -String get horizontalLineQuadrupleDash => _horizontalLineQuadrupleDash; -var _horizontalLineQuadrupleDash = "┈"; +String get horizontalLineQuadrupleDash => + glyph.glyphs.horizontalLineQuadrupleDash; /// A bold dashed horizontal line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┉". If it's `true`, this is /// "-" instead. -String get horizontalLineQuadrupleDashBold => _horizontalLineQuadrupleDashBold; -var _horizontalLineQuadrupleDashBold = "┉"; +String get horizontalLineQuadrupleDashBold => + glyph.glyphs.horizontalLineQuadrupleDashBold; /// A dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┊". If it's `true`, this is /// "|" instead. -String get verticalLineQuadrupleDash => _verticalLineQuadrupleDash; -var _verticalLineQuadrupleDash = "┊"; +String get verticalLineQuadrupleDash => glyph.glyphs.verticalLineQuadrupleDash; /// A bold dashed vertical line that can be used to draw a box. /// /// If [ascii] is `false`, this is "┋". If it's `true`, this is /// "|" instead. -String get verticalLineQuadrupleDashBold => _verticalLineQuadrupleDashBold; -var _verticalLineQuadrupleDashBold = "┋"; +String get verticalLineQuadrupleDashBold => + glyph.glyphs.verticalLineQuadrupleDashBold; diff --git a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart new file mode 100644 index 000000000..4e54068ac --- /dev/null +++ b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart @@ -0,0 +1,322 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +// Don't modify this file by hand! It's generated by tool/generate.dart. + +import 'glyph_set.dart'; + +/// A [GlyphSet] that includes only Unicode glyphs. +class UnicodeGlyphSet implements GlyphSet { + const UnicodeGlyphSet(); + + /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// otherwise. + String glyphOrAscii(String glyph, String alternative) => glyph; + + /// A bullet point. + /// + /// Always "•" for [this]. + String get bullet => "•"; + + /// A left-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + /// + /// Always "←" for [this]. + String get leftArrow => "←"; + + /// A right-pointing arrow. + /// + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some + /// terminal fonts, and should generally be surrounding by spaces. + /// + /// Always "→" for [this]. + String get rightArrow => "→"; + + /// An upwards-pointing arrow. + /// + /// Always "↑" for [this]. + String get upArrow => "↑"; + + /// A downwards-pointing arrow. + /// + /// Always "↓" for [this]. + String get downArrow => "↓"; + + /// A two-character left-pointing arrow. + /// + /// Always "◀━" for [this]. + String get longLeftArrow => "◀━"; + + /// A two-character right-pointing arrow. + /// + /// Always "━▶" for [this]. + String get longRightArrow => "━▶"; + + /// A horizontal line that can be used to draw a box. + /// + /// Always "─" for [this]. + String get horizontalLine => "─"; + + /// A vertical line that can be used to draw a box. + /// + /// Always "│" for [this]. + String get verticalLine => "│"; + + /// The upper left-hand corner of a box. + /// + /// Always "┌" for [this]. + String get topLeftCorner => "┌"; + + /// The upper right-hand corner of a box. + /// + /// Always "┐" for [this]. + String get topRightCorner => "┐"; + + /// The lower left-hand corner of a box. + /// + /// Always "└" for [this]. + String get bottomLeftCorner => "└"; + + /// The lower right-hand corner of a box. + /// + /// Always "┘" for [this]. + String get bottomRightCorner => "┘"; + + /// An intersection of vertical and horizontal box lines. + /// + /// Always "┼" for [this]. + String get cross => "┼"; + + /// A horizontal box line with a vertical line going up from the middle. + /// + /// Always "┴" for [this]. + String get teeUp => "┴"; + + /// A horizontal box line with a vertical line going down from the middle. + /// + /// Always "┬" for [this]. + String get teeDown => "┬"; + + /// A vertical box line with a horizontal line going left from the middle. + /// + /// Always "┤" for [this]. + String get teeLeft => "┤"; + + /// A vertical box line with a horizontal line going right from the middle. + /// + /// Always "├" for [this]. + String get teeRight => "├"; + + /// The top half of a vertical box line. + /// + /// Always "╵" for [this]. + String get upEnd => "╵"; + + /// The bottom half of a vertical box line. + /// + /// Always "╷" for [this]. + String get downEnd => "╷"; + + /// The left half of a horizontal box line. + /// + /// Always "╴" for [this]. + String get leftEnd => "╴"; + + /// The right half of a horizontal box line. + /// + /// Always "╶" for [this]. + String get rightEnd => "╶"; + + /// A bold horizontal line that can be used to draw a box. + /// + /// Always "━" for [this]. + String get horizontalLineBold => "━"; + + /// A bold vertical line that can be used to draw a box. + /// + /// Always "┃" for [this]. + String get verticalLineBold => "┃"; + + /// The bold upper left-hand corner of a box. + /// + /// Always "┏" for [this]. + String get topLeftCornerBold => "┏"; + + /// The bold upper right-hand corner of a box. + /// + /// Always "┓" for [this]. + String get topRightCornerBold => "┓"; + + /// The bold lower left-hand corner of a box. + /// + /// Always "┗" for [this]. + String get bottomLeftCornerBold => "┗"; + + /// The bold lower right-hand corner of a box. + /// + /// Always "┛" for [this]. + String get bottomRightCornerBold => "┛"; + + /// An intersection of bold vertical and horizontal box lines. + /// + /// Always "╋" for [this]. + String get crossBold => "╋"; + + /// A bold horizontal box line with a vertical line going up from the middle. + /// + /// Always "┻" for [this]. + String get teeUpBold => "┻"; + + /// A bold horizontal box line with a vertical line going down from the middle. + /// + /// Always "┳" for [this]. + String get teeDownBold => "┳"; + + /// A bold vertical box line with a horizontal line going left from the middle. + /// + /// Always "┫" for [this]. + String get teeLeftBold => "┫"; + + /// A bold vertical box line with a horizontal line going right from the middle. + /// + /// Always "┣" for [this]. + String get teeRightBold => "┣"; + + /// The top half of a bold vertical box line. + /// + /// Always "╹" for [this]. + String get upEndBold => "╹"; + + /// The bottom half of a bold vertical box line. + /// + /// Always "╻" for [this]. + String get downEndBold => "╻"; + + /// The left half of a bold horizontal box line. + /// + /// Always "╸" for [this]. + String get leftEndBold => "╸"; + + /// The right half of a bold horizontal box line. + /// + /// Always "╺" for [this]. + String get rightEndBold => "╺"; + + /// A double horizontal line that can be used to draw a box. + /// + /// Always "═" for [this]. + String get horizontalLineDouble => "═"; + + /// A double vertical line that can be used to draw a box. + /// + /// Always "║" for [this]. + String get verticalLineDouble => "║"; + + /// The double upper left-hand corner of a box. + /// + /// Always "╔" for [this]. + String get topLeftCornerDouble => "╔"; + + /// The double upper right-hand corner of a box. + /// + /// Always "╗" for [this]. + String get topRightCornerDouble => "╗"; + + /// The double lower left-hand corner of a box. + /// + /// Always "╚" for [this]. + String get bottomLeftCornerDouble => "╚"; + + /// The double lower right-hand corner of a box. + /// + /// Always "╝" for [this]. + String get bottomRightCornerDouble => "╝"; + + /// An intersection of double vertical and horizontal box lines. + /// + /// Always "╬" for [this]. + String get crossDouble => "╬"; + + /// A double horizontal box line with a vertical line going up from the middle. + /// + /// Always "╩" for [this]. + String get teeUpDouble => "╩"; + + /// A double horizontal box line with a vertical line going down from the middle. + /// + /// Always "╦" for [this]. + String get teeDownDouble => "╦"; + + /// A double vertical box line with a horizontal line going left from the middle. + /// + /// Always "╣" for [this]. + String get teeLeftDouble => "╣"; + + /// A double vertical box line with a horizontal line going right from the middle. + /// + /// Always "╠" for [this]. + String get teeRightDouble => "╠"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "╌" for [this]. + String get horizontalLineDoubleDash => "╌"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "╍" for [this]. + String get horizontalLineDoubleDashBold => "╍"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "╎" for [this]. + String get verticalLineDoubleDash => "╎"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "╏" for [this]. + String get verticalLineDoubleDashBold => "╏"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "┄" for [this]. + String get horizontalLineTripleDash => "┄"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "┅" for [this]. + String get horizontalLineTripleDashBold => "┅"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "┆" for [this]. + String get verticalLineTripleDash => "┆"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "┇" for [this]. + String get verticalLineTripleDashBold => "┇"; + + /// A dashed horizontal line that can be used to draw a box. + /// + /// Always "┈" for [this]. + String get horizontalLineQuadrupleDash => "┈"; + + /// A bold dashed horizontal line that can be used to draw a box. + /// + /// Always "┉" for [this]. + String get horizontalLineQuadrupleDashBold => "┉"; + + /// A dashed vertical line that can be used to draw a box. + /// + /// Always "┊" for [this]. + String get verticalLineQuadrupleDash => "┊"; + + /// A bold dashed vertical line that can be used to draw a box. + /// + /// Always "┋" for [this]. + String get verticalLineQuadrupleDashBold => "┋"; +} diff --git a/pkgs/term_glyph/lib/term_glyph.dart b/pkgs/term_glyph/lib/term_glyph.dart index 8582175ed..57c762e55 100644 --- a/pkgs/term_glyph/lib/term_glyph.dart +++ b/pkgs/term_glyph/lib/term_glyph.dart @@ -2,11 +2,36 @@ // 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. -export 'src/generated.dart'; +export 'src/generated/glyph_set.dart'; +export 'src/generated/top_level.dart'; -import 'src/generated.dart'; +import 'src/generated/ascii_glyph_set.dart'; +import 'src/generated/glyph_set.dart'; +import 'src/generated/unicode_glyph_set.dart'; + +/// A [GlyphSet] that always returns ASCII glyphs. +const GlyphSet asciiGlyphs = const AsciiGlyphSet(); + +/// A [GlyphSet] that always returns Unicode glyphs. +const GlyphSet unicodeGlyphs = const UnicodeGlyphSet(); + +/// Returns [asciiGlyphs] if [ascii] is `true` or [unicodeGlyphs] otherwise. +/// +/// Returns [unicodeGlyphs] by default. +GlyphSet get glyphs => _glyphs; +GlyphSet _glyphs = unicodeGlyphs; + +/// Whether the glyph getters return plain ASCII, as opposed to Unicode +/// characters or sequences. +/// +/// Defaults to `false`. +bool get ascii => glyphs == asciiGlyphs; + +set ascii(bool value) { + _glyphs = value ? asciiGlyphs : unicodeGlyphs; +} /// Returns [glyph] if Unicode glyph are allowed, and [alternative] if they /// aren't. String glyphOrAscii(String glyph, String alternative) => - ascii ? alternative : glyph; + glyphs.glyphOrAscii(glyph, alternative); diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 4cbaeb4be..29ea7d6b6 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,7 +1,7 @@ name: term_glyph -version: 1.0.2-dev +version: 1.1.0 -description: Useful glyphs and Windows-safe equivalents. +description: Useful Unicode glyphs and ASCII substitutes. author: Dart Team homepage: https://github.com/dart-lang/term_glyph @@ -11,4 +11,5 @@ environment: dev_dependencies: csv: '>=3.0.0 <5.0.0' dart_style: '>=0.2.0 <2.0.0' + meta: '>=0.9.0 <2.0.0' test: '>=0.12.0 <2.0.0' diff --git a/pkgs/term_glyph/test/symbol_test.dart b/pkgs/term_glyph/test/symbol_test.dart index e3f94e575..1e665e80c 100644 --- a/pkgs/term_glyph/test/symbol_test.dart +++ b/pkgs/term_glyph/test/symbol_test.dart @@ -12,7 +12,7 @@ void main() { glyph.ascii = false; }); - test("glyphs return Unicode versions", () { + test("glyph getters return Unicode versions", () { expect(glyph.topLeftCorner, equals("┌")); expect(glyph.teeUpBold, equals("┻")); expect(glyph.longLeftArrow, equals("◀━")); @@ -21,6 +21,16 @@ void main() { test("glyphOrAscii returns the first argument", () { expect(glyph.glyphOrAscii("A", "B"), equals("A")); }); + + test("glyphs returns unicodeGlyphs", () { + expect(glyph.glyphs, equals(glyph.unicodeGlyphs)); + }); + + test("asciiGlyphs still returns ASCII characters", () { + expect(glyph.asciiGlyphs.topLeftCorner, equals(",")); + expect(glyph.asciiGlyphs.teeUpBold, equals("+")); + expect(glyph.asciiGlyphs.longLeftArrow, equals("<=")); + }); }); group("with ascii = true", () { @@ -37,5 +47,15 @@ void main() { test("glyphOrAscii returns the second argument", () { expect(glyph.glyphOrAscii("A", "B"), equals("B")); }); + + test("glyphs returns asciiGlyphs", () { + expect(glyph.glyphs, equals(glyph.asciiGlyphs)); + }); + + test("unicodeGlyphs still returns Unicode characters", () { + expect(glyph.unicodeGlyphs.topLeftCorner, equals("┌")); + expect(glyph.unicodeGlyphs.teeUpBold, equals("┻")); + expect(glyph.unicodeGlyphs.longLeftArrow, equals("◀━")); + }); }); } diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index aa05c13fa..b4b3e431c 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:csv/csv.dart'; +import 'package:meta/meta.dart'; void main() { var csv = new CsvCodec(eol: "\n"); @@ -13,36 +14,130 @@ void main() { // Remove comments and empty lines. data.removeWhere((row) => row.length < 3); - var file = new File("lib/src/generated.dart").openSync(mode: FileMode.write); - file.writeStringSync(""" - // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file + new Directory("lib/src/generated").createSync(recursive: true); + + _writeGlyphSetInterface(data); + _writeGlyphSet(data, ascii: false); + _writeGlyphSet(data, ascii: true); + _writeTopLevel(data); + + var result = Process.runSync( + "pub", ["run", "dart_style:format", "-w", "lib/src/generated"]); + print(result.stderr); + exit(result.exitCode); +} + +/// Writes `lib/src/generated/glyph_set.dart`. +void _writeGlyphSetInterface(List data) { + var file = new File("lib/src/generated/glyph_set.dart") + .openSync(mode: FileMode.write); + file.writeStringSync(r""" + // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. // Don't modify this file by hand! It's generated by tool/generate.dart. - /// Whether the glyph getters return plain ASCII, as opposed to Unicode - /// characters or sequences. + /// A class that provides access to every configurable glyph. + /// + /// This is provided as a class so that individual chunks of code can choose + /// between [ascii] and [unicode] glyphs. For example: /// - /// Defaults to `false`. - bool get ascii => _ascii; - var _ascii = false; - set ascii(bool value) { - _ascii = value; - if (value) { + /// ```dart + /// import 'package:term_glyph/term_glyph.dart' as glyph; + /// + /// /// Adds a vertical line to the left of [text]. + /// /// + /// /// If [unicode] is `true`, this uses Unicode for the line. If it's + /// /// `false`, this uses plain ASCII characters. If it's `null`, it + /// /// defaults to [glyph.ascii]. + /// void addVerticalLine(String text, {bool unicode}) { + /// var glyphs = + /// (unicode ?? !glyph.ascii) ? glyph.unicodeGlyphs : glyph.asciiGlyphs; + /// + /// return text + /// .split("\n") + /// .map((line) => "${glyphs.verticalLine} $line") + /// .join("\n"); + /// } + /// ``` + abstract class GlyphSet { + /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// otherwise. + String glyphOrAscii(String glyph, String alternative); """); for (var glyph in data) { - file.writeStringSync("_${glyph[0]} = ${_quote(glyph[2])};"); + for (var line in glyph[3].split("\n")) { + file.writeStringSync("/// $line\n"); + } + + file.writeStringSync("String get ${glyph[0]};"); } - file.writeStringSync("} else {"); + file.writeStringSync("}"); + file.closeSync(); +} + +/// Writes `lib/src/generated/${prefix.toLowerCase()}_glyph_set.dart`. +/// +/// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes +/// the Unicode glyph set. +void _writeGlyphSet(List data, {@required bool ascii}) { + var file = new File( + "lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart") + .openSync(mode: FileMode.write); + + var className = "${ascii ? "Ascii" : "Unicode"}GlyphSet"; + file.writeStringSync(""" + // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file + // 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. + + // Don't modify this file by hand! It's generated by tool/generate.dart. + + import 'glyph_set.dart'; + + /// A [GlyphSet] that includes only ${ascii ? "ASCII" : "Unicode"} glyphs. + class $className implements GlyphSet { + const $className(); + /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// otherwise. + String glyphOrAscii(String glyph, String alternative) => + ${ascii ? "alternative" : "glyph"}; + """); + var index = ascii ? 2 : 1; for (var glyph in data) { - file.writeStringSync("_${glyph[0]} = ${_quote(glyph[1])};"); + for (var line in glyph[3].split("\n")) { + file.writeStringSync("/// $line\n"); + } + + file.writeStringSync(""" + /// + /// Always ${_quote(glyph[index])} for [this]. + String get ${glyph[0]} => ${_quote(glyph[index])}; + """); } - file.writeStringSync("}}"); + file.writeStringSync("}"); + file.closeSync(); +} + +/// Writes `lib/src/generated/top_level.dart`. +void _writeTopLevel(List data) { + var file = new File("lib/src/generated/top_level.dart") + .openSync(mode: FileMode.write); + + file.writeStringSync(""" + // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file + // 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. + + // Don't modify this file by hand! It's generated by tool/generate.dart. + + import '../../term_glyph.dart' as glyph; + """); for (var glyph in data) { for (var line in glyph[3].split("\n")) { @@ -53,15 +148,11 @@ void main() { /// /// If [ascii] is `false`, this is "${glyph[1]}". If it's `true`, this is /// "${glyph[2]}" instead. - String get ${glyph[0]} => _${glyph[0]}; - var _${glyph[0]} = ${_quote(glyph[1])}; + String get ${glyph[0]} => glyph.glyphs.${glyph[0]}; """); } - var result = Process.runSync( - "pub", ["run", "dart_style:format", "-w", "lib/src/generated.dart"]); - print(result.stderr); - exit(result.exitCode); + file.closeSync(); } String _quote(String input) => input.contains('"') ? "'$input'" : '"$input"'; From b82a0ff0a8941de7b20932a10f907f53c387c730 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 17 Jan 2019 16:08:31 -0800 Subject: [PATCH 0512/1215] fix tests with latest source_span release (dart-lang/pubspec_parse#38) --- pkgs/pubspec_parse/test/dependency_test.dart | 134 +++++++++++++------ pkgs/pubspec_parse/test/parse_test.dart | 78 +++++++---- 2 files changed, 150 insertions(+), 62 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 6c7d968fe..11a43824d 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -20,29 +20,39 @@ void main() { test('List', () { _expectThrows([], r''' line 4, column 10: Not a valid dependency value. - "dep": [] - ^^'''); + ╷ +4 │ "dep": [] + │ ^^ + ╵'''); }); test('int', () { _expectThrows(42, r''' line 4, column 10: Not a valid dependency value. - "dep": 42 - ^^^'''); + ╷ +4 │ "dep": 42 + │ ┌──────────^ +5 │ │ } + │ └─^ + ╵'''); }); test('map with too many keys', () { _expectThrows({'path': 'a', 'git': 'b'}, r''' line 5, column 12: A dependency may only have one source. - "path": "a", - ^^^'''); + ╷ +5 │ "path": "a", + │ ^^^ + ╵'''); }); test('map with unsupported keys', () { _expectThrows({'bob': 'a', 'jones': 'b'}, r''' line 6, column 4: Unsupported dependency key. - "jones": "b" - ^^^^^^^'''); + ╷ +6 │ "jones": "b" + │ ^^^^^^^ + ╵'''); }); }); } @@ -71,8 +81,10 @@ void _hostedDependency() { test('bad string version', () { _expectThrows('not a version', r''' line 4, column 10: Could not parse version "not a version". Unknown text at "not a version". - "dep": "not a version" - ^^^^^^^^^^^^^^^'''); + ╷ +4 │ "dep": "not a version" + │ ^^^^^^^^^^^^^^^ + ╵'''); }); test('map w/ just version', () { @@ -99,8 +111,10 @@ line 4, column 10: Could not parse version "not a version". Unknown text at "not 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} }, r''' line 5, column 15: Could not parse version "not a version". Unknown text at "not a version". - "version": "not a version", - ^^^^^^^^^^^^^^^'''); + ╷ +5 │ "version": "not a version", + │ ^^^^^^^^^^^^^^^ + ╵'''); }); test('map w/ extra keys should fail', () { @@ -110,8 +124,10 @@ line 5, column 15: Could not parse version "not a version". Unknown text at "not 'not_supported': null }, r''' line 10, column 4: Unsupported dependency key. - "not_supported": null - ^^^^^^^^^^^^^^^'''); + ╷ +10│ "not_supported": null + │ ^^^^^^^^^^^^^^^ + ╵'''); }); test('map w/ version and hosted as String', () { @@ -134,8 +150,12 @@ line 10, column 4: Unsupported dependency key. test('map w/ null hosted should error', () { _expectThrows({'hosted': null}, r''' line 5, column 14: These keys had `null` values, which is not allowed: [hosted] - "hosted": null - ^^^^^'''); + ╷ +5 │ "hosted": null + │ ┌──────────────^ +6 │ │ } + │ └──^ + ╵'''); }); test('map w/ null version is fine', () { @@ -165,15 +185,23 @@ void _sdkDependency() { test('null content', () { _expectThrows({'sdk': null}, r''' line 5, column 11: These keys had `null` values, which is not allowed: [sdk] - "sdk": null - ^^^^^'''); + ╷ +5 │ "sdk": null + │ ┌───────────^ +6 │ │ } + │ └──^ + ╵'''); }); test('number content', () { _expectThrows({'sdk': 42}, r''' line 5, column 11: Unsupported value for `sdk`. - "sdk": 42 - ^^^'''); + ╷ +5 │ "sdk": 42 + │ ┌───────────^ +6 │ │ } + │ └──^ + ╵'''); }); } @@ -211,8 +239,10 @@ void _gitDependency() { test('string with random extra key fails', () { _expectThrows({'git': 'url', 'bob': '^1.2.3'}, r''' line 6, column 4: Unsupported dependency key. - "bob": "^1.2.3" - ^^^^^'''); + ╷ +6 │ "bob": "^1.2.3" + │ ^^^^^ + ╵'''); }); test('map', () { @@ -228,22 +258,32 @@ line 6, column 4: Unsupported dependency key. test('git - null content', () { _expectThrows({'git': null}, r''' line 5, column 11: Must be a String or a Map. - "git": null - ^^^^^'''); + ╷ +5 │ "git": null + │ ┌───────────^ +6 │ │ } + │ └──^ + ╵'''); }); test('git - int content', () { _expectThrows({'git': 42}, r''' line 5, column 11: Must be a String or a Map. - "git": 42 - ^^^'''); + ╷ +5 │ "git": 42 + │ ┌───────────^ +6 │ │ } + │ └──^ + ╵'''); }); test('git - empty map', () { _expectThrows({'git': {}}, r''' line 5, column 11: Required keys are missing: url. - "git": {} - ^^'''); + ╷ +5 │ "git": {} + │ ^^ + ╵'''); }); test('git - null url', () { @@ -251,8 +291,12 @@ line 5, column 11: Required keys are missing: url. 'git': {'url': null} }, r''' line 6, column 12: These keys had `null` values, which is not allowed: [url] - "url": null - ^^^^^'''); + ╷ +6 │ "url": null + │ ┌────────────^ +7 │ │ } + │ └───^ + ╵'''); }); test('git - int url', () { @@ -260,8 +304,12 @@ line 6, column 12: These keys had `null` values, which is not allowed: [url] 'git': {'url': 42} }, r''' line 6, column 12: Unsupported value for `url`. - "url": 42 - ^^^'''); + ╷ +6 │ "url": 42 + │ ┌────────────^ +7 │ │ } + │ └───^ + ╵'''); }); } @@ -282,22 +330,32 @@ void _pathDependency() { test('valid with random extra key fails', () { _expectThrows({'path': '../path', 'bob': '^1.2.3'}, r''' line 6, column 4: Unsupported dependency key. - "bob": "^1.2.3" - ^^^^^'''); + ╷ +6 │ "bob": "^1.2.3" + │ ^^^^^ + ╵'''); }); test('null content', () { _expectThrows({'path': null}, r''' line 5, column 12: Must be a String. - "path": null - ^^^^^'''); + ╷ +5 │ "path": null + │ ┌────────────^ +6 │ │ } + │ └──^ + ╵'''); }); test('int content', () { _expectThrows({'path': 42}, r''' line 5, column 12: Must be a String. - "path": 42 - ^^^'''); + ╷ +5 │ "path": 42 + │ ┌────────────^ +6 │ │ } + │ └──^ + ╵'''); }); } diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index e00f8b0b8..a943e6acf 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -76,20 +76,28 @@ void main() { for (var entry in { 42: r''' line 3, column 16: Unsupported value for `publish_to`. - "publish_to": 42 - ^^^''', + ╷ +3 │ "publish_to": 42 + │ ^^ + ╵''', '##not a uri!': r''' line 3, column 16: must be an http or https URL. - "publish_to": "##not a uri!" - ^^^^^^^^^^^^^^''', + ╷ +3 │ "publish_to": "##not a uri!" + │ ^^^^^^^^^^^^^^ + ╵''', '/cool/beans': r''' line 3, column 16: must be an http or https URL. - "publish_to": "/cool/beans" - ^^^^^^^^^^^^^''', + ╷ +3 │ "publish_to": "/cool/beans" + │ ^^^^^^^^^^^^^ + ╵''', 'file:///Users/kevmoo/': r''' line 3, column 16: must be an http or https URL. - "publish_to": "file:///Users/kevmoo/" - ^^^^^^^^^^^^^^^^^^^^^^^''' + ╷ +3 │ "publish_to": "file:///Users/kevmoo/" + │ ^^^^^^^^^^^^^^^^^^^^^^^ + ╵''' }.entries) { test('cannot be `${entry.key}`', () { expectParseThrows( @@ -182,15 +190,19 @@ line 3, column 16: must be an http or https URL. test('array', () { expectParseThrows([], r''' line 1, column 1: Does not represent a YAML map. -[] -^^'''); + ╷ +1 │ [] + │ ^^ + ╵'''); }); test('missing name', () { expectParseThrows({}, r''' line 1, column 1: "name" cannot be empty. -{} -^^'''); + ╷ +1 │ {} + │ ^^ + ╵'''); }); test('"dart" is an invalid environment key', () { @@ -199,8 +211,10 @@ line 1, column 1: "name" cannot be empty. 'environment': {'dart': 'cool'} }, r''' line 4, column 3: Use "sdk" to for Dart SDK constraints. - "dart": "cool" - ^^^^^^'''); + ╷ +4 │ "dart": "cool" + │ ^^^^^^ + ╵'''); }); test('environment values cannot be int', () { @@ -209,15 +223,21 @@ line 4, column 3: Use "sdk" to for Dart SDK constraints. 'environment': {'sdk': 42} }, r''' line 4, column 10: `42` is not a String. - "sdk": 42 - ^^^'''); + ╷ +4 │ "sdk": 42 + │ ┌──────────^ +5 │ │ } + │ └─^ + ╵'''); }); test('version', () { expectParseThrows({'name': 'sample', 'version': 'invalid'}, r''' line 3, column 13: Could not parse "invalid". - "version": "invalid" - ^^^^^^^^^'''); + ╷ +3 │ "version": "invalid" + │ ^^^^^^^^^ + ╵'''); }); test('invalid environment value', () { @@ -226,8 +246,10 @@ line 3, column 13: Could not parse "invalid". 'environment': {'sdk': 'silly'} }, r''' line 4, column 10: Could not parse version "silly". Unknown text at "silly". - "sdk": "silly" - ^^^^^^^'''); + ╷ +4 │ "sdk": "silly" + │ ^^^^^^^ + ╵'''); }); test('bad repository url', () { @@ -236,8 +258,12 @@ line 4, column 10: Could not parse version "silly". Unknown text at "silly". 'repository': {'x': 'y'}, }, r''' line 3, column 16: Unsupported value for `repository`. - "repository": { - ^^''', skipTryPub: true); + ╷ +3 │ "repository": { + │ ┌────────────────^ +4 │ │ "x": "y" +5 │ └ } + ╵''', skipTryPub: true); }); test('bad issue_tracker url', () { @@ -246,8 +272,12 @@ line 3, column 16: Unsupported value for `repository`. 'issue_tracker': {'x': 'y'}, }, r''' line 3, column 19: Unsupported value for `issue_tracker`. - "issue_tracker": { - ^^''', skipTryPub: true); + ╷ +3 │ "issue_tracker": { + │ ┌───────────────────^ +4 │ │ "x": "y" +5 │ └ } + ╵''', skipTryPub: true); }); }); From ff2e4d42e184a8fdfdc3997003da639cd1010510 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 24 Jan 2019 22:25:58 -0800 Subject: [PATCH 0513/1215] Update ignores for hint changes in latest dev SDK (dart-lang/pubspec_parse#39) --- pkgs/pubspec_parse/.travis.yml | 10 +++++++++- pkgs/pubspec_parse/test/parse_test.dart | 14 +++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index 8c6a4b8c3..3af3939c7 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -8,7 +8,15 @@ dart_task: - test: -x presubmit-only - test: --run-skipped -t presubmit-only - dartfmt - - dartanalyzer: --fatal-infos --fatal-warnings . + +matrix: + include: + - dart: dev + dart_task: + dartanalyzer: --fatal-infos --fatal-warnings . + - dart: stable + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index a943e6acf..dc469a5b7 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -15,7 +15,7 @@ void main() { expect(value.publishTo, isNull); expect(value.description, isNull); expect(value.homepage, isNull); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, isEmpty); expect(value.environment, isEmpty); @@ -48,7 +48,7 @@ void main() { expect(value.publishTo, 'none'); expect(value.description, 'description'); expect(value.homepage, 'homepage'); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); expect(value.environment, hasLength(1)); @@ -124,7 +124,7 @@ line 3, column 16: must be an http or https URL. group('author, authors', () { test('one author', () { final value = parse({'name': 'sample', 'author': 'name@example.com'}); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); @@ -134,7 +134,7 @@ line 3, column 16: must be an http or https URL. 'name': 'sample', 'authors': ['name@example.com'] }); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); @@ -144,7 +144,7 @@ line 3, column 16: must be an http or https URL. 'name': 'sample', 'authors': ['name@example.com', 'name2@example.com'] }); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); }); @@ -155,7 +155,7 @@ line 3, column 16: must be an http or https URL. 'author': 'name@example.com', 'authors': ['name2@example.com'] }); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); }); @@ -166,7 +166,7 @@ line 3, column 16: must be an http or https URL. 'author': 'name@example.com', 'authors': ['name@example.com', 'name@example.com'] }); - // ignore: deprecated_member_use + // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); From 1a13cc17d84b1607206c077838990ca289da902c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Feb 2019 15:43:31 -0800 Subject: [PATCH 0514/1215] Add whereType transformer (dart-lang/stream_transform#60) This needs to be implemented as it's own class instead of using one of the helpers like `fromHandlers` because it has unique generic type requirements. We want to avoid requring the call site to re-specify the generic type of the input stream. The return type needs to be a `StreamTransformer` to satisfy static checking. However the argument to `bind` at runtime will never be a `Stream` so we need to define it explicitly to widen the allowed argument. --- pkgs/stream_transform/CHANGELOG.md | 4 ++ pkgs/stream_transform/README.md | 4 ++ pkgs/stream_transform/lib/src/where_type.dart | 54 +++++++++++++++++++ .../lib/stream_transform.dart | 1 + pkgs/stream_transform/pubspec.yaml | 2 +- .../test/where_type_test.dart | 50 +++++++++++++++++ 6 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/lib/src/where_type.dart create mode 100644 pkgs/stream_transform/test/where_type_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 515f0edc7..e26b1f182 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.15 + +- Add `whereType`. + ## 0.0.14+1 - Allow using non-dev Dart 2 SDK. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 5e5445746..89ce15d32 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -63,3 +63,7 @@ being a real subscriber. # throttle Blocks events for a duration after an event is successfully emitted. + +# whereType + +Like `Iterable.whereType` for a stream. diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart new file mode 100644 index 000000000..96eb394f1 --- /dev/null +++ b/pkgs/stream_transform/lib/src/where_type.dart @@ -0,0 +1,54 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Emits only the events which have type [R]. +/// +/// If the source stream is a broadcast stream the result will be as well. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// +/// The static type of the returned transformer takes `Null` so that it can +/// satisfy the subtype requirements for the `stream.transform()` argument on +/// any source stream. The argument to `bind` has been broadened to take +/// `Stream` since it will never be passed a `Stream` at runtime. +/// This is safe to use on any source stream. +/// +/// [R] should be a subtype of the stream's generic type, otherwise nothing of +/// type [R] could possibly be emitted, however there is no static or runtime +/// checking that this is the case. +StreamTransformer whereType() => _WhereType(); + +class _WhereType extends StreamTransformerBase { + @override + Stream bind(Stream source) { + var controller = source.isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + StreamSubscription subscription; + controller.onListen = () { + if (subscription != null) return; + subscription = source.listen( + (value) { + if (value is R) controller.add(value); + }, + onError: controller.addError, + onDone: () { + subscription = null; + controller.close(); + }); + if (!source.isBroadcast) { + controller.onPause = subscription.pause; + controller.onResume = subscription.resume; + } + controller.onCancel = () { + subscription?.cancel(); + subscription = null; + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 13b80a463..bddb744bc 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -19,3 +19,4 @@ export 'src/switch.dart'; export 'src/take_until.dart'; export 'src/tap.dart'; export 'src/throttle.dart'; +export 'src/where_type.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index b32a050df..a29a467d3 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.15-dev +version: 0.0.15 environment: sdk: ">=2.1.0 <3.0.0" diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart new file mode 100644 index 000000000..2c6d7ed5a --- /dev/null +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -0,0 +1,50 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + test('forwards only events that match the type', () async { + var values = Stream.fromIterable([1, 'a', 2, 'b']); + var filtered = values.transform(whereType()); + expect(await filtered.toList(), ['a', 'b']); + }); + + test('can result in empty stream', () async { + var values = Stream.fromIterable([1, 2, 3, 4]); + var filtered = values.transform(whereType()); + expect(await filtered.isEmpty, true); + }); + + test('forwards values to multiple listeners', () async { + var values = StreamController.broadcast(); + var filtered = values.stream.transform(whereType()); + var firstValues = []; + var secondValues = []; + filtered..listen(firstValues.add)..listen(secondValues.add); + values..add(1)..add('a')..add(2)..add('b'); + await Future(() {}); + expect(firstValues, ['a', 'b']); + expect(secondValues, ['a', 'b']); + }); + + test('closes streams with multiple listeners', () async { + var values = StreamController.broadcast(); + var filtered = values.stream.transform(whereType()); + var firstDone = false; + var secondDone = false; + filtered + ..listen(null, onDone: () => firstDone = true) + ..listen(null, onDone: () => secondDone = true); + values.add(1); + values.add('a'); + await values.close(); + expect(firstDone, true); + expect(secondDone, true); + }); +} From e51f873513e10f4987f198d83dd2704874a14b0b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 27 Feb 2019 11:03:38 -0800 Subject: [PATCH 0515/1215] Disable prefer_collection_literals, because Dart 2.2 Set (dart-lang/pubspec_parse#40) Enable and fix a few more --- pkgs/pubspec_parse/analysis_options.yaml | 14 ++++++++++++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 3 +-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index b95911604..4f0a48b4d 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -12,6 +12,8 @@ linter: rules: - always_declare_return_types - annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members - avoid_empty_else - avoid_function_literals_in_foreach_calls - avoid_init_to_null @@ -21,12 +23,16 @@ linter: - avoid_return_types_on_setters - avoid_returning_null - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_returning_this - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - await_only_futures - camel_case_types - cancel_subscriptions + - cascade_invocations - comment_references - constant_identifier_names - control_flow_in_finally @@ -34,10 +40,12 @@ linter: - empty_catches - empty_constructor_bodies - empty_statements + - file_names - hash_and_equals - implementation_imports - invariant_booleans - iterable_contains_unrelated_type + - join_return_with_assignment - library_names - library_prefixes - list_remove_unrelated_type @@ -53,7 +61,8 @@ linter: - package_names - package_prefixed_library_names - prefer_adjacent_string_concatenation - - prefer_collection_literals + # TODO: reenable this once we want to pin the SDK to >=2.2.0 + # - prefer_collection_literals - prefer_conditional_assignment - prefer_const_constructors - prefer_contains @@ -64,11 +73,11 @@ linter: - prefer_interpolation_to_compose_strings - prefer_is_empty - prefer_is_not_empty + - prefer_null_aware_operators - prefer_single_quotes - prefer_typing_uninitialized_variables - recursive_getters - slash_for_doc_comments - - super_goes_last - test_types_in_equals - throw_in_finally - type_init_formals @@ -87,3 +96,4 @@ linter: - use_function_type_syntax_for_parameters - use_rethrow_when_possible - valid_regexps + - void_checks diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 4052a7017..c05e8249c 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -126,8 +126,7 @@ class Pubspec { return _$PubspecFromJson(json); } on CheckedFromJsonException catch (e) { if (e.map == json && json.containsKey(e.key)) { - json = Map.from(json); - json.remove(e.key); + json = Map.from(json)..remove(e.key); continue; } rethrow; From 2deb47d217bd22ca3b27d22beac9006eb5662c18 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 7 Mar 2019 08:49:41 -0800 Subject: [PATCH 0516/1215] enable pedantic lints (dart-lang/stream_transform#61) --- pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/pubspec.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index dcfc23987..655288575 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false @@ -39,7 +40,6 @@ linter: - recursive_getters - slash_for_doc_comments - test_types_in_equals - - test_types_in_equals - throw_in_finally - type_init_formals - unrelated_type_equality_checks diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index a29a467d3..722cecd2d 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -8,4 +8,5 @@ environment: sdk: ">=2.1.0 <3.0.0" dev_dependencies: + pedantic: ^1.5.0 test: ^1.0.0 From f2f06264dcd2874cbe0517dc427b40b7dca8f7ce Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 8 Mar 2019 12:48:52 -0800 Subject: [PATCH 0517/1215] Allow a `FutureOr` return in `scan` (dart-lang/stream_transform#64) Closes dart-lang/stream_transform#62 Adds async support in `scan` instead of a new `asyncScan` since the latter would be able to serve both use cases so it would not be clear why both exist. Technically this is breaking but it's such an extreme edge case that it is very unlikely to come up in practice - and the breakage is detected statically. Due to the way `FuturOr` interacts with inference there are some cases where the generic types may need to be explicitly written. This is an unlikely scenario where the transformer emitted a stream of futures. --- pkgs/stream_transform/CHANGELOG.md | 7 ++ pkgs/stream_transform/lib/src/scan.dart | 18 ++++- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/scan_test.dart | 83 ++++++++++++++++++++++- 4 files changed, 104 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index e26b1f182..371889a04 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.0.16 + +- Allow a `combine` callback to return a `FutureOr` in `scan`. There are no + behavior changes for synchronous callbacks. **Potential breaking change** In + the unlikely situation where `scan` was used to produce a `Stream` + inference may now fail and require explicit generic type arguments. + ## 0.0.15 - Add `whereType`. diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index 0936e13e1..b2f76eff2 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -6,9 +6,21 @@ import 'dart:async'; /// Scan is like fold, but instead of producing a single value it yields /// each intermediate accumulation. +/// +/// If [combine] returns a Future it will not be called again for subsequent +/// events from the source until it completes, therefor the combine callback is +/// always called for elements in order, and the result stream always maintains +/// the same order as the original. StreamTransformer scan( - T initialValue, T combine(T previousValue, S element)) => - StreamTransformer.fromBind((stream) { + T initialValue, FutureOr combine(T previousValue, S element)) => + StreamTransformer.fromBind((source) { var accumulated = initialValue; - return stream.map((value) => accumulated = combine(accumulated, value)); + return source.asyncMap((value) { + var result = combine(accumulated, value); + if (result is Future) { + return result.then((r) => accumulated = r); + } else { + return accumulated = result as T; + } + }); }); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 722cecd2d..c0768e920 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.15 +version: 0.0.16 environment: sdk: ">=2.1.0 <3.0.0" diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index db958850e..71472a6ee 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -12,18 +12,97 @@ void main() { group('Scan', () { test('produces intermediate values', () async { var source = Stream.fromIterable([1, 2, 3, 4]); - var sum = (int x, int y) => x + y; + int sum(int x, int y) => x + y; var result = await source.transform(scan(0, sum)).toList(); expect(result, [1, 3, 6, 10]); }); - test('can create a broadcast stream', () async { + test('can create a broadcast stream', () { var source = StreamController.broadcast(); var transformed = source.stream.transform(scan(null, null)); expect(transformed.isBroadcast, true); }); + + test('forwards errors from source', () async { + var source = StreamController(); + + int sum(int x, int y) => x + y; + + var errors = []; + + source.stream.transform((scan(0, sum))).listen(null, onError: errors.add); + + source.addError(StateError('fail')); + await Future(() {}); + + expect(errors, [isStateError]); + }); + + group('with async combine', () { + test('returns a Stream of non-futures', () async { + var source = Stream.fromIterable([1, 2, 3, 4]); + Future sum(int x, int y) async => x + y; + var result = await source.transform(scan(0, sum)).toList(); + + expect(result, [1, 3, 6, 10]); + }); + + test('can return a Stream of futures when specified', () async { + var source = Stream.fromIterable([1, 2]); + Future sum(Future x, int y) async => (await x) + y; + var result = await source + .transform(scan>(Future.value(0), sum)) + .toList(); + + expect(result, [TypeMatcher(), TypeMatcher()]); + expect(await Future.wait(result), [1, 3]); + }); + + test('does not call for subsequent values while waiting', () async { + var source = StreamController(); + + var calledWith = []; + var block = Completer(); + Future combine(int x, int y) async { + calledWith.add(y); + await block.future; + return x + y; + } + + var results = []; + + source.stream.transform(scan(0, combine)).forEach(results.add); + + source..add(1)..add(2); + await Future(() {}); + expect(calledWith, [1]); + expect(results, isEmpty); + + block.complete(); + await Future(() {}); + expect(calledWith, [1, 2]); + expect(results, [1, 3]); + }); + + test('forwards async errors', () async { + var source = StreamController(); + + Future combine(int x, int y) async => throw StateError('fail'); + + var errors = []; + + source.stream + .transform((scan(0, combine))) + .listen(null, onError: errors.add); + + source.add(1); + await Future(() {}); + + expect(errors, [isStateError]); + }); + }); }); } From cda88aebc8f0acd7999e8392a3f017f5a8404012 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 11 Mar 2019 11:25:20 -0700 Subject: [PATCH 0518/1215] Add `combineLatest` (dart-lang/stream_transform#65) Closes dart-lang/stream_transform#63 Uses a manual `StreamTransformer` implementation based closely on the `merge` implementation. This can't be implemented on top of `fromHandlers` or normal stream methods because the events emitted aren't triggered by a single source. --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/README.md | 5 + .../lib/src/combine_latest.dart | 146 ++++++++++++++ .../lib/stream_transform.dart | 1 + .../test/combine_latest_test.dart | 182 ++++++++++++++++++ 5 files changed, 335 insertions(+) create mode 100644 pkgs/stream_transform/lib/src/combine_latest.dart create mode 100644 pkgs/stream_transform/test/combine_latest_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 371889a04..1a2ce6647 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -4,6 +4,7 @@ behavior changes for synchronous callbacks. **Potential breaking change** In the unlikely situation where `scan` was used to produce a `Stream` inference may now fail and require explicit generic type arguments. +- Add `combineLatest`. ## 0.0.15 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 89ce15d32..7e556cb22 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -19,6 +19,11 @@ the most recent value. Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. +# combineLatest + +Combine the most recent event from two streams through a callback and emit the +result. + # debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart new file mode 100644 index 000000000..1fe7d8590 --- /dev/null +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -0,0 +1,146 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Combine the latest value from the source stream with the latest value from +/// [other] using [combine]. +/// +/// No event will be emitted from the result stream until both the source stream +/// and [other] have each emitted at least one event. Once both streams have +/// emitted at least one event, the result stream will emit any time either +/// input stream emits. +/// +/// For example: +/// source.transform(combineLatest(other, (a, b) => a + b)); +/// +/// source: +/// 1--2-----4 +/// other: +/// ------3--- +/// result: +/// ------5--7 +/// +/// The result stream will not close until both the source stream and [other] +/// have closed. +/// +/// Errors thrown by [combine], along with any errors on the source stream or +/// [other], are forwarded to the result stream. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of [other]'s type. If a single subscription stream is +/// combined with a broadcast stream it may never be canceled. +StreamTransformer combineLatest( + Stream other, FutureOr Function(S, T) combine) => + _CombineLatest(other, combine); + +class _CombineLatest extends StreamTransformerBase { + final Stream _other; + final FutureOr Function(S, T) _combine; + + _CombineLatest(this._other, this._combine); + + @override + Stream bind(Stream source) { + final controller = source.isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + final other = (source.isBroadcast && !_other.isBroadcast) + ? _other.asBroadcastStream() + : _other; + + StreamSubscription sourceSubscription; + StreamSubscription otherSubscription; + + var sourceDone = false; + var otherDone = false; + + S latestSource; + T latestOther; + + var sourceStarted = false; + var otherStarted = false; + + void emitCombined() { + if (!sourceStarted || !otherStarted) return; + FutureOr result; + try { + result = _combine(latestSource, latestOther); + } catch (e, s) { + controller.addError(e, s); + return; + } + if (result is Future) { + sourceSubscription.pause(); + otherSubscription.pause(); + result + .then(controller.add, onError: controller.addError) + .whenComplete(() { + sourceSubscription.resume(); + otherSubscription.resume(); + }); + } else { + controller.add(result as R); + } + } + + controller.onListen = () { + assert(sourceSubscription == null); + sourceSubscription = source.listen( + (s) { + sourceStarted = true; + latestSource = s; + emitCombined(); + }, + onError: controller.addError, + onDone: () { + sourceDone = true; + if (otherDone) { + controller.close(); + } else if (!sourceStarted) { + // Nothing can ever be emitted + otherSubscription.cancel(); + controller.close(); + } + }); + otherSubscription = other.listen( + (o) { + otherStarted = true; + latestOther = o; + emitCombined(); + }, + onError: controller.addError, + onDone: () { + otherDone = true; + if (sourceDone) { + controller.close(); + } else if (!otherStarted) { + // Nothing can ever be emitted + sourceSubscription.cancel(); + controller.close(); + } + }); + if (!source.isBroadcast) { + controller + ..onPause = () { + sourceSubscription.pause(); + otherSubscription.pause(); + } + ..onResume = () { + sourceSubscription.resume(); + otherSubscription.resume(); + }; + } + controller.onCancel = () { + var cancelSource = sourceSubscription.cancel(); + var cancelOther = otherSubscription.cancel(); + sourceSubscription = null; + otherSubscription = null; + return Future.wait([cancelSource, cancelOther]); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index bddb744bc..557fc82ef 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -7,6 +7,7 @@ export 'src/async_where.dart'; export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/chain_transformers.dart'; +export 'src/combine_latest.dart'; export 'src/concat.dart'; export 'src/concurrent_async_map.dart'; export 'src/debounce.dart'; diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart new file mode 100644 index 000000000..cbe30507c --- /dev/null +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -0,0 +1,182 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:pedantic/pedantic.dart'; +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + group('combineLatest', () { + test('flows through combine callback', () async { + var source = StreamController(); + var other = StreamController(); + int sum(int a, int b) => a + b; + + var results = []; + unawaited(source.stream + .transform(combineLatest(other.stream, sum)) + .forEach(results.add)); + + source.add(1); + await Future(() {}); + expect(results, isEmpty); + + other.add(2); + await Future(() {}); + expect(results, [3]); + + source.add(3); + await Future(() {}); + expect(results, [3, 5]); + + source.add(4); + await Future(() {}); + expect(results, [3, 5, 6]); + + other.add(5); + await Future(() {}); + expect(results, [3, 5, 6, 9]); + }); + + test('can combine different typed streams', () async { + var source = StreamController(); + var other = StreamController(); + String times(String a, int b) => a * b; + + var results = []; + unawaited(source.stream + .transform(combineLatest(other.stream, times)) + .forEach(results.add)); + + source.add('a'); + source.add('b'); + await Future(() {}); + expect(results, isEmpty); + + other.add(2); + await Future(() {}); + expect(results, ['bb']); + + other.add(3); + await Future(() {}); + expect(results, ['bb', 'bbb']); + + source.add('c'); + await Future(() {}); + expect(results, ['bb', 'bbb', 'ccc']); + }); + + test('ends after both streams have ended', () async { + var source = StreamController(); + var other = StreamController(); + int sum(int a, int b) => a + b; + + var done = false; + source.stream + .transform(combineLatest(other.stream, sum)) + .listen(null, onDone: () => done = true); + + source.add(1); + + await source.close(); + await Future(() {}); + expect(done, false); + + await other.close(); + await Future(() {}); + expect(done, true); + }); + + test('ends if source stream closes without ever emitting a value', + () async { + var source = Stream.empty(); + var other = StreamController(); + + int sum(int a, int b) => a + b; + + var done = false; + source + .transform(combineLatest(other.stream, sum)) + .listen(null, onDone: () => done = true); + + await Future(() {}); + // Nothing can ever be emitted on the result, may as well close. + expect(done, true); + }); + + test('ends if other stream closes without ever emitting a value', () async { + var source = StreamController(); + var other = Stream.empty(); + + int sum(int a, int b) => a + b; + + var done = false; + source.stream + .transform(combineLatest(other, sum)) + .listen(null, onDone: () => done = true); + + await Future(() {}); + // Nothing can ever be emitted on the result, may as well close. + expect(done, true); + }); + + test('forwards errors', () async { + var source = StreamController(); + var other = StreamController(); + int sum(int a, int b) => throw _NumberedException(3); + + var errors = []; + source.stream + .transform(combineLatest(other.stream, sum)) + .listen(null, onError: errors.add); + + source.addError(_NumberedException(1)); + other.addError(_NumberedException(2)); + + source.add(1); + other.add(2); + + await Future(() {}); + + expect(errors, [_isException(1), _isException(2), _isException(3)]); + }); + + group('broadcast source', () { + test('can cancel and relisten to broadcast stream', () async { + var source = StreamController.broadcast(); + var other = StreamController(); + int combine(int a, int b) => a + b; + + var emittedValues = []; + var transformed = + source.stream.transform(combineLatest(other.stream, combine)); + + var subscription = transformed.listen(emittedValues.add); + + source.add(1); + other.add(2); + await Future(() {}); + expect(emittedValues, [3]); + + await subscription.cancel(); + + subscription = transformed.listen(emittedValues.add); + source.add(3); + await Future(() {}); + expect(emittedValues, [3, 5]); + }); + }); + }); +} + +class _NumberedException implements Exception { + final int id; + _NumberedException(this.id); +} + +Matcher _isException(int id) => + TypeMatcher<_NumberedException>().having((n) => n.id, 'id', id); From 75611df3d973389de87fafbcfc8279a2eb7ec8eb Mon Sep 17 00:00:00 2001 From: Brett Peters Date: Tue, 12 Mar 2019 13:17:15 -0700 Subject: [PATCH 0519/1215] Add `combineLatestAll` (dart-lang/stream_transform#67) --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/README.md | 5 + .../lib/src/combine_latest_all.dart | 110 ++++++++++++ .../lib/stream_transform.dart | 1 + .../test/combine_latest_all_test.dart | 166 ++++++++++++++++++ 5 files changed, 283 insertions(+) create mode 100644 pkgs/stream_transform/lib/src/combine_latest_all.dart create mode 100644 pkgs/stream_transform/test/combine_latest_all_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 1a2ce6647..d50c11991 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -5,6 +5,7 @@ the unlikely situation where `scan` was used to produce a `Stream` inference may now fail and require explicit generic type arguments. - Add `combineLatest`. +- Add `combineLatestAll`. ## 0.0.15 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 7e556cb22..5d24caf04 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -24,6 +24,11 @@ collected values are emitted. Combine the most recent event from two streams through a callback and emit the result. +# combineLatestAll + +Combines the latest events emitted from multiple source streams and yields a +list of the values. + # debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart new file mode 100644 index 000000000..8141a3f4e --- /dev/null +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// Combine the latest value emitted from the source stream with the latest +/// values emitted from [others]. +/// +/// [combineLatestAll] subscribes to the source stream and [others] and when +/// any one of the streams emits, the result stream will emit a [List] of +/// the latest values emitted from all streams. +/// +/// The result stream will not emit until all source streams emit at least +/// once. If a source stream emits multiple values before another starts +/// emitting, all but the last value will be lost. +/// +/// The result stream will not close until all source streams have closed. When +/// a source stream closes, the result stream will continue to emit the last +/// value from the closed stream when the other source streams emit until the +/// result stream has closed. If a source stream closes without emitting any +/// value, the result stream will close as well. +/// +/// Errors thrown by any source stream will be forwarded to the result stream. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the types of [others]. If a single subscription stream +/// is combined with a broadcast source stream, it may never be canceled. +/// +/// ## Example +/// +/// (Suppose first, second, and third are Stream) +/// final combined = first +/// .transform(combineLatestAll([second, third])) +/// .map((data) => data.join()); +/// +/// first: a----b------------------c--------d---| +/// second: --1---------2-----------------| +/// third: -------&----------%---| +/// combined: -------b1&--b2&---b2%---c2%------d2%-| +/// +StreamTransformer> combineLatestAll(Iterable> others) => + _CombineLatestAll(others); + +class _CombineLatestAll extends StreamTransformerBase> { + final Iterable> _others; + + _CombineLatestAll(this._others); + + @override + Stream> bind(Stream source) { + final controller = source.isBroadcast + ? StreamController>.broadcast(sync: true) + : StreamController>(sync: true); + + var allStreams = [source]..addAll(_others); + if (source.isBroadcast) { + allStreams = allStreams + .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) + .toList(); + } + + List subscriptions; + + controller.onListen = () { + if (subscriptions != null) return; + + final latestData = List(allStreams.length); + final hasEmitted = {}; + void handleData(int index, T data) { + latestData[index] = data; + hasEmitted.add(index); + if (hasEmitted.length == allStreams.length) { + controller.add(List.from(latestData)); + } + } + + var activeStreamCount = 0; + subscriptions = allStreams.map((stream) { + final index = activeStreamCount; + activeStreamCount++; + return stream.listen((data) => handleData(index, data), + onError: controller.addError, onDone: () { + if (--activeStreamCount <= 0 || !hasEmitted.contains(index)) { + controller.close(); + } + }); + }).toList(); + if (!source.isBroadcast) { + controller.onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } + }; + controller.onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; + } + controller.onCancel = () { + final toCancel = subscriptions; + subscriptions = null; + if (activeStreamCount <= 0) return null; + return Future.wait(toCancel.map((s) => s.cancel())); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 557fc82ef..b8b15f498 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -8,6 +8,7 @@ export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/chain_transformers.dart'; export 'src/combine_latest.dart'; +export 'src/combine_latest_all.dart'; export 'src/concat.dart'; export 'src/concurrent_async_map.dart'; export 'src/debounce.dart'; diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart new file mode 100644 index 000000000..9cf3a9152 --- /dev/null +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -0,0 +1,166 @@ +import 'dart:async'; +import 'package:test/test.dart'; +import 'package:stream_transform/stream_transform.dart'; + +Future tick() => Future(() {}); + +void main() { + group('combineLatestAll', () { + test('emits latest values', () async { + final first = StreamController(); + final second = StreamController(); + final third = StreamController(); + final combined = first.stream + .transform(combineLatestAll([second.stream, third.stream])) + .map((data) => data.join()); + + // first: a----b------------------c--------d---| + // second: --1---------2-----------------| + // third: -------&----------%---| + // combined: -------b1&--b2&---b2%---c2%------d2%-| + + expect(combined, + emitsInOrder(['b1&', 'b2&', 'b2%', 'c2%', 'd2%', emitsDone])); + + first.add('a'); + await tick(); + second.add('1'); + await tick(); + first.add('b'); + await tick(); + third.add('&'); + await tick(); + second.add('2'); + await tick(); + third.add('%'); + await tick(); + await third.close(); + await tick(); + first.add('c'); + await tick(); + await second.close(); + await tick(); + first.add('d'); + await tick(); + await first.close(); + }); + + test('ends if a Stream closes without ever emitting a value', () async { + final first = StreamController(); + final second = StreamController(); + final combined = + first.stream.transform(combineLatestAll([second.stream])); + + // first: -a------b-------| + // second: -----| + // combined: -----| + + expect(combined, emits(emitsDone)); + + first.add('a'); + await tick(); + await second.close(); + await tick(); + first.add('b'); + }); + + test('forwards errors', () async { + final first = StreamController(); + final second = StreamController(); + final combined = first.stream + .transform(combineLatestAll([second.stream])) + .map((data) => data.join()); + + // first: -a---------| + // second: ----1---# + // combined: ----a1--# + + expect(combined, emitsThrough(emitsError('doh'))); + + first.add('a'); + await tick(); + second.add('1'); + await tick(); + second.addError('doh'); + }); + + test('ends after both streams have ended', () async { + final first = StreamController(); + final second = StreamController(); + + var done = false; + first.stream + .transform(combineLatestAll([second.stream])) + .listen(null, onDone: () => done = true); + + // first: -a---| + // second: --------1--| + // combined: --------a1-| + + first.add('a'); + await tick(); + await first.close(); + await tick(); + + expect(done, isFalse); + + second.add('1'); + await tick(); + await second.close(); + await tick(); + + expect(done, isTrue); + }); + + group('broadcast source', () { + test('can cancel and relisten to broadcast stream', () async { + final first = StreamController.broadcast(); + final second = StreamController.broadcast(); + final combined = first.stream + .transform(combineLatestAll([second.stream])) + .map((data) => data.join()); + + // first: a------b----------------c------d----e---| + // second: --1---------2---3---4------5-| + // combined: --a1---b1---b2--b3--b4-----c5--d5---e5--| + // sub1: ^-----------------! + // sub2: ----------------------^-----------------| + + expect(combined.take(4), emitsInOrder(['a1', 'b1', 'b2', 'b3'])); + + first.add('a'); + await tick(); + second.add('1'); + await tick(); + first.add('b'); + await tick(); + second.add('2'); + await tick(); + second.add('3'); + await tick(); + + // First subscription is canceled here by .take(4) + expect(first.hasListener, isFalse); + expect(second.hasListener, isFalse); + + // This emit is thrown away because there are no subscribers + second.add('4'); + await tick(); + + expect(combined, emitsInOrder(['c5', 'd5', 'e5', emitsDone])); + + first.add('c'); + await tick(); + second.add('5'); + await tick(); + await second.close(); + await tick(); + first.add('d'); + await tick(); + first.add('e'); + await tick(); + await first.close(); + }); + }); + }); +} From a7e62266581033b0370193ce4575577c4b89e878 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 12 Mar 2019 13:47:24 -0700 Subject: [PATCH 0520/1215] update generated code --- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index b68e030fa..ba7e6ebf1 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -31,8 +31,12 @@ Pubspec _$PubspecFromJson(Map json) { json, 'dev_dependencies', (v) => parseDeps(v as Map)), dependencyOverrides: $checkedConvert( json, 'dependency_overrides', (v) => parseDeps(v as Map)), - flutter: $checkedConvert(json, 'flutter', - (v) => (v as Map)?.map((k, e) => MapEntry(k as String, e)))); + flutter: $checkedConvert( + json, + 'flutter', + (v) => (v as Map)?.map( + (k, e) => MapEntry(k as String, e), + ))); return val; }, fieldKeyMap: const { 'publishTo': 'publish_to', From aa9fc6e9deab454e5a6ef62cc5a88105652c4e59 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 14:49:22 -0700 Subject: [PATCH 0521/1215] Change onListen bailouts to asserts (dart-lang/stream_transform#68) These transformers had a check that should never be true because the behavior of the `StreamController` should prevent `onListen` from being called multiple times while there is at least one active listener. --- pkgs/stream_transform/lib/src/buffer.dart | 2 +- pkgs/stream_transform/lib/src/combine_latest_all.dart | 2 +- pkgs/stream_transform/lib/src/followed_by.dart | 2 +- pkgs/stream_transform/lib/src/from_handlers.dart | 2 +- pkgs/stream_transform/lib/src/merge.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/lib/src/where_type.dart | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index c05e79ab0..b4c937e07 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -86,7 +86,7 @@ class _Buffer extends StreamTransformerBase> { } controller.onListen = () { - if (valueSub != null) return; + assert(valueSub == null); valueSub = values.listen(onValue, onError: controller.addError, onDone: onValuesDone); if (triggerSub != null) { diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart index 8141a3f4e..679f3efd2 100644 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -63,7 +63,7 @@ class _CombineLatestAll extends StreamTransformerBase> { List subscriptions; controller.onListen = () { - if (subscriptions != null) return; + assert(subscriptions == null); final latestData = List(allStreams.length); final hasEmitted = {}; diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart index df506f3a8..1705542c3 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -60,7 +60,7 @@ class _FollowedBy extends StreamTransformerBase { currentDoneHandler = onFirstDone; controller.onListen = () { - if (subscription != null) return; + assert(subscription == null); listen(); if (!first.isBroadcast) { controller.onPause = () { diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 6096c4c02..99f71cbd7 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -54,7 +54,7 @@ class _StreamTransformer extends StreamTransformerBase { StreamSubscription subscription; controller.onListen = () { - if (subscription != null) return; + assert(subscription == null); var valuesDone = false; subscription = values.listen((value) => _handleData(value, controller), onError: (error, StackTrace stackTrace) { diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index ead8bc6d9..82aa06ab8 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -42,7 +42,7 @@ class _Merge extends StreamTransformerBase { List subscriptions; controller.onListen = () { - if (subscriptions != null) return; + assert(subscriptions == null); var activeStreamCount = 0; subscriptions = allStreams.map((stream) { activeStreamCount++; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 87ae4ffed..54dc843cb 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -38,7 +38,7 @@ class _SwitchTransformer extends StreamTransformerBase, T> { StreamSubscription> outerSubscription; controller.onListen = () { - if (outerSubscription != null) return; + assert(outerSubscription == null); StreamSubscription innerSubscription; var outerStreamDone = false; diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart index 96eb394f1..6e5b08f2e 100644 --- a/pkgs/stream_transform/lib/src/where_type.dart +++ b/pkgs/stream_transform/lib/src/where_type.dart @@ -30,7 +30,7 @@ class _WhereType extends StreamTransformerBase { StreamSubscription subscription; controller.onListen = () { - if (subscription != null) return; + assert(subscription == null); subscription = source.listen( (value) { if (value is R) controller.add(value); From 39180796ec0ad156fb262587a4f4d6f162384c1c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 14:55:42 -0700 Subject: [PATCH 0522/1215] Enable a bunch of lints - Turn on lints that we're already following. - Comment out lints that need some fixes. - Ignore todos. --- pkgs/stream_transform/analysis_options.yaml | 45 +++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 655288575..c015ee7bf 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -3,6 +3,7 @@ analyzer: strong-mode: implicit-casts: false errors: + todo: ignore dead_code: error override_on_non_overriding_method: error unused_element: error @@ -11,37 +12,81 @@ analyzer: linter: rules: - annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members - avoid_empty_else + - avoid_function_literals_in_foreach_calls - avoid_init_to_null + - avoid_null_checks_in_equality_operators - avoid_relative_lib_imports + - avoid_renaming_method_parameters - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_void + - avoid_returning_this + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements - avoid_types_as_parameter_names + - avoid_unused_constructor_parameters - await_only_futures - camel_case_types + #- cascade_invocations - comment_references + - constant_identifier_names - control_flow_in_finally - directives_ordering - empty_catches - empty_constructor_bodies - empty_statements + - file_names - hash_and_equals - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - join_return_with_assignment - library_names - library_prefixes + - list_remove_unrelated_type + - no_adjacent_strings_in_list - no_duplicate_case_values - non_constant_identifier_names + - null_closures - omit_local_variable_types - only_throw_errors + - overridden_fields + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + #- prefer_const_constructors - prefer_contains - prefer_equal_for_default_values - prefer_final_fields + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_is_empty - prefer_is_not_empty + - prefer_null_aware_operators - prefer_single_quotes + #- prefer_typing_uninitialized_variables - recursive_getters - slash_for_doc_comments - test_types_in_equals - throw_in_finally - type_init_formals + #- unawaited_futures + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_new + - unnecessary_null_aware_assignments + #- unnecessary_parenthesis + - unnecessary_statements + - unnecessary_this + - unnecessary_overrides - unrelated_type_equality_checks - use_rethrow_when_possible - valid_regexps + - void_checks From 9ab34fc12700116768f61f63302a0327b182c181 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 14:58:37 -0700 Subject: [PATCH 0523/1215] Enforce and fix cascade_invocations --- pkgs/stream_transform/analysis_options.yaml | 2 +- .../lib/src/async_map_buffer.dart | 6 +++--- pkgs/stream_transform/lib/src/buffer.dart | 17 ++++++++------- .../lib/src/combine_latest_all.dart | 19 +++++++++-------- .../stream_transform/lib/src/followed_by.dart | 19 +++++++++-------- .../lib/src/from_handlers.dart | 5 +++-- pkgs/stream_transform/lib/src/merge.dart | 19 +++++++++-------- pkgs/stream_transform/lib/src/switch.dart | 17 ++++++++------- pkgs/stream_transform/lib/src/take_until.dart | 5 +++-- pkgs/stream_transform/lib/src/where_type.dart | 5 +++-- .../test/async_map_buffer_test.dart | 8 +++---- pkgs/stream_transform/test/audit_test.dart | 6 ++---- pkgs/stream_transform/test/buffer_test.dart | 21 +++++++------------ .../test/combine_latest_test.dart | 3 +-- .../test/concurrent_async_map_test.dart | 4 +--- pkgs/stream_transform/test/debounce_test.dart | 12 ++++------- .../test/from_handlers_test.dart | 9 +++----- pkgs/stream_transform/test/switch_test.dart | 6 ++---- .../test/take_until_test.dart | 6 ++---- pkgs/stream_transform/test/throttle_test.dart | 3 +-- .../test/where_type_test.dart | 3 +-- 21 files changed, 89 insertions(+), 106 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index c015ee7bf..20e06b22b 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -30,7 +30,7 @@ linter: - avoid_unused_constructor_parameters - await_only_futures - camel_case_types - #- cascade_invocations + - cascade_invocations - comment_references - constant_identifier_names - control_flow_in_finally diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index f8046668e..fd25a2127 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -28,9 +28,9 @@ import 'from_handlers.dart'; /// pending conversions have finished. StreamTransformer asyncMapBuffer( Future convert(List collected)) { - var workFinished = StreamController(); - // Let the first event through. - workFinished.add(null); + var workFinished = StreamController() + // Let the first event through. + ..add(null); return chainTransformers( buffer(workFinished.stream), _asyncMapThen(convert, workFinished.add)); } diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index b4c937e07..d09d2daf2 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -96,14 +96,15 @@ class _Buffer extends StreamTransformerBase> { onError: controller.addError, onDone: onTriggerDone); } if (!values.isBroadcast) { - controller.onPause = () { - valueSub?.pause(); - triggerSub?.pause(); - }; - controller.onResume = () { - valueSub?.resume(); - triggerSub?.resume(); - }; + controller + ..onPause = () { + valueSub?.pause(); + triggerSub?.pause(); + } + ..onResume = () { + valueSub?.resume(); + triggerSub?.resume(); + }; } controller.onCancel = () { var toCancel = []; diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart index 679f3efd2..16f2e8089 100644 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -87,16 +87,17 @@ class _CombineLatestAll extends StreamTransformerBase> { }); }).toList(); if (!source.isBroadcast) { - controller.onPause = () { - for (var subscription in subscriptions) { - subscription.pause(); + controller + ..onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } } - }; - controller.onResume = () { - for (var subscription in subscriptions) { - subscription.resume(); - } - }; + ..onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; } controller.onCancel = () { final toCancel = subscriptions; diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart index 1705542c3..779831f70 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -63,15 +63,16 @@ class _FollowedBy extends StreamTransformerBase { assert(subscription == null); listen(); if (!first.isBroadcast) { - controller.onPause = () { - if (!firstDone || !next.isBroadcast) return subscription.pause(); - subscription.cancel(); - subscription = null; - }; - controller.onResume = () { - if (!firstDone || !next.isBroadcast) return subscription.resume(); - listen(); - }; + controller + ..onPause = () { + if (!firstDone || !next.isBroadcast) return subscription.pause(); + subscription.cancel(); + subscription = null; + } + ..onResume = () { + if (!firstDone || !next.isBroadcast) return subscription.resume(); + listen(); + }; } controller.onCancel = () { if (secondDone) return null; diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 99f71cbd7..4f7701d72 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -64,8 +64,9 @@ class _StreamTransformer extends StreamTransformerBase { _handleDone(controller); }); if (!values.isBroadcast) { - controller.onPause = subscription.pause; - controller.onResume = subscription.resume; + controller + ..onPause = subscription.pause + ..onResume = subscription.resume; } controller.onCancel = () { var toCancel = subscription; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 82aa06ab8..a5b4cf33f 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -52,16 +52,17 @@ class _Merge extends StreamTransformerBase { }); }).toList(); if (!first.isBroadcast) { - controller.onPause = () { - for (var subscription in subscriptions) { - subscription.pause(); + controller + ..onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } } - }; - controller.onResume = () { - for (var subscription in subscriptions) { - subscription.resume(); - } - }; + ..onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; } controller.onCancel = () { var toCancel = subscriptions; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 54dc843cb..2f247045c 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -58,14 +58,15 @@ class _SwitchTransformer extends StreamTransformerBase, T> { if (innerSubscription == null) controller.close(); }); if (!outer.isBroadcast) { - controller.onPause = () { - innerSubscription?.pause(); - outerSubscription.pause(); - }; - controller.onResume = () { - innerSubscription?.resume(); - outerSubscription.resume(); - }; + controller + ..onPause = () { + innerSubscription?.pause(); + outerSubscription.pause(); + } + ..onResume = () { + innerSubscription?.resume(); + outerSubscription.resume(); + }; } controller.onCancel = () { var toCancel = []; diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 522ef30c4..62b10131e 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -41,8 +41,9 @@ class _TakeUntil extends StreamTransformerBase { controller.close(); }); if (!values.isBroadcast) { - controller.onPause = subscription.pause; - controller.onResume = subscription.resume; + controller + ..onPause = subscription.pause + ..onResume = subscription.resume; } controller.onCancel = () { if (isDone) return null; diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart index 6e5b08f2e..9164f912d 100644 --- a/pkgs/stream_transform/lib/src/where_type.dart +++ b/pkgs/stream_transform/lib/src/where_type.dart @@ -41,8 +41,9 @@ class _WhereType extends StreamTransformerBase { controller.close(); }); if (!source.isBroadcast) { - controller.onPause = subscription.pause; - controller.onResume = subscription.resume; + controller + ..onPause = subscription.pause + ..onResume = subscription.resume; } controller.onCancel = () { subscription?.cancel(); diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index f96092aae..bf7b9d629 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -76,8 +76,7 @@ void main() { test('buffers values while work is ongoing', () async { values.add(1); await Future(() {}); - values.add(2); - values.add(3); + values..add(2)..add(3); await Future(() {}); finishWork.complete(); await Future(() {}); @@ -116,8 +115,9 @@ void main() { () async { values.add(1); await Future(() {}); - values.addError('error'); - values.add(2); + values + ..addError('error') + ..add(2); await Future(() {}); expect(errors, ['error']); // [work] will assert that the second iteration is not called because diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 55a327e3f..71925fd29 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -51,8 +51,7 @@ void main() { }); test('swallows values that come faster than duration', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [2]); @@ -99,8 +98,7 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values.add(1); - values.add(2); + values..add(1)..add(2); await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 835a7ebf7..2461085b1 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -80,11 +80,9 @@ void main() { }); test('two triggers in a row - emit then emit next value', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); - trigger.add(null); - trigger.add(null); + trigger..add(null)..add(null); await Future(() {}); values.add(3); await Future(() {}); @@ -97,8 +95,7 @@ void main() { test('pre-emptive trigger then trigger after values', () async { trigger.add(null); await Future(() {}); - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); trigger.add(null); await Future(() {}); @@ -109,11 +106,9 @@ void main() { }); test('multiple pre-emptive triggers, only emits first value', () async { - trigger.add(null); - trigger.add(null); + trigger..add(null)..add(null); await Future(() {}); - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [ [1] @@ -121,12 +116,10 @@ void main() { }); test('groups values between trigger', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); trigger.add(null); - values.add(3); - values.add(4); + values..add(3)..add(4); await Future(() {}); trigger.add(null); await Future(() {}); diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index cbe30507c..e3987c7d7 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -52,8 +52,7 @@ void main() { .transform(combineLatest(other.stream, times)) .forEach(results.add)); - source.add('a'); - source.add('b'); + source..add('a')..add('b'); await Future(() {}); expect(results, isEmpty); diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index 531e94128..d26ed0391 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -63,9 +63,7 @@ void main() { }); test('allows calls to convert before the last one finished', () async { - streamController.add(1); - streamController.add(2); - streamController.add(3); + streamController..add(1)..add(2)..add(3); await Future(() {}); expect(values, [1, 2, 3]); }); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index a5dc4b6fb..aa629db1d 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -51,8 +51,7 @@ void main() { }); test('swallows values that come faster than duration', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [2]); @@ -89,8 +88,7 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values.add(1); - values.add(2); + values..add(1)..add(2); await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); @@ -104,8 +102,7 @@ void main() { }); test('Emits all values as a list', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [ @@ -129,8 +126,7 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values.add(1); - values.add(2); + values..add(1)..add(2); await waitForTimer(5); expect(emittedValues, [ [1, 2] diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index d77f676cb..1953b294a 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -45,8 +45,7 @@ void main() { }); test('forwards values', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [1, 2]); }); @@ -90,8 +89,7 @@ void main() { }); test('forwards values', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [1, 2]); expect(emittedValues2, [1, 2]); @@ -128,8 +126,7 @@ void main() { })); }); test('uses transform from handleData', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [2, 3]); }); diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 8fb190df1..d73e7a8b2 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -53,14 +53,12 @@ void main() { test('forwards events', () async { outer.add(first.stream); await Future(() {}); - first.add(1); - first.add(2); + first..add(1)..add(2); await Future(() {}); outer.add(second.stream); await Future(() {}); - second.add(3); - second.add(4); + second..add(3)..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 3c7bb1bef..e7614da86 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -47,8 +47,7 @@ void main() { }); test('lets values through before trigger', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [1, 2]); }); @@ -80,8 +79,7 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values.add(1); - values.add(2); + values..add(1)..add(2); await Future(() {}); expect(emittedValues, [1, 2]); expect(otherValues, [1, 2]); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index b0b839d7f..524f0c0db 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -51,8 +51,7 @@ void main() { }); test('swallows values that come faster than duration', () async { - values.add(1); - values.add(2); + values..add(1)..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [1]); diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart index 2c6d7ed5a..75062c2ce 100644 --- a/pkgs/stream_transform/test/where_type_test.dart +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -41,8 +41,7 @@ void main() { filtered ..listen(null, onDone: () => firstDone = true) ..listen(null, onDone: () => secondDone = true); - values.add(1); - values.add('a'); + values..add(1)..add('a'); await values.close(); expect(firstDone, true); expect(secondDone, true); From 252870cd27ddcf74ac1633aeaf71f8c0a0e1f602 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 14:59:56 -0700 Subject: [PATCH 0524/1215] Enforce and fix prefer_const_constructors --- pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/test/combine_latest_test.dart | 6 +++--- pkgs/stream_transform/test/scan_test.dart | 3 ++- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 20e06b22b..906ceb0a8 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -59,7 +59,7 @@ linter: - prefer_adjacent_string_concatenation - prefer_collection_literals - prefer_conditional_assignment - #- prefer_const_constructors + - prefer_const_constructors - prefer_contains - prefer_equal_for_default_values - prefer_final_fields diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index e3987c7d7..f8156bce4 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -92,7 +92,7 @@ void main() { test('ends if source stream closes without ever emitting a value', () async { - var source = Stream.empty(); + var source = const Stream.empty(); var other = StreamController(); int sum(int a, int b) => a + b; @@ -109,7 +109,7 @@ void main() { test('ends if other stream closes without ever emitting a value', () async { var source = StreamController(); - var other = Stream.empty(); + var other = const Stream.empty(); int sum(int a, int b) => a + b; @@ -178,4 +178,4 @@ class _NumberedException implements Exception { } Matcher _isException(int id) => - TypeMatcher<_NumberedException>().having((n) => n.id, 'id', id); + const TypeMatcher<_NumberedException>().having((n) => n.id, 'id', id); diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 71472a6ee..6c4f41a8b 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -57,7 +57,8 @@ void main() { .transform(scan>(Future.value(0), sum)) .toList(); - expect(result, [TypeMatcher(), TypeMatcher()]); + expect( + result, [const TypeMatcher(), const TypeMatcher()]); expect(await Future.wait(result), [1, 3]); }); From cd105dba05dd931ef84b62c2afa5914eab178e9a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 15:01:26 -0700 Subject: [PATCH 0525/1215] Enforce and fix prefer_typting_uninitialized_variables --- pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/test/tap_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 906ceb0a8..9d680af19 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -69,7 +69,7 @@ linter: - prefer_is_not_empty - prefer_null_aware_operators - prefer_single_quotes - #- prefer_typing_uninitialized_variables + - prefer_typing_uninitialized_variables - recursive_getters - slash_for_doc_comments - test_types_in_equals diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 989c3423e..3b52442e5 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -23,7 +23,7 @@ void main() { }); test('calls function for errors', () async { - var error; + dynamic error; var source = StreamController(); source.stream .transform(tap((_) {}, onError: (e, st) { @@ -36,7 +36,7 @@ void main() { }); test('forwards errors', () async { - var error; + dynamic error; var source = StreamController(); source.stream.transform(tap((_) {}, onError: (e, st) {})).listen((_) {}, onError: (e) { From 6901653c823be59df186553b547536b7bad9cbab Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 15:02:10 -0700 Subject: [PATCH 0526/1215] Enforce and mark for unawaited_futures --- pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/test/scan_test.dart | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 9d680af19..ecc45a638 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -75,7 +75,7 @@ linter: - test_types_in_equals - throw_in_finally - type_init_formals - #- unawaited_futures + - unawaited_futures - unnecessary_brace_in_string_interps - unnecessary_const - unnecessary_getters_setters diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 6c4f41a8b..7fe7bf9e1 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; @@ -75,7 +76,8 @@ void main() { var results = []; - source.stream.transform(scan(0, combine)).forEach(results.add); + unawaited( + source.stream.transform(scan(0, combine)).forEach(results.add)); source..add(1)..add(2); await Future(() {}); From 62cd8f50f678408c266248604530636c788e50bb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 12 Mar 2019 15:02:44 -0700 Subject: [PATCH 0527/1215] Enforce and fix unnecessary_parenthesis --- pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/test/followd_by_test.dart | 2 +- pkgs/stream_transform/test/merge_test.dart | 2 +- pkgs/stream_transform/test/scan_test.dart | 4 ++-- pkgs/stream_transform/test/tap_test.dart | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index ecc45a638..82dd7e892 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -82,7 +82,7 @@ linter: - unnecessary_lambdas - unnecessary_new - unnecessary_null_aware_assignments - #- unnecessary_parenthesis + - unnecessary_parenthesis - unnecessary_statements - unnecessary_this - unnecessary_overrides diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 956bf23a2..0e8853dd9 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -132,7 +132,7 @@ void main() { await Future(() {}); subscription = transformed.listen(emittedValues.add); second.add(3); - await Future((() {})); + await Future(() {}); expect(emittedValues, [3]); }); diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index cf576ac7a..4d3050ad5 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -54,7 +54,7 @@ void main() { var first = StreamController.broadcast(); var second = StreamController(); var emittedValues = []; - var transformed = first.stream.transform((merge(second.stream))); + var transformed = first.stream.transform(merge(second.stream)); var subscription = transformed.listen(emittedValues.add); first.add(1); second.add(2); diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 7fe7bf9e1..f321539f1 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -34,7 +34,7 @@ void main() { var errors = []; - source.stream.transform((scan(0, sum))).listen(null, onError: errors.add); + source.stream.transform(scan(0, sum)).listen(null, onError: errors.add); source.addError(StateError('fail')); await Future(() {}); @@ -98,7 +98,7 @@ void main() { var errors = []; source.stream - .transform((scan(0, combine))) + .transform(scan(0, combine)) .listen(null, onError: errors.add); source.add(1); diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 3b52442e5..816c80f53 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -51,9 +51,9 @@ void main() { var doneCalled = false; var source = StreamController(); source.stream - .transform((tap((_) {}, onDone: () { + .transform(tap((_) {}, onDone: () { doneCalled = true; - }))) + })) .listen((_) {}); await source.close(); expect(doneCalled, true); From 252cf306bd38de13ee48032bc0eaacb47bc165d3 Mon Sep 17 00:00:00 2001 From: Brett Peters Date: Tue, 12 Mar 2019 15:33:48 -0700 Subject: [PATCH 0528/1215] Add missing copyright header (dart-lang/stream_transform#70) --- pkgs/stream_transform/test/combine_latest_all_test.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart index 9cf3a9152..cdfedb0be 100644 --- a/pkgs/stream_transform/test/combine_latest_all_test.dart +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -1,5 +1,11 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + import 'dart:async'; + import 'package:test/test.dart'; + import 'package:stream_transform/stream_transform.dart'; Future tick() => Future(() {}); From 073f53ffe0e198400fd7db918906fd8a19a48533 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Mar 2019 09:59:42 -0700 Subject: [PATCH 0529/1215] Remove usage of Set literal (dart-lang/stream_transform#72) Fixes dart-lang/stream_transform#71 --- pkgs/stream_transform/.travis.yml | 4 ++-- pkgs/stream_transform/CHANGELOG.md | 4 ++++ pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/lib/src/combine_latest_all.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index d18b3db46..e09a3da1c 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -2,9 +2,9 @@ language: dart branches: only: [master] dart: - # Skipping dev until Dart 2.1.0-dev is out - #- dev + - dev - stable + - 2.1.0 cache: directories: - $HOME/.pub-cache diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index d50c11991..25a42a7ea 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.16+1 + +- Remove usage of Set literal which is not available before Dart 2.2.0 + ## 0.0.16 - Allow a `combine` callback to return a `FutureOr` in `scan`. There are no diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 82dd7e892..6c2853e65 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -57,7 +57,7 @@ linter: - package_names - package_prefixed_library_names - prefer_adjacent_string_concatenation - - prefer_collection_literals + #- prefer_collection_literals - prefer_conditional_assignment - prefer_const_constructors - prefer_contains diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart index 16f2e8089..913c3ce0c 100644 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -66,7 +66,7 @@ class _CombineLatestAll extends StreamTransformerBase> { assert(subscriptions == null); final latestData = List(allStreams.length); - final hasEmitted = {}; + final hasEmitted = Set(); void handleData(int index, T data) { latestData[index] = data; hasEmitted.add(index); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c0768e920..a68102415 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,11 +2,11 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.16 +version: 0.0.16+1 environment: sdk: ">=2.1.0 <3.0.0" dev_dependencies: - pedantic: ^1.5.0 + pedantic: ^1.4.0 test: ^1.0.0 From ccea7594e1bead5bb823654db1708da8792491a9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Mar 2019 10:14:39 -0700 Subject: [PATCH 0530/1215] Bump minimum SDK to 2.2.0 (dart-lang/stream_transform#73) --- pkgs/stream_transform/.travis.yml | 1 - pkgs/stream_transform/analysis_options.yaml | 2 +- pkgs/stream_transform/lib/src/combine_latest_all.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 6 +++--- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index e09a3da1c..e6d16f66a 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -4,7 +4,6 @@ branches: dart: - dev - stable - - 2.1.0 cache: directories: - $HOME/.pub-cache diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 6c2853e65..82dd7e892 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -57,7 +57,7 @@ linter: - package_names - package_prefixed_library_names - prefer_adjacent_string_concatenation - #- prefer_collection_literals + - prefer_collection_literals - prefer_conditional_assignment - prefer_const_constructors - prefer_contains diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart index 913c3ce0c..16f2e8089 100644 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -66,7 +66,7 @@ class _CombineLatestAll extends StreamTransformerBase> { assert(subscriptions == null); final latestData = List(allStreams.length); - final hasEmitted = Set(); + final hasEmitted = {}; void handleData(int index, T data) { latestData[index] = data; hasEmitted.add(index); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index a68102415..d61018e0a 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,11 +2,11 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.16+1 +version: 0.0.17-dev environment: - sdk: ">=2.1.0 <3.0.0" + sdk: ">=2.2.0 <3.0.0" dev_dependencies: - pedantic: ^1.4.0 + pedantic: ^1.5.0 test: ^1.0.0 From d39ec7236934dd3eec2d0c56f80d69e3e4b679a6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Mar 2019 12:35:40 -0700 Subject: [PATCH 0531/1215] Explicitly test on earliest supported stable SDK (dart-lang/stream_transform#74) This way when a new stable is released it won't stop the tests on a supported SDK version. --- pkgs/stream_transform/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index e6d16f66a..5cdff4c35 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,7 +3,7 @@ branches: only: [master] dart: - dev - - stable + - 2.2.0 cache: directories: - $HOME/.pub-cache From 8ac2af02cae51b40aa092b52934ebda888acd1a0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 13 Mar 2019 13:10:23 -0700 Subject: [PATCH 0532/1215] Test analysis on oldest supported SDK (dart-lang/pubspec_parse#41) --- pkgs/pubspec_parse/.travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index 3af3939c7..b82f2f3e5 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -2,7 +2,6 @@ language: dart dart: - dev - - stable dart_task: - test: -x presubmit-only @@ -14,7 +13,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: stable + - dart: 2.0.0 dart_task: dartanalyzer: --fatal-warnings . From 34adff9928e2759e308450655de32be7f1983eda Mon Sep 17 00:00:00 2001 From: Graham Rogers Date: Tue, 26 Mar 2019 00:31:35 +0000 Subject: [PATCH 0533/1215] Make tap's onError arguments have specific types (dart-lang/stream_transform#75) Currently onError has type void Function(dynamic, dynamic). This causes a problem with something like: void myOnError(Object error, StackTrace stackTrace) {} stream.transform(tap(null, onError: myOnError)).listen(null); As that causes an error: type '(Object, StackTrace) => void' is not a subtype of type '(dynamic, dynamic) => void' Note that (dynamic, dynamic) => void is a subtype of (Object, StackTrace) => void, so any function that can be passed to the old version can also be passed to the new one. --- pkgs/stream_transform/lib/src/tap.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index bfed97ceb..1b799fa4c 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -22,8 +22,8 @@ import 'from_handlers.dart'; /// /// The callbacks may not be called until the tapped stream has a listener, and /// may not be called after the listener has canceled the subscription. -StreamTransformer tap(void onValue(T value), - {void onError(error, stackTrace), void onDone()}) => +StreamTransformer tap(void Function(T) onValue, + {void Function(Object, StackTrace) onError, void Function() onDone}) => fromHandlers(handleData: (value, sink) { try { onValue?.call(value); From 13aa1c3dd46b2d3a3e998cebd24870b10c0c53e0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Mar 2019 09:22:06 -0700 Subject: [PATCH 0534/1215] Prepare to release 0.0.17 (dart-lang/stream_transform#76) Add a changelog and bump the version. --- pkgs/stream_transform/CHANGELOG.md | 4 ++++ pkgs/stream_transform/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 25a42a7ea..9b8ab296d 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.17 + +- Add concrete types to the `onError` callback in `tap`. + ## 0.0.16+1 - Remove usage of Set literal which is not available before Dart 2.2.0 diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index d61018e0a..a9be96848 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.17-dev +version: 0.0.17 environment: sdk: ">=2.2.0 <3.0.0" From 3191148f2fa5311d55bf717678e2e8d9dc3bece4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Mar 2019 14:00:09 -0700 Subject: [PATCH 0535/1215] Remove optional new/const (dart-lang/stream_channel#37) - Run `dartfmt --fix`. - Update version to start working towards next breaking change. - Update minimum SDK to 2.0.0 stable. --- pkgs/stream_channel/CHANGELOG.md | 5 +++ .../lib/src/close_guarantee_channel.dart | 4 +-- pkgs/stream_channel/lib/src/disconnector.dart | 22 ++++++------- .../lib/src/guarantee_channel.dart | 31 +++++++++---------- .../lib/src/isolate_channel.dart | 27 +++++++--------- .../lib/src/json_document_transformer.dart | 8 ++--- .../stream_channel/lib/src/multi_channel.dart | 22 ++++++------- .../lib/src/stream_channel_completer.dart | 15 +++++---- .../lib/src/stream_channel_controller.dart | 10 +++--- .../lib/src/stream_channel_transformer.dart | 6 ++-- pkgs/stream_channel/lib/stream_channel.dart | 14 ++++----- pkgs/stream_channel/pubspec.yaml | 4 +-- .../test/disconnector_test.dart | 28 ++++++++--------- .../test/isolate_channel_test.dart | 22 ++++++------- .../test/json_document_transformer_test.dart | 20 ++++++------ .../test/multi_channel_test.dart | 6 ++-- .../test/stream_channel_completer_test.dart | 14 ++++----- .../test/stream_channel_controller_test.dart | 6 ++-- .../test/stream_channel_test.dart | 22 ++++++------- .../test/with_close_guarantee_test.dart | 12 +++---- .../test/with_guarantees_test.dart | 24 +++++++------- 21 files changed, 159 insertions(+), 163 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ce98fe038..87ba42fe7 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.6.9 + +* Require `2.0.0` or newer SDK. +* Drop unnecessary `new` and `const`. + ## 1.6.8 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index a2c69bcb8..b8a3f0289 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -27,8 +27,8 @@ class CloseGuaranteeChannel extends StreamChannelMixin { bool _disconnected = false; CloseGuaranteeChannel(Stream innerStream, StreamSink innerSink) { - _sink = new _CloseGuaranteeSink(innerSink, this); - _stream = new _CloseGuaranteeStream(innerStream, this); + _sink = _CloseGuaranteeSink(innerSink, this); + _stream = _CloseGuaranteeStream(innerStream, this); } } diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 37a376c31..9d35cfc63 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,11 +38,11 @@ class Disconnector implements StreamChannelTransformer { _sinks.clear(); return Future.wait(futures, eagerError: true); }); - final _disconnectMemo = new AsyncMemoizer(); + final _disconnectMemo = AsyncMemoizer(); StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { - var sink = new _DisconnectorSink(innerSink); + var sink = _DisconnectorSink(innerSink); if (isDisconnected) { // Ignore errors here, because otherwise there would be no way for the @@ -84,9 +84,9 @@ class _DisconnectorSink implements StreamSink { _DisconnectorSink(this._inner); void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_isDisconnected) return; @@ -94,9 +94,9 @@ class _DisconnectorSink implements StreamSink { } void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_isDisconnected) return; @@ -104,13 +104,13 @@ class _DisconnectorSink implements StreamSink { } Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); + if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); + throw StateError("Cannot add stream while adding stream."); } - if (_isDisconnected) return new Future.value(); + if (_isDisconnected) return Future.value(); - _addStreamCompleter = new Completer.sync(); + _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, onError: _inner.addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { @@ -121,7 +121,7 @@ class _DisconnectorSink implements StreamSink { Future close() { if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); + throw StateError("Cannot close sink while adding stream."); } _closed = true; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index ba79ed9bc..e96f5c3c8 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -31,18 +31,17 @@ class GuaranteeChannel extends StreamChannelMixin { bool _disconnected = false; GuaranteeChannel(Stream innerStream, StreamSink innerSink, - {bool allowSinkErrors: true}) { - _sink = - new _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); + {bool allowSinkErrors = true}) { + _sink = _GuaranteeSink(innerSink, this, allowErrors: allowSinkErrors); // Enforce the single-subscription guarantee by changing a broadcast stream // to single-subscription. if (innerStream.isBroadcast) { innerStream = - innerStream.transform(new SingleSubscriptionTransformer()); + innerStream.transform(SingleSubscriptionTransformer()); } - _streamController = new StreamController( + _streamController = StreamController( onListen: () { // If the sink has disconnected, we've already called // [_streamController.close]. @@ -80,7 +79,7 @@ class _GuaranteeSink implements StreamSink { final GuaranteeChannel _channel; Future get done => _doneCompleter.future; - final _doneCompleter = new Completer(); + final _doneCompleter = Completer(); /// Whether connection is disconnected. /// @@ -108,13 +107,13 @@ class _GuaranteeSink implements StreamSink { /// the underlying sink is closed. final bool _allowErrors; - _GuaranteeSink(this._inner, this._channel, {bool allowErrors: true}) + _GuaranteeSink(this._inner, this._channel, {bool allowErrors = true}) : _allowErrors = allowErrors; void add(T data) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_disconnected) return; @@ -122,9 +121,9 @@ class _GuaranteeSink implements StreamSink { } void addError(error, [StackTrace stackTrace]) { - if (_closed) throw new StateError("Cannot add event after closing."); + if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { - throw new StateError("Cannot add event while adding stream."); + throw StateError("Cannot add event while adding stream."); } if (_disconnected) return; @@ -153,13 +152,13 @@ class _GuaranteeSink implements StreamSink { } Future addStream(Stream stream) { - if (_closed) throw new StateError("Cannot add stream after closing."); + if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { - throw new StateError("Cannot add stream while adding stream."); + throw StateError("Cannot add stream while adding stream."); } - if (_disconnected) return new Future.value(); + if (_disconnected) return Future.value(); - _addStreamCompleter = new Completer.sync(); + _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, onError: _addError, onDone: _addStreamCompleter.complete); return _addStreamCompleter.future.then((_) { @@ -170,7 +169,7 @@ class _GuaranteeSink implements StreamSink { Future close() { if (_inAddStream) { - throw new StateError("Cannot close sink while adding stream."); + throw StateError("Cannot close sink while adding stream."); } if (_closed) return done; diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index d785ae118..c7f573fd2 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -41,10 +41,10 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel.connectReceive(ReceivePort receivePort) { // We can't use a [StreamChannelCompleter] here because we need the return // value to be an [IsolateChannel]. - var streamCompleter = new StreamCompleter(); - var sinkCompleter = new StreamSinkCompleter(); + var streamCompleter = StreamCompleter(); + var sinkCompleter = StreamSinkCompleter(); var channel = - new IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); + IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error @@ -52,11 +52,9 @@ class IsolateChannel extends StreamChannelMixin { StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { - var controller = new StreamChannelController( - allowForeignErrors: false, sync: true); - new SubscriptionStream(subscription) - .cast() - .pipe(controller.local.sink); + var controller = + StreamChannelController(allowForeignErrors: false, sync: true); + SubscriptionStream(subscription).cast().pipe(controller.local.sink); controller.local.stream .listen((data) => message.send(data), onDone: receivePort.close); @@ -66,9 +64,9 @@ class IsolateChannel extends StreamChannelMixin { } streamCompleter.setError( - new StateError('Unexpected Isolate response "$message".'), + StateError('Unexpected Isolate response "$message".'), StackTrace.current); - sinkCompleter.setDestinationSink(new NullStreamSink()); + sinkCompleter.setDestinationSink(NullStreamSink()); subscription.cancel(); }); @@ -85,21 +83,20 @@ class IsolateChannel extends StreamChannelMixin { /// The connection protocol is guaranteed to remain compatible across versions /// at least until the next major version release. factory IsolateChannel.connectSend(SendPort sendPort) { - var receivePort = new ReceivePort(); + var receivePort = ReceivePort(); sendPort.send(receivePort.sendPort); - return new IsolateChannel(receivePort, sendPort); + return IsolateChannel(receivePort, sendPort); } /// Creates a stream channel that receives messages from [receivePort] and /// sends them over [sendPort]. factory IsolateChannel(ReceivePort receivePort, SendPort sendPort) { var controller = - new StreamChannelController(allowForeignErrors: false, sync: true); + StreamChannelController(allowForeignErrors: false, sync: true); receivePort.cast().pipe(controller.local.sink); controller.local.stream .listen((data) => sendPort.send(data), onDone: receivePort.close); - return new IsolateChannel._( - controller.foreign.stream, controller.foreign.sink); + return IsolateChannel._(controller.foreign.stream, controller.foreign.sink); } IsolateChannel._(this.stream, this.sink); diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 6377eeda7..2a3a86f3e 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -10,7 +10,7 @@ import '../stream_channel.dart'; import 'stream_channel_transformer.dart'; /// The canonical instance of [JsonDocumentTransformer]. -final jsonDocument = new JsonDocumentTransformer(); +final jsonDocument = JsonDocumentTransformer(); /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. @@ -31,16 +31,16 @@ class JsonDocumentTransformer /// The [reviver] and [toEncodable] arguments work the same way as the /// corresponding arguments to [new JsonCodec]. JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) - : _codec = new JsonCodec(reviver: reviver, toEncodable: toEncodable); + : _codec = JsonCodec(reviver: reviver, toEncodable: toEncodable); JsonDocumentTransformer._(this._codec); StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); - var sink = new StreamSinkTransformer.fromHandlers( + var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { sink.add(_codec.encode(data)); }).bind(channel.sink); - return new StreamChannel.withCloseGuarantee(stream, sink); + return StreamChannel.withCloseGuarantee(stream, sink); } } diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a6d684a13..139c9aefa 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -58,8 +58,7 @@ abstract class MultiChannel implements StreamChannel { /// [inner]. /// /// The inner channel must take JSON-like objects. - factory MultiChannel(StreamChannel inner) => - new _MultiChannel(inner); + factory MultiChannel(StreamChannel inner) => _MultiChannel(inner); /// Creates a new virtual channel. /// @@ -93,7 +92,7 @@ class _MultiChannel extends StreamChannelMixin StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. - final _mainController = new StreamChannelController(sync: true); + final _mainController = StreamChannelController(sync: true); /// A map from input IDs to [StreamChannelController]s that should be used to /// communicate over those channels. @@ -101,11 +100,11 @@ class _MultiChannel extends StreamChannelMixin /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. - final _pendingIds = new Set(); + final _pendingIds = Set(); /// Input IDs of virtual channels that used to exist but have since been /// closed. - final _closedIds = new Set(); + final _closedIds = Set(); /// The next id to use for a local virtual channel. /// @@ -149,7 +148,7 @@ class _MultiChannel extends StreamChannelMixin // counterpart yet, create a controller for it to buffer incoming // messages for when a local connection is created. _pendingIds.add(id); - return new StreamChannelController(sync: true); + return StreamChannelController(sync: true); }); if (message.length > 1) { @@ -187,8 +186,7 @@ class _MultiChannel extends StreamChannelMixin // If the inner channel has already closed, create new virtual channels in a // closed state. if (_inner == null) { - return new VirtualChannel._( - this, inputId, new Stream.empty(), new NullStreamSink()); + return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); } StreamChannelController controller; @@ -198,16 +196,16 @@ class _MultiChannel extends StreamChannelMixin controller = _controllers[inputId]; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { - throw new ArgumentError("A virtual channel with id $id already exists."); + throw ArgumentError("A virtual channel with id $id already exists."); } else { - controller = new StreamChannelController(sync: true); + controller = StreamChannelController(sync: true); _controllers[inputId] = controller; } controller.local.stream.listen( (message) => _inner.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); - return new VirtualChannel._( + return VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); } @@ -234,7 +232,7 @@ class _MultiChannel extends StreamChannelMixin // Convert this to a list because the close is dispatched synchronously, and // that could conceivably remove a controller from [_controllers]. - for (var controller in new List.from(_controllers.values)) { + for (var controller in List.from(_controllers.values)) { controller.local.sink.close(); } _controllers.clear(); diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index b9881b913..e94eda66e 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -15,10 +15,10 @@ import '../stream_channel.dart'; /// any events and all events added to it will be buffered. class StreamChannelCompleter { /// The completer for this channel's stream. - final _streamCompleter = new StreamCompleter(); + final _streamCompleter = StreamCompleter(); /// The completer for this channel's sink. - final _sinkCompleter = new StreamSinkCompleter(); + final _sinkCompleter = StreamSinkCompleter(); /// The channel for this completer. StreamChannel get channel => _channel; @@ -36,14 +36,13 @@ class StreamChannelCompleter { /// instead contain just that error. The sink will silently discard all /// events. static StreamChannel fromFuture(Future channelFuture) { - var completer = new StreamChannelCompleter(); + var completer = StreamChannelCompleter(); channelFuture.then(completer.setChannel, onError: completer.setError); return completer.channel; } StreamChannelCompleter() { - _channel = - new StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); + _channel = StreamChannel(_streamCompleter.stream, _sinkCompleter.sink); } /// Set a channel as the source and destination for [channel]. @@ -53,7 +52,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setChannel(StreamChannel channel) { - if (_set) throw new StateError("The channel has already been set."); + if (_set) throw StateError("The channel has already been set."); _set = true; _streamCompleter.setSourceStream(channel.stream); @@ -68,10 +67,10 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setError(error, [StackTrace stackTrace]) { - if (_set) throw new StateError("The channel has already been set."); + if (_set) throw StateError("The channel has already been set."); _set = true; _streamCompleter.setError(error, stackTrace); - _sinkCompleter.setDestinationSink(new NullStreamSink()); + _sinkCompleter.setDestinationSink(NullStreamSink()); } } diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 146e99667..136886df7 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -52,12 +52,12 @@ class StreamChannelController { /// the foreign channel's sink. If any are, the connection will close and the /// error will be forwarded to the foreign channel's [StreamSink.done] future. /// This guarantees that the local stream will never emit errors. - StreamChannelController({bool allowForeignErrors: true, bool sync: false}) { - var localToForeignController = new StreamController(sync: sync); - var foreignToLocalController = new StreamController(sync: sync); - _local = new StreamChannel.withGuarantees( + StreamChannelController({bool allowForeignErrors = true, bool sync = false}) { + var localToForeignController = StreamController(sync: sync); + var foreignToLocalController = StreamController(sync: sync); + _local = StreamChannel.withGuarantees( foreignToLocalController.stream, localToForeignController.sink); - _foreign = new StreamChannel.withGuarantees( + _foreign = StreamChannel.withGuarantees( localToForeignController.stream, foreignToLocalController.sink, allowSinkErrors: allowForeignErrors); } diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index cc9bad881..32d36b6b0 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -45,7 +45,7 @@ class StreamChannelTransformer { StreamChannelTransformer transformer) => transformer is StreamChannelTransformer ? transformer - : new TypeSafeStreamChannelTransformer(transformer); + : TypeSafeStreamChannelTransformer(transformer); /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. @@ -58,7 +58,7 @@ class StreamChannelTransformer { /// and all output from its stream is decoded using [Codec.decoder]. StreamChannelTransformer.fromCodec(Codec codec) : this(codec.decoder, - new StreamSinkTransformer.fromStreamTransformer(codec.encoder)); + StreamSinkTransformer.fromStreamTransformer(codec.encoder)); /// Transforms the events sent to and emitted by [channel]. /// @@ -68,7 +68,7 @@ class StreamChannelTransformer { /// `channel.straem`, the transformer will transform them and pass the /// transformed versions to the returned channel's stream. StreamChannel bind(StreamChannel channel) => - new StreamChannel.withCloseGuarantee( + StreamChannel.withCloseGuarantee( channel.stream.transform(_streamTransformer), _sinkTransformer.bind(channel.sink)); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index ce3cf04a7..b50116044 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -72,7 +72,7 @@ abstract class StreamChannel { /// [StreamChannel] documentation. If they don't do so natively, /// [StreamChannel.withGuarantees] should be used instead. factory StreamChannel(Stream stream, StreamSink sink) => - new _StreamChannel(stream, sink); + _StreamChannel(stream, sink); /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// @@ -85,8 +85,8 @@ abstract class StreamChannel { /// [sink]. If any are, the connection will close and the error will be /// forwarded to [sink].done. factory StreamChannel.withGuarantees(Stream stream, StreamSink sink, - {bool allowSinkErrors: true}) => - new GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); + {bool allowSinkErrors = true}) => + GuaranteeChannel(stream, sink, allowSinkErrors: allowSinkErrors); /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// @@ -99,7 +99,7 @@ abstract class StreamChannel { /// [StreamChannel.withGuarantees]. factory StreamChannel.withCloseGuarantee( Stream stream, StreamSink sink) => - new CloseGuaranteeChannel(stream, sink); + CloseGuaranteeChannel(stream, sink); /// Connects this to [other], so that any values emitted by either are sent /// directly to the other. @@ -162,11 +162,11 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); StreamChannel changeStream(Stream change(Stream stream)) => - new StreamChannel.withCloseGuarantee(change(stream), sink); + StreamChannel.withCloseGuarantee(change(stream), sink); StreamChannel changeSink(StreamSink change(StreamSink sink)) => - new StreamChannel.withCloseGuarantee(stream, change(sink)); + StreamChannel.withCloseGuarantee(stream, change(sink)); - StreamChannel cast() => new StreamChannel( + StreamChannel cast() => StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 6b1ace36f..996cd7047 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_channel -version: 1.6.8 +version: 1.6.9 description: An abstraction for two-way communication channels. author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.0.0-dev.17.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: async: '>=1.11.0 <3.0.0' diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 62ef78b54..7b36c29b6 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -14,10 +14,10 @@ void main() { Disconnector disconnector; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - disconnector = new Disconnector(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + disconnector = Disconnector(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink) .transform(disconnector); }); @@ -47,17 +47,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -67,7 +67,7 @@ void main() { test("cancels addStream when disconnected", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); @@ -78,11 +78,11 @@ void main() { }); test("disconnect() returns the close future from the inner sink", () async { - var streamController = new StreamController(); - var sinkController = new StreamController(); - var disconnector = new Disconnector(); - var sink = new _CloseCompleterSink(sinkController.sink); - new StreamChannel.withGuarantees(streamController.stream, sink) + var streamController = StreamController(); + var sinkController = StreamController(); + var disconnector = Disconnector(); + var sink = _CloseCompleterSink(sinkController.sink); + StreamChannel.withGuarantees(streamController.stream, sink) .transform(disconnector); var disconnectFutureFired = false; @@ -140,7 +140,7 @@ void main() { /// returned by [close] using [completer]. class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. - final completer = new Completer(); + final completer = Completer(); _CloseCompleterSink(StreamSink inner) : super(inner); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 4c73ab090..8971972b5 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -15,10 +15,10 @@ void main() { SendPort sendPort; StreamChannel channel; setUp(() { - receivePort = new ReceivePort(); - var receivePortForSend = new ReceivePort(); + receivePort = ReceivePort(); + var receivePortForSend = ReceivePort(); sendPort = receivePortForSend.sendPort; - channel = new IsolateChannel(receivePortForSend, receivePort.sendPort); + channel = IsolateChannel(receivePortForSend, receivePort.sendPort); }); tearDown(() { @@ -46,17 +46,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -107,7 +107,7 @@ void main() { test("the sink closes as soon as an error is added via addStream", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); @@ -128,7 +128,7 @@ void main() { group("connect constructors", () { ReceivePort connectPort; setUp(() { - connectPort = new ReceivePort(); + connectPort = ReceivePort(); }); tearDown(() { @@ -136,8 +136,8 @@ void main() { }); test("create a connected pair of channels", () { - var channel1 = new IsolateChannel.connectReceive(connectPort); - var channel2 = new IsolateChannel.connectSend(connectPort.sendPort); + var channel1 = IsolateChannel.connectReceive(connectPort); + var channel2 = IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); @@ -152,7 +152,7 @@ void main() { test("the receiving channel produces an error if it gets the wrong message", () { - var connectedChannel = new IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); connectPort.sendPort.send("wrong value"); expect(connectedChannel.stream.toList(), throwsStateError); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 6cb97f945..83ee09929 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -13,10 +13,10 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = - new StreamChannel(streamController.stream, sinkController.sink); + StreamChannel(streamController.stream, sinkController.sink); }); test("decodes JSON emitted by the channel", () { @@ -33,16 +33,16 @@ void main() { }); test("supports the reviver function", () { - var transformed = channel.transform( - new JsonDocumentTransformer(reviver: (key, value) => "decoded")); + var transformed = channel + .transform(JsonDocumentTransformer(reviver: (key, value) => "decoded")); streamController.add('{"foo": "bar"}'); expect(transformed.stream.first, completion(equals("decoded"))); }); test("supports the toEncodable function", () { - var transformed = channel.transform( - new JsonDocumentTransformer(toEncodable: (object) => "encoded")); - transformed.sink.add(new Object()); + var transformed = channel + .transform(JsonDocumentTransformer(toEncodable: (object) => "encoded")); + transformed.sink.add(Object()); expect(sinkController.stream.first, completion(equals('"encoded"'))); }); @@ -54,7 +54,7 @@ void main() { test("synchronously throws if an unencodable object is added", () { var transformed = channel.transform(jsonDocument); - expect(() => transformed.sink.add(new Object()), - throwsA(new TypeMatcher())); + expect(() => transformed.sink.add(Object()), + throwsA(TypeMatcher())); }); } diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index ddc4150bb..80c595a39 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -10,9 +10,9 @@ void main() { MultiChannel channel1; MultiChannel channel2; setUp(() { - controller = new StreamChannelController(); - channel1 = new MultiChannel(controller.local); - channel2 = new MultiChannel(controller.foreign); + controller = StreamChannelController(); + channel1 = MultiChannel(controller.local); + channel2 = MultiChannel(controller.foreign); }); group("the default virtual channel", () { diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 666efe9ed..c20f9af11 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -13,11 +13,10 @@ void main() { StreamController sinkController; StreamChannel innerChannel; setUp(() { - completer = new StreamChannelCompleter(); - streamController = new StreamController(); - sinkController = new StreamController(); - innerChannel = - new StreamChannel(streamController.stream, sinkController.sink); + completer = StreamChannelCompleter(); + streamController = StreamController(); + sinkController = StreamController(); + innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); group("when a channel is set before accessing", () { @@ -97,7 +96,7 @@ void main() { group("forFuture", () { test("forwards a StreamChannel", () { var channel = - StreamChannelCompleter.fromFuture(new Future.value(innerChannel)); + StreamChannelCompleter.fromFuture(Future.value(innerChannel)); channel.sink.add(1); channel.sink.close(); streamController.sink.add(2); @@ -108,8 +107,7 @@ void main() { }); test("forwards an error", () { - var channel = - StreamChannelCompleter.fromFuture(new Future.error("oh no")); + var channel = StreamChannelCompleter.fromFuture(Future.error("oh no")); expect(channel.stream.toList(), throwsA("oh no")); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 483b7f6f1..62f883fa5 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -9,7 +9,7 @@ void main() { group("asynchronously", () { StreamChannelController controller; setUp(() { - controller = new StreamChannelController(); + controller = StreamChannelController(); }); test("forwards events from the local sink to the foreign stream", () { @@ -33,7 +33,7 @@ void main() { test( "with allowForeignErrors: false, shuts down the connection if an " "error is added to the foreign channel", () { - controller = new StreamChannelController(allowForeignErrors: false); + controller = StreamChannelController(allowForeignErrors: false); controller.foreign.sink.addError("oh no"); expect(controller.foreign.sink.done, throwsA("oh no")); @@ -46,7 +46,7 @@ void main() { group("synchronously", () { StreamChannelController controller; setUp(() { - controller = new StreamChannelController(sync: true); + controller = StreamChannelController(sync: true); }); test( diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index dbe421195..2f05a9ef1 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -14,17 +14,17 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel(streamController.stream, sinkController.sink); + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel(streamController.stream, sinkController.sink); }); test("pipe() pipes data from each channel's stream into the other's sink", () { - var otherStreamController = new StreamController(); - var otherSinkController = new StreamController(); - var otherChannel = new StreamChannel( - otherStreamController.stream, otherSinkController.sink); + var otherStreamController = StreamController(); + var otherSinkController = StreamController(); + var otherChannel = + StreamChannel(otherStreamController.stream, otherSinkController.sink); channel.pipe(otherChannel); streamController.add(1); @@ -43,7 +43,7 @@ void main() { test("transform() transforms the channel", () async { var transformed = channel .cast>() - .transform(new StreamChannelTransformer.fromCodec(utf8)); + .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); streamController.close(); @@ -76,7 +76,7 @@ void main() { test("transformSink() transforms only the sink", () async { var transformed = channel.cast().transformSink( - new StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); + StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); streamController.add("fbl\nthp"); streamController.close(); @@ -91,7 +91,7 @@ void main() { }); test("changeStream() changes the stream", () { - var newController = new StreamController(); + var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); return newController.stream; @@ -107,7 +107,7 @@ void main() { }); test("changeSink() changes the sink", () { - var newController = new StreamController(); + var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); return newController.sink; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 8e1b63119..1749bacb7 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -8,18 +8,18 @@ import 'package:async/async.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; -final _delayTransformer = new StreamTransformer.fromHandlers( - handleData: (data, sink) => new Future.microtask(() => sink.add(data)), - handleDone: (sink) => new Future.microtask(() => sink.close())); +final _delayTransformer = StreamTransformer.fromHandlers( + handleData: (data, sink) => Future.microtask(() => sink.add(data)), + handleDone: (sink) => Future.microtask(() => sink.close())); final _delaySinkTransformer = - new StreamSinkTransformer.fromStreamTransformer(_delayTransformer); + StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { StreamChannelController controller; StreamChannel channel; setUp(() { - controller = new StreamChannelController(); + controller = StreamChannelController(); // Add a bunch of layers of asynchronous dispatch between the channel and // the underlying controllers. @@ -30,7 +30,7 @@ void main() { sink = _delaySinkTransformer.bind(sink); } - channel = new StreamChannel.withCloseGuarantee(stream, sink); + channel = StreamChannel.withCloseGuarantee(stream, sink); }); test( diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index dcdffe089..0ea59525e 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -12,16 +12,16 @@ void main() { StreamController sinkController; StreamChannel channel; setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); group("with a broadcast stream", () { setUp(() { - streamController = new StreamController.broadcast(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController.broadcast(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); @@ -121,17 +121,17 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); test("events can't be added while a stream is being added", () { - var controller = new StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); expect(() => channel.sink.addError("oh no"), throwsStateError); - expect(() => channel.sink.addStream(new Stream.fromIterable([])), + expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -140,9 +140,9 @@ void main() { group("with allowSinkErrors: false", () { setUp(() { - streamController = new StreamController(); - sinkController = new StreamController(); - channel = new StreamChannel.withGuarantees( + streamController = StreamController(); + sinkController = StreamController(); + channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink, allowSinkErrors: false); }); @@ -180,7 +180,7 @@ void main() { "adding an error via via addStream causes the stream to emit a done " "event", () async { var canceled = false; - var controller = new StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); From b86f7a0e74b91682ce3e6889278ea0f7724c4689 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 26 Mar 2019 15:38:48 -0700 Subject: [PATCH 0536/1215] Add separate import for `IsolateChannel` (dart-lang/stream_channel#40) This will allow us to move to this import in the few packages which are using this class, like test, without having a fully broken state in between, and without required `git` dependency overrides. --- pkgs/stream_channel/CHANGELOG.md | 7 +++++-- pkgs/stream_channel/lib/isolate_channel.dart | 5 +++++ pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 1 + 4 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 pkgs/stream_channel/lib/isolate_channel.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 87ba42fe7..68b68a112 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,10 @@ -## 1.6.9 +## 1.7.0 +* Make `IsolateChannel` available through + `package:stream_channel/isolate_channel.dart`. This will be the required + import in the next release. * Require `2.0.0` or newer SDK. -* Drop unnecessary `new` and `const`. +* Internal style changes. ## 1.6.8 diff --git a/pkgs/stream_channel/lib/isolate_channel.dart b/pkgs/stream_channel/lib/isolate_channel.dart new file mode 100644 index 000000000..5d9f6e19f --- /dev/null +++ b/pkgs/stream_channel/lib/isolate_channel.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +export 'src/isolate_channel.dart' show IsolateChannel; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 996cd7047..da152fb39 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.6.9 +version: 1.7.0 description: An abstraction for two-way communication channels. author: Dart Team diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 8971972b5..776928d72 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; From c3babdc1bac5cabeda1d41b48fda4840d7a84d3d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Mar 2019 09:00:36 -0700 Subject: [PATCH 0537/1215] Enforce override annotations (dart-lang/stream_channel#42) --- pkgs/stream_channel/analysis_options.yaml | 1 + pkgs/stream_channel/lib/src/close_guarantee_channel.dart | 4 ++++ .../lib/src/delegating_stream_channel.dart | 2 ++ pkgs/stream_channel/lib/src/disconnector.dart | 6 ++++++ pkgs/stream_channel/lib/src/guarantee_channel.dart | 7 +++++++ pkgs/stream_channel/lib/src/isolate_channel.dart | 2 ++ .../lib/src/json_document_transformer.dart | 1 + pkgs/stream_channel/lib/src/multi_channel.dart | 8 ++++++++ pkgs/stream_channel/lib/src/transformer/typed.dart | 1 + pkgs/stream_channel/lib/stream_channel.dart | 9 +++++++++ pkgs/stream_channel/test/disconnector_test.dart | 1 + 11 files changed, 42 insertions(+) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index d19ee843f..866c1585a 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,5 +8,6 @@ analyzer: linter: rules: + - annotate_overrides - comment_references - prefer_typing_uninitialized_variables diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index b8a3f0289..c534a919e 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -14,9 +14,11 @@ import '../stream_channel.dart'; /// /// This is exposed via [new StreamChannel.withCloseGuarantee]. class CloseGuaranteeChannel extends StreamChannelMixin { + @override Stream get stream => _stream; _CloseGuaranteeStream _stream; + @override StreamSink get sink => _sink; _CloseGuaranteeSink _sink; @@ -45,6 +47,7 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); + @override StreamSubscription listen(void onData(T event), {Function onError, void onDone(), bool cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything @@ -73,6 +76,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + @override Future close() { var done = super.close(); _channel._disconnected = true; diff --git a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart index 4434cf62a..4484a5989 100644 --- a/pkgs/stream_channel/lib/src/delegating_stream_channel.dart +++ b/pkgs/stream_channel/lib/src/delegating_stream_channel.dart @@ -14,7 +14,9 @@ class DelegatingStreamChannel extends StreamChannelMixin { /// The inner channel to which methods are forwarded. final StreamChannel _inner; + @override Stream get stream => _inner.stream; + @override StreamSink get sink => _inner.sink; DelegatingStreamChannel(this._inner); diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 9d35cfc63..83defb8c3 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -40,6 +40,7 @@ class Disconnector implements StreamChannelTransformer { }); final _disconnectMemo = AsyncMemoizer(); + @override StreamChannel bind(StreamChannel channel) { return channel.changeSink((innerSink) { var sink = _DisconnectorSink(innerSink); @@ -62,6 +63,7 @@ class _DisconnectorSink implements StreamSink { /// The inner sink. final StreamSink _inner; + @override Future get done => _inner.done; /// Whether [Disconnector.disconnect] has been called. @@ -83,6 +85,7 @@ class _DisconnectorSink implements StreamSink { _DisconnectorSink(this._inner); + @override void add(T data) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -93,6 +96,7 @@ class _DisconnectorSink implements StreamSink { _inner.add(data); } + @override void addError(error, [StackTrace stackTrace]) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -103,6 +107,7 @@ class _DisconnectorSink implements StreamSink { _inner.addError(error, stackTrace); } + @override Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { @@ -119,6 +124,7 @@ class _DisconnectorSink implements StreamSink { }); } + @override Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index e96f5c3c8..ce7f70736 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -12,8 +12,10 @@ import '../stream_channel.dart'; /// /// This is exposed via [new StreamChannel.withGuarantees]. class GuaranteeChannel extends StreamChannelMixin { + @override Stream get stream => _streamController.stream; + @override StreamSink get sink => _sink; _GuaranteeSink _sink; @@ -78,6 +80,7 @@ class _GuaranteeSink implements StreamSink { /// The [GuaranteeChannel] this belongs to. final GuaranteeChannel _channel; + @override Future get done => _doneCompleter.future; final _doneCompleter = Completer(); @@ -110,6 +113,7 @@ class _GuaranteeSink implements StreamSink { _GuaranteeSink(this._inner, this._channel, {bool allowErrors = true}) : _allowErrors = allowErrors; + @override void add(T data) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -120,6 +124,7 @@ class _GuaranteeSink implements StreamSink { _inner.add(data); } + @override void addError(error, [StackTrace stackTrace]) { if (_closed) throw StateError("Cannot add event after closing."); if (_inAddStream) { @@ -151,6 +156,7 @@ class _GuaranteeSink implements StreamSink { _inner.close().catchError((_) {}); } + @override Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { @@ -167,6 +173,7 @@ class _GuaranteeSink implements StreamSink { }); } + @override Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index c7f573fd2..8c1b56842 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -24,7 +24,9 @@ import '../stream_channel.dart'; /// ensure that they always close the [sink] of every [IsolateChannel] they use /// to avoid leaving dangling [ReceivePort]s. class IsolateChannel extends StreamChannelMixin { + @override final Stream stream; + @override final StreamSink sink; /// Connects to a remote channel that was created with diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 2a3a86f3e..a53ac92ad 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -35,6 +35,7 @@ class JsonDocumentTransformer JsonDocumentTransformer._(this._codec); + @override StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(_codec.decode); var sink = StreamSinkTransformer.fromHandlers( diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 139c9aefa..d729eb7bb 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -45,6 +45,7 @@ abstract class MultiChannel implements StreamChannel { /// The default input stream. /// /// This connects to the remote [sink]. + @override Stream get stream; /// The default output stream. @@ -52,6 +53,7 @@ abstract class MultiChannel implements StreamChannel { /// This connects to the remote [stream]. If this is closed, the remote /// [stream] will close, but other virtual channels will remain open and new /// virtual channels may be opened. + @override StreamSink get sink; /// Creates a new [MultiChannel] that sends and receives messages over @@ -88,7 +90,9 @@ class _MultiChannel extends StreamChannelMixin /// The subscription to [_inner].stream. StreamSubscription _innerStreamSubscription; + @override Stream get stream => _mainController.foreign.stream; + @override StreamSink get sink => _mainController.foreign.sink; /// The controller for this channel. @@ -165,6 +169,7 @@ class _MultiChannel extends StreamChannelMixin onError: _mainController.local.sink.addError); } + @override VirtualChannel virtualChannel([int id]) { int inputId; int outputId; @@ -256,10 +261,13 @@ class VirtualChannel extends StreamChannelMixin /// except that it will be JSON-serializable. final int id; + @override final Stream stream; + @override final StreamSink sink; VirtualChannel._(this._parent, this.id, this.stream, this.sink); + @override VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart index 9c2d72b41..875cdac37 100644 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ b/pkgs/stream_channel/lib/src/transformer/typed.dart @@ -12,6 +12,7 @@ class TypeSafeStreamChannelTransformer TypeSafeStreamChannelTransformer(this._inner); + @override StreamChannel bind(StreamChannel channel) => _inner.bind(channel).cast(); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index b50116044..a5cd5849c 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -138,7 +138,9 @@ abstract class StreamChannel { /// This is distinct from [StreamChannel] so that it can use /// [StreamChannelMixin]. class _StreamChannel extends StreamChannelMixin { + @override final Stream stream; + @override final StreamSink sink; _StreamChannel(this.stream, this.sink); @@ -147,26 +149,33 @@ class _StreamChannel extends StreamChannelMixin { /// A mixin that implements the instance methods of [StreamChannel] in terms of /// [stream] and [sink]. abstract class StreamChannelMixin implements StreamChannel { + @override void pipe(StreamChannel other) { stream.pipe(other.sink); other.stream.pipe(sink); } + @override StreamChannel transform(StreamChannelTransformer transformer) => transformer.bind(this); + @override StreamChannel transformStream(StreamTransformer transformer) => changeStream(transformer.bind); + @override StreamChannel transformSink(StreamSinkTransformer transformer) => changeSink(transformer.bind); + @override StreamChannel changeStream(Stream change(Stream stream)) => StreamChannel.withCloseGuarantee(change(stream), sink); + @override StreamChannel changeSink(StreamSink change(StreamSink sink)) => StreamChannel.withCloseGuarantee(stream, change(sink)); + @override StreamChannel cast() => StreamChannel( DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); } diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 7b36c29b6..aefad28d4 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -144,6 +144,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { _CloseCompleterSink(StreamSink inner) : super(inner); + @override Future close() { super.close(); return completer.future; From db09351495a71df5445a627a8b01bd3af23f8073 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Mar 2019 17:26:19 -0700 Subject: [PATCH 0538/1215] Move isolate_channel to it's own import (dart-lang/stream_channel#39) Closes dart-lang/stream_channel#36 This allows the default import to work without triggering any warnings on the web due to transitively importing `dart:isolate`. This is required to allow restricting imports based on platform. --- pkgs/stream_channel/CHANGELOG.md | 7 +++++++ pkgs/stream_channel/lib/stream_channel.dart | 1 - pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 68b68a112..0e125ddae 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,10 @@ +## 2.0.0 + +* **Breaking change** `IsolateChannel` requires a separate import + `package:stram_channel/isolate_channel.dart`. + `package:stream_channel/stream_channel.dart` will now not trigger any platform + concerns due to importing `dart:isolate`. + ## 1.7.0 * Make `IsolateChannel` available through diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index a5cd5849c..e99de08f0 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -12,7 +12,6 @@ import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; export 'src/disconnector.dart'; -export 'src/isolate_channel.dart'; export 'src/json_document_transformer.dart'; export 'src/multi_channel.dart'; export 'src/stream_channel_completer.dart'; diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index da152fb39..917f5bc38 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 1.7.0 +version: 2.0.0 description: An abstraction for two-way communication channels. author: Dart Team From 662bcb457877736852df2640998d22cdea7ce9f6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 08:26:01 -0700 Subject: [PATCH 0539/1215] Hide JsonDocumentTransformer (dart-lang/stream_channel#43) Closes dart-lang/stream_channel#34 This was only used through the top level variable `jsonDocument` and no use cases have surfaced for being able to pass a `reviver` or `toEncodable` callback. This implementation does not use `StreamChannelTransformer.fromCodec` with a `JsonCodec` since the encoder and decoder are not 1:1. - Remove the `JsonCodec` field and use `jsonEncode` and `jsonDecode` calls directly. - Move the detailed doc to `jsonDocument`. - Make the class private. - Remove the tests constructing the class directly. --- pkgs/stream_channel/CHANGELOG.md | 6 ++++- .../lib/src/json_document_transformer.dart | 23 +++++-------------- .../test/json_document_transformer_test.dart | 14 ----------- 3 files changed, 11 insertions(+), 32 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0e125ddae..8ebdc2874 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,9 +1,13 @@ ## 2.0.0 -* **Breaking change** `IsolateChannel` requires a separate import +**Breaking changes** + +* `IsolateChannel` requires a separate import `package:stram_channel/isolate_channel.dart`. `package:stream_channel/stream_channel.dart` will now not trigger any platform concerns due to importing `dart:isolate`. +* Remove `JsonDocumentTransformer` class. The `jsonDocument` top level is still + available. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index a53ac92ad..8bffc8ab9 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -9,9 +9,6 @@ import 'package:async/async.dart'; import '../stream_channel.dart'; import 'stream_channel_transformer.dart'; -/// The canonical instance of [JsonDocumentTransformer]. -final jsonDocument = JsonDocumentTransformer(); - /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. /// @@ -21,26 +18,18 @@ final jsonDocument = JsonDocumentTransformer(); /// If the transformed channel emits invalid JSON, this emits a /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. -class JsonDocumentTransformer - implements StreamChannelTransformer { - /// The underlying codec that implements the encoding and decoding logic. - final JsonCodec _codec; - - /// Creates a new transformer. - /// - /// The [reviver] and [toEncodable] arguments work the same way as the - /// corresponding arguments to [new JsonCodec]. - JsonDocumentTransformer({reviver(key, value), toEncodable(object)}) - : _codec = JsonCodec(reviver: reviver, toEncodable: toEncodable); +final StreamChannelTransformer jsonDocument = + const _JsonDocument(); - JsonDocumentTransformer._(this._codec); +class _JsonDocument implements StreamChannelTransformer { + const _JsonDocument(); @override StreamChannel bind(StreamChannel channel) { - var stream = channel.stream.map(_codec.decode); + var stream = channel.stream.map(jsonDecode); var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { - sink.add(_codec.encode(data)); + sink.add(jsonEncode(data)); }).bind(channel.sink); return StreamChannel.withCloseGuarantee(stream, sink); } diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 83ee09929..e6c560ade 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -32,20 +32,6 @@ void main() { completion(equals(jsonEncode({"foo": "bar"})))); }); - test("supports the reviver function", () { - var transformed = channel - .transform(JsonDocumentTransformer(reviver: (key, value) => "decoded")); - streamController.add('{"foo": "bar"}'); - expect(transformed.stream.first, completion(equals("decoded"))); - }); - - test("supports the toEncodable function", () { - var transformed = channel - .transform(JsonDocumentTransformer(toEncodable: (object) => "encoded")); - transformed.sink.add(Object()); - expect(sinkController.stream.first, completion(equals('"encoded"'))); - }); - test("emits a stream error when incoming JSON is malformed", () { var transformed = channel.transform(jsonDocument); streamController.add("{invalid"); From 7c910babe483446f0641fbb398fce4abf66e56e0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 09:48:58 -0700 Subject: [PATCH 0540/1215] Remove StreamChannelTransformer.typed (dart-lang/stream_channel#44) Closes dart-lang/stream_channel#41 I cannot find any uses of this and it can be replaced with a call to `cast`. --- pkgs/stream_channel/CHANGELOG.md | 2 ++ .../lib/src/stream_channel_transformer.dart | 16 ---------------- .../lib/src/transformer/typed.dart | 18 ------------------ 3 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 pkgs/stream_channel/lib/src/transformer/typed.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 8ebdc2874..60400e0df 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -8,6 +8,8 @@ concerns due to importing `dart:isolate`. * Remove `JsonDocumentTransformer` class. The `jsonDocument` top level is still available. +* Remove `StreamChannelTransformer.typed`. Use `.cast` on the transformed + channel instead. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart index 32d36b6b0..cf62c76c2 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_transformer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_transformer.dart @@ -8,7 +8,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'transformer/typed.dart'; /// A [StreamChannelTransformer] transforms the events being passed to and /// emitted by a [StreamChannel]. @@ -32,21 +31,6 @@ class StreamChannelTransformer { /// The transformer to use on the channel's sink. final StreamSinkTransformer _sinkTransformer; - /// Creates a wrapper that coerces the type of [transformer]. - /// - /// This soundly converts a [StreamChannelTransformer] to a - /// `StreamChannelTransformer`, regardless of its original generic type, - /// by asserting that the events emitted by the transformed channel's stream - /// are instances of `T` whenever they're provided. If they're not, the stream - /// throws a [CastError]. This also means that calls to [StreamSink.add] on - /// the transformed channel's sink may throw a [CastError] if the argument - /// type doesn't match the reified type of the sink. - static StreamChannelTransformer typed( - StreamChannelTransformer transformer) => - transformer is StreamChannelTransformer - ? transformer - : TypeSafeStreamChannelTransformer(transformer); - /// Creates a [StreamChannelTransformer] from existing stream and sink /// transformers. const StreamChannelTransformer( diff --git a/pkgs/stream_channel/lib/src/transformer/typed.dart b/pkgs/stream_channel/lib/src/transformer/typed.dart deleted file mode 100644 index 875cdac37..000000000 --- a/pkgs/stream_channel/lib/src/transformer/typed.dart +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file -// 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. - -import '../../stream_channel.dart'; - -/// A wrapper that coerces the generic type of the channel returned by an inner -/// transformer to `S`. -class TypeSafeStreamChannelTransformer - implements StreamChannelTransformer { - final StreamChannelTransformer _inner; - - TypeSafeStreamChannelTransformer(this._inner); - - @override - StreamChannel bind(StreamChannel channel) => - _inner.bind(channel).cast(); -} From e4af414323baea76d971da80e8a48748d3983467 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Mar 2019 11:06:27 -0700 Subject: [PATCH 0541/1215] Change all bare Future to Future (dart-lang/stream_channel#45) Closes dart-lang/stream_channel#35 It looks less like a potential bug and more explicitly expresses that these functions don't return useful values. --- pkgs/stream_channel/CHANGELOG.md | 1 + .../lib/src/close_guarantee_channel.dart | 2 +- pkgs/stream_channel/lib/src/disconnector.dart | 10 +++++----- pkgs/stream_channel/lib/src/guarantee_channel.dart | 6 +++--- pkgs/stream_channel/test/disconnector_test.dart | 2 +- 5 files changed, 11 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 60400e0df..24564ede1 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -10,6 +10,7 @@ available. * Remove `StreamChannelTransformer.typed`. Use `.cast` on the transformed channel instead. +* Change `Future` returns to `Future`. ## 1.7.0 diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index c534a919e..33296da43 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -77,7 +77,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); @override - Future close() { + Future close() { var done = super.close(); _channel._disconnected = true; if (_channel._subscription != null) { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 83defb8c3..69fbab727 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -33,7 +33,7 @@ class Disconnector implements StreamChannelTransformer { /// Returns a future that completes when all inner sinks' [StreamSink.close] /// futures have completed. Note that a [StreamController]'s sink won't close /// until the corresponding stream has a listener. - Future disconnect() => _disconnectMemo.runOnce(() { + Future disconnect() => _disconnectMemo.runOnce(() { var futures = _sinks.map((sink) => sink._disconnect()).toList(); _sinks.clear(); return Future.wait(futures, eagerError: true); @@ -64,7 +64,7 @@ class _DisconnectorSink implements StreamSink { final StreamSink _inner; @override - Future get done => _inner.done; + Future get done => _inner.done; /// Whether [Disconnector.disconnect] has been called. var _isDisconnected = false; @@ -108,7 +108,7 @@ class _DisconnectorSink implements StreamSink { } @override - Future addStream(Stream stream) { + Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { throw StateError("Cannot add stream while adding stream."); @@ -125,7 +125,7 @@ class _DisconnectorSink implements StreamSink { } @override - Future close() { + Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); } @@ -138,7 +138,7 @@ class _DisconnectorSink implements StreamSink { /// /// This closes the underlying sink and stops forwarding events. It returns /// the [StreamSink.close] future for the underlying sink. - Future _disconnect() { + Future _disconnect() { _isDisconnected = true; var future = _inner.close(); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index ce7f70736..d8add39e8 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -81,7 +81,7 @@ class _GuaranteeSink implements StreamSink { final GuaranteeChannel _channel; @override - Future get done => _doneCompleter.future; + Future get done => _doneCompleter.future; final _doneCompleter = Completer(); /// Whether connection is disconnected. @@ -157,7 +157,7 @@ class _GuaranteeSink implements StreamSink { } @override - Future addStream(Stream stream) { + Future addStream(Stream stream) { if (_closed) throw StateError("Cannot add stream after closing."); if (_inAddStream) { throw StateError("Cannot add stream while adding stream."); @@ -174,7 +174,7 @@ class _GuaranteeSink implements StreamSink { } @override - Future close() { + Future close() { if (_inAddStream) { throw StateError("Cannot close sink while adding stream."); } diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index aefad28d4..0992b3634 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -145,7 +145,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { _CloseCompleterSink(StreamSink inner) : super(inner); @override - Future close() { + Future close() { super.close(); return completer.future; } From d69e98b1d2d496601db1bda617ca96f741b8998f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 2 Apr 2019 14:35:11 -0700 Subject: [PATCH 0542/1215] Remove a work-around for a long-ago fixed issue (dart-lang/pubspec_parse#42) --- pkgs/pubspec_parse/lib/src/dependency.dart | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index d9b3db247..52057eb43 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -21,15 +21,7 @@ Map parseDeps(Map source) => // This is likely a "synthetic" map created from a String value // Use `source` to throw this exception with an actual YamlMap and // extract the associated error information. - - var message = e.message; - final innerError = e.innerError; - // json_annotation should handle FormatException... - // https://github.com/dart-lang/json_serializable/issues/233 - if (innerError is FormatException) { - message = innerError.message; - } - throw CheckedFromJsonException(source, key, e.className, message); + throw CheckedFromJsonException(source, key, e.className, e.message); } rethrow; } From 9a15a6b5e1d864b69ac91377154f30c742e3fe0e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 26 Apr 2019 09:10:14 -0700 Subject: [PATCH 0543/1215] Update SDK constraint, enable/fix lints (dart-lang/pubspec_parse#43) --- pkgs/pubspec_parse/.travis.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/analysis_options.yaml | 4 ++-- pkgs/pubspec_parse/lib/src/pubspec.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index b82f2f3e5..536ccee72 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -13,7 +13,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.0.0 + - dart: 2.2.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index d43264920..1f62e3afd 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5 + +- Update SDK requirement to `>=2.2.0 <3.0.0`. + ## 0.1.4 - Added `lenient` named argument to `Pubspec.fromJson` to ignore format and type errors. diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 4f0a48b4d..f983bb3b8 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -61,14 +61,14 @@ linter: - package_names - package_prefixed_library_names - prefer_adjacent_string_concatenation - # TODO: reenable this once we want to pin the SDK to >=2.2.0 - # - prefer_collection_literals + - prefer_collection_literals - prefer_conditional_assignment - prefer_const_constructors - prefer_contains - prefer_equal_for_default_values - prefer_final_fields - prefer_final_locals + - prefer_generic_function_type_aliases - prefer_initializing_formals - prefer_interpolation_to_compose_strings - prefer_is_empty diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index c05e8249c..3d542d7a9 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -166,7 +166,7 @@ class Pubspec { } static List _normalizeAuthors(String author, List authors) { - final value = Set(); + final value = {}; if (author != null) { value.add(author); } diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 0b48262e4..c1df008a9 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,12 +2,12 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.4 +version: 0.1.5-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.2.0 <3.0.0' dependencies: # Verified that no new features since 1.0.0 are used - be careful! From 8503dd7a1bcd82894bb1f63c32e5f81c7498089c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 26 Apr 2019 13:04:02 -0700 Subject: [PATCH 0544/1215] Enable and fix strict-raw-types checks (dart-lang/stream_transform#78) Most changes are in tests where we implicitly were using `` but only ever passing a single type. Add specific types and clean up the few cases where a different type from the norm was used. Extract utilities for constructing both types of stream to do the tests in a loop, since it's not using function literals anymore it can be a generic function. In `lib/` add a few `` type arguments for things like "trigger" streams since we were never reading the value. --- pkgs/stream_transform/CHANGELOG.md | 7 +- pkgs/stream_transform/analysis_options.yaml | 2 + .../lib/src/async_map_buffer.dart | 6 +- pkgs/stream_transform/lib/src/buffer.dart | 11 ++-- .../lib/src/combine_latest.dart | 4 +- .../lib/src/combine_latest_all.dart | 2 +- .../stream_transform/lib/src/followed_by.dart | 2 +- pkgs/stream_transform/lib/src/merge.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/lib/src/take_until.dart | 7 +- pkgs/stream_transform/pubspec.yaml | 2 +- .../test/async_map_buffer_test.dart | 32 ++++----- pkgs/stream_transform/test/audit_test.dart | 20 +++--- pkgs/stream_transform/test/buffer_test.dart | 28 ++++---- .../test/concurrent_async_map_test.dart | 61 ++++++++--------- pkgs/stream_transform/test/debounce_test.dart | 66 ++++++++++--------- .../test/followd_by_test.dart | 26 ++++---- .../test/from_handlers_test.dart | 20 +++--- pkgs/stream_transform/test/scan_test.dart | 6 +- .../test/start_with_test.dart | 29 ++++---- pkgs/stream_transform/test/switch_test.dart | 31 ++++----- .../test/take_until_test.dart | 22 +++---- pkgs/stream_transform/test/throttle_test.dart | 23 +++---- pkgs/stream_transform/test/utils.dart | 16 ++++- 24 files changed, 215 insertions(+), 212 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 9b8ab296d..3f502d3e9 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.0.18 + +- Internal cleanup. Passed "trigger" streams or futures now allow `` + generic type rather than an implicit `dynamic>` + ## 0.0.17 - Add concrete types to the `onError` callback in `tap`. @@ -47,7 +52,7 @@ - Updates to support Dart 2.0 core library changes (wave 2.2). See [issue 31847][sdk#31847] for details. - + [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 ## 0.0.9 diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 82dd7e892..67baa3ed2 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -2,6 +2,8 @@ include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false + language: + strict-raw-types: true errors: todo: ignore dead_code: error diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index fd25a2127..a4e346fe7 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -28,7 +28,7 @@ import 'from_handlers.dart'; /// pending conversions have finished. StreamTransformer asyncMapBuffer( Future convert(List collected)) { - var workFinished = StreamController() + var workFinished = StreamController() // Let the first event through. ..add(null); return chainTransformers( @@ -39,8 +39,8 @@ StreamTransformer asyncMapBuffer( /// rather than once per listener, and [then] is called after completing the /// work. StreamTransformer _asyncMapThen( - Future convert(S event), void then(Object _)) { - Future pendingEvent; + Future convert(S event), void Function(void) then) { + Future pendingEvent; return fromHandlers(handleData: (event, sink) { pendingEvent = convert(event).then(sink.add).catchError(sink.addError).then(then); diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index d09d2daf2..8641b1552 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -12,7 +12,8 @@ import 'dart:async'; /// /// Errors from the source stream or the trigger are immediately forwarded to /// the output. -StreamTransformer> buffer(Stream trigger) => _Buffer(trigger); +StreamTransformer> buffer(Stream trigger) => + _Buffer(trigger); /// A StreamTransformer which aggregates values and emits when it sees a value /// on [_trigger]. @@ -24,7 +25,7 @@ StreamTransformer> buffer(Stream trigger) => _Buffer(trigger); /// Errors from the source stream or the trigger are immediately forwarded to /// the output. class _Buffer extends StreamTransformerBase> { - final Stream _trigger; + final Stream _trigger; _Buffer(this._trigger); @@ -38,8 +39,8 @@ class _Buffer extends StreamTransformerBase> { var waitingForTrigger = true; var isTriggerDone = false; var isValueDone = false; - StreamSubscription valueSub; - StreamSubscription triggerSub; + StreamSubscription valueSub; + StreamSubscription triggerSub; emit() { controller.add(currentResults); @@ -107,7 +108,7 @@ class _Buffer extends StreamTransformerBase> { }; } controller.onCancel = () { - var toCancel = []; + var toCancel = >[]; if (!isValueDone) toCancel.add(valueSub); valueSub = null; if (_trigger.isBroadcast || !values.isBroadcast) { diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 1fe7d8590..489f344c3 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -51,8 +51,8 @@ class _CombineLatest extends StreamTransformerBase { ? _other.asBroadcastStream() : _other; - StreamSubscription sourceSubscription; - StreamSubscription otherSubscription; + StreamSubscription sourceSubscription; + StreamSubscription otherSubscription; var sourceDone = false; var otherDone = false; diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart index 16f2e8089..045ccdced 100644 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ b/pkgs/stream_transform/lib/src/combine_latest_all.dart @@ -60,7 +60,7 @@ class _CombineLatestAll extends StreamTransformerBase> { .toList(); } - List subscriptions; + List> subscriptions; controller.onListen = () { assert(subscriptions == null); diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart index 779831f70..3c5c6b340 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -33,7 +33,7 @@ class _FollowedBy extends StreamTransformerBase { ? _next.asBroadcastStream() : _next; - StreamSubscription subscription; + StreamSubscription subscription; var currentStream = first; var firstDone = false; var secondDone = false; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index a5b4cf33f..74a1e1a4a 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -39,7 +39,7 @@ class _Merge extends StreamTransformerBase { .toList(); } - List subscriptions; + List> subscriptions; controller.onListen = () { assert(subscriptions == null); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 2f247045c..e02917d2e 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -69,7 +69,7 @@ class _SwitchTransformer extends StreamTransformerBase, T> { }; } controller.onCancel = () { - var toCancel = []; + var toCancel = >[]; if (!outerStreamDone) toCancel.add(outerSubscription); if (innerSubscription != null) { toCancel.add(innerSubscription); diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 62b10131e..ad12ae849 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -10,10 +10,11 @@ import 'dart:async'; /// which are emitted before the trigger, but have further asynchronous delays /// in transformations following the takeUtil, will still go through. Cancelling /// a subscription immediately stops values. -StreamTransformer takeUntil(Future trigger) => _TakeUntil(trigger); +StreamTransformer takeUntil(Future trigger) => + _TakeUntil(trigger); class _TakeUntil extends StreamTransformerBase { - final Future _trigger; + final Future _trigger; _TakeUntil(this._trigger); @@ -23,7 +24,7 @@ class _TakeUntil extends StreamTransformerBase { ? StreamController.broadcast(sync: true) : StreamController(sync: true); - StreamSubscription subscription; + StreamSubscription subscription; var isDone = false; _trigger.then((_) { if (isDone) return; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index a9be96848..37a6cbfaf 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.17 +version: 0.0.18 environment: sdk: ">=2.2.0 <3.0.0" diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index bf7b9d629..021755af6 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -8,25 +8,23 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - StreamController values; - List emittedValues; + StreamController values; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream transformed; + StreamSubscription subscription; - Completer finishWork; - List workArgument; + Completer finishWork; + List workArgument; /// Represents the async `convert` function and asserts that is is only called /// after the previous iteration has completed. - Future work(List values) { + Future work(List values) { expect(finishWork, isNull, reason: 'See $values befor previous work is complete'); workArgument = values; @@ -41,11 +39,11 @@ void main() { return finishWork.future; } - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('asyncMapBuffer for stream type: [$streamType]', () { setUp(() { valuesCanceled = false; - values = streamTypes[streamType]() + values = createController(streamType) ..onCancel = () { valuesCanceled = true; }; @@ -66,11 +64,9 @@ void main() { await Future(() {}); expect(emittedValues, isEmpty); expect(workArgument, [1]); - finishWork.complete(workArgument); + finishWork.complete('result'); await Future(() {}); - expect(emittedValues, [ - [1] - ]); + expect(emittedValues, ['result']); }); test('buffers values while work is ongoing', () async { diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 71925fd29..168227a42 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -10,23 +10,19 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - StreamController values; - List emittedValues; + StreamController values; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream transformed; + StreamSubscription subscription; - void setUpStreams(StreamTransformer transformer) { + void setUpStreams(StreamTransformer transformer) { valuesCanceled = false; - values = streamTypes[streamType]() + values = createController(streamType) ..onCancel = () { valuesCanceled = true; }; diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 2461085b1..3dcd505b9 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -7,27 +7,25 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - StreamController trigger; - StreamController values; - List emittedValues; + StreamController trigger; + StreamController values; + List> emittedValues; bool valuesCanceled; bool triggerCanceled; bool triggerPaused; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream> transformed; + StreamSubscription> subscription; void setUpForStreamTypes(String triggerType, String valuesType) { valuesCanceled = false; triggerCanceled = false; triggerPaused = false; - trigger = streamTypes[triggerType]() + trigger = createController(triggerType) ..onCancel = () { triggerCanceled = true; }; @@ -36,7 +34,7 @@ void main() { triggerPaused = true; }; } - values = streamTypes[valuesType]() + values = createController(valuesType) ..onCancel = () { valuesCanceled = true; }; @@ -50,8 +48,8 @@ void main() { }); } - for (var triggerType in streamTypes.keys) { - for (var valuesType in streamTypes.keys) { + for (var triggerType in streamTypes) { + for (var valuesType in streamTypes) { group('Trigger type: [$triggerType], Values type: [$valuesType]', () { setUp(() { setUpForStreamTypes(triggerType, valuesType); @@ -222,7 +220,7 @@ void main() { expect(triggerPaused, true); }); - for (var triggerType in streamTypes.keys) { + for (var triggerType in streamTypes) { test('cancel and relisten with [$triggerType] trigger', () async { setUpForStreamTypes(triggerType, 'broadcast'); values.add(1); diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index d26ed0391..dceaa879b 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -8,34 +8,32 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - StreamController streamController; - List emittedValues; + StreamController controller; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream transformed; + StreamSubscription subscription; - List finishWork; + List> finishWork; List values; - Future convert(dynamic value) { + Future convert(int value) { values.add(value); - var completer = Completer(); + var completer = Completer(); finishWork.add(completer); return completer.future; } - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('concurrentAsyncMap for stream type: [$streamType]', () { setUp(() { valuesCanceled = false; - streamController = streamTypes[streamType]() + controller = createController(streamType) ..onCancel = () { valuesCanceled = true; }; @@ -44,8 +42,7 @@ void main() { isDone = false; finishWork = []; values = []; - transformed = - streamController.stream.transform(concurrentAsyncMap(convert)); + transformed = controller.stream.transform(concurrentAsyncMap(convert)); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; @@ -53,32 +50,32 @@ void main() { }); test('does not emit before convert finishes', () async { - streamController.add(1); + controller.add(1); await Future(() {}); expect(emittedValues, isEmpty); expect(values, [1]); - finishWork.first.complete(1); + finishWork.first.complete('result'); await Future(() {}); - expect(emittedValues, [1]); + expect(emittedValues, ['result']); }); test('allows calls to convert before the last one finished', () async { - streamController..add(1)..add(2)..add(3); + controller..add(1)..add(2)..add(3); await Future(() {}); expect(values, [1, 2, 3]); }); test('forwards errors directly without waiting for previous convert', () async { - streamController.add(1); + controller.add(1); await Future(() {}); - streamController.addError('error'); + controller.addError('error'); await Future(() {}); expect(errors, ['error']); }); test('forwards errors which occur during the convert', () async { - streamController.add(1); + controller.add(1); await Future(() {}); finishWork.first.completeError('error'); await Future(() {}); @@ -86,10 +83,10 @@ void main() { }); test('can continue handling events after an error', () async { - streamController.add(1); + controller.add(1); await Future(() {}); finishWork[0].completeError('error'); - streamController.add(2); + controller.add(2); await Future(() {}); expect(values, [1, 2]); finishWork[1].completeError('another'); @@ -105,7 +102,7 @@ void main() { test('closes when values end if no conversion is pending', () async { expect(isDone, false); - await streamController.close(); + await controller.close(); await Future(() {}); expect(isDone, true); }); @@ -114,7 +111,7 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - streamController.add(1); + controller.add(1); await Future(() {}); finishWork.first.complete('result'); await Future(() {}); @@ -125,9 +122,9 @@ void main() { test('multiple listeners get done when values end', () async { var otherDone = false; transformed.listen(null, onDone: () => otherDone = true); - streamController.add(1); + controller.add(1); await Future(() {}); - await streamController.close(); + await controller.close(); expect(isDone, false); expect(otherDone, false); finishWork.first.complete(); @@ -137,15 +134,15 @@ void main() { }); test('can cancel and relisten', () async { - streamController.add(1); + controller.add(1); await Future(() {}); finishWork.first.complete('first'); await Future(() {}); await subscription.cancel(); - streamController.add(2); + controller.add(2); await Future(() {}); subscription = transformed.listen(emittedValues.add); - streamController.add(3); + controller.add(3); await Future(() {}); expect(values, [1, 3]); finishWork[1].complete('second'); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index aa629db1d..89fede93e 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -10,37 +10,33 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - StreamSubscription subscription; - Stream transformed; - - void setUpStreams(StreamTransformer transformer) { - valuesCanceled = false; - values = streamTypes[streamType]() - ..onCancel = () { - valuesCanceled = true; - }; - emittedValues = []; - errors = []; - isDone = false; - transformed = values.stream.transform(transformer); - subscription = transformed - .listen(emittedValues.add, onError: errors.add, onDone: () { - isDone = true; - }); - } - group('debounce', () { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + StreamSubscription subscription; + Stream transformed; + + void setUpStreams(StreamTransformer transformer) { + valuesCanceled = false; + values = createController(streamType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = values.stream.transform(transformer); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + setUp(() async { setUpStreams(debounce(const Duration(milliseconds: 5))); }); @@ -97,8 +93,18 @@ void main() { }); group('debounceBuffer', () { + StreamController values; + List> emittedValues; + List errors; + Stream> transformed; + setUp(() async { - setUpStreams(debounceBuffer(const Duration(milliseconds: 5))); + values = createController(streamType); + emittedValues = []; + errors = []; + transformed = values.stream + .transform(debounceBuffer(const Duration(milliseconds: 5))) + ..listen(emittedValues.add, onError: errors.add); }); test('Emits all values as a list', () async { diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 0e8853dd9..c5f48aaf0 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -7,35 +7,33 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var firstType in streamTypes.keys) { - for (var secondType in streamTypes.keys) { + for (var firstType in streamTypes) { + for (var secondType in streamTypes) { group('followedBy [$firstType] with [$secondType]', () { - StreamController first; - StreamController second; + StreamController first; + StreamController second; - List emittedValues; + List emittedValues; bool firstCanceled; bool secondCanceled; bool secondListened; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream transformed; + StreamSubscription subscription; setUp(() async { firstCanceled = false; secondCanceled = false; secondListened = false; - first = streamTypes[firstType]() + first = createController(firstType) ..onCancel = () { firstCanceled = true; }; - second = streamTypes[secondType]() + second = createController(secondType) ..onCancel = () { secondCanceled = true; } diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 1953b294a..50d59c5d0 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -9,16 +9,16 @@ import 'package:test/test.dart'; import 'package:stream_transform/src/from_handlers.dart'; void main() { - StreamController values; - List emittedValues; + StreamController values; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + List errors; + Stream transformed; + StreamSubscription subscription; - void setUpForController( - StreamController controller, StreamTransformer transformer) { + void setUpForController(StreamController controller, + StreamTransformer transformer) { valuesCanceled = false; values = controller ..onCancel = () { @@ -68,10 +68,10 @@ void main() { }); group('broadcast stream with muliple listeners', () { - List emittedValues2; - List errors2; + List emittedValues2; + List errors2; bool isDone2; - StreamSubscription subscription2; + StreamSubscription subscription2; setUp(() { setUpForController(StreamController.broadcast(), fromHandlers()); diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index f321539f1..662831c01 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -58,8 +58,10 @@ void main() { .transform(scan>(Future.value(0), sum)) .toList(); - expect( - result, [const TypeMatcher(), const TypeMatcher()]); + expect(result, [ + const TypeMatcher>(), + const TypeMatcher>() + ]); expect(await Future.wait(result), [1, 3]); }); diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index c02e2a3b6..8ce8075a7 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -8,28 +8,27 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - StreamController values; - Stream transformed; - StreamSubscription subscription; - - List emittedValues; + StreamController values; + Stream transformed; + StreamSubscription subscription; + + List emittedValues; bool isDone; - setupForStreamType(String streamType, StreamTransformer transformer) { + setupForStreamType( + String streamType, StreamTransformer transformer) { emittedValues = []; isDone = false; - values = streamTypes[streamType](); + values = createController(streamType); transformed = values.stream.transform(transformer); subscription = transformed.listen(emittedValues.add, onDone: () => isDone = true); } - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('startWith then [$streamType]', () { setUp(() => setupForStreamType(streamType, startWith(1))); @@ -101,11 +100,11 @@ void main() { } }); - for (var startingStreamType in streamTypes.keys) { + for (var startingStreamType in streamTypes) { group('startWithStream [$startingStreamType] then [$streamType]', () { - StreamController starting; + StreamController starting; setUp(() async { - starting = streamTypes[startingStreamType](); + starting = createController(startingStreamType); setupForStreamType(streamType, startWithStream(starting.stream)); }); diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index d73e7a8b2..e32026ad5 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -8,42 +8,39 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var outerType in streamTypes.keys) { - for (var innerType in streamTypes.keys) { + for (var outerType in streamTypes) { + for (var innerType in streamTypes) { group('Outer type: [$outerType], Inner type: [$innerType]', () { - StreamController first; - StreamController second; - StreamController outer; + StreamController first; + StreamController second; + StreamController> outer; - List emittedValues; + List emittedValues; bool firstCanceled; bool outerCanceled; bool isDone; - List errors; - StreamSubscription subscription; + List errors; + StreamSubscription subscription; setUp(() async { firstCanceled = false; outerCanceled = false; - outer = streamTypes[outerType]() + outer = createController(outerType) ..onCancel = () { outerCanceled = true; }; - first = streamTypes[innerType]() + first = createController(innerType) ..onCancel = () { firstCanceled = true; }; - second = streamTypes[innerType](); + second = createController(innerType); emittedValues = []; errors = []; isDone = false; subscription = outer.stream - .cast() .transform(switchLatest()) .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; @@ -129,7 +126,7 @@ void main() { group('switchMap', () { test('uses map function', () async { - var outer = StreamController(); + var outer = StreamController>(); var values = []; outer.stream diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index e7614da86..74c516707 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -8,25 +8,23 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('takeUntil on Stream type [$streamType]', () { - StreamController values; - List emittedValues; + StreamController values; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; - Completer closeTrigger; + List errors; + Stream transformed; + StreamSubscription subscription; + Completer closeTrigger; setUp(() { valuesCanceled = false; - values = streamTypes[streamType]() + values = createController(streamType) ..onCancel = () { valuesCanceled = true; }; diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 524f0c0db..ae77b7c5a 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -10,32 +10,25 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - var streamTypes = { - 'single subscription': () => StreamController(), - 'broadcast': () => StreamController.broadcast() - }; - for (var streamType in streamTypes.keys) { + for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - StreamController values; - List emittedValues; + StreamController values; + List emittedValues; bool valuesCanceled; bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + Stream transformed; + StreamSubscription subscription; - void setUpStreams(StreamTransformer transformer) { + void setUpStreams(StreamTransformer transformer) { valuesCanceled = false; - values = streamTypes[streamType]() + values = createController(streamType) ..onCancel = () { valuesCanceled = true; }; emittedValues = []; - errors = []; isDone = false; transformed = values.stream.transform(transformer); - subscription = transformed - .listen(emittedValues.add, onError: errors.add, onDone: () { + subscription = transformed.listen(emittedValues.add, onDone: () { isDone = true; }); } diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart index 2bb76795f..b6196d687 100644 --- a/pkgs/stream_transform/test/utils.dart +++ b/pkgs/stream_transform/test/utils.dart @@ -6,6 +6,20 @@ import 'dart:async'; /// Cycle the event loop to ensure timers are started, then wait for a delay /// longer than [milliseconds] to allow for the timer to fire. -Future waitForTimer(int milliseconds) => +Future waitForTimer(int milliseconds) => Future(() {/* ensure Timer is started*/}) .then((_) => Future.delayed(Duration(milliseconds: milliseconds + 1))); + +StreamController createController(String streamType) { + switch (streamType) { + case 'single subscription': + return StreamController(); + case 'broadcast': + return StreamController.broadcast(); + default: + throw ArgumentError.value( + streamType, 'streamType', 'Must be one of $streamTypes'); + } +} + +const streamTypes = ['single subscription', 'broadcast']; From 45f181a632e2c2976e07a01fa466618a959d22bf Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 3 May 2019 11:24:49 -0700 Subject: [PATCH 0545/1215] Add asyncMapSample transform (dart-lang/stream_transform#79) Like `asyncMapBuffer` but drops instead of collecting previous events. - Refactor `_Buffer` class into `Aggregate` which takes a function to aggregate values instead of only collecting them to a List. This will not be published. - Add `asyncMapSample` which is effectively an identical implementation to `asyncMapBuffer` except it chooses a different aggregation function. --- pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/README.md | 5 + .../lib/src/aggregate_sample.dart | 116 ++++++++++ .../lib/src/async_map_buffer.dart | 32 ++- pkgs/stream_transform/lib/src/buffer.dart | 115 +--------- pkgs/stream_transform/pubspec.yaml | 2 +- .../test/async_map_sample_test.dart | 203 ++++++++++++++++++ 7 files changed, 365 insertions(+), 112 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/aggregate_sample.dart create mode 100644 pkgs/stream_transform/test/async_map_sample_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 3f502d3e9..e631a9752 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.0.19 + +- Add `asyncMapSample` transform. + ## 0.0.18 - Internal cleanup. Passed "trigger" streams or futures now allow `` diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 5d24caf04..fc44207ce 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -5,6 +5,11 @@ Utility methods to create `StreamTransfomer` instances to manipulate Streams. Like `asyncMap` but events are buffered in a List until previous events have been processed rather than being called for each element individually. +# asyncMapSample + +Like `asyncMap` but events are discarded, keeping only the latest, until +previous events have been processed rather than being called for every element. + # asyncWhere Like `where` but allows an asynchronous predicate. diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart new file mode 100644 index 000000000..a069af737 --- /dev/null +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -0,0 +1,116 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +/// A StreamTransformer which aggregates values and emits when it sees a value +/// on [_trigger]. +/// +/// If there are no pending values when [_trigger] emits the first value on the +/// source Stream will immediately flow through. Otherwise, the pending values +/// and released when [_trigger] emits. +/// +/// Errors from the source stream or the trigger are immediately forwarded to +/// the output. +class AggregateSample extends StreamTransformerBase { + final Stream _trigger; + final T Function(S, T) _aggregate; + + AggregateSample(this._trigger, this._aggregate); + + @override + Stream bind(Stream values) { + var controller = values.isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + T currentResults; + var waitingForTrigger = true; + var isTriggerDone = false; + var isValueDone = false; + StreamSubscription valueSub; + StreamSubscription triggerSub; + + emit() { + controller.add(currentResults); + currentResults = null; + waitingForTrigger = true; + } + + onValue(S value) { + currentResults = _aggregate(value, currentResults); + + if (!waitingForTrigger) emit(); + + if (isTriggerDone) { + valueSub.cancel(); + controller.close(); + } + } + + onValuesDone() { + isValueDone = true; + if (currentResults == null) { + triggerSub?.cancel(); + controller.close(); + } + } + + onTrigger(_) { + waitingForTrigger = false; + + if (currentResults != null) emit(); + + if (isValueDone) { + triggerSub.cancel(); + controller.close(); + } + } + + onTriggerDone() { + isTriggerDone = true; + if (waitingForTrigger) { + valueSub?.cancel(); + controller.close(); + } + } + + controller.onListen = () { + assert(valueSub == null); + valueSub = values.listen(onValue, + onError: controller.addError, onDone: onValuesDone); + if (triggerSub != null) { + if (triggerSub.isPaused) triggerSub.resume(); + } else { + triggerSub = _trigger.listen(onTrigger, + onError: controller.addError, onDone: onTriggerDone); + } + if (!values.isBroadcast) { + controller + ..onPause = () { + valueSub?.pause(); + triggerSub?.pause(); + } + ..onResume = () { + valueSub?.resume(); + triggerSub?.resume(); + }; + } + controller.onCancel = () { + var toCancel = >[]; + if (!isValueDone) toCancel.add(valueSub); + valueSub = null; + if (_trigger.isBroadcast || !values.isBroadcast) { + if (!isTriggerDone) toCancel.add(triggerSub); + triggerSub = null; + } else { + triggerSub.pause(); + } + if (toCancel.isEmpty) return null; + return Future.wait(toCancel.map((s) => s.cancel())); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index a4e346fe7..70c5bdb9e 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'aggregate_sample.dart'; import 'buffer.dart'; import 'chain_transformers.dart'; import 'from_handlers.dart'; @@ -27,7 +28,7 @@ import 'from_handlers.dart'; /// The result stream will not close until the source stream closes and all /// pending conversions have finished. StreamTransformer asyncMapBuffer( - Future convert(List collected)) { + Future Function(List) convert) { var workFinished = StreamController() // Let the first event through. ..add(null); @@ -35,6 +36,35 @@ StreamTransformer asyncMapBuffer( buffer(workFinished.stream), _asyncMapThen(convert, workFinished.add)); } +/// Like [Stream.asyncMap] but events are discarded while work is happening in +/// [convert]. +/// +/// If the source stream is a broadcast stream the result will be as well. When +/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in +/// that the [convert] function is only called once per event, rather than once +/// per listener per event. +/// +/// If no work is happening when an event is emitted it will be immediately +/// passed to [convert]. If there is ongoing work when an event is emitted it +/// will be held until the work is finished. New events emitted will replace a +/// pending event. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// Errors during the conversion are also forwarded to the result stream and are +/// considered completing work so the next values are let through. +/// +/// The result stream will not close until the source stream closes and all +/// pending conversions have finished. +StreamTransformer asyncMapSample(Future Function(S) convert) { + var workFinished = StreamController() + // Let the first event through. + ..add(null); + return chainTransformers(AggregateSample(workFinished.stream, _dropPrevious), + _asyncMapThen(convert, workFinished.add)); +} + +T _dropPrevious(T event, _) => event; + /// Like [Stream.asyncMap] but the [convert] is only called once per event, /// rather than once per listener, and [then] is called after completing the /// work. diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index 8641b1552..3478a52f5 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -1,8 +1,11 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. + import 'dart:async'; +import 'aggregate_sample.dart'; + /// Creates a [StreamTransformer] which collects values and emits when it sees a /// value on [trigger]. /// @@ -13,114 +16,6 @@ import 'dart:async'; /// Errors from the source stream or the trigger are immediately forwarded to /// the output. StreamTransformer> buffer(Stream trigger) => - _Buffer(trigger); - -/// A StreamTransformer which aggregates values and emits when it sees a value -/// on [_trigger]. -/// -/// If there are no pending values when [_trigger] emits the first value on the -/// source Stream will immediately flow through. Otherwise, the pending values -/// and released when [_trigger] emits. -/// -/// Errors from the source stream or the trigger are immediately forwarded to -/// the output. -class _Buffer extends StreamTransformerBase> { - final Stream _trigger; - - _Buffer(this._trigger); - - @override - Stream> bind(Stream values) { - var controller = values.isBroadcast - ? StreamController>.broadcast(sync: true) - : StreamController>(sync: true); - - List currentResults; - var waitingForTrigger = true; - var isTriggerDone = false; - var isValueDone = false; - StreamSubscription valueSub; - StreamSubscription triggerSub; - - emit() { - controller.add(currentResults); - currentResults = null; - waitingForTrigger = true; - } - - onValue(T value) { - (currentResults ??= []).add(value); - - if (!waitingForTrigger) emit(); - - if (isTriggerDone) { - valueSub.cancel(); - controller.close(); - } - } - - onValuesDone() { - isValueDone = true; - if (currentResults == null) { - triggerSub?.cancel(); - controller.close(); - } - } - - onTrigger(_) { - waitingForTrigger = false; - - if (currentResults != null) emit(); - - if (isValueDone) { - triggerSub.cancel(); - controller.close(); - } - } - - onTriggerDone() { - isTriggerDone = true; - if (waitingForTrigger) { - valueSub?.cancel(); - controller.close(); - } - } + AggregateSample>(trigger, _collect); - controller.onListen = () { - assert(valueSub == null); - valueSub = values.listen(onValue, - onError: controller.addError, onDone: onValuesDone); - if (triggerSub != null) { - if (triggerSub.isPaused) triggerSub.resume(); - } else { - triggerSub = _trigger.listen(onTrigger, - onError: controller.addError, onDone: onTriggerDone); - } - if (!values.isBroadcast) { - controller - ..onPause = () { - valueSub?.pause(); - triggerSub?.pause(); - } - ..onResume = () { - valueSub?.resume(); - triggerSub?.resume(); - }; - } - controller.onCancel = () { - var toCancel = >[]; - if (!isValueDone) toCancel.add(valueSub); - valueSub = null; - if (_trigger.isBroadcast || !values.isBroadcast) { - if (!isTriggerDone) toCancel.add(triggerSub); - triggerSub = null; - } else { - triggerSub.pause(); - } - if (toCancel.isEmpty) return null; - return Future.wait(toCancel.map((s) => s.cancel())); - }; - }; - return controller.stream; - } -} +List _collect(T event, List soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 37a6cbfaf..38ad8d52f 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.18 +version: 0.0.19 environment: sdk: ">=2.2.0 <3.0.0" diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart new file mode 100644 index 000000000..1a6440ecf --- /dev/null +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -0,0 +1,203 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +import 'utils.dart'; + +void main() { + StreamController values; + List emittedValues; + bool valuesCanceled; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + Completer finishWork; + int workArgument; + + /// Represents the async `convert` function and asserts that is is only called + /// after the previous iteration has completed. + Future work(int value) { + expect(finishWork, isNull, + reason: 'See $values befor previous work is complete'); + workArgument = value; + finishWork = Completer(); + finishWork.future.then((_) { + workArgument = null; + finishWork = null; + }).catchError((_) { + workArgument = null; + finishWork = null; + }); + return finishWork.future; + } + + for (var streamType in streamTypes) { + group('asyncMapSample for stream type: [$streamType]', () { + setUp(() { + valuesCanceled = false; + values = createController(streamType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + finishWork = null; + workArgument = null; + transformed = values.stream.transform(asyncMapSample(work)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('does not emit before work finishes', () async { + values.add(1); + await Future(() {}); + expect(emittedValues, isEmpty); + expect(workArgument, 1); + finishWork.complete('result'); + await Future(() {}); + expect(emittedValues, ['result']); + }); + + test('buffers values while work is ongoing', () async { + values.add(1); + await Future(() {}); + values..add(2)..add(3); + await Future(() {}); + finishWork.complete(); + await Future(() {}); + expect(workArgument, 3); + }); + + test('forwards errors without waiting for work', () async { + values.add(1); + await Future(() {}); + values.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors which occur during the work', () async { + values.add(1); + await Future(() {}); + finishWork.completeError('error'); + await Future(() {}); + expect(errors, ['error']); + }); + + test('can continue handling events after an error', () async { + values.add(1); + await Future(() {}); + finishWork.completeError('error'); + values.add(2); + await Future(() {}); + expect(workArgument, 2); + finishWork.completeError('another'); + await Future(() {}); + expect(errors, ['error', 'another']); + }); + + test('does not start next work early due to an error in values', + () async { + values.add(1); + await Future(() {}); + values + ..addError('error') + ..add(2); + await Future(() {}); + expect(errors, ['error']); + // [work] will assert that the second iteration is not called because + // the first has not completed. + }); + + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('closes when values end if no work is pending', () async { + expect(isDone, false); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); + + test('waits for pending work when values close', () async { + values.add(1); + await Future(() {}); + expect(isDone, false); + values.add(2); + await values.close(); + expect(isDone, false); + finishWork.complete(null); + await Future(() {}); + // Still a pending value + expect(isDone, false); + finishWork.complete(null); + await Future(() {}); + expect(isDone, true); + }); + + test('forwards errors from values', () async { + values.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + await Future(() {}); + finishWork.complete('result'); + await Future(() {}); + expect(emittedValues, ['result']); + expect(otherValues, ['result']); + }); + + test('multiple listeners get done when values end', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + values.add(1); + await Future(() {}); + await values.close(); + expect(isDone, false); + expect(otherDone, false); + finishWork.complete(); + await Future(() {}); + expect(isDone, true); + expect(otherDone, true); + }); + + test('can cancel and relisten', () async { + values.add(1); + await Future(() {}); + finishWork.complete('first'); + await Future(() {}); + await subscription.cancel(); + values.add(2); + await Future(() {}); + subscription = transformed.listen(emittedValues.add); + values.add(3); + await Future(() {}); + expect(workArgument, 3); + finishWork.complete('second'); + await Future(() {}); + expect(emittedValues, ['first', 'second']); + }); + } + }); + } +} From 6c137d32e7cbb53566b2d96d794951fe28e79647 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 26 Apr 2019 10:27:58 -0700 Subject: [PATCH 0546/1215] Remove custom Yaml error class --- pkgs/pubspec_parse/lib/src/dependency.dart | 5 +---- pkgs/pubspec_parse/lib/src/errors.dart | 18 +++--------------- pkgs/pubspec_parse/lib/src/pubspec.dart | 3 +-- pkgs/pubspec_parse/test/dependency_test.dart | 8 ++++---- pkgs/pubspec_parse/test/parse_test.dart | 2 +- 5 files changed, 10 insertions(+), 26 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 52057eb43..364e70361 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -6,8 +6,6 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; -import 'errors.dart'; - part 'dependency.g.dart'; Map parseDeps(Map source) => @@ -53,8 +51,7 @@ Dependency _fromJson(dynamic data) { orElse: () => null); if (weirdKey != null) { - throw InvalidKeyException( - data, weirdKey, 'Unsupported dependency key.'); + throw UnrecognizedKeysException([weirdKey], data, _sourceKeys); } if (matchedKeys.length > 1) { throw CheckedFromJsonException(data, matchedKeys[1], 'Dependency', diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart index aba69709b..6d2b38ce7 100644 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ b/pkgs/pubspec_parse/lib/src/errors.dart @@ -11,13 +11,13 @@ ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => ParsedYamlException parsedYamlExceptionFromError( CheckedFromJsonException error, StackTrace stack) { final innerError = error.innerError; - if (innerError is InvalidKeyException) { + if (innerError is UnrecognizedKeysException) { final map = innerError.map; if (map is YamlMap) { // if the associated key exists, use that as the error node, // otherwise use the map itself - final node = map.nodes.keys.cast().singleWhere((key) { - return key.value == innerError.key; + final node = map.nodes.keys.cast().firstWhere((key) { + return innerError.unrecognizedKeys.contains(key.value); }, orElse: () => map); return ParsedYamlException._(innerError.message, node, @@ -72,15 +72,3 @@ class ParsedYamlException implements Exception { @override String toString() => message; } - -/// Package-private class representing an invalid key. -/// -/// Used instead of [CheckedFromJsonException] when highlighting a bad [key] -/// is desired, instead of the associated value. -class InvalidKeyException implements Exception { - final Map map; - final String key; - final String message; - - InvalidKeyException(this.map, this.key, this.message); -} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 3d542d7a9..a8dacf68d 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -185,8 +185,7 @@ Map _environmentMap(Map source) => if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! - throw InvalidKeyException( - source, 'dart', 'Use "sdk" to for Dart SDK constraints.'); + throw UnrecognizedKeysException(['dart'], source, ['sdk']); } VersionConstraint constraint; diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 11a43824d..9e9099731 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -48,7 +48,7 @@ line 5, column 12: A dependency may only have one source. test('map with unsupported keys', () { _expectThrows({'bob': 'a', 'jones': 'b'}, r''' -line 6, column 4: Unsupported dependency key. +line 6, column 4: Unrecognized keys: [jones]; supported keys: [sdk, git, path, hosted] ╷ 6 │ "jones": "b" │ ^^^^^^^ @@ -123,7 +123,7 @@ line 5, column 15: Could not parse version "not a version". Unknown text at "not 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, 'not_supported': null }, r''' -line 10, column 4: Unsupported dependency key. +line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git, path, hosted] ╷ 10│ "not_supported": null │ ^^^^^^^^^^^^^^^ @@ -238,7 +238,7 @@ void _gitDependency() { test('string with random extra key fails', () { _expectThrows({'git': 'url', 'bob': '^1.2.3'}, r''' -line 6, column 4: Unsupported dependency key. +line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ 6 │ "bob": "^1.2.3" │ ^^^^^ @@ -329,7 +329,7 @@ void _pathDependency() { test('valid with random extra key fails', () { _expectThrows({'path': '../path', 'bob': '^1.2.3'}, r''' -line 6, column 4: Unsupported dependency key. +line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ 6 │ "bob": "^1.2.3" │ ^^^^^ diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index dc469a5b7..3c79d87f2 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -210,7 +210,7 @@ line 1, column 1: "name" cannot be empty. 'name': 'sample', 'environment': {'dart': 'cool'} }, r''' -line 4, column 3: Use "sdk" to for Dart SDK constraints. +line 4, column 3: Unrecognized keys: [dart]; supported keys: [sdk] ╷ 4 │ "dart": "cool" │ ^^^^^^ From 7790dff1ab030803aa2613c7b13bf9275a97b650 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 26 Apr 2019 10:11:27 -0700 Subject: [PATCH 0547/1215] use pkg:checked_yaml --- pkgs/pubspec_parse/lib/pubspec_parse.dart | 1 - pkgs/pubspec_parse/lib/src/dependency.dart | 28 ++-- pkgs/pubspec_parse/lib/src/errors.dart | 74 --------- pkgs/pubspec_parse/lib/src/pubspec.dart | 35 ++-- pkgs/pubspec_parse/pubspec.yaml | 1 + pkgs/pubspec_parse/test/dependency_test.dart | 158 ++++++++++++------- pkgs/pubspec_parse/test/parse_test.dart | 125 +++++++++++---- pkgs/pubspec_parse/test/test_utils.dart | 20 ++- 8 files changed, 229 insertions(+), 213 deletions(-) delete mode 100644 pkgs/pubspec_parse/lib/src/errors.dart diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart index 99886c44a..132263a8a 100644 --- a/pkgs/pubspec_parse/lib/pubspec_parse.dart +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -9,5 +9,4 @@ export 'src/dependency.dart' GitDependency, SdkDependency, PathDependency; -export 'src/errors.dart' show ParsedYamlException; export 'src/pubspec.dart' show Pubspec; diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 364e70361..e2b07702d 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -47,20 +47,21 @@ Dependency _fromJson(dynamic data) { if (data.isEmpty || (matchedKeys.isEmpty && data.containsKey('version'))) { return _$HostedDependencyFromJson(data); } else { - final weirdKey = matchedKeys.firstWhere((k) => !_sourceKeys.contains(k), - orElse: () => null); + final firstUnrecognizedKey = matchedKeys + .firstWhere((k) => !_sourceKeys.contains(k), orElse: () => null); - if (weirdKey != null) { - throw UnrecognizedKeysException([weirdKey], data, _sourceKeys); - } - if (matchedKeys.length > 1) { - throw CheckedFromJsonException(data, matchedKeys[1], 'Dependency', - 'A dependency may only have one source.'); - } + return $checkedNew('Dependency', data, () { + if (firstUnrecognizedKey != null) { + throw UnrecognizedKeysException( + [firstUnrecognizedKey], data, _sourceKeys); + } + if (matchedKeys.length > 1) { + throw CheckedFromJsonException(data, matchedKeys[1], 'Dependency', + 'A dependency may only have one source.'); + } - final key = matchedKeys.single; + final key = matchedKeys.single; - try { switch (key) { case 'git': return GitDependency.fromData(data[key]); @@ -72,10 +73,7 @@ Dependency _fromJson(dynamic data) { return _$HostedDependencyFromJson(data); } throw StateError('There is a bug in pubspec_parse.'); - } on ArgumentError catch (e) { - throw CheckedFromJsonException( - data, e.name, 'Dependency', e.message.toString()); - } + }); } } diff --git a/pkgs/pubspec_parse/lib/src/errors.dart b/pkgs/pubspec_parse/lib/src/errors.dart deleted file mode 100644 index 6d2b38ce7..000000000 --- a/pkgs/pubspec_parse/lib/src/errors.dart +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'package:json_annotation/json_annotation.dart'; -import 'package:yaml/yaml.dart'; - -ParsedYamlException parsedYamlException(String message, YamlNode yamlNode) => - ParsedYamlException._(message, yamlNode); - -ParsedYamlException parsedYamlExceptionFromError( - CheckedFromJsonException error, StackTrace stack) { - final innerError = error.innerError; - if (innerError is UnrecognizedKeysException) { - final map = innerError.map; - if (map is YamlMap) { - // if the associated key exists, use that as the error node, - // otherwise use the map itself - final node = map.nodes.keys.cast().firstWhere((key) { - return innerError.unrecognizedKeys.contains(key.value); - }, orElse: () => map); - - return ParsedYamlException._(innerError.message, node, - innerError: error, innerStack: stack); - } - } else if (innerError is ParsedYamlException) { - return innerError; - } - - final yamlMap = error.map as YamlMap; - var yamlNode = yamlMap.nodes[error.key]; - - String message; - if (yamlNode == null) { - assert(error.message != null); - message = error.message; - yamlNode = yamlMap; - } else { - if (error.message == null) { - message = 'Unsupported value for `${error.key}`.'; - } else { - message = error.message.toString(); - } - } - - return ParsedYamlException._(message, yamlNode, - innerError: error, innerStack: stack); -} - -/// Thrown when parsing a YAML document fails. -class ParsedYamlException implements Exception { - /// Describes the nature of the parse failure. - final String message; - - final YamlNode yamlNode; - - /// If this exception was thrown as a result of another error, - /// contains the source error object. - final Object innerError; - - /// If this exception was thrown as a result of another error, - /// contains the corresponding [StackTrace]. - final StackTrace innerStack; - - ParsedYamlException._(this.message, this.yamlNode, - {this.innerError, this.innerStack}); - - /// Returns [message] formatted with source information provided by - /// [yamlNode]. - String get formattedMessage => yamlNode.span.message(message); - - @override - String toString() => message; -} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index a8dacf68d..d31e65773 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -4,10 +4,9 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; -import 'package:yaml/yaml.dart'; +import 'package:checked_yaml/checked_yaml.dart'; import 'dependency.dart'; -import 'errors.dart'; part 'pubspec.g.dart'; @@ -108,7 +107,7 @@ class Pubspec { try { final targetUri = Uri.parse(publishTo); if (!(targetUri.isScheme('http') || targetUri.isScheme('https'))) { - throw const FormatException('must be an http or https URL.'); + throw const FormatException('Must be an http or https URL.'); } } on FormatException catch (e) { throw ArgumentError.value(publishTo, 'publishTo', e.message); @@ -144,25 +143,9 @@ class Pubspec { factory Pubspec.parse(String yaml, {sourceUrl, bool lenient = false}) { lenient ??= false; - final item = loadYaml(yaml, sourceUrl: sourceUrl); - - if (item == null) { - throw ArgumentError.notNull('yaml'); - } - - if (item is! YamlMap) { - if (item is YamlNode) { - throw parsedYamlException('Does not represent a YAML map.', item); - } - - throw ArgumentError.value(yaml, 'yaml', 'Does not represent a YAML map.'); - } - - try { - return Pubspec.fromJson(item as YamlMap, lenient: lenient); - } on CheckedFromJsonException catch (error, stack) { - throw parsedYamlExceptionFromError(error, stack); - } + return checkedYamlDecode( + yaml, (map) => Pubspec.fromJson(map, lenient: lenient), + sourceUrl: sourceUrl); } static List _normalizeAuthors(String author, List authors) { @@ -185,7 +168,13 @@ Map _environmentMap(Map source) => if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 // 'dart' is not allowed as a key! - throw UnrecognizedKeysException(['dart'], source, ['sdk']); + throw CheckedFromJsonException( + source, + 'dart', + 'VersionConstraint', + 'Use "sdk" to for Dart SDK constraints.', + badKey: true, + ); } VersionConstraint constraint; diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index c1df008a9..2ae7fb28f 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -10,6 +10,7 @@ environment: sdk: '>=2.2.0 <3.0.0' dependencies: + checked_yaml: ^1.0.0 # Verified that no new features since 1.0.0 are used - be careful! json_annotation: '>=1.0.0 <3.0.0' pub_semver: ^1.3.2 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 9e9099731..948010558 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -18,32 +18,41 @@ void main() { group('errors', () { test('List', () { - _expectThrows([], r''' -line 4, column 10: Not a valid dependency value. + _expectThrows( + [], + r''' +line 4, column 10: Unsupported value for "dep". Not a valid dependency value. ╷ 4 │ "dep": [] │ ^^ - ╵'''); + ╵''', + ); }); test('int', () { - _expectThrows(42, r''' -line 4, column 10: Not a valid dependency value. + _expectThrows( + 42, + r''' +line 4, column 10: Unsupported value for "dep". Not a valid dependency value. ╷ 4 │ "dep": 42 │ ┌──────────^ 5 │ │ } │ └─^ - ╵'''); + ╵''', + ); }); test('map with too many keys', () { - _expectThrows({'path': 'a', 'git': 'b'}, r''' -line 5, column 12: A dependency may only have one source. + _expectThrows( + {'path': 'a', 'git': 'b'}, + r''' +line 5, column 12: Unsupported value for "path". A dependency may only have one source. ╷ 5 │ "path": "a", │ ^^^ - ╵'''); + ╵''', + ); }); test('map with unsupported keys', () { @@ -79,12 +88,15 @@ void _hostedDependency() { }); test('bad string version', () { - _expectThrows('not a version', r''' -line 4, column 10: Could not parse version "not a version". Unknown text at "not a version". + _expectThrows( + 'not a version', + r''' +line 4, column 10: Unsupported value for "dep". Could not parse version "not a version". Unknown text at "not a version". ╷ 4 │ "dep": "not a version" │ ^^^^^^^^^^^^^^^ - ╵'''); + ╵''', + ); }); test('map w/ just version', () { @@ -106,15 +118,18 @@ line 4, column 10: Could not parse version "not a version". Unknown text at "not }); test('map w/ bad version value', () { - _expectThrows({ - 'version': 'not a version', - 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} - }, r''' -line 5, column 15: Could not parse version "not a version". Unknown text at "not a version". + _expectThrows( + { + 'version': 'not a version', + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} + }, + r''' +line 5, column 15: Unsupported value for "version". Could not parse version "not a version". Unknown text at "not a version". ╷ 5 │ "version": "not a version", │ ^^^^^^^^^^^^^^^ - ╵'''); + ╵''', + ); }); test('map w/ extra keys should fail', () { @@ -148,14 +163,15 @@ line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git }); test('map w/ null hosted should error', () { - _expectThrows({'hosted': null}, r''' -line 5, column 14: These keys had `null` values, which is not allowed: [hosted] + _expectThrows( + {'hosted': null}, + r''' +line 5, column 4: These keys had `null` values, which is not allowed: [hosted] ╷ -5 │ "hosted": null - │ ┌──────────────^ -6 │ │ } - │ └──^ - ╵'''); +5 │ "hosted": null + │ ^^^^^^^^ + ╵''', + ); }); test('map w/ null version is fine', () { @@ -183,25 +199,29 @@ void _sdkDependency() { }); test('null content', () { - _expectThrows({'sdk': null}, r''' -line 5, column 11: These keys had `null` values, which is not allowed: [sdk] + _expectThrows( + {'sdk': null}, + r''' +line 5, column 4: These keys had `null` values, which is not allowed: [sdk] ╷ -5 │ "sdk": null - │ ┌───────────^ -6 │ │ } - │ └──^ - ╵'''); +5 │ "sdk": null + │ ^^^^^ + ╵''', + ); }); test('number content', () { - _expectThrows({'sdk': 42}, r''' -line 5, column 11: Unsupported value for `sdk`. + _expectThrows( + {'sdk': 42}, + r''' +line 5, column 11: Unsupported value for "sdk". ╷ 5 │ "sdk": 42 │ ┌───────────^ 6 │ │ } │ └──^ - ╵'''); + ╵''', + ); }); } @@ -256,25 +276,31 @@ line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hos }); test('git - null content', () { - _expectThrows({'git': null}, r''' -line 5, column 11: Must be a String or a Map. + _expectThrows( + {'git': null}, + r''' +line 5, column 11: Unsupported value for "git". Must be a String or a Map. ╷ 5 │ "git": null │ ┌───────────^ 6 │ │ } │ └──^ - ╵'''); + ╵''', + ); }); test('git - int content', () { - _expectThrows({'git': 42}, r''' -line 5, column 11: Must be a String or a Map. + _expectThrows( + {'git': 42}, + r''' +line 5, column 11: Unsupported value for "git". Must be a String or a Map. ╷ 5 │ "git": 42 │ ┌───────────^ 6 │ │ } │ └──^ - ╵'''); + ╵''', + ); }); test('git - empty map', () { @@ -287,29 +313,33 @@ line 5, column 11: Required keys are missing: url. }); test('git - null url', () { - _expectThrows({ - 'git': {'url': null} - }, r''' -line 6, column 12: These keys had `null` values, which is not allowed: [url] + _expectThrows( + { + 'git': {'url': null} + }, + r''' +line 6, column 5: These keys had `null` values, which is not allowed: [url] ╷ -6 │ "url": null - │ ┌────────────^ -7 │ │ } - │ └───^ - ╵'''); +6 │ "url": null + │ ^^^^^ + ╵''', + ); }); test('git - int url', () { - _expectThrows({ - 'git': {'url': 42} - }, r''' -line 6, column 12: Unsupported value for `url`. + _expectThrows( + { + 'git': {'url': 42} + }, + r''' +line 6, column 12: Unsupported value for "url". ╷ 6 │ "url": 42 │ ┌────────────^ 7 │ │ } │ └───^ - ╵'''); + ╵''', + ); }); } @@ -337,25 +367,31 @@ line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hos }); test('null content', () { - _expectThrows({'path': null}, r''' -line 5, column 12: Must be a String. + _expectThrows( + {'path': null}, + r''' +line 5, column 12: Unsupported value for "path". Must be a String. ╷ 5 │ "path": null │ ┌────────────^ 6 │ │ } │ └──^ - ╵'''); + ╵''', + ); }); test('int content', () { - _expectThrows({'path': 42}, r''' -line 5, column 12: Must be a String. + _expectThrows( + {'path': 42}, + r''' +line 5, column 12: Unsupported value for "path". Must be a String. ╷ 5 │ "path": 42 │ ┌────────────^ 6 │ │ } │ └──^ - ╵'''); + ╵''', + ); }); } diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 3c79d87f2..ca822e7fa 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -75,29 +75,29 @@ void main() { group('publish_to', () { for (var entry in { 42: r''' -line 3, column 16: Unsupported value for `publish_to`. +line 3, column 16: Unsupported value for "publish_to". ╷ 3 │ "publish_to": 42 │ ^^ ╵''', '##not a uri!': r''' -line 3, column 16: must be an http or https URL. +line 3, column 16: Unsupported value for "publish_to". Must be an http or https URL. ╷ 3 │ "publish_to": "##not a uri!" │ ^^^^^^^^^^^^^^ ╵''', '/cool/beans': r''' -line 3, column 16: must be an http or https URL. +line 3, column 16: Unsupported value for "publish_to". Must be an http or https URL. ╷ 3 │ "publish_to": "/cool/beans" │ ^^^^^^^^^^^^^ ╵''', 'file:///Users/kevmoo/': r''' -line 3, column 16: must be an http or https URL. +line 3, column 16: Unsupported value for "publish_to". Must be an http or https URL. ╷ 3 │ "publish_to": "file:///Users/kevmoo/" │ ^^^^^^^^^^^^^^^^^^^^^^^ - ╵''' + ╵''', }.entries) { test('cannot be `${entry.key}`', () { expectParseThrows( @@ -182,14 +182,30 @@ line 3, column 16: must be an http or https URL. group('invalid', () { test('null', () { - expect(() => parse(null), throwsArgumentError); + expectParseThrows( + null, + r''' +line 1, column 1: Not a map + ╷ +1 │ null + │ ^^^^ + ╵''', + ); }); test('empty string', () { - expect(() => parse(''), throwsArgumentError); + expectParseThrows( + '', + r''' +line 1, column 1: Not a map + ╷ +1 │ "" + │ ^^ + ╵''', + ); }); test('array', () { expectParseThrows([], r''' -line 1, column 1: Does not represent a YAML map. +line 1, column 1: Not a map ╷ 1 │ [] │ ^^ @@ -210,7 +226,7 @@ line 1, column 1: "name" cannot be empty. 'name': 'sample', 'environment': {'dart': 'cool'} }, r''' -line 4, column 3: Unrecognized keys: [dart]; supported keys: [sdk] +line 4, column 3: Use "sdk" to for Dart SDK constraints. ╷ 4 │ "dart": "cool" │ ^^^^^^ @@ -218,26 +234,32 @@ line 4, column 3: Unrecognized keys: [dart]; supported keys: [sdk] }); test('environment values cannot be int', () { - expectParseThrows({ - 'name': 'sample', - 'environment': {'sdk': 42} - }, r''' -line 4, column 10: `42` is not a String. + expectParseThrows( + { + 'name': 'sample', + 'environment': {'sdk': 42} + }, + r''' +line 4, column 10: Unsupported value for "sdk". `42` is not a String. ╷ 4 │ "sdk": 42 │ ┌──────────^ 5 │ │ } │ └─^ - ╵'''); + ╵''', + ); }); test('version', () { - expectParseThrows({'name': 'sample', 'version': 'invalid'}, r''' -line 3, column 13: Could not parse "invalid". + expectParseThrows( + {'name': 'sample', 'version': 'invalid'}, + r''' +line 3, column 13: Unsupported value for "version". Could not parse "invalid". ╷ 3 │ "version": "invalid" │ ^^^^^^^^^ - ╵'''); + ╵''', + ); }); test('invalid environment value', () { @@ -245,7 +267,7 @@ line 3, column 13: Could not parse "invalid". 'name': 'sample', 'environment': {'sdk': 'silly'} }, r''' -line 4, column 10: Could not parse version "silly". Unknown text at "silly". +line 4, column 10: Unsupported value for "sdk". Could not parse version "silly". Unknown text at "silly". ╷ 4 │ "sdk": "silly" │ ^^^^^^^ @@ -253,45 +275,80 @@ line 4, column 10: Could not parse version "silly". Unknown text at "silly". }); test('bad repository url', () { - expectParseThrows({ - 'name': 'foo', - 'repository': {'x': 'y'}, - }, r''' -line 3, column 16: Unsupported value for `repository`. + expectParseThrows( + { + 'name': 'foo', + 'repository': {'x': 'y'}, + }, + r''' +line 3, column 16: Unsupported value for "repository". ╷ 3 │ "repository": { │ ┌────────────────^ 4 │ │ "x": "y" 5 │ └ } - ╵''', skipTryPub: true); + ╵''', + skipTryPub: true, + ); }); test('bad issue_tracker url', () { - expectParseThrows({ - 'name': 'foo', - 'issue_tracker': {'x': 'y'}, - }, r''' -line 3, column 19: Unsupported value for `issue_tracker`. + expectParseThrows( + { + 'name': 'foo', + 'issue_tracker': {'x': 'y'}, + }, + r''' +line 3, column 19: Unsupported value for "issue_tracker". ╷ 3 │ "issue_tracker": { │ ┌───────────────────^ 4 │ │ "x": "y" 5 │ └ } - ╵''', skipTryPub: true); + ╵''', + skipTryPub: true, + ); }); }); group('lenient', () { test('null', () { - expect(() => parse(null, lenient: true), throwsArgumentError); + expectParseThrows( + null, + r''' +line 1, column 1: Not a map + ╷ +1 │ null + │ ^^^^ + ╵''', + lenient: true, + ); }); test('empty string', () { - expect(() => parse('', lenient: true), throwsArgumentError); + expectParseThrows( + '', + r''' +line 1, column 1: Not a map + ╷ +1 │ "" + │ ^^ + ╵''', + lenient: true, + ); }); test('name cannot be empty', () { - expect(() => parse({}, lenient: true), throwsException); + expectParseThrows( + {}, + r''' +line 1, column 1: "name" cannot be empty. + ╷ +1 │ {} + │ ^^ + ╵''', + lenient: true, + ); }); test('bad repository url', () { diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 7f8ae87ae..b61cdbd6a 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -5,6 +5,7 @@ import 'dart:cli'; import 'dart:convert'; +import 'package:checked_yaml/checked_yaml.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:pubspec_parse/pubspec_parse.dart'; import 'package:stack_trace/stack_trace.dart'; @@ -25,10 +26,11 @@ Matcher _throwsParsedYamlException(String prettyValue) => void _printDebugParsedYamlException(ParsedYamlException e) { var innerError = e.innerError; - var innerStack = e.innerStack; + StackTrace innerStack; + + if (innerError is CheckedFromJsonException) { + final cfje = innerError as CheckedFromJsonException; - if (e.innerError is CheckedFromJsonException) { - final cfje = e.innerError as CheckedFromJsonException; if (cfje.innerError != null) { innerError = cfje.innerError; innerStack = cfje.innerStack; @@ -98,6 +100,14 @@ void expectParseThrows( Object content, String expectedError, { bool skipTryPub = false, + bool lenient = false, }) => - expect(() => parse(content, quietOnError: true, skipTryPub: skipTryPub), - _throwsParsedYamlException(expectedError)); + expect( + () => parse( + content, + lenient: lenient, + quietOnError: true, + skipTryPub: skipTryPub, + ), + _throwsParsedYamlException(expectedError), + ); From af64d42ca8cd764c49dadc8c97e69a9750ec5a7f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 6 May 2019 09:51:30 -0700 Subject: [PATCH 0548/1215] Enable and fix a number of lints, test on oldest supported SDK (dart-lang/string_scanner#15) Bump min SDK to Dart 2.0 --- pkgs/string_scanner/.travis.yml | 8 +- pkgs/string_scanner/CHANGELOG.md | 4 + pkgs/string_scanner/analysis_options.yaml | 93 +++++++++++++++++++ .../lib/src/eager_span_scanner.dart | 6 +- pkgs/string_scanner/lib/src/exception.dart | 2 + pkgs/string_scanner/lib/src/line_scanner.dart | 6 +- .../lib/src/relative_span_scanner.dart | 16 ++-- pkgs/string_scanner/lib/src/span_scanner.dart | 24 +++-- .../lib/src/string_scanner.dart | 22 ++--- pkgs/string_scanner/lib/src/utils.dart | 12 ++- pkgs/string_scanner/pubspec.yaml | 6 +- pkgs/string_scanner/test/error_test.dart | 32 +++---- .../test/line_scanner_test.dart | 6 +- .../test/span_scanner_test.dart | 18 ++-- .../test/string_scanner_test.dart | 62 ++++++------- pkgs/string_scanner/test/utils.dart | 15 +-- 16 files changed, 210 insertions(+), 122 deletions(-) create mode 100644 pkgs/string_scanner/analysis_options.yaml diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml index 4496f3a4e..48e46ca18 100644 --- a/pkgs/string_scanner/.travis.yml +++ b/pkgs/string_scanner/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev - - stable + - 2.0.0 dart_task: - test: --platform vm,chrome @@ -13,7 +13,11 @@ matrix: - dart: dev dart_task: dartfmt - dart: dev - dart_task: analyzer + dart_task: + dartanalyzer: --fatal-warnings --fatal-hints . + - dart: 2.0.0 + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 43b94535a..1fba528d3 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.5 + +- Update Dart SDK constraint to `>=2.0.0 <3.0.0`. + ## 1.0.4 * Add @alwaysThrows annotation to error method. diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml new file mode 100644 index 000000000..d5d521374 --- /dev/null +++ b/pkgs/string_scanner/analysis_options.yaml @@ -0,0 +1,93 @@ +include: package:pedantic/analysis_options.yaml +analyzer: +# strong-mode: +# implicit-casts: false +linter: + rules: + - always_declare_return_types + #- annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + #- avoid_returning_null + - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_returning_this + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_types_as_parameter_names + - avoid_unused_constructor_parameters + - await_only_futures + - camel_case_types + - cancel_subscriptions + #- cascade_invocations + - comment_references + - constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - file_names + - hash_and_equals + - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - join_return_with_assignment + - library_names + - library_prefixes + - list_remove_unrelated_type + - literal_only_boolean_expressions + - no_adjacent_strings_in_list + - no_duplicate_case_values + - non_constant_identifier_names + - null_closures + - omit_local_variable_types + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + #- prefer_final_locals + - prefer_generic_function_type_aliases + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_is_empty + - prefer_is_not_empty + - prefer_null_aware_operators + #- prefer_single_quotes + - prefer_typing_uninitialized_variables + - recursive_getters + - slash_for_doc_comments + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unawaited_futures + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps + - unnecessary_const + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_this + - unrelated_type_equality_checks + - use_function_type_syntax_for_parameters + - use_rethrow_when_possible + - valid_regexps + - void_checks diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 96c7362e0..a2df0f880 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -11,7 +11,7 @@ import 'span_scanner.dart'; // sdk#23770 is fully complete, we should move the shared code into a mixin. /// A regular expression matching newlines across platforms. -final _newlineRegExp = new RegExp(r"\r\n?|\n"); +final _newlineRegExp = RegExp(r"\r\n?|\n"); /// A [SpanScanner] that tracks the line and column eagerly, like [LineScanner]. class EagerSpanScanner extends SpanScanner { @@ -22,14 +22,14 @@ class EagerSpanScanner extends SpanScanner { int _column = 0; LineScannerState get state => - new _EagerSpanScannerState(this, position, line, column); + _EagerSpanScannerState(this, position, line, column); bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; set state(LineScannerState state) { if (state is! _EagerSpanScannerState || !identical((state as _EagerSpanScannerState)._scanner, this)) { - throw new ArgumentError("The given LineScannerState was not returned by " + throw ArgumentError("The given LineScannerState was not returned by " "this LineScanner."); } diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 84bf5e861..3710ae814 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -4,6 +4,8 @@ import 'package:source_span/source_span.dart'; +import 'string_scanner.dart'; + /// An exception thrown by a [StringScanner] that failed to parse a string. class StringScannerException extends SourceSpanFormatException { String get source => super.source; diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 518203530..e16302a06 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -9,7 +9,7 @@ import 'string_scanner.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. /// A regular expression matching newlines across platforms. -final _newlineRegExp = new RegExp(r"\r\n?|\n"); +final _newlineRegExp = RegExp(r"\r\n?|\n"); /// A subclass of [StringScanner] that tracks line and column information. class LineScanner extends StringScanner { @@ -29,7 +29,7 @@ class LineScanner extends StringScanner { /// /// This does not include the scanner's match information. LineScannerState get state => - new LineScannerState._(this, position, line, column); + LineScannerState._(this, position, line, column); /// Whether the current position is between a CR character and an LF /// charactet. @@ -37,7 +37,7 @@ class LineScanner extends StringScanner { set state(LineScannerState state) { if (!identical(state._scanner, this)) { - throw new ArgumentError("The given LineScannerState was not returned by " + throw ArgumentError("The given LineScannerState was not returned by " "this LineScanner."); } diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index 088ff481f..1a992e41b 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -19,7 +19,7 @@ import 'utils.dart'; class RelativeSpanScanner extends StringScanner implements SpanScanner { /// The source of the scanner. /// - /// This caches line break information and is used to generate [Span]s. + /// This caches line break information and is used to generate [SourceSpan]s. final SourceFile _sourceFile; /// The start location of the span within which this scanner is scanning. @@ -40,16 +40,16 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { : column; } - LineScannerState get state => new _SpanScannerState(this, position); + LineScannerState get state => _SpanScannerState(this, position); set state(LineScannerState state) { if (state is! _SpanScannerState || !identical((state as _SpanScannerState)._scanner, this)) { - throw new ArgumentError("The given LineScannerState was not returned by " + throw ArgumentError("The given LineScannerState was not returned by " "this LineScanner."); } - this.position = state.position; + position = state.position; } FileSpan get lastSpan => _lastSpan; @@ -86,14 +86,12 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; - if (position == null) { - position = match == null ? this.position : match.start; - } - if (length == null) length = match == null ? 1 : match.end - match.start; + position ??= match == null ? this.position : match.start; + length ??= match == null ? 1 : match.end - match.start; var span = _sourceFile.span(_startLocation.offset + position, _startLocation.offset + position + length); - throw new StringScannerException(message, span, string); + throw StringScannerException(message, span, string); } } diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index a629f1327..d33221626 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -12,26 +12,26 @@ import 'string_scanner.dart'; import 'utils.dart'; /// A subclass of [LineScanner] that exposes matched ranges as source map -/// [Span]s. +/// [FileSpan]s. class SpanScanner extends StringScanner implements LineScanner { /// The source of the scanner. /// - /// This caches line break information and is used to generate [Span]s. + /// This caches line break information and is used to generate [FileSpan]s. final SourceFile _sourceFile; int get line => _sourceFile.getLine(position); int get column => _sourceFile.getColumn(position); - LineScannerState get state => new _SpanScannerState(this, position); + LineScannerState get state => _SpanScannerState(this, position); set state(LineScannerState state) { if (state is! _SpanScannerState || !identical((state as _SpanScannerState)._scanner, this)) { - throw new ArgumentError("The given LineScannerState was not returned by " + throw ArgumentError("The given LineScannerState was not returned by " "this LineScanner."); } - this.position = state.position; + position = state.position; } /// The [FileSpan] for [lastMatch]. @@ -57,7 +57,7 @@ class SpanScanner extends StringScanner implements LineScanner { /// [FileSpan]s as well as for error reporting. It can be a [String], a /// [Uri], or `null`. SpanScanner(String string, {sourceUrl, int position}) - : _sourceFile = new SourceFile.fromString(string, url: sourceUrl), + : _sourceFile = SourceFile.fromString(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); /// Creates a new [SpanScanner] that eagerly computes line and column numbers. @@ -76,9 +76,9 @@ class SpanScanner extends StringScanner implements LineScanner { /// Creates a new [SpanScanner] that scans within [span]. /// - /// This scans through [span.text], but emits new spans from [span.file] in + /// This scans through [span]`.text, but emits new spans from [span]`.file` in /// their appropriate relative positions. The [string] field contains only - /// [span.text], and [position], [line], and [column] are all relative to the + /// [span]`.text`, and [position], [line], and [column] are all relative to the /// span. factory SpanScanner.within(FileSpan span) = RelativeSpanScanner; @@ -103,13 +103,11 @@ class SpanScanner extends StringScanner implements LineScanner { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; - if (position == null) { - position = match == null ? this.position : match.start; - } - if (length == null) length = match == null ? 0 : match.end - match.start; + position ??= match == null ? this.position : match.start; + length ??= match == null ? 0 : match.end - match.start; var span = _sourceFile.span(position, position + length); - throw new StringScannerException(message, span, string); + throw StringScannerException(message, span, string); } } diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index d32dc38ad..4506355d2 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -12,7 +12,7 @@ import 'utils.dart'; /// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. /// /// See issue 17998. -final _slashAutoEscape = new RegExp("/").pattern == "\\/"; +final _slashAutoEscape = RegExp("/").pattern == "\\/"; /// A class that scans through a string using [Pattern]s. class StringScanner { @@ -29,7 +29,7 @@ class StringScanner { int get position => _position; set position(int position) { if (position < 0 || position > string.length) { - throw new ArgumentError("Invalid position $position"); + throw ArgumentError("Invalid position $position"); } _position = position; @@ -84,7 +84,7 @@ class StringScanner { /// This returns `null` if [offset] points outside the string. It doesn't /// affect [lastMatch]. int peekChar([int offset]) { - if (offset == null) offset = 0; + offset ??= 0; var index = position + offset; if (index < 0 || index >= string.length) return null; return string.codeUnitAt(index); @@ -115,7 +115,7 @@ class StringScanner { } else if (character == $double_quote) { name = r'"\""'; } else { - name = '"${new String.fromCharCode(character)}"'; + name = '"${String.fromCharCode(character)}"'; } } @@ -181,7 +181,7 @@ class StringScanner { /// Unlike [String.substring], [end] defaults to [position] rather than the /// end of the string. String substring(int start, [int end]) { - if (end == null) end = position; + end ??= position; return string.substring(start, end); } @@ -203,20 +203,18 @@ class StringScanner { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; - if (position == null) { - position = match == null ? this.position : match.start; - } - if (length == null) length = match == null ? 0 : match.end - match.start; + position ??= match == null ? this.position : match.start; + length ??= match == null ? 0 : match.end - match.start; - var sourceFile = new SourceFile.fromString(string, url: sourceUrl); + var sourceFile = SourceFile.fromString(string, url: sourceUrl); var span = sourceFile.span(position, position + length); - throw new StringScannerException(message, span, string); + throw StringScannerException(message, span, string); } // TODO(nweiz): Make this handle long lines more gracefully. /// Throws a [FormatException] describing that [name] is expected at the /// current position in the string. void _fail(String name) { - error("expected $name.", position: this.position, length: 0); + error("expected $name.", position: position, length: 0); } } diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index aa3e95736..df29ba21b 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -2,27 +2,29 @@ // 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. +import 'string_scanner.dart'; + /// Validates the arguments passed to [StringScanner.error]. void validateErrorArgs(String string, Match match, int position, int length) { if (match != null && (position != null || length != null)) { - throw new ArgumentError("Can't pass both match and position/length."); + throw ArgumentError("Can't pass both match and position/length."); } if (position != null) { if (position < 0) { - throw new RangeError("position must be greater than or equal to 0."); + throw RangeError("position must be greater than or equal to 0."); } else if (position > string.length) { - throw new RangeError("position must be less than or equal to the " + throw RangeError("position must be less than or equal to the " "string length."); } } if (length != null && length < 0) { - throw new RangeError("length must be greater than or equal to 0."); + throw RangeError("length must be greater than or equal to 0."); } if (position != null && length != null && position + length > string.length) { - throw new RangeError("position plus length must not go beyond the end of " + throw RangeError("position plus length must not go beyond the end of " "the string."); } } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 769199054..2bc50d6e4 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 1.0.4 +version: 1.0.5-dev description: A class for parsing strings using a sequence of patterns. author: Dart Team homepage: https://github.com/dart-lang/string_scanner environment: - sdk: '>=1.8.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: charcode: ^1.1.0 @@ -14,5 +14,5 @@ dependencies: source_span: ^1.4.0 dev_dependencies: - test: '>=0.12.0 <2.0.0' + test: ^1.0.0 diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index 166077d5e..b966b1bca 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -9,7 +9,7 @@ import 'utils.dart'; void main() { test('defaults to the last match', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); scanner.expect('bar'); expect(() => scanner.error('oh no!'), throwsStringScannerException('bar')); @@ -17,7 +17,7 @@ void main() { group("with match", () { test('supports an earlier match', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); var match = scanner.lastMatch; scanner.expect('bar'); @@ -26,8 +26,7 @@ void main() { }); test('supports a match on a previous line', () { - var scanner = - new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo '); scanner.expect('re'); var match = scanner.lastMatch; @@ -37,8 +36,7 @@ void main() { }); test('supports a multiline match', () { - var scanner = - new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar '); scanner.expect('baz\ndo'); var match = scanner.lastMatch; @@ -48,7 +46,7 @@ void main() { }); test('supports a match after position', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); scanner.expect('bar'); var match = scanner.lastMatch; @@ -60,59 +58,57 @@ void main() { group("with position and/or length", () { test('defaults to length 0', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1), throwsStringScannerException('')); }); test('defaults to the current position', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', length: 3), throwsStringScannerException('bar')); }); test('supports an earlier position', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1, length: 2), throwsStringScannerException('oo')); }); test('supports a position on a previous line', () { - var scanner = - new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 15, length: 2), throwsStringScannerException('re')); }); test('supports a multiline length', () { - var scanner = - new StringScanner('foo bar baz\ndo re mi\nearth fire water'); + var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 8, length: 8), throwsStringScannerException('baz\ndo r')); }); test('supports a position after the current one', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); expect(() => scanner.error('oh no!', position: 4, length: 3), throwsStringScannerException('bar')); }); test('supports a length of zero', () { - var scanner = new StringScanner('foo bar baz'); + var scanner = StringScanner('foo bar baz'); expect(() => scanner.error('oh no!', position: 4, length: 0), throwsStringScannerException('')); }); }); group("argument errors", () { - var scanner; + StringScanner scanner; setUp(() { - scanner = new StringScanner('foo bar baz'); + scanner = StringScanner('foo bar baz'); scanner.scan('foo'); }); diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index ed04b371c..876714271 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -7,9 +7,9 @@ import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; void main() { - var scanner; + LineScanner scanner; setUp(() { - scanner = new LineScanner('foo\nbar\r\nbaz'); + scanner = LineScanner('foo\nbar\r\nbaz'); }); test('begins with line and column 0', () { @@ -162,7 +162,7 @@ void main() { test("state= rejects a foreign state", () { scanner.scan('foo\nb'); - expect(() => new LineScanner(scanner.string).state = scanner.state, + expect(() => LineScanner(scanner.string).state = scanner.state, throwsArgumentError); }); } diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 37a01e025..65694eaac 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -10,23 +10,22 @@ import 'utils.dart'; void main() { testForImplementation("lazy", ([String string]) { - return new SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); + return SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); testForImplementation("eager", ([String string]) { - return new SpanScanner.eager(string ?? 'foo\nbar\nbaz', - sourceUrl: 'source'); + return SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); group("within", () { var text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; var startOffset = text.indexOf('foo'); - var scanner; + SpanScanner scanner; setUp(() { - var file = new SourceFile.fromString(text, url: 'source'); - scanner = new SpanScanner.within( - file.span(startOffset, text.indexOf(' :after'))); + var file = SourceFile.fromString(text, url: 'source'); + scanner = + SpanScanner.within(file.span(startOffset, text.indexOf(' :after'))); }); test("string only includes the span text", () { @@ -104,9 +103,10 @@ void main() { }); } -void testForImplementation(String name, SpanScanner create([String string])) { +void testForImplementation( + String name, SpanScanner Function([String string]) create) { group("for a $name scanner", () { - var scanner; + SpanScanner scanner; setUp(() => scanner = create()); test("tracks the span for the last match", () { diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 30711f5ae..9d6d6b860 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -8,9 +8,9 @@ import 'package:test/test.dart'; void main() { group('with an empty string', () { - var scanner; + StringScanner scanner; setUp(() { - scanner = new StringScanner(''); + scanner = StringScanner(''); }); test('is done', () { @@ -55,19 +55,19 @@ void main() { }); test("scan returns false and doesn't change the state", () { - expect(scanner.scan(new RegExp('.')), isFalse); + expect(scanner.scan(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); test("expect throws a FormatException and doesn't change the state", () { - expect(() => scanner.expect(new RegExp('.')), throwsFormatException); + expect(() => scanner.expect(RegExp('.')), throwsFormatException); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); test("matches returns false and doesn't change the state", () { - expect(scanner.matches(new RegExp('.')), isFalse); + expect(scanner.matches(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); @@ -90,9 +90,9 @@ void main() { }); group('at the beginning of a string', () { - var scanner; + StringScanner scanner; setUp(() { - scanner = new StringScanner('foo bar'); + scanner = StringScanner('foo bar'); }); test('is not done', () { @@ -155,24 +155,24 @@ void main() { }); test("a matching scan returns true and changes the state", () { - expect(scanner.scan(new RegExp('f(..)')), isTrue); + expect(scanner.scan(RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); }); test("a non-matching scan returns false and sets lastMatch to null", () { - expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch, isNotNull); - expect(scanner.scan(new RegExp('b(..)')), isFalse); + expect(scanner.scan(RegExp('b(..)')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); expect(scanner.rest, equals('foo bar')); }); test("a matching expect changes the state", () { - scanner.expect(new RegExp('f(..)')); + scanner.expect(RegExp('f(..)')); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); @@ -181,17 +181,17 @@ void main() { test( "a non-matching expect throws a FormatException and sets lastMatch to " "null", () { - expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch, isNotNull); - expect(() => scanner.expect(new RegExp('b(..)')), throwsFormatException); + expect(() => scanner.expect(RegExp('b(..)')), throwsFormatException); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); expect(scanner.rest, equals('foo bar')); }); test("a matching matches returns true and only changes lastMatch", () { - expect(scanner.matches(new RegExp('f(..)')), isTrue); + expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(0)); expect(scanner.rest, equals('foo bar')); @@ -199,7 +199,7 @@ void main() { test("a non-matching matches returns false and doesn't change the state", () { - expect(scanner.matches(new RegExp('b(..)')), isFalse); + expect(scanner.matches(RegExp('b(..)')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); expect(scanner.rest, equals('foo bar')); @@ -222,7 +222,7 @@ void main() { expect(scanner.position, equals(1)); expect(scanner.rest, equals('oo bar')); - expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.scan(RegExp('oo.')), isTrue); expect(scanner.lastMatch[0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); @@ -248,12 +248,12 @@ void main() { }); test('scans multiple times', () { - expect(scanner.scan(new RegExp('f(..)')), isTrue); + expect(scanner.scan(RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); - expect(scanner.scan(new RegExp(' b(..)')), isTrue); + expect(scanner.scan(RegExp(' b(..)')), isTrue); expect(scanner.lastMatch[1], equals('ar')); expect(scanner.position, equals(7)); expect(scanner.rest, equals('')); @@ -263,9 +263,9 @@ void main() { }); group('after a scan', () { - var scanner; + StringScanner scanner; setUp(() { - scanner = new StringScanner('foo bar'); + scanner = StringScanner('foo bar'); expect(scanner.scan('foo'), isTrue); }); @@ -289,9 +289,9 @@ void main() { }); group('at the end of a string', () { - var scanner; + StringScanner scanner; setUp(() { - scanner = new StringScanner('foo bar'); + scanner = StringScanner('foo bar'); expect(scanner.scan('foo bar'), isTrue); }); @@ -333,19 +333,19 @@ void main() { }); test("scan returns false and sets lastMatch to null", () { - expect(scanner.scan(new RegExp('.')), isFalse); + expect(scanner.scan(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); test("expect throws a FormatException and sets lastMatch to null", () { - expect(() => scanner.expect(new RegExp('.')), throwsFormatException); + expect(() => scanner.expect(RegExp('.')), throwsFormatException); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); test("matches returns false sets lastMatch to null", () { - expect(scanner.matches(new RegExp('.')), isFalse); + expect(scanner.matches(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); @@ -367,7 +367,7 @@ void main() { expect(scanner.position, equals(1)); expect(scanner.rest, equals('oo bar')); - expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.scan(RegExp('oo.')), isTrue); expect(scanner.lastMatch[0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); @@ -395,24 +395,22 @@ void main() { group('a scanner constructed with a custom position', () { test('starts scanning from that position', () { - var scanner = new StringScanner('foo bar', position: 1); + var scanner = StringScanner('foo bar', position: 1); expect(scanner.position, equals(1)); expect(scanner.rest, equals('oo bar')); - expect(scanner.scan(new RegExp('oo.')), isTrue); + expect(scanner.scan(RegExp('oo.')), isTrue); expect(scanner.lastMatch[0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); }); test('throws an ArgumentError if the position is -1', () { - expect(() => new StringScanner('foo bar', position: -1), - throwsArgumentError); + expect(() => StringScanner('foo bar', position: -1), throwsArgumentError); }); test('throws an ArgumentError if the position is beyond the string', () { - expect( - () => new StringScanner('foo bar', position: 8), throwsArgumentError); + expect(() => StringScanner('foo bar', position: 8), throwsArgumentError); }); }); } diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index 7767fbc88..676b69555 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -5,13 +5,8 @@ import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; -/// Returns a matcher that asserts that a closure throws a [FormatException] -/// with the given [message]. -Matcher throwsStringScannerException(String text) { - return throwsA(predicate((error) { - // ignore: deprecated_member_use - expect(error, new isInstanceOf()); - expect(error.span.text, equals(text)); - return true; - })); -} +/// Returns a matcher that asserts that a closure throws a +/// [StringScannerException] with the given [text]. +Matcher throwsStringScannerException(String text) => + throwsA(const TypeMatcher() + .having((e) => e.span.text, 'span.text', text)); From 5277da0689a5a47ab369b5289b453ad2a5bdd8fc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 10 May 2019 11:50:30 -0700 Subject: [PATCH 0549/1215] Fix lints --- pkgs/timing/analysis_options.yaml | 3 +++ pkgs/timing/lib/src/clock.dart | 2 +- pkgs/timing/lib/src/timing.dart | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index 3155c7fc0..dd6881e3f 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -12,4 +12,7 @@ analyzer: linter: rules: - comment_references + - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables + - unnecessary_const + - unnecessary_new diff --git a/pkgs/timing/lib/src/clock.dart b/pkgs/timing/lib/src/clock.dart index 1974c4a79..a3ad7d445 100644 --- a/pkgs/timing/lib/src/clock.dart +++ b/pkgs/timing/lib/src/clock.dart @@ -5,7 +5,7 @@ import 'dart:async'; /// A function that returns the current [DateTime]. -typedef DateTime _Clock(); +typedef _Clock = DateTime Function(); DateTime _defaultClock() => DateTime.now(); const _ZoneKey = #timing_Clock; diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index 15e885471..8959cae53 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -60,7 +60,7 @@ class TimeSliceGroup implements TimeSlice { duration + (slice is TimeSliceGroup ? slice.innerDuration : slice.duration)); - TimeSliceGroup(List this.slices); + TimeSliceGroup(this.slices); /// Constructs TimeSliceGroup from JSON representation factory TimeSliceGroup.fromJson(Map json) => From eef2bff4d391f66d94a670b217320cc6682be676 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 10 May 2019 11:51:08 -0700 Subject: [PATCH 0550/1215] Test on oldest supported SDK --- pkgs/timing/.travis.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/timing/.travis.yml b/pkgs/timing/.travis.yml index 77141bf1a..20c457c6a 100644 --- a/pkgs/timing/.travis.yml +++ b/pkgs/timing/.travis.yml @@ -1,13 +1,19 @@ language: dart dart: + - 2.0.0 - dev dart_task: -- dartfmt - dartanalyzer: --fatal-infos --fatal-warnings . - test +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt + branches: only: - master From 3b98d7f8fab111e4bf6abe392e958fbebd1f6393 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 16 May 2019 16:22:37 -0600 Subject: [PATCH 0551/1215] Enable and fix lints, test on oldest supported Dart SDK, verify lints on Travis (dart-lang/watcher#68) --- pkgs/watcher/.travis.yml | 20 +++++++++++++------ pkgs/watcher/analysis_options.yaml | 3 +++ pkgs/watcher/benchmark/path_set.dart | 10 +++++++--- pkgs/watcher/lib/src/async_queue.dart | 2 +- .../watcher/lib/src/file_watcher/polling.dart | 4 +++- pkgs/watcher/lib/src/stat.dart | 2 +- pkgs/watcher/pubspec.yaml | 6 +++--- .../test/directory_watcher/shared.dart | 6 +++--- pkgs/watcher/test/no_subscription/shared.dart | 3 ++- pkgs/watcher/test/ready/shared.dart | 5 +++-- pkgs/watcher/test/utils.dart | 6 +++--- 11 files changed, 43 insertions(+), 24 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index 254764448..c15590ba4 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -1,15 +1,23 @@ language: dart -dart: dev + +dart: +- dev +- 2.0.0 dart_task: - - test - - dartfmt - - dartanalyzer +- test +- dartanalyzer: --fatal-warnings --fatal-infos . + +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt # Only building master means that we don't run two builds for each pull request. branches: only: [master] cache: - directories: - - $HOME/.pub-cache + directories: + - $HOME/.pub-cache diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index 3155c7fc0..dd6881e3f 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -12,4 +12,7 @@ analyzer: linter: rules: - comment_references + - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables + - unnecessary_const + - unnecessary_new diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index 8a5b843ef..1ec333626 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -21,7 +21,7 @@ abstract class PathSetBenchmark extends BenchmarkBase { final PathSet pathSet = PathSet(root); - /// Use a fixed [Random] with a constant seed to ensure the tests are + /// Use a fixed [math.Random] with a constant seed to ensure the tests are /// deterministic. final math.Random random = math.Random(1234); @@ -59,7 +59,9 @@ class AddBenchmark extends PathSetBenchmark { } void run() { - for (var path in paths) pathSet.add(path); + for (var path in paths) { + pathSet.add(path); + } } } @@ -135,7 +137,9 @@ class RemoveBenchmark extends PathSetBenchmark { } void run() { - for (var path in paths) pathSet.remove(path); + for (var path in paths) { + pathSet.remove(path); + } } } diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index de7b7188a..d864b1bea 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:collection'; -typedef Future ItemProcessor(T item); +typedef ItemProcessor = Future Function(T item); /// A queue of items that are sequentially, asynchronously processed. /// diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 877031ecb..a0466b599 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:io'; +import 'package:pedantic/pedantic.dart'; + import '../file_watcher.dart'; import '../resubscribable.dart'; import '../stat.dart'; @@ -54,7 +56,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { if (_lastModified != null && !pathExists) { _eventsController.add(WatchEvent(ChangeType.REMOVE, path)); - close(); + unawaited(close()); return; } diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 59a5eb6f0..a569208ac 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -7,7 +7,7 @@ import 'dart:io'; /// A function that takes a file path and returns the last modified time for /// the file at that path. -typedef DateTime MockTimeCallback(String path); +typedef MockTimeCallback = DateTime Function(String path); MockTimeCallback _mockTimeCallback; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 163e70ec1..3722c8419 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,7 +1,7 @@ name: watcher -version: 0.9.7+12 +version: 0.9.8-dev -description: > +description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. author: Dart Team @@ -13,9 +13,9 @@ environment: dependencies: async: '>=1.10.0 <3.0.0' path: '>=0.9.0 <2.0.0' + pedantic: ^1.1.0 dev_dependencies: benchmark_harness: ^1.0.4 - pedantic: ^1.1.0 test: '>=0.12.42 <2.0.0' test_descriptor: ^1.0.0 diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index f6e451cbc..a302c933e 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -115,7 +115,7 @@ void sharedTests() { await startWatcher(path: "dir"); renameFile("old.txt", "dir/new.txt"); - expectAddEvent("dir/new.txt"); + await expectAddEvent("dir/new.txt"); }); test('notifies when a file is moved outside the watched directory', @@ -124,7 +124,7 @@ void sharedTests() { await startWatcher(path: "dir"); renameFile("dir/old.txt", "new.txt"); - expectRemoveEvent("dir/old.txt"); + await expectRemoveEvent("dir/old.txt"); }); test('notifies when a file is moved onto an existing one', () async { @@ -231,7 +231,7 @@ void sharedTests() { test('watches files in subdirectories', () async { await startWatcher(); writeFile("a/b/c/d/file.txt"); - expectAddEvent("a/b/c/d/file.txt"); + await expectAddEvent("a/b/c/d/file.txt"); }); test( diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index 2fa3353e0..e82692ec4 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; @@ -15,7 +16,7 @@ void sharedTests() { // stream is and is not subscribed. var watcher = createWatcher(); var queue = StreamQueue(watcher.events); - queue.hasNext; + unawaited(queue.hasNext); var future = expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "file.txt"))); diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index 76089e25e..ebe2f0cf4 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.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. +import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import '../utils.dart'; @@ -11,9 +12,9 @@ void sharedTests() { var watcher = createWatcher(); var ready = false; - watcher.ready.then((_) { + unawaited(watcher.ready.then((_) { ready = true; - }); + })); await pumpEventQueue(); expect(ready, isFalse); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 95f594d8a..57b4563f9 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -7,13 +7,13 @@ import 'dart:io'; import 'package:async/async.dart'; import 'package:path/path.dart' as p; +import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; - import 'package:watcher/src/stat.dart'; import 'package:watcher/watcher.dart'; -typedef Watcher WatcherFactory(String directory); +typedef WatcherFactory = Watcher Function(String directory); /// Sets the function used to create the watcher. set watcherFactory(WatcherFactory factory) { @@ -69,7 +69,7 @@ Future startWatcher({String path}) async { var watcher = createWatcher(path: path); _watcherEvents = StreamQueue(watcher.events); // Forces a subscription to the underlying stream. - _watcherEvents.hasNext; + unawaited(_watcherEvents.hasNext); await watcher.ready; } From e4cc83d61f14c0fc9f85bfdb9ada3e227158e9e8 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 10 May 2019 15:53:38 -0700 Subject: [PATCH 0552/1215] Work-around dart-lang/linterdart-lang/pubspec_parse#1393 Fix is in https://github.com/dart-lang/sdk/commit/dac5a56422 Need it to get into a shipped SDK --- pkgs/pubspec_parse/test/parse_test.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index ca822e7fa..75c3f83e8 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -2,6 +2,11 @@ // 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. +// TODO(kevmoo) Remove when github.com/dart-lang/sdk/commit/dac5a56422 lands +// in a shipped SDK. +// ignore_for_file: deprecated_member_use +library parse_test; + import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; From 38e75a22be4d0c3558fbc5a2e649b8150917879d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 10 May 2019 16:18:26 -0700 Subject: [PATCH 0553/1215] fix debugging tests --- pkgs/pubspec_parse/test/pub_utils.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart index 1ebb9c7ca..17e8970f7 100644 --- a/pkgs/pubspec_parse/test/pub_utils.dart +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -13,8 +13,13 @@ import 'package:test_process/test_process.dart'; Future tryPub(String content) async { await d.file('pubspec.yaml', content).create(); - final proc = await TestProcess.start(_pubPath, ['get', '--offline'], - workingDirectory: d.sandbox); + final proc = await TestProcess.start( + _pubPath, + ['get', '--offline'], + workingDirectory: d.sandbox, + // Don't pass current process VM options to child + environment: Map.from(Platform.environment)..remove('DART_VM_OPTIONS'), + ); final result = await ProcResult.fromTestProcess(proc); From 6315549d42a51be2df6134653e787b5a0a39ca7e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 10 May 2019 16:19:51 -0700 Subject: [PATCH 0554/1215] migrate to json_serializable v3 --- pkgs/pubspec_parse/lib/src/dependency.dart | 5 +++-- pkgs/pubspec_parse/lib/src/dependency.g.dart | 17 +++++++---------- pkgs/pubspec_parse/lib/src/pubspec.dart | 7 ++++--- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 8 ++++---- pkgs/pubspec_parse/pubspec.yaml | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index e2b07702d..2d4eda696 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -128,7 +128,8 @@ class GitDependency extends Dependency { String get _info => 'url@$url'; } -Uri parseGitUri(String value) => _tryParseScpUri(value) ?? Uri.parse(value); +Uri parseGitUri(String value) => + value == null ? null : _tryParseScpUri(value) ?? Uri.parse(value); /// Supports URIs like `[user@]host.xz:path/to/repo.git/` /// See https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a @@ -217,4 +218,4 @@ class HostedDetails { } VersionConstraint _constraintFromString(String input) => - VersionConstraint.parse(input); + input == null ? null : VersionConstraint.parse(input); diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 243a5b3d1..534c03a6b 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -11,8 +11,8 @@ SdkDependency _$SdkDependencyFromJson(Map json) { $checkKeys(json, requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); final val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), - version: $checkedConvert(json, 'version', - (v) => v == null ? null : _constraintFromString(v as String))); + version: $checkedConvert( + json, 'version', (v) => _constraintFromString(v as String))); return val; }); } @@ -22,8 +22,7 @@ GitDependency _$GitDependencyFromJson(Map json) { $checkKeys(json, requiredKeys: const ['url'], disallowNullValues: const ['url']); final val = GitDependency( - $checkedConvert( - json, 'url', (v) => v == null ? null : parseGitUri(v as String)), + $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), $checkedConvert(json, 'ref', (v) => v as String), $checkedConvert(json, 'path', (v) => v as String)); return val; @@ -36,8 +35,8 @@ HostedDependency _$HostedDependencyFromJson(Map json) { allowedKeys: const ['version', 'hosted'], disallowNullValues: const ['hosted']); final val = HostedDependency( - version: $checkedConvert(json, 'version', - (v) => v == null ? null : _constraintFromString(v as String)), + version: $checkedConvert( + json, 'version', (v) => _constraintFromString(v as String)), hosted: $checkedConvert(json, 'hosted', (v) => v == null ? null : HostedDetails.fromJson(v))); return val; @@ -50,10 +49,8 @@ HostedDetails _$HostedDetailsFromJson(Map json) { allowedKeys: const ['name', 'url'], requiredKeys: const ['name'], disallowNullValues: const ['name', 'url']); - final val = HostedDetails( - $checkedConvert(json, 'name', (v) => v as String), - $checkedConvert( - json, 'url', (v) => v == null ? null : parseGitUri(v as String))); + final val = HostedDetails($checkedConvert(json, 'name', (v) => v as String), + $checkedConvert(json, 'url', (v) => parseGitUri(v as String))); return val; }); } diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index d31e65773..735838907 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -2,9 +2,9 @@ // 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. +import 'package:checked_yaml/checked_yaml.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; -import 'package:checked_yaml/checked_yaml.dart'; import 'dependency.dart'; @@ -160,10 +160,11 @@ class Pubspec { } } -Version _versionFromString(String input) => Version.parse(input); +Version _versionFromString(String input) => + input == null ? null : Version.parse(input); Map _environmentMap(Map source) => - source.map((k, value) { + source?.map((k, value) { final key = k as String; if (key == 'dart') { // github.com/dart-lang/pub/blob/d84173eeb03c3/lib/src/pubspec.dart#L342 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index ba7e6ebf1..d3e18f744 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -9,14 +9,14 @@ part of 'pubspec.dart'; Pubspec _$PubspecFromJson(Map json) { return $checkedNew('Pubspec', json, () { final val = Pubspec($checkedConvert(json, 'name', (v) => v as String), - version: $checkedConvert(json, 'version', - (v) => v == null ? null : _versionFromString(v as String)), + version: $checkedConvert( + json, 'version', (v) => _versionFromString(v as String)), publishTo: $checkedConvert(json, 'publish_to', (v) => v as String), author: $checkedConvert(json, 'author', (v) => v as String), authors: $checkedConvert(json, 'authors', (v) => (v as List)?.map((e) => e as String)?.toList()), - environment: $checkedConvert(json, 'environment', - (v) => v == null ? null : _environmentMap(v as Map)), + environment: $checkedConvert( + json, 'environment', (v) => _environmentMap(v as Map)), homepage: $checkedConvert(json, 'homepage', (v) => v as String), repository: $checkedConvert(json, 'repository', (v) => v == null ? null : Uri.parse(v as String)), diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 2ae7fb28f..39e627cc2 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -19,7 +19,7 @@ dependencies: dev_dependencies: build_runner: ^1.0.0 build_verify: ^1.0.0 - json_serializable: ^2.0.0 + json_serializable: ^3.0.0 path: ^1.5.1 pedantic: ^1.4.0 stack_trace: ^1.9.2 From 1ebb78828050a6b65feadfc9b1c4dc396372bb20 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 22 May 2019 16:18:01 -0700 Subject: [PATCH 0555/1215] Use more async/await (dart-lang/watcher#70) * Use more async/await - Change some bare `Future` into `Future` to make sure we aren't silently passing state where we don't expect. - Change some methods with `.then` calls inside to `async`. * Add another await --- pkgs/watcher/lib/src/async_queue.dart | 17 +++--- .../lib/src/directory_watcher/polling.dart | 54 ++++++++++--------- .../lib/src/directory_watcher/windows.dart | 4 +- .../watcher/lib/src/file_watcher/polling.dart | 2 +- pkgs/watcher/lib/src/resubscribable.dart | 15 +++--- pkgs/watcher/lib/src/stat.dart | 7 +-- pkgs/watcher/test/utils.dart | 5 +- 7 files changed, 54 insertions(+), 50 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index d864b1bea..9f8bedf54 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'dart:collection'; -typedef ItemProcessor = Future Function(T item); +typedef ItemProcessor = Future Function(T item); /// A queue of items that are sequentially, asynchronously processed. /// @@ -57,15 +57,14 @@ class AsyncQueue { /// /// When complete, recursively calls itself to continue processing unless /// the process was cancelled. - Future _processNextItem() { + Future _processNextItem() async { var item = _items.removeFirst(); - return _processor(item).then((_) async { - if (_items.isNotEmpty) return await _processNextItem(); + await _processor(item); + if (_items.isNotEmpty) return _processNextItem(); - // We have drained the queue, stop processing and wait until something - // has been enqueued. - _isProcessing = false; - return null; - }); + // We have drained the queue, stop processing and wait until something + // has been enqueued. + _isProcessing = false; + return null; } } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 735a80722..f21a239e9 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -40,8 +40,8 @@ class _PollingDirectoryWatcher bool get isReady => _ready.isCompleted; - Future get ready => _ready.future; - final _ready = Completer(); + Future get ready => _ready.future; + final _ready = Completer(); /// The amount of time the watcher pauses between successive polls of the /// directory contents. @@ -129,38 +129,41 @@ class _PollingDirectoryWatcher /// Processes [file] to determine if it has been modified since the last /// time it was scanned. - Future _processFile(String file) { + Future _processFile(String file) async { // `null` is the sentinel which means the directory listing is complete. - if (file == null) return _completePoll(); - - return getModificationTime(file).then((modified) { - if (_events.isClosed) return null; + if (file == null) { + await _completePoll(); + return; + } - var lastModified = _lastModifieds[file]; + final modified = await modificationTime(file); - // If its modification time hasn't changed, assume the file is unchanged. - if (lastModified != null && lastModified == modified) { - // The file is still here. - _polledFiles.add(file); - return null; - } + if (_events.isClosed) return; - if (_events.isClosed) return null; + var lastModified = _lastModifieds[file]; - _lastModifieds[file] = modified; + // If its modification time hasn't changed, assume the file is unchanged. + if (lastModified != null && lastModified == modified) { + // The file is still here. _polledFiles.add(file); + return; + } - // Only notify if we're ready to emit events. - if (!isReady) return null; + if (_events.isClosed) return; - var type = lastModified == null ? ChangeType.ADD : ChangeType.MODIFY; - _events.add(WatchEvent(type, file)); - }); + _lastModifieds[file] = modified; + _polledFiles.add(file); + + // Only notify if we're ready to emit events. + if (!isReady) return; + + var type = lastModified == null ? ChangeType.ADD : ChangeType.MODIFY; + _events.add(WatchEvent(type, file)); } /// After the directory listing is complete, this determines which files were /// removed and then restarts the next poll. - Future _completePoll() { + Future _completePoll() async { // Any files that were not seen in the last poll but that we have a // status for must have been removed. var removedFiles = _lastModifieds.keys.toSet().difference(_polledFiles); @@ -172,9 +175,8 @@ class _PollingDirectoryWatcher if (!isReady) _ready.complete(); // Wait and then poll again. - return Future.delayed(_pollingDelay).then((_) { - if (_events.isClosed) return; - _poll(); - }); + await Future.delayed(_pollingDelay); + if (_events.isClosed) return; + _poll(); } } diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 7294c170d..85fef5f54 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -52,7 +52,7 @@ class _WindowsDirectoryWatcher bool get isReady => _readyCompleter.isCompleted; - Future get ready => _readyCompleter.future; + Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); final Map _eventBatchers = @@ -380,7 +380,7 @@ class _WindowsDirectoryWatcher /// Starts or restarts listing the watched directory to get an initial picture /// of its state. - Future _listDir() { + Future _listDir() { assert(!isReady); if (_initialListSubscription != null) _initialListSubscription.cancel(); diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index a0466b599..e2bf5dd95 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -62,7 +62,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { DateTime modified; try { - modified = await getModificationTime(path); + modified = await modificationTime(path); } on FileSystemException catch (error, stackTrace) { if (!_eventsController.isClosed) { _eventsController.addError(error, stackTrace); diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index e00ebb0d1..8de3dfb5a 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -31,8 +31,8 @@ abstract class ResubscribableWatcher implements Watcher { bool get isReady => _readyCompleter.isCompleted; - Future get ready => _readyCompleter.future; - var _readyCompleter = Completer(); + Future get ready => _readyCompleter.future; + var _readyCompleter = Completer(); /// Creates a new [ResubscribableWatcher] wrapping the watchers /// emitted by [_factory]. @@ -41,16 +41,17 @@ abstract class ResubscribableWatcher implements Watcher { StreamSubscription subscription; _eventsController = StreamController.broadcast( - onListen: () { + onListen: () async { watcher = _factory(); subscription = watcher.events.listen(_eventsController.add, onError: _eventsController.addError, onDone: _eventsController.close); - // It's important that we complete the value of [_readyCompleter] at the - // time [onListen] is called, as opposed to the value when [watcher.ready] - // fires. A new completer may be created by that time. - watcher.ready.then(_readyCompleter.complete); + // It's important that we complete the value of [_readyCompleter] at + // the time [onListen] is called, as opposed to the value when + // [watcher.ready] fires. A new completer may be created by that time. + await watcher.ready; + _readyCompleter.complete(); }, onCancel: () { // Cancel the subscription before closing the watcher so that the diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index a569208ac..6430d0b56 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -22,10 +22,11 @@ void mockGetModificationTime(MockTimeCallback callback) { } /// Gets the modification time for the file at [path]. -Future getModificationTime(String path) { +Future modificationTime(String path) async { if (_mockTimeCallback != null) { - return Future.value(_mockTimeCallback(path)); + return _mockTimeCallback(path); } - return FileStat.stat(path).then((stat) => stat.modified); + final stat = await FileStat.stat(path); + return stat.modified; } diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 57b4563f9..2e0ad014e 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -79,8 +79,9 @@ Future startWatcher({String path}) async { /// at the end of a test. Otherwise, if they don't occur, the test will wait /// indefinitely because they might in the future and because the watcher is /// normally only closed after the test completes. -void startClosingEventStream() { - pumpEventQueue().then((_) => _watcherEvents.cancel(immediate: true)); +void startClosingEventStream() async { + await pumpEventQueue(); + await _watcherEvents.cancel(immediate: true); } /// A list of [StreamMatcher]s that have been collected using From 41ab62292d63c58913cd694f940975dca2a693ae Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 13 Jun 2019 16:22:23 -0700 Subject: [PATCH 0556/1215] dartfmt, only test dartfmt on dev (dart-lang/pubspec_parse#50) Run tests on 2.2.0 --- pkgs/pubspec_parse/.travis.yml | 5 ++++- pkgs/pubspec_parse/test/test_utils.dart | 10 +++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index 536ccee72..ccb1cafa5 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -1,15 +1,18 @@ language: dart dart: + - 2.2.0 - dev dart_task: - test: -x presubmit-only - test: --run-skipped -t presubmit-only - - dartfmt matrix: include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index b61cdbd6a..00196bb11 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -104,10 +104,10 @@ void expectParseThrows( }) => expect( () => parse( - content, - lenient: lenient, - quietOnError: true, - skipTryPub: skipTryPub, - ), + content, + lenient: lenient, + quietOnError: true, + skipTryPub: skipTryPub, + ), _throwsParsedYamlException(expectedError), ); From b2919b3402080b891f20674f8dd141dfbafdae3b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 12 Jul 2019 16:08:39 -0700 Subject: [PATCH 0557/1215] Prepare to publish 0.9.7+12 (dart-lang/watcher#72) --- pkgs/watcher/CHANGELOG.md | 1 + pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 251c13e96..44fbda520 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,6 +1,7 @@ # 0.9.7+12 * Catch `FileSystemException` during `existsSync()` on Windows. +* Internal cleanup. # 0.9.7+11 diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 3722c8419..f999c2a91 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.8-dev +version: 0.9.7+12 description: >- A file system watcher. It monitors changes to contents of directories and From a1cfd8637399b2b847ed71f7feae2a95b9e1ffcf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 18 Jul 2019 17:16:37 -0700 Subject: [PATCH 0558/1215] enable prefer_generic_function_type_aliases lint (dart-lang/stream_transform#80) --- pkgs/stream_transform/analysis_options.yaml | 1 + pkgs/stream_transform/lib/src/from_handlers.dart | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 67baa3ed2..90cc2c2fa 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -65,6 +65,7 @@ linter: - prefer_contains - prefer_equal_for_default_values - prefer_final_fields + - prefer_generic_function_type_aliases - prefer_initializing_formals - prefer_interpolation_to_compose_strings - prefer_is_empty diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 4f7701d72..93986fa00 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -4,9 +4,9 @@ import 'dart:async'; -typedef void HandleData(S value, EventSink sink); -typedef void HandleDone(EventSink sink); -typedef void HandleError( +typedef HandleData = void Function(S value, EventSink sink); +typedef HandleDone = void Function(EventSink sink); +typedef HandleError = void Function( Object error, StackTrace stackTrace, EventSink sink); /// Like [new StreamTransformer.fromHandlers] but the handlers are called once From dbc38a62a996fa90804084ee2e5d7d5290f0fd36 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 18 Jul 2019 20:13:20 -0700 Subject: [PATCH 0559/1215] Inline some typedefs (dart-lang/stream_transform#81) In each place where these were used they matched the argument/field name anyway so it was repetitive and the name was not adding useful information. They were all a bit shorter than the function type, but not so much so that it's worth the extra level of indirection. --- .../lib/src/from_handlers.dart | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 93986fa00..3e5689fba 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -4,31 +4,26 @@ import 'dart:async'; -typedef HandleData = void Function(S value, EventSink sink); -typedef HandleDone = void Function(EventSink sink); -typedef HandleError = void Function( - Object error, StackTrace stackTrace, EventSink sink); - /// Like [new StreamTransformer.fromHandlers] but the handlers are called once /// per event rather than once per listener for broadcast streams. StreamTransformer fromHandlers( - {HandleData handleData, - HandleError handleError, - HandleDone handleDone}) => + {void Function(S, EventSink) handleData, + void Function(Object, StackTrace, EventSink) handleError, + void Function(EventSink) handleDone}) => _StreamTransformer( handleData: handleData, handleError: handleError, handleDone: handleDone); class _StreamTransformer extends StreamTransformerBase { - final HandleData _handleData; - final HandleDone _handleDone; - final HandleError _handleError; + final void Function(S, EventSink) _handleData; + final void Function(EventSink) _handleDone; + final void Function(Object, StackTrace, EventSink) _handleError; _StreamTransformer( - {HandleData handleData, - HandleError handleError, - HandleDone handleDone}) + {void Function(S, EventSink) handleData, + void Function(Object, StackTrace, EventSink) handleError, + void Function(EventSink) handleDone}) : _handleData = handleData ?? _defaultHandleData, _handleError = handleError ?? _defaultHandleError, _handleDone = handleDone ?? _defaultHandleDone; From a9e09ce3dbdf02952f7f74f94668f0d2d67f8497 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 22 Jul 2019 00:10:53 -0700 Subject: [PATCH 0560/1215] Require Dart 2.2+, use latest json_serializable --- pkgs/timing/.travis.yml | 2 +- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/lib/src/timing.g.dart | 20 +++++++++++++------- pkgs/timing/pubspec.yaml | 6 +++--- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/pkgs/timing/.travis.yml b/pkgs/timing/.travis.yml index 20c457c6a..581db8936 100644 --- a/pkgs/timing/.travis.yml +++ b/pkgs/timing/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - - 2.0.0 + - 2.2.0 - dev dart_task: diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index a8ae834de..855ae6df0 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1+2 + +- Require Dart 2.2 or later. + ## 0.1.1+1 - Support the latest version of `package:json_annotation`. diff --git a/pkgs/timing/lib/src/timing.g.dart b/pkgs/timing/lib/src/timing.g.dart index 214dd82f1..91293b2f8 100644 --- a/pkgs/timing/lib/src/timing.g.dart +++ b/pkgs/timing/lib/src/timing.g.dart @@ -7,20 +7,26 @@ part of 'timing.dart'; // ************************************************************************** TimeSlice _$TimeSliceFromJson(Map json) { - return TimeSlice(DateTime.parse(json['startTime'] as String), - DateTime.parse(json['stopTime'] as String)); + return TimeSlice( + DateTime.parse(json['startTime'] as String), + DateTime.parse(json['stopTime'] as String), + ); } Map _$TimeSliceToJson(TimeSlice instance) => { 'startTime': instance.startTime.toIso8601String(), - 'stopTime': instance.stopTime.toIso8601String() + 'stopTime': instance.stopTime.toIso8601String(), }; TimeSliceGroup _$TimeSliceGroupFromJson(Map json) { - return TimeSliceGroup((json['slices'] as List) - .map((e) => TimeSlice.fromJson(e as Map)) - .toList()); + return TimeSliceGroup( + (json['slices'] as List) + .map((e) => TimeSlice.fromJson(e as Map)) + .toList(), + ); } Map _$TimeSliceGroupToJson(TimeSliceGroup instance) => - {'slices': instance.slices}; + { + 'slices': instance.slices, + }; diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index efda7ce99..663169f08 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,17 +1,17 @@ name: timing -version: 0.1.1+1 description: Timing is a simple package for tracking performance of both async and sync actions +version: 0.1.1+2 author: Dart Team homepage: https://github.com/dart-lang/timing environment: - sdk: ">=2.0.0 <3.0.0" + sdk: ">=2.2.0 <3.0.0" dependencies: json_annotation: '>=1.0.0 <3.0.0' dev_dependencies: build_runner: ^1.0.0 - json_serializable: ^2.0.0 + json_serializable: ^3.1.0 pedantic: ^1.1.0 test: ^1.0.0 From d4f2306f8f51812780a6a745c1211dc2f12b04a6 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 22 Jul 2019 00:11:05 -0700 Subject: [PATCH 0561/1215] Small cleanup to description --- pkgs/timing/pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 663169f08..a04726489 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,6 +1,8 @@ name: timing -description: Timing is a simple package for tracking performance of both async and sync actions version: 0.1.1+2 +description: >- + A simple package for tracking the performance of synchronous and asynchronous + actions. author: Dart Team homepage: https://github.com/dart-lang/timing From dafa868d669e0e22676c1cf7dd2914b21a479516 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 22 Jul 2019 00:15:43 -0700 Subject: [PATCH 0562/1215] Enable and fix a number of lints --- pkgs/timing/analysis_options.yaml | 89 ++++++++++++++++++++++++++++--- pkgs/timing/lib/src/clock.dart | 6 +-- pkgs/timing/lib/src/timing.dart | 24 ++++----- pkgs/timing/test/timing_test.dart | 30 ++++++----- 4 files changed, 113 insertions(+), 36 deletions(-) diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index dd6881e3f..210b18f99 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -2,17 +2,92 @@ include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false - errors: - todo: ignore - unused_import: error - unused_element: error - unused_local_variable: error - dead_code: error - linter: rules: + - always_declare_return_types + - annotate_overrides + - avoid_bool_literals_in_conditional_expressions + - avoid_classes_with_only_static_members + - avoid_empty_else + - avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports + - avoid_renaming_method_parameters + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_returning_null_for_void + - avoid_returning_this + - avoid_shadowing_type_parameters + - avoid_single_cascade_in_expression_statements + - avoid_types_as_parameter_names + - avoid_unused_constructor_parameters + - await_only_futures + - camel_case_types + - cancel_subscriptions + - cascade_invocations - comment_references + - constant_identifier_names + - control_flow_in_finally + - curly_braces_in_flow_control_structures + - directives_ordering + - empty_catches + - empty_constructor_bodies + - empty_statements + - file_names + - hash_and_equals + - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - join_return_with_assignment + - library_names + - library_prefixes + - list_remove_unrelated_type + - literal_only_boolean_expressions + - no_duplicate_case_values + - non_constant_identifier_names + - null_closures + - omit_local_variable_types + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + - prefer_collection_literals + - prefer_conditional_assignment + - prefer_const_constructors + - prefer_contains + - prefer_equal_for_default_values + - prefer_final_fields + - prefer_final_locals - prefer_generic_function_type_aliases + - prefer_initializing_formals + - prefer_interpolation_to_compose_strings + - prefer_iterable_whereType + - prefer_is_empty + - prefer_is_not_empty + - prefer_null_aware_operators + - prefer_single_quotes - prefer_typing_uninitialized_variables + - prefer_void_to_null + - recursive_getters + - slash_for_doc_comments + - test_types_in_equals + - throw_in_finally + - type_init_formals + - unawaited_futures + - unnecessary_brace_in_string_interps - unnecessary_const + - unnecessary_getters_setters + - unnecessary_lambdas - unnecessary_new + - unnecessary_null_aware_assignments + - unnecessary_null_in_if_null_operators + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_this + - unrelated_type_equality_checks + - use_rethrow_when_possible + - valid_regexps + - void_checks diff --git a/pkgs/timing/lib/src/clock.dart b/pkgs/timing/lib/src/clock.dart index a3ad7d445..ae1f25fcc 100644 --- a/pkgs/timing/lib/src/clock.dart +++ b/pkgs/timing/lib/src/clock.dart @@ -8,13 +8,13 @@ import 'dart:async'; typedef _Clock = DateTime Function(); DateTime _defaultClock() => DateTime.now(); -const _ZoneKey = #timing_Clock; +const _zoneKey = #timing_Clock; /// Returns the current [DateTime]. /// /// May be overridden for tests using [scopeClock]. -DateTime now() => (Zone.current[_ZoneKey] as _Clock ?? _defaultClock)(); +DateTime now() => (Zone.current[_zoneKey] as _Clock ?? _defaultClock)(); /// Runs [f], with [clock] scoped whenever [now] is called. T scopeClock(DateTime clock(), T f()) => - runZoned(f, zoneValues: {_ZoneKey: clock}); + runZoned(f, zoneValues: {_zoneKey: clock}); diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index 8959cae53..17e2fb11d 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -127,8 +127,8 @@ class SyncTimeTracker implements TimeTracker { if (!isTracking) { throw StateError('Can be only called while tracking'); } - var _now = now(); - var prevSlice = TimeSlice(_startTime, _now); + final _now = now(); + final prevSlice = TimeSlice(_startTime, _now); _startTime = _now; return prevSlice; } @@ -236,7 +236,7 @@ class NoOpTimeTracker implements TimeTracker { class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { final bool trackNested; - static const _ZoneKey = #timing_AsyncTimeTracker; + static const _zoneKey = #timing_AsyncTimeTracker; AsyncTimeTracker({this.trackNested = true}) : super([]); @@ -246,14 +246,14 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { return action(); } - var isNestedRun = slices.isNotEmpty && + final isNestedRun = slices.isNotEmpty && slices.last is SyncTimeTracker && (slices.last as SyncTimeTracker).isTracking; - var isExcludedNestedTrack = !trackNested && zone[_ZoneKey] != this; + final isExcludedNestedTrack = !trackNested && zone[_zoneKey] != this; // Exclude nested sync tracks if (isNestedRun && isExcludedNestedTrack) { - var timer = slices.last as SyncTimeTracker; + final timer = slices.last as SyncTimeTracker; // Split already tracked time into new slice. // Replace tracker in slices.last with splitted slice, to indicate for // recursive calls that we not tracking. @@ -278,7 +278,7 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { return action(); } - var timer = SyncTimeTracker(); + final timer = SyncTimeTracker(); slices.add(timer); // Pass to parent zone, in case of overwritten clock @@ -287,18 +287,18 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { static final asyncTimeTrackerZoneSpecification = ZoneSpecification( run: (Zone self, ZoneDelegate parent, Zone zone, R Function() f) { - var tracker = self[_ZoneKey] as AsyncTimeTracker; + final tracker = self[_zoneKey] as AsyncTimeTracker; return tracker._trackSyncSlice(parent, zone, () => parent.run(zone, f)); }, runUnary: (Zone self, ZoneDelegate parent, Zone zone, R Function(T) f, T arg) { - var tracker = self[_ZoneKey] as AsyncTimeTracker; + final tracker = self[_zoneKey] as AsyncTimeTracker; return tracker._trackSyncSlice( parent, zone, () => parent.runUnary(zone, f, arg)); }, runBinary: (Zone self, ZoneDelegate parent, Zone zone, R Function(T1, T2) f, T1 arg1, T2 arg2) { - var tracker = self[_ZoneKey] as AsyncTimeTracker; + final tracker = self[_zoneKey] as AsyncTimeTracker; return tracker._trackSyncSlice( parent, zone, () => parent.runBinary(zone, f, arg1, arg2)); }, @@ -310,9 +310,9 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { throw StateError('Can not be tracked twice'); } _tracking = true; - var result = runZoned(action, + final result = runZoned(action, zoneSpecification: asyncTimeTrackerZoneSpecification, - zoneValues: {_ZoneKey: this}); + zoneValues: {_zoneKey: this}); if (result is Future) { return result // Break possible sync processing of future completion, so slice trackers can be finished diff --git a/pkgs/timing/test/timing_test.dart b/pkgs/timing/test/timing_test.dart index 9f3f3acff..b2ea8dad8 100644 --- a/pkgs/timing/test/timing_test.dart +++ b/pkgs/timing/test/timing_test.dart @@ -2,15 +2,17 @@ // 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. +// ignore_for_file: only_throw_errors + import 'dart:async'; import 'package:test/test.dart'; import 'package:timing/src/clock.dart'; import 'package:timing/src/timing.dart'; -_noop() {} +void _noop() {} -main() { +void main() { DateTime time; final startTime = DateTime(2017); DateTime fakeClock() => time; @@ -24,7 +26,7 @@ main() { time = startTime; }); - canHandleSync([additionalExpects() = _noop]) { + void canHandleSync([additionalExpects() = _noop]) { test('Can track sync code', () { expect(tracker.isStarted, false); expect(tracker.isTracking, false); @@ -66,7 +68,7 @@ main() { time = time.add(const Duration(seconds: 5)); throw 'error'; }), - throwsA(TypeMatcher())); + throwsA(const TypeMatcher())); expect(tracker.startTime, startTime); expect(tracker.stopTime, time); expect(tracker.duration, const Duration(seconds: 5)); @@ -92,7 +94,7 @@ main() { }); } - canHandleAsync([additionalExpects() = _noop]) { + void canHandleAsync([additionalExpects() = _noop]) { test('Can track async code', () async { expect(tracker.isStarted, false); expect(tracker.isTracking, false); @@ -132,7 +134,7 @@ main() { }); test('Can track in case of unhandled async exceptions', () async { - var future = scopedTrack(() { + final future = scopedTrack(() { time = time.add(const Duration(seconds: 1)); return Future(() { time = time.add(const Duration(seconds: 2)); @@ -141,7 +143,7 @@ main() { time = time.add(const Duration(seconds: 4)); }); }); - await expectLater(future, throwsA(TypeMatcher())); + await expectLater(future, throwsA(const TypeMatcher())); expect(tracker.isFinished, true); expect(tracker.startTime, startTime); expect(tracker.stopTime, time); @@ -206,7 +208,7 @@ main() { canHandleAsync(); test('Can not distinguish own async code', () async { - var future = scopedTrack(() => Future(() { + final future = scopedTrack(() => Future(() { time = time.add(const Duration(seconds: 5)); })); time = time.add(const Duration(seconds: 10)); @@ -237,8 +239,8 @@ main() { }); test('Can track complex async innerDuration', () async { - var completer = Completer(); - var future = scopedTrack(() async { + final completer = Completer(); + final future = scopedTrack(() async { time = time.add(const Duration(seconds: 1)); // Tracked sync await Future.value(); time = time.add(const Duration(seconds: 2)); // Tracked async @@ -288,7 +290,7 @@ main() { test('Can exclude complex nested sync', () { tracker = asyncTracker = AsyncTimeTracker(trackNested: false); nestedAsyncTracker = AsyncTimeTracker(trackNested: false); - var nestedAsyncTracker2 = AsyncTimeTracker(trackNested: false); + final nestedAsyncTracker2 = AsyncTimeTracker(trackNested: false); scopedTrack(() { time = time.add(const Duration(seconds: 1)); nestedAsyncTracker.track(() { @@ -323,7 +325,7 @@ main() { 'exclude grand-childrens from parent', () { tracker = asyncTracker = AsyncTimeTracker(trackNested: true); nestedAsyncTracker = AsyncTimeTracker(trackNested: false); - var nestedAsyncTracker2 = AsyncTimeTracker(); + final nestedAsyncTracker2 = AsyncTimeTracker(); scopedTrack(() { time = time.add(const Duration(seconds: 1)); nestedAsyncTracker.track(() { @@ -383,8 +385,8 @@ main() { tracker = asyncTracker = AsyncTimeTracker(trackNested: false); await scopedTrack(() async { time = time.add(const Duration(seconds: 1)); - var completer = Completer(); - var future = completer.future.then((_) { + final completer = Completer(); + final future = completer.future.then((_) { time = time.add(const Duration(seconds: 2)); }); await nestedAsyncTracker.track(() async { From 56ef31eb7647a35d69332249d2051c60a73798c1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 23 Jul 2019 12:41:26 -0700 Subject: [PATCH 0563/1215] Use pedantic lints --- pkgs/stream_channel/analysis_options.yaml | 1 + pkgs/stream_channel/pubspec.yaml | 3 +- .../test/disconnector_test.dart | 3 +- .../test/isolate_channel_test.dart | 3 +- .../test/multi_channel_test.dart | 43 ++++++++++--------- .../test/stream_channel_completer_test.dart | 5 ++- .../test/stream_channel_test.dart | 13 +++--- .../test/with_close_guarantee_test.dart | 5 ++- .../test/with_guarantees_test.dart | 17 ++++---- 9 files changed, 51 insertions(+), 42 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 866c1585a..1e02731d7 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,3 +1,4 @@ +include: package:pedantic/analysis_options.yaml analyzer: # These are errors when building in Google errors: diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 917f5bc38..dfd3af83d 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.0.0 +version: 2.0.1-dev description: An abstraction for two-way communication channels. author: Dart Team @@ -12,4 +12,5 @@ dependencies: async: '>=1.11.0 <3.0.0' dev_dependencies: + pedantic: ^1.8.0 test: ^1.2.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 0992b3634..a5ea2ebb5 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -71,7 +72,7 @@ void main() { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); - disconnector.disconnect(); + unawaited(disconnector.disconnect()); await pumpEventQueue(); expect(canceled, isTrue); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 776928d72..fd14b8407 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -7,6 +7,7 @@ import 'dart:async'; import 'dart:isolate'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -82,7 +83,7 @@ void main() { test("cancelling the stream's subscription has no effect on the sink", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); channel.sink.add(1); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 80c595a39..b1659a03a 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.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. +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -143,13 +144,13 @@ void main() { "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. - channel1.sink.close(); + unawaited(channel1.sink.close()); await channel2.stream.toList(); expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); }); test( @@ -243,13 +244,13 @@ void main() { "virtual channels", () async { // First close the default channel so we can test the new channel as the // last living virtual channel. - channel2.sink.close(); + unawaited(channel2.sink.close()); await channel1.stream.toList(); expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); }); test( @@ -287,7 +288,7 @@ void main() { "created", () async { virtual1 = channel1.virtualChannel(); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); await pumpEventQueue(); expect(channel2.virtualChannel(virtual1.id).stream.toList(), @@ -317,8 +318,8 @@ void main() { }); test("closes, more virtual channels are created closed", () async { - channel2.sink.close(); - virtual2.sink.close(); + unawaited(channel2.sink.close()); + unawaited(virtual2.sink.close()); // Wait for the existing channels to emit done events. await channel1.stream.toList(); @@ -359,14 +360,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - channel1.sink.close(); + unawaited(channel1.sink.close()); // Wait for the done event to be delivered. await channel2.stream.toList(); channel2.sink.add(1); channel2.sink.add(2); channel2.sink.add(3); - channel2.sink.close(); + unawaited(channel2.sink.close()); // None of our channel.sink additions should make it to the other endpoint. channel1.stream.listen(expectAsync1((_) {}, count: 0)); @@ -375,28 +376,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - channel1.stream.listen(null).cancel(); + unawaited(channel1.stream.listen(null).cancel()); await pumpEventQueue(); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - channel1.sink.close(); + unawaited(channel1.sink.close()); expect(channel2.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - channel1.stream.listen(null).cancel(); + unawaited(channel1.stream.listen(null).cancel()); await pumpEventQueue(); - channel2.sink.close(); + unawaited(channel2.sink.close()); await pumpEventQueue(); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - channel1.sink.close(); + unawaited(channel1.sink.close()); // The sink should be ignoring events because the channel closed. channel2.stream.listen(expectAsync1((_) {}, count: 0)); @@ -426,14 +427,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - virtual1.sink.close(); + unawaited(virtual1.sink.close()); // Wait for the done event to be delivered. await virtual2.stream.toList(); virtual2.sink.add(1); virtual2.sink.add(2); virtual2.sink.add(3); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); // None of our virtual.sink additions should make it to the other endpoint. virtual1.stream.listen(expectAsync1((_) {}, count: 0)); @@ -442,28 +443,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - virtual1.stream.listen(null).cancel(); + unawaited(virtual1.stream.listen(null).cancel()); await pumpEventQueue(); virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); expect(virtual2.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - virtual1.stream.listen(null).cancel(); + unawaited(virtual1.stream.listen(null).cancel()); await pumpEventQueue(); - virtual2.sink.close(); + unawaited(virtual2.sink.close()); await pumpEventQueue(); virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); - virtual1.sink.close(); + unawaited(virtual1.sink.close()); // The sink should be ignoring events because the stream closed. virtual2.stream.listen(expectAsync1((_) {}, count: 0)); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index c20f9af11..070035e7b 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -62,14 +63,14 @@ void main() { streamController.add(1); streamController.add(2); streamController.add(3); - streamController.close(); + unawaited(streamController.close()); }); test("forwards events through the sink", () async { completer.channel.sink.add(1); completer.channel.sink.add(2); completer.channel.sink.add(3); - completer.channel.sink.close(); + unawaited(completer.channel.sink.close()); await pumpEventQueue(); completer.setChannel(innerChannel); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 2f05a9ef1..3f4e896b3 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,6 +6,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -46,11 +47,11 @@ void main() { .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["foobar"])); transformed.sink.add("fblthp"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect( sinkController.stream.toList(), completion(equals([ @@ -65,12 +66,12 @@ void main() { streamController.add("hello world"); streamController.add(" what\nis"); streamController.add("\nup"); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["hello world what", "is", "up"])); transformed.sink.add("fbl\nthp"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); }); @@ -79,13 +80,13 @@ void main() { StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); streamController.add("fbl\nthp"); - streamController.close(); + unawaited(streamController.close()); expect(await transformed.stream.toList(), equals(["fbl\nthp"])); transformed.sink.add("hello world"); transformed.sink.add(" what\nis"); transformed.sink.add("\nup"); - transformed.sink.close(); + unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), completion(equals(["hello world what", "is", "up"]))); }); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 1749bacb7..803dc61f1 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:async/async.dart'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -54,7 +55,7 @@ void main() { test( "closing the event sink before events are emitted causes the stream to " "close immediately", () async { - channel.sink.close(); + unawaited(channel.sink.close()); channel.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync2((_, __) {}, count: 0), onDone: expectAsync0(() {})); @@ -62,7 +63,7 @@ void main() { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); - controller.local.sink.close(); + unawaited(controller.local.sink.close()); await pumpEventQueue(); }); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 0ea59525e..c9ff59f1e 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; @@ -32,7 +33,7 @@ void main() { await pumpEventQueue(); expect(channel.stream.toList(), completion(equals([1, 2, 3]))); - streamController.close(); + unawaited(streamController.close()); }); test("only allows a single subscription", () { @@ -58,14 +59,14 @@ void main() { }); test("after the stream closes, the sink ignores events", () async { - streamController.close(); + unawaited(streamController.close()); // Wait for the done event to be delivered. await channel.stream.toList(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); // None of our channel.sink additions should make it to the other endpoint. sinkController.stream.listen(expectAsync1((_) {}, count: 0), @@ -75,28 +76,28 @@ void main() { test("canceling the stream's subscription has no effect on the sink", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); test("canceling the stream's subscription doesn't stop a done event", () async { - channel.stream.listen(null).cancel(); + unawaited(channel.stream.listen(null).cancel()); await pumpEventQueue(); - streamController.close(); + unawaited(streamController.close()); await pumpEventQueue(); channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); - channel.sink.close(); + unawaited(channel.sink.close()); // The sink should be ignoring events because the stream closed. sinkController.stream.listen(expectAsync1((_) {}, count: 0), From 33592843725d99b811c25f942de1edf76c5a69a0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:10 -0700 Subject: [PATCH 0564/1215] Remove unneeded codereview.settings --- pkgs/stream_channel/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stream_channel/codereview.settings diff --git a/pkgs/stream_channel/codereview.settings b/pkgs/stream_channel/codereview.settings deleted file mode 100644 index 7b0a9edc6..000000000 --- a/pkgs/stream_channel/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: https://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/stream_channel/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From d77f04738c492f95aca41c991c454f99d36bdafc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:23 -0700 Subject: [PATCH 0565/1215] Fix outdated URLs --- pkgs/stream_channel/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index 5d6a2b4e0..2ec970b8e 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -7,10 +7,10 @@ protocol. For example, the [`test`][test] package re-uses its test suite communication protocol for both WebSocket connections to browser suites and Isolate connections to VM tests. -[test]: https://pub.dartlang.org/packages/test +[test]: https://pub.dev/packages/test This package also contains utilities for dealing with `StreamChannel`s and with two-way communications in general. For documentation of these utilities, see [the API docs][api]. -[api]: https://www.dartdocs.org/documentation/stream_channel/latest +[api]: https://pub.dev/documentation/stream_channel/latest/ From 077574a8b132d7f9a2199dc9bbbdcb5a23b940f9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:34 -0700 Subject: [PATCH 0566/1215] Add missing dartfmt --fix lint --- pkgs/stream_channel/analysis_options.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 1e02731d7..df4128a17 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -11,4 +11,5 @@ linter: rules: - annotate_overrides - comment_references + - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables From 4d81dead936cf59e79334fbc02b404f8f8959edd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:54:55 -0700 Subject: [PATCH 0567/1215] Test on oldest supported Dart SDK --- pkgs/stream_channel/.travis.yml | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 45359fb40..69f24c3fa 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,12 +1,23 @@ language: dart dart: - - dev +- 2.0.0 +- dev + dart_task: - - test: --platform vm - - test: --platform firefox -j 1 - - dartfmt - - dartanalyzer +- test: --platform vm,chrome + +matrix: + include: + # Only validate formatting using the dev release + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: + dartanalyzer: --fatal-infos --fatal-warnings . + - dart: 2.0.0 + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: @@ -14,4 +25,4 @@ branches: cache: directories: - - $HOME/.pub-cache + - $HOME/.pub-cache From a3da73812869c4e593b57eb6d04967dee16a949a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 09:56:05 -0700 Subject: [PATCH 0568/1215] pubspec: Make the description a bit longer --- pkgs/stream_channel/pubspec.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index dfd3af83d..bef50e1cb 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,7 +1,9 @@ name: stream_channel version: 2.0.1-dev -description: An abstraction for two-way communication channels. +description: >- + An abstraction for two-way communication channels based on the Dart Stream + class. author: Dart Team homepage: https://github.com/dart-lang/stream_channel From f1838d9b911a1865eb92c3c968f6d541e24c6fbe Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 25 Jul 2019 10:14:41 -0700 Subject: [PATCH 0569/1215] =?UTF-8?q?Require=20Dart=202.2=20=E2=80=93?= =?UTF-8?q?=C2=A0because=20pkg:pedantic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkgs/stream_channel/.travis.yml | 4 ++-- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 69f24c3fa..d6a545496 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- 2.0.0 +- 2.2.0 - dev dart_task: @@ -15,7 +15,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.0.0 + - dart: 2.2.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 24564ede1..4f345106a 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Require Dart `2.2.0` or later. + ## 2.0.0 **Breaking changes** diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index bef50e1cb..61e78c0f3 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.0.1-dev +version: 2.1.0-dev description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,7 +8,7 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.2.0 <3.0.0' dependencies: async: '>=1.11.0 <3.0.0' From 85941fc296cb287862ac659261eeb8ea27633189 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 26 Jul 2019 18:36:41 -0700 Subject: [PATCH 0570/1215] regenerate code (dart-lang/pubspec_parse#51) --- pkgs/pubspec_parse/lib/src/dependency.g.dart | 30 ++++++---- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 59 ++++++++++---------- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 534c03a6b..4e137fad7 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -10,9 +10,11 @@ SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { $checkKeys(json, requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); - final val = SdkDependency($checkedConvert(json, 'sdk', (v) => v as String), - version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String))); + final val = SdkDependency( + $checkedConvert(json, 'sdk', (v) => v as String), + version: $checkedConvert( + json, 'version', (v) => _constraintFromString(v as String)), + ); return val; }); } @@ -22,9 +24,10 @@ GitDependency _$GitDependencyFromJson(Map json) { $checkKeys(json, requiredKeys: const ['url'], disallowNullValues: const ['url']); final val = GitDependency( - $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), - $checkedConvert(json, 'ref', (v) => v as String), - $checkedConvert(json, 'path', (v) => v as String)); + $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), + $checkedConvert(json, 'ref', (v) => v as String), + $checkedConvert(json, 'path', (v) => v as String), + ); return val; }); } @@ -35,10 +38,11 @@ HostedDependency _$HostedDependencyFromJson(Map json) { allowedKeys: const ['version', 'hosted'], disallowNullValues: const ['hosted']); final val = HostedDependency( - version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String)), - hosted: $checkedConvert(json, 'hosted', - (v) => v == null ? null : HostedDetails.fromJson(v))); + version: $checkedConvert( + json, 'version', (v) => _constraintFromString(v as String)), + hosted: $checkedConvert( + json, 'hosted', (v) => v == null ? null : HostedDetails.fromJson(v)), + ); return val; }); } @@ -49,8 +53,10 @@ HostedDetails _$HostedDetailsFromJson(Map json) { allowedKeys: const ['name', 'url'], requiredKeys: const ['name'], disallowNullValues: const ['name', 'url']); - final val = HostedDetails($checkedConvert(json, 'name', (v) => v as String), - $checkedConvert(json, 'url', (v) => parseGitUri(v as String))); + final val = HostedDetails( + $checkedConvert(json, 'name', (v) => v as String), + $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), + ); return val; }); } diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index d3e18f744..eb062b8fd 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -8,35 +8,36 @@ part of 'pubspec.dart'; Pubspec _$PubspecFromJson(Map json) { return $checkedNew('Pubspec', json, () { - final val = Pubspec($checkedConvert(json, 'name', (v) => v as String), - version: $checkedConvert( - json, 'version', (v) => _versionFromString(v as String)), - publishTo: $checkedConvert(json, 'publish_to', (v) => v as String), - author: $checkedConvert(json, 'author', (v) => v as String), - authors: $checkedConvert(json, 'authors', - (v) => (v as List)?.map((e) => e as String)?.toList()), - environment: $checkedConvert( - json, 'environment', (v) => _environmentMap(v as Map)), - homepage: $checkedConvert(json, 'homepage', (v) => v as String), - repository: $checkedConvert(json, 'repository', - (v) => v == null ? null : Uri.parse(v as String)), - issueTracker: $checkedConvert(json, 'issue_tracker', - (v) => v == null ? null : Uri.parse(v as String)), - documentation: - $checkedConvert(json, 'documentation', (v) => v as String), - description: $checkedConvert(json, 'description', (v) => v as String), - dependencies: - $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map)), - devDependencies: $checkedConvert( - json, 'dev_dependencies', (v) => parseDeps(v as Map)), - dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => parseDeps(v as Map)), - flutter: $checkedConvert( - json, - 'flutter', - (v) => (v as Map)?.map( - (k, e) => MapEntry(k as String, e), - ))); + final val = Pubspec( + $checkedConvert(json, 'name', (v) => v as String), + version: $checkedConvert( + json, 'version', (v) => _versionFromString(v as String)), + publishTo: $checkedConvert(json, 'publish_to', (v) => v as String), + author: $checkedConvert(json, 'author', (v) => v as String), + authors: $checkedConvert(json, 'authors', + (v) => (v as List)?.map((e) => e as String)?.toList()), + environment: $checkedConvert( + json, 'environment', (v) => _environmentMap(v as Map)), + homepage: $checkedConvert(json, 'homepage', (v) => v as String), + repository: $checkedConvert( + json, 'repository', (v) => v == null ? null : Uri.parse(v as String)), + issueTracker: $checkedConvert(json, 'issue_tracker', + (v) => v == null ? null : Uri.parse(v as String)), + documentation: $checkedConvert(json, 'documentation', (v) => v as String), + description: $checkedConvert(json, 'description', (v) => v as String), + dependencies: + $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map)), + devDependencies: + $checkedConvert(json, 'dev_dependencies', (v) => parseDeps(v as Map)), + dependencyOverrides: $checkedConvert( + json, 'dependency_overrides', (v) => parseDeps(v as Map)), + flutter: $checkedConvert( + json, + 'flutter', + (v) => (v as Map)?.map( + (k, e) => MapEntry(k as String, e), + )), + ); return val; }, fieldKeyMap: const { 'publishTo': 'publish_to', From 24174b888bad8e74f3a480389f75bc4b031a205a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 12:57:24 -0700 Subject: [PATCH 0571/1215] Remove unneeded codereview.settings --- pkgs/string_scanner/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/string_scanner/codereview.settings diff --git a/pkgs/string_scanner/codereview.settings b/pkgs/string_scanner/codereview.settings deleted file mode 100644 index 31c557fbd..000000000 --- a/pkgs/string_scanner/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/string_scanner/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From 3ce0df0bf54fbabcfc50348dc64d5fc7a66881ad Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 12:57:54 -0700 Subject: [PATCH 0572/1215] Remove very old work-around Fixes https://github.com/dart-lang/string_scanner/issues/1 --- pkgs/string_scanner/lib/src/string_scanner.dart | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 4506355d2..f6243aa1b 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -9,11 +9,6 @@ import 'package:source_span/source_span.dart'; import 'exception.dart'; import 'utils.dart'; -/// When compiled to JS, forward slashes are always escaped in [RegExp.pattern]. -/// -/// See issue 17998. -final _slashAutoEscape = RegExp("/").pattern == "\\/"; - /// A class that scans through a string using [Pattern]s. class StringScanner { /// The URL of the source of the string being scanned. @@ -148,7 +143,6 @@ class StringScanner { if (name == null) { if (pattern is RegExp) { var source = pattern.pattern; - if (!_slashAutoEscape) source = source.replaceAll("/", "\\/"); name = "/$source/"; } else { name = From 20a000b1be08899037efb6103f4d69b4cabc9876 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 13:02:31 -0700 Subject: [PATCH 0573/1215] Remove and fix dead links in changelog --- pkgs/string_scanner/CHANGELOG.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 1fba528d3..afef24087 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -88,10 +88,7 @@ than 1.0.0. For example, `string_scanner: ">=0.1.5 <2.0.0"`. ## 0.0.3 -* Make `StringScannerException` inherit from source_map's - [`SpanFormatException`][]. - -[SpanFormatException]: (http://www.dartdocs.org/documentation/source_maps/0.9.2/index.html#source_maps/source_maps.SpanFormatException) +* Make `StringScannerException` inherit from source_map's `SpanFormatException`. ## 0.0.2 @@ -111,4 +108,4 @@ than 1.0.0. For example, `string_scanner: ">=0.1.5 <2.0.0"`. * Add a `SpanScanner` subclass of `LineScanner` that exposes matched ranges as [source map][] `Span` objects. -[source_map]: http://pub.dartlang.org/packages/source_maps +[source_map]: https://pub.dev/packages/source_maps From f0cc5da720a156eafdb2597716573809f8a81bd0 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 13:09:28 -0700 Subject: [PATCH 0574/1215] Added example/example.dart, update README to working, valid code Fixes https://github.com/dart-lang/string_scanner/issues/9 --- pkgs/string_scanner/README.md | 8 ++--- pkgs/string_scanner/example/example.dart | 40 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 pkgs/string_scanner/example/example.dart diff --git a/pkgs/string_scanner/README.md b/pkgs/string_scanner/README.md index 90660fc8c..15aa24261 100644 --- a/pkgs/string_scanner/README.md +++ b/pkgs/string_scanner/README.md @@ -8,7 +8,7 @@ import 'package:string_scanner/string_scanner.dart'; num parseNumber(String source) { // Scan a number ("1", "1.5", "-3"). - var scanner = new StringScanner(source); + var scanner = StringScanner(source); // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it // succeeded. It will move the scan pointer past the end of the pattern. @@ -16,14 +16,14 @@ num parseNumber(String source) { // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it // fails. Like [Scanner.scan], it will move the scan pointer forward. - scanner.expect(new RegExp(r"\d+")); + scanner.expect(RegExp(r"\d+")); // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. - var number = int.parse(scanner.lastMatch[0]); + var number = num.parse(scanner.lastMatch[0]); if (scanner.scan(".")) { - scanner.expect(new RegExp(r"\d+")); + scanner.expect(RegExp(r"\d+")); var decimal = scanner.lastMatch[0]; number += int.parse(decimal) / math.pow(10, decimal.length); } diff --git a/pkgs/string_scanner/example/example.dart b/pkgs/string_scanner/example/example.dart new file mode 100644 index 000000000..ddd9d3ead --- /dev/null +++ b/pkgs/string_scanner/example/example.dart @@ -0,0 +1,40 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:math' as math; + +import 'package:string_scanner/string_scanner.dart'; + +void main(List args) { + print(parseNumber(args.single)); +} + +num parseNumber(String source) { + // Scan a number ("1", "1.5", "-3"). + var scanner = StringScanner(source); + + // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it + // succeeded. It will move the scan pointer past the end of the pattern. + var negative = scanner.scan("-"); + + // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it + // fails. Like [Scanner.scan], it will move the scan pointer forward. + scanner.expect(RegExp(r"\d+")); + + // [Scanner.lastMatch] holds the [MatchData] for the most recent call to + // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. + var number = num.parse(scanner.lastMatch[0]); + + if (scanner.scan(".")) { + scanner.expect(RegExp(r"\d+")); + var decimal = scanner.lastMatch[0]; + number += int.parse(decimal) / math.pow(10, decimal.length); + } + + // [Scanner.expectDone] will throw a [FormatError] if there's any input that + // hasn't yet been consumed. + scanner.expectDone(); + + return (negative ? -1 : 1) * number; +} From f4b2fb681bc96f91de0c1b9ed3687f3c87b25a7b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 13:14:28 -0700 Subject: [PATCH 0575/1215] analysis_options: disallow implicit casts --- pkgs/string_scanner/analysis_options.yaml | 4 ++-- pkgs/string_scanner/lib/src/exception.dart | 2 +- pkgs/string_scanner/lib/src/string_scanner.dart | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index d5d521374..6e8826ba9 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -1,7 +1,7 @@ include: package:pedantic/analysis_options.yaml analyzer: -# strong-mode: -# implicit-casts: false + strong-mode: + implicit-casts: false linter: rules: - always_declare_return_types diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 3710ae814..bad08f6e2 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -8,7 +8,7 @@ import 'string_scanner.dart'; /// An exception thrown by a [StringScanner] that failed to parse a string. class StringScannerException extends SourceSpanFormatException { - String get source => super.source; + String get source => super.source as String; /// The URL of the source file being parsed. /// diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index f6243aa1b..4a1d10c0c 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -58,7 +58,8 @@ class StringScanner { /// URL of the source of the string being scanned, if available. It can be /// a [String], a [Uri], or `null`. StringScanner(this.string, {sourceUrl, int position}) - : sourceUrl = sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl { + : sourceUrl = + sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl as Uri { if (position != null) this.position = position; } From 3b93ffe9a99974ebcb38972a91a57a3d096294b3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 13:12:46 -0700 Subject: [PATCH 0576/1215] prepare for release --- pkgs/string_scanner/CHANGELOG.md | 2 ++ pkgs/string_scanner/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index afef24087..fb7f74dd1 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.0.5 +- Added an example. + - Update Dart SDK constraint to `>=2.0.0 <3.0.0`. ## 1.0.4 diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 2bc50d6e4..6cba21e76 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.0.5-dev +version: 1.0.5 description: A class for parsing strings using a sequence of patterns. author: Dart Team From d30eec77a19ca16bc24fc455742debbae02c9ac7 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 21:06:13 -0700 Subject: [PATCH 0577/1215] Delete codereview.settings --- pkgs/test_reflective_loader/codereview.settings | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 pkgs/test_reflective_loader/codereview.settings diff --git a/pkgs/test_reflective_loader/codereview.settings b/pkgs/test_reflective_loader/codereview.settings deleted file mode 100644 index 3ba713c75..000000000 --- a/pkgs/test_reflective_loader/codereview.settings +++ /dev/null @@ -1,4 +0,0 @@ -# This file is used by gcl to get repository specific information. -CODE_REVIEW_SERVER: http://codereview.chromium.org -VIEW_VC: https://github.com/dart-lang/test_reflective_loader/commit/ -CC_LIST: reviews@dartlang.org From a6d082eb189f1eb285e9f68bbfdcb52985b23d8b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 21:06:41 -0700 Subject: [PATCH 0578/1215] Delete codereview.settings --- pkgs/watcher/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/watcher/codereview.settings diff --git a/pkgs/watcher/codereview.settings b/pkgs/watcher/codereview.settings deleted file mode 100644 index 25367dd29..000000000 --- a/pkgs/watcher/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/watcher/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From 9d20e86f9ab4e485aa4e132ec92c1d083fdd2d0e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 31 Jul 2019 21:06:53 -0700 Subject: [PATCH 0579/1215] Delete codereview.settings --- pkgs/stack_trace/codereview.settings | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stack_trace/codereview.settings diff --git a/pkgs/stack_trace/codereview.settings b/pkgs/stack_trace/codereview.settings deleted file mode 100644 index aff5c3747..000000000 --- a/pkgs/stack_trace/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/stack_trace/commit/ -CC_LIST: reviews@dartlang.org \ No newline at end of file From b2e43593d01b965afade8081f40cfae2fe198a37 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 7 Aug 2019 17:16:47 -0700 Subject: [PATCH 0580/1215] Prepare for release (dart-lang/pubspec_parse#52) --- pkgs/pubspec_parse/CHANGELOG.md | 1 + pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 1f62e3afd..f2c254244 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.1.5 - Update SDK requirement to `>=2.2.0 <3.0.0`. +- Support the latest `package:json_annotation`. ## 0.1.4 diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 39e627cc2..fc54d1240 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.5-dev +version: 0.1.5 homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team @@ -12,7 +12,7 @@ environment: dependencies: checked_yaml: ^1.0.0 # Verified that no new features since 1.0.0 are used - be careful! - json_annotation: '>=1.0.0 <3.0.0' + json_annotation: '>=1.0.0 <4.0.0' pub_semver: ^1.3.2 yaml: ^2.1.12 From 022119575ac622365f7796c4d20608d8f75a87df Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 8 Aug 2019 10:36:05 -0700 Subject: [PATCH 0581/1215] prepare next release, support latest json_annotation (dart-lang/timing#12) --- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 855ae6df0..9790efa7b 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1+3 + +- Support the latest version of `package:json_annotation`. + ## 0.1.1+2 - Require Dart 2.2 or later. diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index a04726489..10e0118c6 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.1+2 +version: 0.1.1+3 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. @@ -10,7 +10,7 @@ environment: sdk: ">=2.2.0 <3.0.0" dependencies: - json_annotation: '>=1.0.0 <3.0.0' + json_annotation: '>=1.0.0 <4.0.0' dev_dependencies: build_runner: ^1.0.0 From e30a22a3eed88c7da17878bed7d3f814db47ff02 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 8 Aug 2019 10:37:00 -0700 Subject: [PATCH 0582/1215] fix version --- pkgs/timing/CHANGELOG.md | 5 +---- pkgs/timing/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 9790efa7b..8cb1627c1 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,9 +1,6 @@ -## 0.1.1+3 - -- Support the latest version of `package:json_annotation`. - ## 0.1.1+2 +- Support the latest version of `package:json_annotation`. - Require Dart 2.2 or later. ## 0.1.1+1 diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 10e0118c6..0b451234a 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 0.1.1+3 +version: 0.1.1+2 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. From 3b0884964297a7c9845f7a0b64090e8ff857e964 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 24 Sep 2019 09:10:53 -0700 Subject: [PATCH 0583/1215] fix tests w/ latest pkg:yaml (dart-lang/pubspec_parse#53) --- pkgs/pubspec_parse/test/dependency_test.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 948010558..d3bf3ad70 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -47,20 +47,20 @@ line 4, column 10: Unsupported value for "dep". Not a valid dependency value. _expectThrows( {'path': 'a', 'git': 'b'}, r''' -line 5, column 12: Unsupported value for "path". A dependency may only have one source. +line 6, column 11: Unsupported value for "git". A dependency may only have one source. ╷ -5 │ "path": "a", - │ ^^^ +6 │ "git": "b" + │ ^^^ ╵''', ); }); test('map with unsupported keys', () { _expectThrows({'bob': 'a', 'jones': 'b'}, r''' -line 6, column 4: Unrecognized keys: [jones]; supported keys: [sdk, git, path, hosted] +line 5, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ -6 │ "jones": "b" - │ ^^^^^^^ +5 │ "bob": "a", + │ ^^^^^ ╵'''); }); }); From 964693d7c56ecfe9f307fbd53a99acecb2886f97 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 30 Sep 2019 11:53:12 -0700 Subject: [PATCH 0584/1215] Add support for skipping tests --- .../lib/test_reflective_loader.dart | 61 ++++++++++++++++--- .../test/test_reflective_loader_test.dart | 10 +++ 2 files changed, 61 insertions(+), 10 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 25868d9ca..4312ba5c5 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -26,6 +26,11 @@ const FailingTest failingTest = const FailingTest(); */ const _ReflectiveTest reflectiveTest = const _ReflectiveTest(); +/** + * A marker annotation used to annotate test methods that should be skipped. + */ +const SkippedTest skippedTest = const SkippedTest(); + /** * A marker annotation used to annotate "solo" groups and tests. */ @@ -115,14 +120,18 @@ void defineReflectiveTests(Type type) { _hasAnnotationInstance(memberMirror, soloTest); // test_ if (memberName.startsWith('test_')) { - group.addTest(isSolo, memberName, memberMirror, () { - if (_hasFailingTestAnnotation(memberMirror) || - _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { - return _runFailingTest(classMirror, symbol); - } else { - return _runTest(classMirror, symbol); - } - }); + if (_hasSkippedTestAnnotation(memberMirror)) { + group.addSkippedTest(memberName); + } else { + group.addTest(isSolo, memberName, memberMirror, () { + if (_hasFailingTestAnnotation(memberMirror) || + _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) { + return _runFailingTest(classMirror, symbol); + } else { + return _runTest(classMirror, symbol); + } + }); + } return; } // solo_test_ @@ -143,6 +152,10 @@ void defineReflectiveTests(Type type) { return _runFailingTest(classMirror, symbol); }); } + // skip_test_ + if (memberName.startsWith('skip_test_')) { + group.addSkippedTest(memberName); + } }); // Support for the case of missing enclosing [defineReflectiveSuite]. @@ -160,7 +173,7 @@ void _addTestsIfTopLevelSuite() { for (_Test test in group.tests) { if (allTests || test.isSolo) { test_package.test(test.name, test.function, - timeout: test.timeout); + timeout: test.timeout, skip: test.isSkipped); } } } @@ -211,6 +224,9 @@ bool _hasAssertFailingTestAnnotation(MethodMirror method) => bool _hasFailingTestAnnotation(MethodMirror method) => _hasAnnotationInstance(method, failingTest); +bool _hasSkippedTestAnnotation(MethodMirror method) => + _hasAnnotationInstance(method, skippedTest); + Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { var invocationResult = null; InstanceMirror closure; @@ -276,6 +292,19 @@ class FailingTest { const FailingTest({String issue, String reason}); } +/** + * A marker annotation used to annotate test methods which are skipped. + */ +class SkippedTest { + /** + * Initialize this annotation with the given arguments. + * + * [issue] is a full URI describing the failure and used for tracking. + * [reason] is a free form textual description. + */ + const SkippedTest({String issue, String reason}); +} + /** * A marker annotation used to annotate test methods with additional timeout * information. @@ -309,6 +338,11 @@ class _Group { bool get hasSoloTest => tests.any((test) => test.isSolo); + void addSkippedTest(String name) { + String fullName = _combineNames(this.name, name); + tests.add(new _Test.skipped(isSolo, fullName)); + } + void addTest(bool isSolo, String name, MethodMirror memberMirror, _TestFunction function) { String fullName = _combineNames(this.name, name); @@ -341,5 +375,12 @@ class _Test { final _TestFunction function; final test_package.Timeout timeout; - _Test(this.isSolo, this.name, this.function, this.timeout); + final bool isSkipped; + + _Test(this.isSolo, this.name, this.function, this.timeout) + : isSkipped = false; + _Test.skipped(this.isSolo, this.name) + : isSkipped = true, + function = null, + timeout = null; } diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index 952fe0a1d..a657b0477 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -35,4 +35,14 @@ class TestReflectiveLoaderTest { Future test_fails_throws_async() { return new Future.error('foo'); } + + @skippedTest + void test_fails_but_skipped() { + throw 'foo'; + } + + @skippedTest + void test_times_out_but_skipped() { + while (true) {} + } } From e7b823436d851452f6167b806412f00e8bb3a79b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 30 Sep 2019 13:56:08 -0700 Subject: [PATCH 0585/1215] Feedback from Konstantin --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 4312ba5c5..6430c6676 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -379,6 +379,7 @@ class _Test { _Test(this.isSolo, this.name, this.function, this.timeout) : isSkipped = false; + _Test.skipped(this.isSolo, this.name) : isSkipped = true, function = null, From 24782ed0637007761af0ca3f6ae779fd55d5a62b Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Mon, 30 Sep 2019 14:05:02 -0700 Subject: [PATCH 0586/1215] prep publish 1.9 --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ pkgs/test_reflective_loader/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index b6121a198..616d02194 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.9 + +- Add `@SkippedTest` annotation and `skip_test` prefix. + ## 0.1.8 - Update `FailingTest` to add named parameters `issue` and `reason`. diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 3f399eab0..8cfc3fa6f 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.1.8 +version: 0.1.9 description: Support for discovering tests and test suites using reflection. author: Dart Team From 3ff2e669c6503a2d80a77a342bd8fd50ebbb1637 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 7 Oct 2019 12:36:56 -0700 Subject: [PATCH 0587/1215] Rewrite transformers as extension methods (dart-lang/stream_transform#83) The usage is much nicer as extension methods. In most cases a small bit of code is copied for the replacement, though in some cases nearly the entire implementation is copied. This was done over extracting shared pieces so that the deprecated methods can be removed outright in the next major version change. Update and clean up some doc comments in the extension method version of these functions. Migrate tests to use the extension method versions. The old copies are now untested but they won't be modified before they are removed. Since there aren't useful needs within this package for `chainTransformers` or `map` they are deprecated without a replacement. --- pkgs/stream_transform/.travis.yml | 2 +- pkgs/stream_transform/CHANGELOG.md | 22 +++ pkgs/stream_transform/README.md | 58 +++--- .../lib/src/async_map_buffer.dart | 58 ++++++ .../stream_transform/lib/src/async_where.dart | 38 ++++ pkgs/stream_transform/lib/src/audit.dart | 53 ++++++ pkgs/stream_transform/lib/src/buffer.dart | 16 ++ .../lib/src/chain_transformers.dart | 1 + .../lib/src/combine_latest.dart | 178 ++++++++++++++++++ .../lib/src/combine_latest_all.dart | 111 ----------- .../lib/src/concurrent_async_map.dart | 40 ++++ pkgs/stream_transform/lib/src/debounce.dart | 42 +++++ .../stream_transform/lib/src/followed_by.dart | 20 ++ pkgs/stream_transform/lib/src/map.dart | 1 + pkgs/stream_transform/lib/src/merge.dart | 53 ++++++ pkgs/stream_transform/lib/src/scan.dart | 23 +++ pkgs/stream_transform/lib/src/start_with.dart | 34 ++++ pkgs/stream_transform/lib/src/switch.dart | 32 +++- pkgs/stream_transform/lib/src/take_until.dart | 12 ++ pkgs/stream_transform/lib/src/tap.dart | 40 ++++ pkgs/stream_transform/lib/src/throttle.dart | 21 +++ pkgs/stream_transform/lib/src/where_type.dart | 14 ++ .../lib/stream_transform.dart | 1 - pkgs/stream_transform/pubspec.yaml | 4 +- .../test/async_map_buffer_test.dart | 2 +- .../test/async_map_sample_test.dart | 2 +- .../test/async_where_test.dart | 18 +- pkgs/stream_transform/test/audit_test.dart | 30 ++- pkgs/stream_transform/test/buffer_test.dart | 2 +- .../test/combine_latest_all_test.dart | 19 +- .../test/combine_latest_test.dart | 18 +- .../test/concurrent_async_map_test.dart | 2 +- pkgs/stream_transform/test/debounce_test.dart | 10 +- .../test/followd_by_test.dart | 2 +- pkgs/stream_transform/test/merge_test.dart | 15 +- pkgs/stream_transform/test/scan_test.dart | 20 +- .../test/start_with_test.dart | 11 +- pkgs/stream_transform/test/switch_test.dart | 8 +- .../test/take_until_test.dart | 2 +- pkgs/stream_transform/test/tap_test.dart | 39 ++-- pkgs/stream_transform/test/throttle_test.dart | 26 ++- .../test/where_type_test.dart | 8 +- 42 files changed, 837 insertions(+), 271 deletions(-) delete mode 100644 pkgs/stream_transform/lib/src/combine_latest_all.dart diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 5cdff4c35..0bd0f9c9e 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,7 +3,7 @@ branches: only: [master] dart: - dev - - 2.2.0 + # 2.2.0 cache: directories: - $HOME/.pub-cache diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index e631a9752..52b1c51d0 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,25 @@ +## 0.0.20-dev + +- Add extension methods for most transformers. These should be used in place + of the current methods. All current implementations are deprecated and will + be removed in the next major version bump. + - Migrating typical use: Instead of + `stream.transform(debounce(Duration(seconds: 1)))` use + `stream.debounce(Duration(seconds: 1))`. + - To migrate a usage where a `StreamTransformer` instance is stored or + passed see "Getting a StreamTransformer instance" on the README. +- The `map` and `chainTransformers` utilities are no longer useful with the + new patterns so they are deprecated without a replacement. If you still have + a need for them they can be replicated with `StreamTransformer.fromBind`: + + ``` + // Replace `map(convert)` + StreamTransformer.fromBind((s) => s.map(convert)); + + // Replace `chainTransformers(first, second)` + StreamTransformer.fromBind((s) => s.transform(first).transform(second)); + ``` + ## 0.0.19 - Add `asyncMapSample` transform. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index fc44207ce..313e6f19d 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,84 +1,100 @@ -Utility methods to create `StreamTransfomer` instances to manipulate Streams. +Extension methods on `Stream` adding common transform operators. -# asyncMapBuffer +# Operators + +## asyncMapBuffer Like `asyncMap` but events are buffered in a List until previous events have been processed rather than being called for each element individually. -# asyncMapSample +## asyncMapSample Like `asyncMap` but events are discarded, keeping only the latest, until previous events have been processed rather than being called for every element. -# asyncWhere +## asyncWhere Like `where` but allows an asynchronous predicate. -# audit +## audit -Audit waits for a period of time after receiving a value and then only emits -the most recent value. +Waits for a period of time after receiving a value and then only emits the most +recent value. -# buffer +## buffer Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. -# combineLatest +## combineLatest Combine the most recent event from two streams through a callback and emit the result. -# combineLatestAll +## combineLatestAll Combines the latest events emitted from multiple source streams and yields a list of the values. -# debounce, debounceBuffer +## debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. -# concurrentAsyncMap +## concurrentAsyncMap Like `asyncMap` but the convert callback can be called with subsequent values before it has finished for previous values. -# followedBy +## followedBy Appends the values of a stream after another stream finishes. -# merge, mergeAll +## merge, mergeAll Interleaves events from multiple streams into a single stream. -# scan +## scan Scan is like fold, but instead of producing a single value it yields each intermediate accumulation. -# startWith, startWithMany, startWithStream +## startWith, startWithMany, startWithStream Prepend a value, an iterable, or a stream to the beginning of another stream. -# switchMap, switchLatest +## switchMap, switchLatest Flatten a Stream of Streams into a Stream which forwards values from the most recent Stream -# takeUntil +## takeUntil Let values through until a Future fires. -# tap +## tap Taps into a single-subscriber stream to react to values as they pass, without being a real subscriber. -# throttle +## throttle Blocks events for a duration after an event is successfully emitted. -# whereType +## whereType Like `Iterable.whereType` for a stream. + +# Getting a `StreamTransformer` instance + +It may be useful to pass an instance of `StreamTransformer` so that it can be +used with `stream.transform` calls rather than reference the specific operator +in place. Any operator on `Stream` that returns a `Stream` can be modeled as a +`StreamTransformer` using the [`fromBind` constructor][fromBind]. + +```dart +final debounce = StreamTransformer.fromBind( + (s) => s.debounce(const Duration(milliseconds: 100))); +``` + +[fromBind]: https://api.dart.dev/stable/dart-async/StreamTransformer/StreamTransformer.fromBind.html diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map_buffer.dart index 70c5bdb9e..57defc22b 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map_buffer.dart @@ -9,6 +9,62 @@ import 'buffer.dart'; import 'chain_transformers.dart'; import 'from_handlers.dart'; +extension AsyncMap on Stream { + /// Like [asyncMap] but events are buffered until previous events have been + /// processed by [convert]. + /// + /// If the source stream is a broadcast stream the result will be as well. When + /// used with a broadcast stream behavior also differs from [Stream.asyncMap] in + /// that the [convert] function is only called once per event, rather than once + /// per listener per event. + /// + /// The first event from the source stream is always passed to [convert] as a + /// List with a single element. After that events are buffered until the + /// previous Future returned from [convert] has fired. + /// + /// Errors from the source stream are forwarded directly to the result stream. + /// Errors during the conversion are also forwarded to the result stream and + /// are considered completing work so the next values are let through. + /// + /// The result stream will not close until the source stream closes and all + /// pending conversions have finished. + Stream asyncMapBuffer(Future Function(List) convert) { + var workFinished = StreamController() + // Let the first event through. + ..add(null); + return this + .buffer(workFinished.stream) + .transform(_asyncMapThen(convert, workFinished.add)); + } + + /// Like [asyncMap] but events are discarded while work is happening in + /// [convert]. + /// + /// If the source stream is a broadcast stream the result will be as well. When + /// used with a broadcast stream behavior also differs from [Stream.asyncMap] in + /// that the [convert] function is only called once per event, rather than once + /// per listener per event. + /// + /// If no work is happening when an event is emitted it will be immediately + /// passed to [convert]. If there is ongoing work when an event is emitted it + /// will be held until the work is finished. New events emitted will replace a + /// pending event. + /// + /// Errors from the source stream are forwarded directly to the result stream. + /// Errors during the conversion are also forwarded to the result stream and are + /// considered completing work so the next values are let through. + /// + /// The result stream will not close until the source stream closes and all + /// pending conversions have finished. + Stream asyncMapSample(Future Function(T) convert) { + var workFinished = StreamController() + // Let the first event through. + ..add(null); + return transform(AggregateSample(workFinished.stream, _dropPrevious)) + .transform(_asyncMapThen(convert, workFinished.add)); + } +} + /// Like [Stream.asyncMap] but events are buffered until previous events have /// been processed by [convert]. /// @@ -27,6 +83,7 @@ import 'from_handlers.dart'; /// /// The result stream will not close until the source stream closes and all /// pending conversions have finished. +@Deprecated('Use the extension instead') StreamTransformer asyncMapBuffer( Future Function(List) convert) { var workFinished = StreamController() @@ -55,6 +112,7 @@ StreamTransformer asyncMapBuffer( /// /// The result stream will not close until the source stream closes and all /// pending conversions have finished. +@Deprecated('Use the extension instead') StreamTransformer asyncMapSample(Future Function(S) convert) { var workFinished = StreamController() // Let the first event through. diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/async_where.dart index 734f65f9e..a611063d6 100644 --- a/pkgs/stream_transform/lib/src/async_where.dart +++ b/pkgs/stream_transform/lib/src/async_where.dart @@ -5,6 +5,43 @@ import 'dart:async'; import 'from_handlers.dart'; +extension AsyncWhere on Stream { + /// Like [where] but allows the [test] to return a [Future]. + /// + /// Events on the result stream will be emitted in the order that [test] + /// completes which may not match the order of the original stream. + /// + /// If the source stream is a broadcast stream the result will be as well. When + /// used with a broadcast stream behavior also differs from [Stream.where] in + /// that the [test] function is only called once per event, rather than once + /// per listener per event. + /// + /// Errors from the source stream are forwarded directly to the result stream. + /// Errors from [test] are also forwarded to the result stream. + /// + /// The result stream will not close until the source stream closes and all + /// pending [test] calls have finished. + Stream asyncWhere(FutureOr test(T element)) { + var valuesWaiting = 0; + var sourceDone = false; + return transform(fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + try { + if (await test(element)) sink.add(element); + } catch (e, st) { + sink.addError(e, st); + } + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + })); + } +} + /// Like [Stream.where] but allows the [test] to return a [Future]. /// /// Events on the result stream will be emitted in the order that [test] @@ -20,6 +57,7 @@ import 'from_handlers.dart'; /// /// The result stream will not close until the source stream closes and all /// pending [test] calls have finished. +@Deprecated('Use the extension instead') StreamTransformer asyncWhere(FutureOr test(T element)) { var valuesWaiting = 0; var sourceDone = false; diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart index 7b4d7676e..b175e6d02 100644 --- a/pkgs/stream_transform/lib/src/audit.dart +++ b/pkgs/stream_transform/lib/src/audit.dart @@ -5,6 +5,58 @@ import 'dart:async'; import 'from_handlers.dart'; +extension Audit on Stream { + /// Returns a Stream which only emits once per [duration], at the end of the + /// period. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there is no pending event when the source stream closes the output + /// stream will close immediately. If there is a pending event the output + /// stream will wait to emit it before closing. + /// + /// Differs from `throttle` in that it always emits the most recently received + /// event rather than the first in the period. The events that are emitted are + /// always delayed by some amount. If the event that started the period is the + /// one that is emitted it will be delayed by [duration]. If a later event + /// comes in within the period it's delay will be shorter by the difference in + /// arrival times. + /// + /// Differs from `debounce` in that a value will always be emitted after + /// [duration], the output will not be starved by values coming in repeatedly + /// within [duration]. + /// + /// For example: + /// + /// source.audit(Duration(seconds: 5)); + /// + /// source: a------b--c----d--| + /// output: -----a------c--------d| + Stream audit(Duration duration) { + Timer timer; + var shouldClose = false; + T recentData; + + return transform(fromHandlers(handleData: (T data, EventSink sink) { + recentData = data; + timer ??= Timer(duration, () { + sink.add(recentData); + timer = null; + if (shouldClose) { + sink.close(); + } + }); + }, handleDone: (EventSink sink) { + if (timer != null) { + shouldClose = true; + } else { + sink.close(); + } + })); + } +} + /// Creates a StreamTransformer which only emits once per [duration], at the /// end of the period. /// @@ -16,6 +68,7 @@ import 'from_handlers.dart'; /// Differs from `debounce` in that a value will always be emitted after /// [duration], the output will not be starved by values coming in repeatedly /// within [duration]. +@Deprecated('Use the extension instead') StreamTransformer audit(Duration duration) { Timer timer; var shouldClose = false; diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart index 3478a52f5..cf8b0c3a4 100644 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ b/pkgs/stream_transform/lib/src/buffer.dart @@ -6,6 +6,21 @@ import 'dart:async'; import 'aggregate_sample.dart'; +extension Buffer on Stream { + /// Returns a Stream which collects values and emits when it sees a value on + /// [trigger]. + /// + /// If there are no pending values when [trigger] emits, the next value on the + /// source Stream will immediately flow through. Otherwise, the pending values + /// are released when [trigger] emits. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors from the source stream or the trigger are immediately forwarded to + /// the output. + Stream> buffer(Stream trigger) => + transform(AggregateSample>(trigger, _collect)); +} + /// Creates a [StreamTransformer] which collects values and emits when it sees a /// value on [trigger]. /// @@ -15,6 +30,7 @@ import 'aggregate_sample.dart'; /// /// Errors from the source stream or the trigger are immediately forwarded to /// the output. +@Deprecated('Use the extension instead') StreamTransformer> buffer(Stream trigger) => AggregateSample>(trigger, _collect); diff --git a/pkgs/stream_transform/lib/src/chain_transformers.dart b/pkgs/stream_transform/lib/src/chain_transformers.dart index 549befc10..1e812d9c3 100644 --- a/pkgs/stream_transform/lib/src/chain_transformers.dart +++ b/pkgs/stream_transform/lib/src/chain_transformers.dart @@ -17,6 +17,7 @@ import 'dart:async'; /// /// values.transform(utf8.decoder).transform(const LineSplitter()) /// final splitDecoded = chainTransformers(utf8.decoder, const LineSplitter()); /// ``` +@Deprecated('This utility should not be needed with extension methods') StreamTransformer chainTransformers( StreamTransformer first, StreamTransformer second) => StreamTransformer.fromBind( diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 489f344c3..7fb9ac9dd 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -4,6 +4,76 @@ import 'dart:async'; +extension CombineLatest on Stream { + /// Returns a stream which combines the latest value from the source stream + /// with the latest value from [other] using [combine]. + /// + /// No event will be emitted until both the source stream and [other] have + /// each emitted at least one event. If either the source stream or [other] + /// emit multiple events before the other emits the first event, all but the + /// last value will be discarded. Once both streams have emitted at least + /// once, the result stream will emit any time either input stream emits. + /// + /// The result stream will not close until both the source stream and [other] + /// have closed. + /// + /// For example: + /// + /// source.combineLatest(other, (a, b) => a + b); + /// + /// source: --1--2--------4--| + /// other: -------3--| + /// result: -------5------7--| + /// + /// Errors thrown by [combine], along with any errors on the source stream or + /// [other], are forwarded to the result stream. + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of [other]'s type. If a single subscription stream is + /// combined with a broadcast stream it may never be canceled. + Stream combineLatest( + Stream other, FutureOr Function(T, T2) combine) => + transform(_CombineLatest(other, combine)); + + /// Combine the latest value emitted from the source stream with the latest + /// values emitted from [others]. + /// + /// [combineLatestAll] subscribes to the source stream and [others] and when + /// any one of the streams emits, the result stream will emit a [List] of + /// the latest values emitted from all streams. + /// + /// No event will be emitted until all source streams emit at least once. If a + /// source stream emits multiple values before another starts emitting, all + /// but the last value will be discarded. Once all source streams have emitted + /// at least once, the result stream will emit any time any source stream + /// emits. + /// + /// The result stream will not close until all source streams have closed. When + /// a source stream closes, the result stream will continue to emit the last + /// value from the closed stream when the other source streams emit until the + /// result stream has closed. If a source stream closes without emitting any + /// value, the result stream will close as well. + /// + /// For example: + /// + /// final combined = first + /// .combineLatestAll([second, third]) + /// .map((data) => data.join()); + /// + /// first: a----b------------------c--------d---| + /// second: --1---------2-----------------| + /// third: -------&----------%---| + /// combined: -------b1&--b2&---b2%---c2%------d2%-| + /// + /// Errors thrown by any source stream will be forwarded to the result stream. + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of the types of [others]. If a single subscription stream + /// is combined with a broadcast source stream, it may never be canceled. + Stream> combineLatestAll(Iterable> others) => + transform(_CombineLatestAll(others)); +} + /// Combine the latest value from the source stream with the latest value from /// [other] using [combine]. /// @@ -31,6 +101,7 @@ import 'dart:async'; /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of [other]'s type. If a single subscription stream is /// combined with a broadcast stream it may never be canceled. +@Deprecated('Use the extension instead') StreamTransformer combineLatest( Stream other, FutureOr Function(S, T) combine) => _CombineLatest(other, combine); @@ -144,3 +215,110 @@ class _CombineLatest extends StreamTransformerBase { return controller.stream; } } + +/// Combine the latest value emitted from the source stream with the latest +/// values emitted from [others]. +/// +/// [combineLatestAll] subscribes to the source stream and [others] and when +/// any one of the streams emits, the result stream will emit a [List] of +/// the latest values emitted from all streams. +/// +/// The result stream will not emit until all source streams emit at least +/// once. If a source stream emits multiple values before another starts +/// emitting, all but the last value will be lost. +/// +/// The result stream will not close until all source streams have closed. When +/// a source stream closes, the result stream will continue to emit the last +/// value from the closed stream when the other source streams emit until the +/// result stream has closed. If a source stream closes without emitting any +/// value, the result stream will close as well. +/// +/// Errors thrown by any source stream will be forwarded to the result stream. +/// +/// If the source stream is a broadcast stream, the result stream will be as +/// well, regardless of the types of [others]. If a single subscription stream +/// is combined with a broadcast source stream, it may never be canceled. +/// +/// ## Example +/// +/// (Suppose first, second, and third are Stream) +/// final combined = first +/// .transform(combineLatestAll([second, third])) +/// .map((data) => data.join()); +/// +/// first: a----b------------------c--------d---| +/// second: --1---------2-----------------| +/// third: -------&----------%---| +/// combined: -------b1&--b2&---b2%---c2%------d2%-| +/// +@Deprecated('Use the extension instead') +StreamTransformer> combineLatestAll(Iterable> others) => + _CombineLatestAll(others); + +class _CombineLatestAll extends StreamTransformerBase> { + final Iterable> _others; + + _CombineLatestAll(this._others); + + @override + Stream> bind(Stream source) { + final controller = source.isBroadcast + ? StreamController>.broadcast(sync: true) + : StreamController>(sync: true); + + var allStreams = [source]..addAll(_others); + if (source.isBroadcast) { + allStreams = allStreams + .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) + .toList(); + } + + List> subscriptions; + + controller.onListen = () { + assert(subscriptions == null); + + final latestData = List(allStreams.length); + final hasEmitted = {}; + void handleData(int index, T data) { + latestData[index] = data; + hasEmitted.add(index); + if (hasEmitted.length == allStreams.length) { + controller.add(List.from(latestData)); + } + } + + var activeStreamCount = 0; + subscriptions = allStreams.map((stream) { + final index = activeStreamCount; + activeStreamCount++; + return stream.listen((data) => handleData(index, data), + onError: controller.addError, onDone: () { + if (--activeStreamCount <= 0 || !hasEmitted.contains(index)) { + controller.close(); + } + }); + }).toList(); + if (!source.isBroadcast) { + controller + ..onPause = () { + for (var subscription in subscriptions) { + subscription.pause(); + } + } + ..onResume = () { + for (var subscription in subscriptions) { + subscription.resume(); + } + }; + } + controller.onCancel = () { + final toCancel = subscriptions; + subscriptions = null; + if (activeStreamCount <= 0) return null; + return Future.wait(toCancel.map((s) => s.cancel())); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/src/combine_latest_all.dart b/pkgs/stream_transform/lib/src/combine_latest_all.dart deleted file mode 100644 index 045ccdced..000000000 --- a/pkgs/stream_transform/lib/src/combine_latest_all.dart +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// Combine the latest value emitted from the source stream with the latest -/// values emitted from [others]. -/// -/// [combineLatestAll] subscribes to the source stream and [others] and when -/// any one of the streams emits, the result stream will emit a [List] of -/// the latest values emitted from all streams. -/// -/// The result stream will not emit until all source streams emit at least -/// once. If a source stream emits multiple values before another starts -/// emitting, all but the last value will be lost. -/// -/// The result stream will not close until all source streams have closed. When -/// a source stream closes, the result stream will continue to emit the last -/// value from the closed stream when the other source streams emit until the -/// result stream has closed. If a source stream closes without emitting any -/// value, the result stream will close as well. -/// -/// Errors thrown by any source stream will be forwarded to the result stream. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of [others]. If a single subscription stream -/// is combined with a broadcast source stream, it may never be canceled. -/// -/// ## Example -/// -/// (Suppose first, second, and third are Stream) -/// final combined = first -/// .transform(combineLatestAll([second, third])) -/// .map((data) => data.join()); -/// -/// first: a----b------------------c--------d---| -/// second: --1---------2-----------------| -/// third: -------&----------%---| -/// combined: -------b1&--b2&---b2%---c2%------d2%-| -/// -StreamTransformer> combineLatestAll(Iterable> others) => - _CombineLatestAll(others); - -class _CombineLatestAll extends StreamTransformerBase> { - final Iterable> _others; - - _CombineLatestAll(this._others); - - @override - Stream> bind(Stream source) { - final controller = source.isBroadcast - ? StreamController>.broadcast(sync: true) - : StreamController>(sync: true); - - var allStreams = [source]..addAll(_others); - if (source.isBroadcast) { - allStreams = allStreams - .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) - .toList(); - } - - List> subscriptions; - - controller.onListen = () { - assert(subscriptions == null); - - final latestData = List(allStreams.length); - final hasEmitted = {}; - void handleData(int index, T data) { - latestData[index] = data; - hasEmitted.add(index); - if (hasEmitted.length == allStreams.length) { - controller.add(List.from(latestData)); - } - } - - var activeStreamCount = 0; - subscriptions = allStreams.map((stream) { - final index = activeStreamCount; - activeStreamCount++; - return stream.listen((data) => handleData(index, data), - onError: controller.addError, onDone: () { - if (--activeStreamCount <= 0 || !hasEmitted.contains(index)) { - controller.close(); - } - }); - }).toList(); - if (!source.isBroadcast) { - controller - ..onPause = () { - for (var subscription in subscriptions) { - subscription.pause(); - } - } - ..onResume = () { - for (var subscription in subscriptions) { - subscription.resume(); - } - }; - } - controller.onCancel = () { - final toCancel = subscriptions; - subscriptions = null; - if (activeStreamCount <= 0) return null; - return Future.wait(toCancel.map((s) => s.cancel())); - }; - }; - return controller.stream; - } -} diff --git a/pkgs/stream_transform/lib/src/concurrent_async_map.dart b/pkgs/stream_transform/lib/src/concurrent_async_map.dart index 791c84c82..c0fae2f4c 100644 --- a/pkgs/stream_transform/lib/src/concurrent_async_map.dart +++ b/pkgs/stream_transform/lib/src/concurrent_async_map.dart @@ -6,6 +6,45 @@ import 'dart:async'; import 'from_handlers.dart'; +extension ConcurrentAsyncMap on Stream { + /// Like [asyncMap] but the [convert] callback may be called for an element + /// before processing for the previous element is finished. + /// + /// Events on the result stream will be emitted in the order that [convert] + /// completed which may not match the order of the original stream. + /// + /// If the source stream is a broadcast stream the result will be as well. + /// When used with a broadcast stream behavior also differs from [asyncMap] in + /// that the [convert] function is only called once per event, rather than + /// once per listener per event. The [convert] callback won't be called for + /// events while a broadcast stream has no listener. + /// + /// Errors from [convert] or the source stream are forwarded directly to the + /// result stream. + /// + /// The result stream will not close until the source stream closes and all + /// pending conversions have finished. + Stream concurrentAsyncMap(FutureOr convert(T event)) { + var valuesWaiting = 0; + var sourceDone = false; + return transform(fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + try { + sink.add(await convert(element)); + } catch (e, st) { + sink.addError(e, st); + } + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + })); + } +} + /// Like [Stream.asyncMap] but the [convert] callback may be called for an /// element before processing for the previous element is finished. /// @@ -23,6 +62,7 @@ import 'from_handlers.dart'; /// /// The result stream will not close until the source stream closes and all /// pending conversions have finished. +@Deprecated('Use the extension instead') StreamTransformer concurrentAsyncMap(FutureOr convert(S event)) { var valuesWaiting = 0; var sourceDone = false; diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart index ff3f21ff2..0987ec6cb 100644 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ b/pkgs/stream_transform/lib/src/debounce.dart @@ -5,12 +5,53 @@ import 'dart:async'; import 'from_handlers.dart'; +extension Debounce on Stream { + /// Returns a Stream which only emits when the source stream does not emit for + /// [duration]. + /// + /// Values will always be delayed by at least [duration], and values which + /// come within this time will replace the old values, only the most + /// recent value will be emitted. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there is an event waiting during the debounce period when the source + /// stream closes the returned stream will wait to emit it following the + /// debounce period before closing. If there is no pending debounced event + /// when the source stream closes the returned stream will close immediately. + /// + /// To collect values emitted during the debounce period see [debounceBuffer]. + Stream debounce(Duration duration) => + transform(_debounceAggregate(duration, _dropPrevious)); + + /// Returns a Stream which collects values until the source stream does not + /// emit for [duration] then emits the collected values. + /// + /// Values will always be delayed by at least [duration], and values which + /// come within this time will be aggregated into the same list. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there are events waiting during the debounce period when the source + /// stream closes the returned stream will wait to emit them following the + /// debounce period before closing. If there are no pending debounced events + /// when the source stream closes the returned stream will close immediately. + /// + /// To keep only the most recent event during the debounce perios see + /// [debounce]. + Stream> debounceBuffer(Duration duration) => + transform(_debounceAggregate(duration, _collectToList)); +} + /// Creates a StreamTransformer which only emits when the source stream does not /// emit for [duration]. /// /// Source values will always be delayed by at least [duration], and values /// which come within this time will replace the old values, only the most /// recent value will be emitted. +@Deprecated('Use the extension instead') StreamTransformer debounce(Duration duration) => _debounceAggregate(duration, _dropPrevious); @@ -19,6 +60,7 @@ StreamTransformer debounce(Duration duration) => /// /// This differs from [debounce] in that values are aggregated instead of /// skipped. +@Deprecated('Use the extension instead') StreamTransformer> debounceBuffer(Duration duration) => _debounceAggregate(duration, _collectToList); diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/followed_by.dart index 3c5c6b340..41c771809 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/followed_by.dart @@ -4,6 +4,25 @@ import 'dart:async'; +extension FollowedBy on Stream { + /// Returns a stream which emits values and errors from [next] after the + /// original stream is complete. + /// + /// If the source stream never finishes, the [next] stream will never be + /// listened to. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// If a single-subscription follows a broadcast stream it may be listened + /// to and never canceled since there may be broadcast listeners added later. + /// + /// If a broadcast stream follows any other stream it will miss any events or + /// errors which occur before the first stream is done. If a broadcast stream + /// follows a single-subscription stream, pausing the stream while it is + /// listening to the second stream will cause events to be dropped rather than + /// buffered. + Stream followedBy(Stream next) => transform(_FollowedBy(next)); +} + /// Starts emitting values from [next] after the original stream is complete. /// /// If the initial stream never finishes, the [next] stream will never be @@ -16,6 +35,7 @@ import 'dart:async'; /// occur before the first stream is done. If a broadcast stream follows a /// single-subscription stream, pausing the stream while it is listening to the /// second stream will cause events to be dropped rather than buffered. +@Deprecated('Use the extension instead') StreamTransformer followedBy(Stream next) => _FollowedBy(next); class _FollowedBy extends StreamTransformerBase { diff --git a/pkgs/stream_transform/lib/src/map.dart b/pkgs/stream_transform/lib/src/map.dart index 09ea0d6f0..e1f7137f8 100644 --- a/pkgs/stream_transform/lib/src/map.dart +++ b/pkgs/stream_transform/lib/src/map.dart @@ -16,5 +16,6 @@ import 'dart:async'; /// final sinkMapper = new StreamSinkTransformer.fromStreamTransformer( /// map((v) => '$v')); /// ``` +@Deprecated('This utility should not be needed with extension methods') StreamTransformer map(T convert(S event)) => StreamTransformer.fromBind((stream) => stream.map(convert)); diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 74a1e1a4a..878a8d11b 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -4,11 +4,63 @@ import 'dart:async'; +extension Merge on Stream { + /// Returns a stream which emits values and errors from the source stream and + /// [other] in any order as they arrive. + /// + /// The result stream will not close until both the source stream and [other] + /// have closed. + /// + /// For example: + /// + /// final result = source.merge(other); + /// + /// source: 1--2-----3--| + /// other: ------4-------5--| + /// result: 1--2--4--3----5--| + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of [other]'s type. If a single subscription stream is + /// merged into a broadcast stream it may never be canceled since there may be + /// broadcast listeners added later. + /// + /// If a broadcast stream is merged into a single-subscription stream any + /// events emitted by [other] before the result stream has a subscriber will + /// be discarded. + Stream merge(Stream other) => transform(_Merge([other])); + + /// Returns a stream which emits values and errors from the source stream and + /// any stream in [others] in any order as they arrive. + /// + /// The result stream will not close until the source stream and all streams + /// in [others] have closed. + /// + /// For example: + /// + /// final result = first.mergeAll([second, third]); + /// + /// first: 1--2--------3--| + /// second: ---------4-------5--| + /// third: ------6---------------7--| + /// result: 1--2--6--4--3----5----7--| + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless the types of streams in [others]. If a single + /// subscription stream is merged into a broadcast stream it may never be + /// canceled since there may be broadcast listeners added later. + /// + /// If a broadcast stream is merged into a single-subscription stream any + /// events emitted by that stream before the result stream has a subscriber + /// will be discarded. + Stream mergeAll(Iterable> others) => transform(_Merge(others)); +} + /// Emits values from the source stream and [other] in any order as they arrive. /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of [other]'s type. If a single subscription stream is /// merged into a broadcast stream it may never be canceled. +@Deprecated('Use the extension instead') StreamTransformer merge(Stream other) => _Merge([other]); /// Emits values from the source stream and all streams in [others] in any order @@ -18,6 +70,7 @@ StreamTransformer merge(Stream other) => _Merge([other]); /// well, regardless of the types of streams in [others]. If single /// subscription streams are merged into a broadcast stream they may never be /// canceled. +@Deprecated('Use the extension instead') StreamTransformer mergeAll(Iterable> others) => _Merge(others); diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index b2f76eff2..be9899e15 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -4,6 +4,28 @@ import 'dart:async'; +extension Scan on Stream { + /// Like [fold], but instead of producing a single value it yields each + /// intermediate accumulation. + /// + /// If [combine] returns a Future it will not be called again for subsequent + /// events from the source until it completes, therefor the combine callback + /// is always called for elements in order, and the result stream always + /// maintains the same order as the original. + Stream scan( + S initialValue, FutureOr combine(S previousValue, T element)) { + var accumulated = initialValue; + return asyncMap((value) { + var result = combine(accumulated, value); + if (result is Future) { + return result.then((r) => accumulated = r); + } else { + return accumulated = result as S; + } + }); + } +} + /// Scan is like fold, but instead of producing a single value it yields /// each intermediate accumulation. /// @@ -11,6 +33,7 @@ import 'dart:async'; /// events from the source until it completes, therefor the combine callback is /// always called for elements in order, and the result stream always maintains /// the same order as the original. +@Deprecated('Use the extension instead') StreamTransformer scan( T initialValue, FutureOr combine(T previousValue, S element)) => StreamTransformer.fromBind((source) { diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart index fbaf46a7a..a9ecaef26 100644 --- a/pkgs/stream_transform/lib/src/start_with.dart +++ b/pkgs/stream_transform/lib/src/start_with.dart @@ -6,9 +6,41 @@ import 'dart:async'; import 'followed_by.dart'; +extension StartWith on Stream { + /// Returns a stream which emits [initial] before any values from the original + /// stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + Stream startWith(T initial) => + startWithStream(Future.value(initial).asStream()); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + /// If the original stream is a broadcast stream it will miss any events which + /// occur before the initial values are all emitted. + Stream startWithMany(Iterable initial) => + startWithStream(Stream.fromIterable(initial)); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. If + /// the original stream is a broadcast stream it will miss any events which + /// occur before [initial] closes. + Stream startWithStream(Stream initial) { + if (isBroadcast && !initial.isBroadcast) { + initial = initial.asBroadcastStream(); + } + return initial.followedBy(this); + } +} + /// Emits [initial] before any values from the original stream. /// /// If the original stream is a broadcast stream the result will be as well. +@Deprecated('Use the extension instead') StreamTransformer startWith(T initial) => startWithStream(Future.value(initial).asStream()); @@ -17,6 +49,7 @@ StreamTransformer startWith(T initial) => /// If the original stream is a broadcast stream the result will be as well. If /// the original stream is a broadcast stream it will miss any events which /// occur before the initial values are all emitted. +@Deprecated('Use the extension instead') StreamTransformer startWithMany(Iterable initial) => startWithStream(Stream.fromIterable(initial)); @@ -25,6 +58,7 @@ StreamTransformer startWithMany(Iterable initial) => /// If the original stream is a broadcast stream the result will be as well. If /// the original stream is a broadcast stream it will miss any events which /// occur before [initial] closes. +@Deprecated('Use the extension instead') StreamTransformer startWithStream(Stream initial) => StreamTransformer.fromBind((values) { if (values.isBroadcast && !initial.isBroadcast) { diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index e02917d2e..e4f47876d 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -1,10 +1,33 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. + import 'dart:async'; -import 'chain_transformers.dart'; -import 'map.dart'; +extension Switch on Stream { + /// Maps events to a Stream and emits values from the most recently created + /// Stream. + /// + /// When the source emits a value it will be converted to a [Stream] using + /// [convert] and the output will switch to emitting events from that result. + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of the types of the streams produced by [convert]. + Stream switchMap(Stream convert(T event)) { + return map(convert).switchLatest(); + } +} + +extension SwitchLatest on Stream> { + /// Emits values from the most recently emitted Stream. + /// + /// When the source emits a stream the output will switch to emitting events + /// from that stream. + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of the types of streams emitted. + Stream switchLatest() => transform(_SwitchTransformer()); +} /// Maps events to a Stream and emits values from the most recently created /// Stream. @@ -14,8 +37,10 @@ import 'map.dart'; /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of the streams produced by [map]. +@Deprecated('Use the extension instead') StreamTransformer switchMap(Stream convert(S event)) => - chainTransformers(map(convert), switchLatest()); + StreamTransformer.fromBind( + (source) => source.map(convert).transform(switchLatest())); /// Emits values from the most recently emitted Stream. /// @@ -24,6 +49,7 @@ StreamTransformer switchMap(Stream convert(S event)) => /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of streams emitted. +@Deprecated('Use the extension instead') StreamTransformer, T> switchLatest() => _SwitchTransformer(); class _SwitchTransformer extends StreamTransformerBase, T> { diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index ad12ae849..d415c2428 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -4,12 +4,24 @@ import 'dart:async'; +extension TakeUntil on Stream { + /// Returns a stram which emits values from the source stream until [trigger] + /// fires. + /// + /// Completing [trigger] differs from canceling a subscription in that values + /// which are emitted before the trigger, but have further asynchronous delays + /// in transformations following the takeUtil, will still go through. + /// Cancelling a subscription immediately stops values. + Stream takeUntil(Future trigger) => transform(_TakeUntil(trigger)); +} + /// Emits values from the stream until [trigger] fires. /// /// Completing [trigger] differs from canceling a subscription in that values /// which are emitted before the trigger, but have further asynchronous delays /// in transformations following the takeUtil, will still go through. Cancelling /// a subscription immediately stops values. +@Deprecated('Use the extension instead') StreamTransformer takeUntil(Future trigger) => _TakeUntil(trigger); diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 1b799fa4c..61ee1987d 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -5,6 +5,45 @@ import 'dart:async'; import 'from_handlers.dart'; +extension Tap on Stream { + /// Taps into this stream to allow additional handling on a single-subscriber + /// stream without first wrapping as a broadcast stream. + /// + /// The [onValue] callback will be called with every value from the source + /// stream before it is forwarded to listeners on the resulting stream. May be + /// null if only [onError] or [onDone] callbacks are needed. + /// + /// The [onError] callback will be called with every error from the source + /// stream before it is forwarded to listeners on the resulting stream. + /// + /// The [onDone] callback will be called after the source stream closes and + /// before the resulting stream is closed. + /// + /// Errors from any of the callbacks are caught and ignored. + /// + /// The callbacks may not be called until the tapped stream has a listener, + /// and may not be called after the listener has canceled the subscription. + Stream tap(void Function(T) onValue, + {void Function(Object, StackTrace) onError, + void Function() onDone}) => + transform(fromHandlers(handleData: (value, sink) { + try { + onValue?.call(value); + } catch (_) {/*Ignore*/} + sink.add(value); + }, handleError: (error, stackTrace, sink) { + try { + onError?.call(error, stackTrace); + } catch (_) {/*Ignore*/} + sink.addError(error, stackTrace); + }, handleDone: (sink) { + try { + onDone?.call(); + } catch (_) {/*Ignore*/} + sink.close(); + })); +} + /// Taps into a Stream to allow additional handling on a single-subscriber /// stream without first wrapping as a broadcast stream. /// @@ -22,6 +61,7 @@ import 'from_handlers.dart'; /// /// The callbacks may not be called until the tapped stream has a listener, and /// may not be called after the listener has canceled the subscription. +@Deprecated('Use the extension instead') StreamTransformer tap(void Function(T) onValue, {void Function(Object, StackTrace) onError, void Function() onDone}) => fromHandlers(handleData: (value, sink) { diff --git a/pkgs/stream_transform/lib/src/throttle.dart b/pkgs/stream_transform/lib/src/throttle.dart index 475ad92cb..bea2980fb 100644 --- a/pkgs/stream_transform/lib/src/throttle.dart +++ b/pkgs/stream_transform/lib/src/throttle.dart @@ -5,8 +5,29 @@ import 'dart:async'; import 'from_handlers.dart'; +extension Throttle on Stream { + /// Returns a stream which only emits once per [duration], at the beginning of + /// the period. + /// + /// Events emitted by the source stream within [duration] following an emitted + /// event will be discarded. Errors are always forwarded immediately. + Stream throttle(Duration duration) { + Timer timer; + + return transform(fromHandlers(handleData: (data, sink) { + if (timer == null) { + sink.add(data); + timer = Timer(duration, () { + timer = null; + }); + } + })); + } +} + /// Creates a StreamTransformer which only emits once per [duration], at the /// beginning of the period. +@Deprecated('Use the extension instead') StreamTransformer throttle(Duration duration) { Timer timer; diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart index 9164f912d..eb79bb507 100644 --- a/pkgs/stream_transform/lib/src/where_type.dart +++ b/pkgs/stream_transform/lib/src/where_type.dart @@ -4,6 +4,19 @@ import 'dart:async'; +extension WhereType on Stream { + /// Returns a stream which emits only the events which have type [S]. + /// + /// If the source stream is a broadcast stream the result will be as well. + /// + /// Errors from the source stream are forwarded directly to the result stream. + /// + /// [S] should be a subtype of the stream's generic type, otherwise nothing of + /// type [S] could possibly be emitted, however there is no static or runtime + /// checking that this is the case. + Stream whereType() => transform(_WhereType()); +} + /// Emits only the events which have type [R]. /// /// If the source stream is a broadcast stream the result will be as well. @@ -19,6 +32,7 @@ import 'dart:async'; /// [R] should be a subtype of the stream's generic type, otherwise nothing of /// type [R] could possibly be emitted, however there is no static or runtime /// checking that this is the case. +@Deprecated('Use the extension instead') StreamTransformer whereType() => _WhereType(); class _WhereType extends StreamTransformerBase { diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index b8b15f498..557fc82ef 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -8,7 +8,6 @@ export 'src/audit.dart'; export 'src/buffer.dart'; export 'src/chain_transformers.dart'; export 'src/combine_latest.dart'; -export 'src/combine_latest_all.dart'; export 'src/concat.dart'; export 'src/concurrent_async_map.dart'; export 'src/debounce.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 38ad8d52f..75428878f 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,10 +2,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.19 +version: 0.0.20-dev environment: - sdk: ">=2.2.0 <3.0.0" + sdk: ">=2.6.0-dev.5.0 <3.0.0" dev_dependencies: pedantic: ^1.5.0 diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index 021755af6..9b46e1fe5 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -52,7 +52,7 @@ void main() { isDone = false; finishWork = null; workArgument = null; - transformed = values.stream.transform(asyncMapBuffer(work)); + transformed = values.stream.asyncMapBuffer(work); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 1a6440ecf..119e0c85e 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -52,7 +52,7 @@ void main() { isDone = false; finishWork = null; workArgument = null; - transformed = values.stream.transform(asyncMapSample(work)); + transformed = values.stream.asyncMapSample(work); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 9d0c9f201..a90210caa 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -10,34 +10,34 @@ import 'package:stream_transform/stream_transform.dart'; void main() { test('forwards only events that pass the predicate', () async { var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(asyncWhere((e) async => e > 2)); + var filtered = values.asyncWhere((e) async => e > 2); expect(await filtered.toList(), [3, 4]); }); test('allows predicates that go through event loop', () async { var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(asyncWhere((e) async { + var filtered = values.asyncWhere((e) async { await Future(() {}); return e > 2; - })); + }); expect(await filtered.toList(), [3, 4]); }); test('allows synchronous predicate', () async { var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(asyncWhere((e) => e > 2)); + var filtered = values.asyncWhere((e) => e > 2); expect(await filtered.toList(), [3, 4]); }); test('can result in empty stream', () async { var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(asyncWhere((e) => e > 4)); + var filtered = values.asyncWhere((e) => e > 4); expect(await filtered.isEmpty, true); }); test('forwards values to multiple listeners', () async { var values = StreamController.broadcast(); - var filtered = values.stream.transform(asyncWhere((e) async => e > 2)); + var filtered = values.stream.asyncWhere((e) async => e > 2); var firstValues = []; var secondValues = []; filtered..listen(firstValues.add)..listen(secondValues.add); @@ -50,7 +50,7 @@ void main() { test('closes streams with multiple listeners', () async { var values = StreamController.broadcast(); var predicate = Completer(); - var filtered = values.stream.transform(asyncWhere((_) => predicate.future)); + var filtered = values.stream.asyncWhere((_) => predicate.future); var firstDone = false; var secondDone = false; filtered @@ -71,11 +71,11 @@ void main() { var errors = []; var emitted = []; var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(asyncWhere((e) async { + var filtered = values.asyncWhere((e) async { await Future(() {}); if (e.isEven) throw Exception('$e'); return true; - })); + }); var done = Completer(); filtered.listen(emitted.add, onError: errors.add, onDone: done.complete); await done.future; diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 168227a42..58cb95bcb 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -20,25 +20,21 @@ void main() { Stream transformed; StreamSubscription subscription; - void setUpStreams(StreamTransformer transformer) { - valuesCanceled = false; - values = createController(streamType) - ..onCancel = () { - valuesCanceled = true; - }; - emittedValues = []; - errors = []; - isDone = false; - transformed = values.stream.transform(transformer); - subscription = transformed - .listen(emittedValues.add, onError: errors.add, onDone: () { - isDone = true; - }); - } - group('audit', () { setUp(() async { - setUpStreams(audit(const Duration(milliseconds: 5))); + valuesCanceled = false; + values = createController(streamType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = values.stream.audit(const Duration(milliseconds: 5)); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); }); test('cancels values', () async { diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 3dcd505b9..580058600 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -41,7 +41,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = values.stream.transform(buffer(trigger.stream)); + transformed = values.stream.buffer(trigger.stream); subscription = transformed.listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart index cdfedb0be..2943449fd 100644 --- a/pkgs/stream_transform/test/combine_latest_all_test.dart +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -16,9 +16,8 @@ void main() { final first = StreamController(); final second = StreamController(); final third = StreamController(); - final combined = first.stream - .transform(combineLatestAll([second.stream, third.stream])) - .map((data) => data.join()); + final combined = first.stream.combineLatestAll( + [second.stream, third.stream]).map((data) => data.join()); // first: a----b------------------c--------d---| // second: --1---------2-----------------| @@ -54,8 +53,7 @@ void main() { test('ends if a Stream closes without ever emitting a value', () async { final first = StreamController(); final second = StreamController(); - final combined = - first.stream.transform(combineLatestAll([second.stream])); + final combined = first.stream.combineLatestAll([second.stream]); // first: -a------b-------| // second: -----| @@ -74,8 +72,7 @@ void main() { final first = StreamController(); final second = StreamController(); final combined = first.stream - .transform(combineLatestAll([second.stream])) - .map((data) => data.join()); + .combineLatestAll([second.stream]).map((data) => data.join()); // first: -a---------| // second: ----1---# @@ -95,9 +92,8 @@ void main() { final second = StreamController(); var done = false; - first.stream - .transform(combineLatestAll([second.stream])) - .listen(null, onDone: () => done = true); + first.stream.combineLatestAll([second.stream]).listen(null, + onDone: () => done = true); // first: -a---| // second: --------1--| @@ -123,8 +119,7 @@ void main() { final first = StreamController.broadcast(); final second = StreamController.broadcast(); final combined = first.stream - .transform(combineLatestAll([second.stream])) - .map((data) => data.join()); + .combineLatestAll([second.stream]).map((data) => data.join()); // first: a------b----------------c------d----e---| // second: --1---------2---3---4------5-| diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index f8156bce4..2b35e2c21 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -17,9 +17,8 @@ void main() { int sum(int a, int b) => a + b; var results = []; - unawaited(source.stream - .transform(combineLatest(other.stream, sum)) - .forEach(results.add)); + unawaited( + source.stream.combineLatest(other.stream, sum).forEach(results.add)); source.add(1); await Future(() {}); @@ -49,7 +48,7 @@ void main() { var results = []; unawaited(source.stream - .transform(combineLatest(other.stream, times)) + .combineLatest(other.stream, times) .forEach(results.add)); source..add('a')..add('b'); @@ -76,7 +75,7 @@ void main() { var done = false; source.stream - .transform(combineLatest(other.stream, sum)) + .combineLatest(other.stream, sum) .listen(null, onDone: () => done = true); source.add(1); @@ -99,7 +98,7 @@ void main() { var done = false; source - .transform(combineLatest(other.stream, sum)) + .combineLatest(other.stream, sum) .listen(null, onDone: () => done = true); await Future(() {}); @@ -115,7 +114,7 @@ void main() { var done = false; source.stream - .transform(combineLatest(other, sum)) + .combineLatest(other, sum) .listen(null, onDone: () => done = true); await Future(() {}); @@ -130,7 +129,7 @@ void main() { var errors = []; source.stream - .transform(combineLatest(other.stream, sum)) + .combineLatest(other.stream, sum) .listen(null, onError: errors.add); source.addError(_NumberedException(1)); @@ -151,8 +150,7 @@ void main() { int combine(int a, int b) => a + b; var emittedValues = []; - var transformed = - source.stream.transform(combineLatest(other.stream, combine)); + var transformed = source.stream.combineLatest(other.stream, combine); var subscription = transformed.listen(emittedValues.add); diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index dceaa879b..6da21012e 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -42,7 +42,7 @@ void main() { isDone = false; finishWork = []; values = []; - transformed = controller.stream.transform(concurrentAsyncMap(convert)); + transformed = controller.stream.concurrentAsyncMap(convert); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index 89fede93e..cb027c58b 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -21,7 +21,7 @@ void main() { StreamSubscription subscription; Stream transformed; - void setUpStreams(StreamTransformer transformer) { + setUp(() async { valuesCanceled = false; values = createController(streamType) ..onCancel = () { @@ -30,15 +30,11 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = values.stream.transform(transformer); + transformed = values.stream.debounce(const Duration(milliseconds: 5)); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); - } - - setUp(() async { - setUpStreams(debounce(const Duration(milliseconds: 5))); }); test('cancels values', () async { @@ -103,7 +99,7 @@ void main() { emittedValues = []; errors = []; transformed = values.stream - .transform(debounceBuffer(const Duration(milliseconds: 5))) + .debounceBuffer(const Duration(milliseconds: 5)) ..listen(emittedValues.add, onError: errors.add); }); diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index c5f48aaf0..c8864b5bc 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -43,7 +43,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = first.stream.transform(followedBy(second.stream)); + transformed = first.stream.followedBy(second.stream); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 4d3050ad5..24cd76b16 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -13,7 +13,7 @@ void main() { test('includes all values', () async { var first = Stream.fromIterable([1, 2, 3]); var second = Stream.fromIterable([4, 5, 6]); - var allValues = await first.transform(merge(second)).toList(); + var allValues = await first.merge(second).toList(); expect(allValues, containsAllInOrder([1, 2, 3])); expect(allValues, containsAllInOrder([4, 5, 6])); expect(allValues, hasLength(6)); @@ -30,8 +30,7 @@ void main() { ..onCancel = () { secondCanceled = true; }; - var subscription = - first.stream.transform(merge(second.stream)).listen((_) {}); + var subscription = first.stream.merge(second.stream).listen((_) {}); await subscription.cancel(); expect(firstCanceled, true); expect(secondCanceled, true); @@ -41,7 +40,7 @@ void main() { var first = StreamController(); var second = StreamController(); var isDone = false; - first.stream.transform(merge(second.stream)).listen((_) {}, onDone: () { + first.stream.merge(second.stream).listen((_) {}, onDone: () { isDone = true; }); await first.close(); @@ -54,7 +53,7 @@ void main() { var first = StreamController.broadcast(); var second = StreamController(); var emittedValues = []; - var transformed = first.stream.transform(merge(second.stream)); + var transformed = first.stream.merge(second.stream); var subscription = transformed.listen(emittedValues.add); first.add(1); second.add(2); @@ -77,7 +76,7 @@ void main() { var first = Stream.fromIterable([1, 2, 3]); var second = Stream.fromIterable([4, 5, 6]); var third = Stream.fromIterable([7, 8, 9]); - var allValues = await first.transform(mergeAll([second, third])).toList(); + var allValues = await first.mergeAll([second, third]).toList(); expect(allValues, containsAllInOrder([1, 2, 3])); expect(allValues, containsAllInOrder([4, 5, 6])); expect(allValues, containsAllInOrder([7, 8, 9])); @@ -101,8 +100,8 @@ void main() { secondSingleCanceled = true; }; - var merged = first.stream - .transform(mergeAll([secondBroadcast.stream, secondSingle.stream])); + var merged = + first.stream.mergeAll([secondBroadcast.stream, secondSingle.stream]); var firstListenerValues = []; var secondListenerValues = []; diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 662831c01..4e58680dc 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -14,7 +14,7 @@ void main() { test('produces intermediate values', () async { var source = Stream.fromIterable([1, 2, 3, 4]); int sum(int x, int y) => x + y; - var result = await source.transform(scan(0, sum)).toList(); + var result = await source.scan(0, sum).toList(); expect(result, [1, 3, 6, 10]); }); @@ -22,7 +22,7 @@ void main() { test('can create a broadcast stream', () { var source = StreamController.broadcast(); - var transformed = source.stream.transform(scan(null, null)); + var transformed = source.stream.scan(null, null); expect(transformed.isBroadcast, true); }); @@ -34,7 +34,7 @@ void main() { var errors = []; - source.stream.transform(scan(0, sum)).listen(null, onError: errors.add); + source.stream.scan(0, sum).listen(null, onError: errors.add); source.addError(StateError('fail')); await Future(() {}); @@ -46,7 +46,7 @@ void main() { test('returns a Stream of non-futures', () async { var source = Stream.fromIterable([1, 2, 3, 4]); Future sum(int x, int y) async => x + y; - var result = await source.transform(scan(0, sum)).toList(); + var result = await source.scan(0, sum).toList(); expect(result, [1, 3, 6, 10]); }); @@ -54,9 +54,8 @@ void main() { test('can return a Stream of futures when specified', () async { var source = Stream.fromIterable([1, 2]); Future sum(Future x, int y) async => (await x) + y; - var result = await source - .transform(scan>(Future.value(0), sum)) - .toList(); + var result = + await source.scan>(Future.value(0), sum).toList(); expect(result, [ const TypeMatcher>(), @@ -78,8 +77,7 @@ void main() { var results = []; - unawaited( - source.stream.transform(scan(0, combine)).forEach(results.add)); + unawaited(source.stream.scan(0, combine).forEach(results.add)); source..add(1)..add(2); await Future(() {}); @@ -99,9 +97,7 @@ void main() { var errors = []; - source.stream - .transform(scan(0, combine)) - .listen(null, onError: errors.add); + source.stream.scan(0, combine).listen(null, onError: errors.add); source.add(1); await Future(() {}); diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 8ce8075a7..3208903c6 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -19,18 +19,18 @@ void main() { bool isDone; setupForStreamType( - String streamType, StreamTransformer transformer) { + String streamType, Stream Function(Stream) transform) { emittedValues = []; isDone = false; values = createController(streamType); - transformed = values.stream.transform(transformer); + transformed = transform(values.stream); subscription = transformed.listen(emittedValues.add, onDone: () => isDone = true); } for (var streamType in streamTypes) { group('startWith then [$streamType]', () { - setUp(() => setupForStreamType(streamType, startWith(1))); + setUp(() => setupForStreamType(streamType, (s) => s.startWith(1))); test('outputs all values', () async { values..add(2)..add(3); @@ -65,7 +65,7 @@ void main() { group('startWithMany then [$streamType]', () { setUp(() async { - setupForStreamType(streamType, startWithMany([1, 2])); + setupForStreamType(streamType, (s) => s.startWithMany([1, 2])); // Ensure all initial values go through await Future(() {}); }); @@ -105,7 +105,8 @@ void main() { StreamController starting; setUp(() async { starting = createController(startingStreamType); - setupForStreamType(streamType, startWithStream(starting.stream)); + setupForStreamType( + streamType, (s) => s.startWithStream(starting.stream)); }); test('outputs all values', () async { diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index e32026ad5..ba265033b 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -41,7 +41,7 @@ void main() { errors = []; isDone = false; subscription = outer.stream - .transform(switchLatest()) + .switchLatest() .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); @@ -129,9 +129,7 @@ void main() { var outer = StreamController>(); var values = []; - outer.stream - .transform(switchMap((l) => Stream.fromIterable(l))) - .listen(values.add); + outer.stream.switchMap((l) => Stream.fromIterable(l)).listen(values.add); outer.add([1, 2, 3]); await Future(() {}); @@ -143,7 +141,7 @@ void main() { test('can create a broadcast stream', () async { var outer = StreamController.broadcast(); - var transformed = outer.stream.transform(switchMap(null)); + var transformed = outer.stream.switchMap(null); expect(transformed.isBroadcast, true); }); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 74c516707..c25d34288 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -32,7 +32,7 @@ void main() { errors = []; isDone = false; closeTrigger = Completer(); - transformed = values.stream.transform(takeUntil(closeTrigger.future)); + transformed = values.stream.takeUntil(closeTrigger.future); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 816c80f53..79d47b4c1 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -12,24 +12,22 @@ void main() { test('calls function for values', () async { var valuesSeen = []; var stream = Stream.fromIterable([1, 2, 3]); - await stream.transform(tap(valuesSeen.add)).last; + await stream.tap(valuesSeen.add).last; expect(valuesSeen, [1, 2, 3]); }); test('forwards values', () async { var stream = Stream.fromIterable([1, 2, 3]); - var values = await stream.transform(tap((_) {})).toList(); + var values = await stream.tap((_) {}).toList(); expect(values, [1, 2, 3]); }); test('calls function for errors', () async { dynamic error; var source = StreamController(); - source.stream - .transform(tap((_) {}, onError: (e, st) { - error = e; - })) - .listen((_) {}, onError: (_) {}); + source.stream.tap((_) {}, onError: (e, st) { + error = e; + }).listen((_) {}, onError: (_) {}); source.addError('error'); await Future(() {}); expect(error, 'error'); @@ -38,8 +36,7 @@ void main() { test('forwards errors', () async { dynamic error; var source = StreamController(); - source.stream.transform(tap((_) {}, onError: (e, st) {})).listen((_) {}, - onError: (e) { + source.stream.tap((_) {}, onError: (e, st) {}).listen((_) {}, onError: (e) { error = e; }); source.addError('error'); @@ -50,11 +47,9 @@ void main() { test('calls function on done', () async { var doneCalled = false; var source = StreamController(); - source.stream - .transform(tap((_) {}, onDone: () { - doneCalled = true; - })) - .listen((_) {}); + source.stream.tap((_) {}, onDone: () { + doneCalled = true; + }).listen((_) {}); await source.close(); expect(doneCalled, true); }); @@ -63,9 +58,9 @@ void main() { () async { var dataCallCount = 0; var source = StreamController.broadcast(); - source.stream.transform(tap((_) { + source.stream.tap((_) { dataCallCount++; - })) + }) ..listen((_) {}) ..listen((_) {}); source.add(1); @@ -78,9 +73,9 @@ void main() { () async { var errorCallCount = 0; var source = StreamController.broadcast(); - source.stream.transform(tap((_) {}, onError: (_, __) { + source.stream.tap((_) {}, onError: (_, __) { errorCallCount++; - })) + }) ..listen((_) {}, onError: (_, __) {}) ..listen((_) {}, onError: (_, __) {}); source.addError('error'); @@ -92,9 +87,9 @@ void main() { () async { var doneCallCount = 0; var source = StreamController.broadcast(); - source.stream.transform(tap((_) {}, onDone: () { + source.stream.tap((_) {}, onDone: () { doneCallCount++; - })) + }) ..listen((_) {}) ..listen((_) {}); await source.close(); @@ -105,7 +100,7 @@ void main() { var source = StreamController.broadcast(); var emittedValues1 = []; var emittedValues2 = []; - source.stream.transform(tap((_) {})) + source.stream.tap((_) {}) ..listen(emittedValues1.add) ..listen(emittedValues2.add); source.add(1); @@ -116,6 +111,6 @@ void main() { test('allows null callback', () async { var stream = Stream.fromIterable([1, 2, 3]); - await stream.transform(tap(null)).last; + await stream.tap(null).last; }); } diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index ae77b7c5a..e51ef844f 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -19,23 +19,19 @@ void main() { Stream transformed; StreamSubscription subscription; - void setUpStreams(StreamTransformer transformer) { - valuesCanceled = false; - values = createController(streamType) - ..onCancel = () { - valuesCanceled = true; - }; - emittedValues = []; - isDone = false; - transformed = values.stream.transform(transformer); - subscription = transformed.listen(emittedValues.add, onDone: () { - isDone = true; - }); - } - group('throttle', () { setUp(() async { - setUpStreams(throttle(const Duration(milliseconds: 5))); + valuesCanceled = false; + values = createController(streamType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + isDone = false; + transformed = values.stream.throttle(const Duration(milliseconds: 5)); + subscription = transformed.listen(emittedValues.add, onDone: () { + isDone = true; + }); }); test('cancels values', () async { diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart index 75062c2ce..2ea478222 100644 --- a/pkgs/stream_transform/test/where_type_test.dart +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -11,19 +11,19 @@ import 'package:stream_transform/stream_transform.dart'; void main() { test('forwards only events that match the type', () async { var values = Stream.fromIterable([1, 'a', 2, 'b']); - var filtered = values.transform(whereType()); + var filtered = values.whereType(); expect(await filtered.toList(), ['a', 'b']); }); test('can result in empty stream', () async { var values = Stream.fromIterable([1, 2, 3, 4]); - var filtered = values.transform(whereType()); + var filtered = values.whereType(); expect(await filtered.isEmpty, true); }); test('forwards values to multiple listeners', () async { var values = StreamController.broadcast(); - var filtered = values.stream.transform(whereType()); + var filtered = values.stream.whereType(); var firstValues = []; var secondValues = []; filtered..listen(firstValues.add)..listen(secondValues.add); @@ -35,7 +35,7 @@ void main() { test('closes streams with multiple listeners', () async { var values = StreamController.broadcast(); - var filtered = values.stream.transform(whereType()); + var filtered = values.stream.whereType(); var firstDone = false; var secondDone = false; filtered From 14455ec9fab51e5f14dc3bcf31251e3cc98aeb74 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 7 Oct 2019 14:08:07 -0700 Subject: [PATCH 0588/1215] Add extension comments and regroup them (dart-lang/stream_transform#84) Add doc comments on all extensions. Merge some related extensions into larger groups and add comments that specifically describe differences between them. --- pkgs/stream_transform/README.md | 29 +- .../{async_map_buffer.dart => async_map.dart} | 87 +++++- .../stream_transform/lib/src/async_where.dart | 1 + pkgs/stream_transform/lib/src/audit.dart | 93 ------- pkgs/stream_transform/lib/src/buffer.dart | 37 --- .../lib/src/combine_latest.dart | 2 + pkgs/stream_transform/lib/src/concat.dart | 9 - .../{followed_by.dart => concatenate.dart} | 65 ++++- .../lib/src/concurrent_async_map.dart | 84 ------ pkgs/stream_transform/lib/src/debounce.dart | 100 ------- pkgs/stream_transform/lib/src/merge.dart | 1 + pkgs/stream_transform/lib/src/rate_limit.dart | 256 ++++++++++++++++++ pkgs/stream_transform/lib/src/scan.dart | 7 +- pkgs/stream_transform/lib/src/start_with.dart | 68 ----- pkgs/stream_transform/lib/src/switch.dart | 9 +- pkgs/stream_transform/lib/src/take_until.dart | 3 +- pkgs/stream_transform/lib/src/tap.dart | 1 + pkgs/stream_transform/lib/src/throttle.dart | 42 --- pkgs/stream_transform/lib/src/where_type.dart | 1 + .../lib/stream_transform.dart | 12 +- 20 files changed, 437 insertions(+), 470 deletions(-) rename pkgs/stream_transform/lib/src/{async_map_buffer.dart => async_map.dart} (63%) delete mode 100644 pkgs/stream_transform/lib/src/audit.dart delete mode 100644 pkgs/stream_transform/lib/src/buffer.dart delete mode 100644 pkgs/stream_transform/lib/src/concat.dart rename pkgs/stream_transform/lib/src/{followed_by.dart => concatenate.dart} (55%) delete mode 100644 pkgs/stream_transform/lib/src/concurrent_async_map.dart delete mode 100644 pkgs/stream_transform/lib/src/debounce.dart create mode 100644 pkgs/stream_transform/lib/src/rate_limit.dart delete mode 100644 pkgs/stream_transform/lib/src/start_with.dart delete mode 100644 pkgs/stream_transform/lib/src/throttle.dart diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 313e6f19d..785adf1a9 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -2,16 +2,17 @@ Extension methods on `Stream` adding common transform operators. # Operators -## asyncMapBuffer +## asyncMapBuffer, asyncMapSample, concurrentAsyncMap + +Alternatives to `asyncMap`. `asyncMapBuffer` prevents the callback from +overlapping execution and collects events while it is executing. +`asyncMapSample` prevents overlapping execution and discards events while it is +executing. `concurrentAsyncMap` allows overlap and removes ordering guarantees +for higher throughput. Like `asyncMap` but events are buffered in a List until previous events have been processed rather than being called for each element individually. -## asyncMapSample - -Like `asyncMap` but events are discarded, keeping only the latest, until -previous events have been processed rather than being called for every element. - ## asyncWhere Like `where` but allows an asynchronous predicate. @@ -26,26 +27,16 @@ recent value. Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. -## combineLatest - -Combine the most recent event from two streams through a callback and emit the -result. +## combineLatest, combineLatestAll -## combineLatestAll - -Combines the latest events emitted from multiple source streams and yields a -list of the values. +Combine the most recent event from multiple streams through a callback or into a +list. ## debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. -## concurrentAsyncMap - -Like `asyncMap` but the convert callback can be called with subsequent values -before it has finished for previous values. - ## followedBy Appends the values of a stream after another stream finishes. diff --git a/pkgs/stream_transform/lib/src/async_map_buffer.dart b/pkgs/stream_transform/lib/src/async_map.dart similarity index 63% rename from pkgs/stream_transform/lib/src/async_map_buffer.dart rename to pkgs/stream_transform/lib/src/async_map.dart index 57defc22b..c9b263f09 100644 --- a/pkgs/stream_transform/lib/src/async_map_buffer.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -5,10 +5,20 @@ import 'dart:async'; import 'aggregate_sample.dart'; -import 'buffer.dart'; import 'chain_transformers.dart'; import 'from_handlers.dart'; +import 'rate_limit.dart'; +/// Alternatives to [asyncMap]. +/// +/// The built in [asyncMap] will not overlap execution of the passed callback, +/// and every event will be sent to the callback individually. +/// +/// - [asyncMapBuffer] prevents the callback from overlapping execution and +/// collects events while it is executing to process in batches. +/// - [asyncMapSample] prevents overlapping execution and discards events while +/// it is executing. +/// - [concurrentAsyncMap] allows overlap and removes ordering guarantees. extension AsyncMap on Stream { /// Like [asyncMap] but events are buffered until previous events have been /// processed by [convert]. @@ -63,6 +73,43 @@ extension AsyncMap on Stream { return transform(AggregateSample(workFinished.stream, _dropPrevious)) .transform(_asyncMapThen(convert, workFinished.add)); } + + /// Like [asyncMap] but the [convert] callback may be called for an element + /// before processing for the previous element is finished. + /// + /// Events on the result stream will be emitted in the order that [convert] + /// completed which may not match the order of the original stream. + /// + /// If the source stream is a broadcast stream the result will be as well. + /// When used with a broadcast stream behavior also differs from [asyncMap] in + /// that the [convert] function is only called once per event, rather than + /// once per listener per event. The [convert] callback won't be called for + /// events while a broadcast stream has no listener. + /// + /// Errors from [convert] or the source stream are forwarded directly to the + /// result stream. + /// + /// The result stream will not close until the source stream closes and all + /// pending conversions have finished. + Stream concurrentAsyncMap(FutureOr convert(T event)) { + var valuesWaiting = 0; + var sourceDone = false; + return transform(fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + try { + sink.add(await convert(element)); + } catch (e, st) { + sink.addError(e, st); + } + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + })); + } } /// Like [Stream.asyncMap] but events are buffered until previous events have @@ -140,3 +187,41 @@ StreamTransformer _asyncMapThen( } }); } + +/// Like [Stream.asyncMap] but the [convert] callback may be called for an +/// element before processing for the previous element is finished. +/// +/// Events on the result stream will be emitted in the order that [convert] +/// completed which may not match the order of the original stream. +/// +/// If the source stream is a broadcast stream the result will be as well. When +/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in +/// that the [convert] function is only called once per event, rather than once +/// per listener per event. The [convert] callback won't be called for events +/// while a broadcast stream has no listener. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// Errors during the conversion are also forwarded to the result stream. +/// +/// The result stream will not close until the source stream closes and all +/// pending conversions have finished. +@Deprecated('Use the extension instead') +StreamTransformer concurrentAsyncMap(FutureOr convert(S event)) { + var valuesWaiting = 0; + var sourceDone = false; + return fromHandlers(handleData: (element, sink) { + valuesWaiting++; + () async { + try { + sink.add(await convert(element)); + } catch (e, st) { + sink.addError(e, st); + } + valuesWaiting--; + if (valuesWaiting <= 0 && sourceDone) sink.close(); + }(); + }, handleDone: (sink) { + sourceDone = true; + if (valuesWaiting <= 0) sink.close(); + }); +} diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/async_where.dart index a611063d6..f2fe10888 100644 --- a/pkgs/stream_transform/lib/src/async_where.dart +++ b/pkgs/stream_transform/lib/src/async_where.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'from_handlers.dart'; +/// An asynchronous [where]. extension AsyncWhere on Stream { /// Like [where] but allows the [test] to return a [Future]. /// diff --git a/pkgs/stream_transform/lib/src/audit.dart b/pkgs/stream_transform/lib/src/audit.dart deleted file mode 100644 index b175e6d02..000000000 --- a/pkgs/stream_transform/lib/src/audit.dart +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. -import 'dart:async'; - -import 'from_handlers.dart'; - -extension Audit on Stream { - /// Returns a Stream which only emits once per [duration], at the end of the - /// period. - /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors are forwarded immediately. - /// - /// If there is no pending event when the source stream closes the output - /// stream will close immediately. If there is a pending event the output - /// stream will wait to emit it before closing. - /// - /// Differs from `throttle` in that it always emits the most recently received - /// event rather than the first in the period. The events that are emitted are - /// always delayed by some amount. If the event that started the period is the - /// one that is emitted it will be delayed by [duration]. If a later event - /// comes in within the period it's delay will be shorter by the difference in - /// arrival times. - /// - /// Differs from `debounce` in that a value will always be emitted after - /// [duration], the output will not be starved by values coming in repeatedly - /// within [duration]. - /// - /// For example: - /// - /// source.audit(Duration(seconds: 5)); - /// - /// source: a------b--c----d--| - /// output: -----a------c--------d| - Stream audit(Duration duration) { - Timer timer; - var shouldClose = false; - T recentData; - - return transform(fromHandlers(handleData: (T data, EventSink sink) { - recentData = data; - timer ??= Timer(duration, () { - sink.add(recentData); - timer = null; - if (shouldClose) { - sink.close(); - } - }); - }, handleDone: (EventSink sink) { - if (timer != null) { - shouldClose = true; - } else { - sink.close(); - } - })); - } -} - -/// Creates a StreamTransformer which only emits once per [duration], at the -/// end of the period. -/// -/// Always introduces a delay of at most [duration]. -/// -/// Differs from `throttle` in that it always emits the most recently received -/// event rather than the first in the period. -/// -/// Differs from `debounce` in that a value will always be emitted after -/// [duration], the output will not be starved by values coming in repeatedly -/// within [duration]. -@Deprecated('Use the extension instead') -StreamTransformer audit(Duration duration) { - Timer timer; - var shouldClose = false; - T recentData; - - return fromHandlers(handleData: (T data, EventSink sink) { - recentData = data; - timer ??= Timer(duration, () { - sink.add(recentData); - timer = null; - if (shouldClose) { - sink.close(); - } - }); - }, handleDone: (EventSink sink) { - if (timer != null) { - shouldClose = true; - } else { - sink.close(); - } - }); -} diff --git a/pkgs/stream_transform/lib/src/buffer.dart b/pkgs/stream_transform/lib/src/buffer.dart deleted file mode 100644 index cf8b0c3a4..000000000 --- a/pkgs/stream_transform/lib/src/buffer.dart +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -import 'aggregate_sample.dart'; - -extension Buffer on Stream { - /// Returns a Stream which collects values and emits when it sees a value on - /// [trigger]. - /// - /// If there are no pending values when [trigger] emits, the next value on the - /// source Stream will immediately flow through. Otherwise, the pending values - /// are released when [trigger] emits. - /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors from the source stream or the trigger are immediately forwarded to - /// the output. - Stream> buffer(Stream trigger) => - transform(AggregateSample>(trigger, _collect)); -} - -/// Creates a [StreamTransformer] which collects values and emits when it sees a -/// value on [trigger]. -/// -/// If there are no pending values when [trigger] emits, the next value on the -/// source Stream will immediately flow through. Otherwise, the pending values -/// are released when [trigger] emits. -/// -/// Errors from the source stream or the trigger are immediately forwarded to -/// the output. -@Deprecated('Use the extension instead') -StreamTransformer> buffer(Stream trigger) => - AggregateSample>(trigger, _collect); - -List _collect(T event, List soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 7fb9ac9dd..4e35997c1 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -4,6 +4,8 @@ import 'dart:async'; +/// Utilities to combine events from multiple streams through a callback or into +/// a list. extension CombineLatest on Stream { /// Returns a stream which combines the latest value from the source stream /// with the latest value from [other] using [combine]. diff --git a/pkgs/stream_transform/lib/src/concat.dart b/pkgs/stream_transform/lib/src/concat.dart deleted file mode 100644 index 565a2906c..000000000 --- a/pkgs/stream_transform/lib/src/concat.dart +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. -import 'dart:async'; - -import 'followed_by.dart'; - -@Deprecated('Use followedBy instead') -StreamTransformer concat(Stream next) => followedBy(next); diff --git a/pkgs/stream_transform/lib/src/followed_by.dart b/pkgs/stream_transform/lib/src/concatenate.dart similarity index 55% rename from pkgs/stream_transform/lib/src/followed_by.dart rename to pkgs/stream_transform/lib/src/concatenate.dart index 41c771809..402a4bc68 100644 --- a/pkgs/stream_transform/lib/src/followed_by.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -4,7 +4,8 @@ import 'dart:async'; -extension FollowedBy on Stream { +/// Utilities to append or prepend to a stream. +extension Concatenate on Stream { /// Returns a stream which emits values and errors from [next] after the /// original stream is complete. /// @@ -21,6 +22,35 @@ extension FollowedBy on Stream { /// listening to the second stream will cause events to be dropped rather than /// buffered. Stream followedBy(Stream next) => transform(_FollowedBy(next)); + + /// Returns a stream which emits [initial] before any values from the original + /// stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + Stream startWith(T initial) => + startWithStream(Future.value(initial).asStream()); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + /// If the original stream is a broadcast stream it will miss any events which + /// occur before the initial values are all emitted. + Stream startWithMany(Iterable initial) => + startWithStream(Stream.fromIterable(initial)); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. If + /// the original stream is a broadcast stream it will miss any events which + /// occur before [initial] closes. + Stream startWithStream(Stream initial) { + if (isBroadcast && !initial.isBroadcast) { + initial = initial.asBroadcastStream(); + } + return initial.followedBy(this); + } } /// Starts emitting values from [next] after the original stream is complete. @@ -104,3 +134,36 @@ class _FollowedBy extends StreamTransformerBase { return controller.stream; } } + +/// Emits [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. +@Deprecated('Use the extension instead') +StreamTransformer startWith(T initial) => + startWithStream(Future.value(initial).asStream()); + +/// Emits all values in [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. If +/// the original stream is a broadcast stream it will miss any events which +/// occur before the initial values are all emitted. +@Deprecated('Use the extension instead') +StreamTransformer startWithMany(Iterable initial) => + startWithStream(Stream.fromIterable(initial)); + +/// Emits all values in [initial] before any values from the original stream. +/// +/// If the original stream is a broadcast stream the result will be as well. If +/// the original stream is a broadcast stream it will miss any events which +/// occur before [initial] closes. +@Deprecated('Use the extension instead') +StreamTransformer startWithStream(Stream initial) => + StreamTransformer.fromBind((values) { + if (values.isBroadcast && !initial.isBroadcast) { + initial = initial.asBroadcastStream(); + } + return initial.transform(followedBy(values)); + }); + +@Deprecated('Use followedBy instead') +StreamTransformer concat(Stream next) => followedBy(next); diff --git a/pkgs/stream_transform/lib/src/concurrent_async_map.dart b/pkgs/stream_transform/lib/src/concurrent_async_map.dart deleted file mode 100644 index c0fae2f4c..000000000 --- a/pkgs/stream_transform/lib/src/concurrent_async_map.dart +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -import 'from_handlers.dart'; - -extension ConcurrentAsyncMap on Stream { - /// Like [asyncMap] but the [convert] callback may be called for an element - /// before processing for the previous element is finished. - /// - /// Events on the result stream will be emitted in the order that [convert] - /// completed which may not match the order of the original stream. - /// - /// If the source stream is a broadcast stream the result will be as well. - /// When used with a broadcast stream behavior also differs from [asyncMap] in - /// that the [convert] function is only called once per event, rather than - /// once per listener per event. The [convert] callback won't be called for - /// events while a broadcast stream has no listener. - /// - /// Errors from [convert] or the source stream are forwarded directly to the - /// result stream. - /// - /// The result stream will not close until the source stream closes and all - /// pending conversions have finished. - Stream concurrentAsyncMap(FutureOr convert(T event)) { - var valuesWaiting = 0; - var sourceDone = false; - return transform(fromHandlers(handleData: (element, sink) { - valuesWaiting++; - () async { - try { - sink.add(await convert(element)); - } catch (e, st) { - sink.addError(e, st); - } - valuesWaiting--; - if (valuesWaiting <= 0 && sourceDone) sink.close(); - }(); - }, handleDone: (sink) { - sourceDone = true; - if (valuesWaiting <= 0) sink.close(); - })); - } -} - -/// Like [Stream.asyncMap] but the [convert] callback may be called for an -/// element before processing for the previous element is finished. -/// -/// Events on the result stream will be emitted in the order that [convert] -/// completed which may not match the order of the original stream. -/// -/// If the source stream is a broadcast stream the result will be as well. When -/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in -/// that the [convert] function is only called once per event, rather than once -/// per listener per event. The [convert] callback won't be called for events -/// while a broadcast stream has no listener. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// Errors during the conversion are also forwarded to the result stream. -/// -/// The result stream will not close until the source stream closes and all -/// pending conversions have finished. -@Deprecated('Use the extension instead') -StreamTransformer concurrentAsyncMap(FutureOr convert(S event)) { - var valuesWaiting = 0; - var sourceDone = false; - return fromHandlers(handleData: (element, sink) { - valuesWaiting++; - () async { - try { - sink.add(await convert(element)); - } catch (e, st) { - sink.addError(e, st); - } - valuesWaiting--; - if (valuesWaiting <= 0 && sourceDone) sink.close(); - }(); - }, handleDone: (sink) { - sourceDone = true; - if (valuesWaiting <= 0) sink.close(); - }); -} diff --git a/pkgs/stream_transform/lib/src/debounce.dart b/pkgs/stream_transform/lib/src/debounce.dart deleted file mode 100644 index 0987ec6cb..000000000 --- a/pkgs/stream_transform/lib/src/debounce.dart +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. -import 'dart:async'; - -import 'from_handlers.dart'; - -extension Debounce on Stream { - /// Returns a Stream which only emits when the source stream does not emit for - /// [duration]. - /// - /// Values will always be delayed by at least [duration], and values which - /// come within this time will replace the old values, only the most - /// recent value will be emitted. - /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors are forwarded immediately. - /// - /// If there is an event waiting during the debounce period when the source - /// stream closes the returned stream will wait to emit it following the - /// debounce period before closing. If there is no pending debounced event - /// when the source stream closes the returned stream will close immediately. - /// - /// To collect values emitted during the debounce period see [debounceBuffer]. - Stream debounce(Duration duration) => - transform(_debounceAggregate(duration, _dropPrevious)); - - /// Returns a Stream which collects values until the source stream does not - /// emit for [duration] then emits the collected values. - /// - /// Values will always be delayed by at least [duration], and values which - /// come within this time will be aggregated into the same list. - /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors are forwarded immediately. - /// - /// If there are events waiting during the debounce period when the source - /// stream closes the returned stream will wait to emit them following the - /// debounce period before closing. If there are no pending debounced events - /// when the source stream closes the returned stream will close immediately. - /// - /// To keep only the most recent event during the debounce perios see - /// [debounce]. - Stream> debounceBuffer(Duration duration) => - transform(_debounceAggregate(duration, _collectToList)); -} - -/// Creates a StreamTransformer which only emits when the source stream does not -/// emit for [duration]. -/// -/// Source values will always be delayed by at least [duration], and values -/// which come within this time will replace the old values, only the most -/// recent value will be emitted. -@Deprecated('Use the extension instead') -StreamTransformer debounce(Duration duration) => - _debounceAggregate(duration, _dropPrevious); - -/// Creates a StreamTransformer which collects values until the source stream -/// does not emit for [duration] then emits the collected values. -/// -/// This differs from [debounce] in that values are aggregated instead of -/// skipped. -@Deprecated('Use the extension instead') -StreamTransformer> debounceBuffer(Duration duration) => - _debounceAggregate(duration, _collectToList); - -List _collectToList(T element, List soFar) { - soFar ??= []; - soFar.add(element); - return soFar; -} - -T _dropPrevious(T element, _) => element; - -/// Creates a StreamTransformer which aggregates values until the source stream -/// does not emit for [duration], then emits the aggregated values. -StreamTransformer _debounceAggregate( - Duration duration, R collect(T element, R soFar)) { - Timer timer; - R soFar; - var shouldClose = false; - return fromHandlers(handleData: (T value, EventSink sink) { - timer?.cancel(); - timer = Timer(duration, () { - sink.add(soFar); - if (shouldClose) { - sink.close(); - } - soFar = null; - timer = null; - }); - soFar = collect(value, soFar); - }, handleDone: (EventSink sink) { - if (soFar != null) { - shouldClose = true; - } else { - sink.close(); - } - }); -} diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 878a8d11b..736cde511 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -4,6 +4,7 @@ import 'dart:async'; +/// Utilities to interleave events from multiple streams. extension Merge on Stream { /// Returns a stream which emits values and errors from the source stream and /// [other] in any order as they arrive. diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart new file mode 100644 index 000000000..91a764866 --- /dev/null +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -0,0 +1,256 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'aggregate_sample.dart'; +import 'from_handlers.dart'; + +/// Utilities to rate limit events. +/// +/// - [debounce] - emit the _first_ event at the _end_ of the period. +/// - [debounceBuffer] - emit _all_ events at the _end_ of the period. +/// - [throttle] - emit the _first_ event at the _beginning_ of the period. +/// - [audit] - emit the _last_ event at the _end_ of the period. +/// - [buffer] - emit _all_ events on a _trigger_. +extension RateLimit on Stream { + /// Returns a Stream which only emits when the source stream does not emit for + /// [duration]. + /// + /// Values will always be delayed by at least [duration], and values which + /// come within this time will replace the old values, only the most + /// recent value will be emitted. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there is an event waiting during the debounce period when the source + /// stream closes the returned stream will wait to emit it following the + /// debounce period before closing. If there is no pending debounced event + /// when the source stream closes the returned stream will close immediately. + /// + /// To collect values emitted during the debounce period see [debounceBuffer]. + Stream debounce(Duration duration) => + transform(_debounceAggregate(duration, _dropPrevious)); + + /// Returns a Stream which collects values until the source stream does not + /// emit for [duration] then emits the collected values. + /// + /// Values will always be delayed by at least [duration], and values which + /// come within this time will be aggregated into the same list. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there are events waiting during the debounce period when the source + /// stream closes the returned stream will wait to emit them following the + /// debounce period before closing. If there are no pending debounced events + /// when the source stream closes the returned stream will close immediately. + /// + /// To keep only the most recent event during the debounce perios see + /// [debounce]. + Stream> debounceBuffer(Duration duration) => + transform(_debounceAggregate(duration, _collectToList)); + + /// Returns a stream which only emits once per [duration], at the beginning of + /// the period. + /// + /// Events emitted by the source stream within [duration] following an emitted + /// event will be discarded. Errors are always forwarded immediately. + Stream throttle(Duration duration) { + Timer timer; + + return transform(fromHandlers(handleData: (data, sink) { + if (timer == null) { + sink.add(data); + timer = Timer(duration, () { + timer = null; + }); + } + })); + } + + /// Returns a Stream which only emits once per [duration], at the end of the + /// period. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If there is no pending event when the source stream closes the output + /// stream will close immediately. If there is a pending event the output + /// stream will wait to emit it before closing. + /// + /// Differs from `throttle` in that it always emits the most recently received + /// event rather than the first in the period. The events that are emitted are + /// always delayed by some amount. If the event that started the period is the + /// one that is emitted it will be delayed by [duration]. If a later event + /// comes in within the period it's delay will be shorter by the difference in + /// arrival times. + /// + /// Differs from `debounce` in that a value will always be emitted after + /// [duration], the output will not be starved by values coming in repeatedly + /// within [duration]. + /// + /// For example: + /// + /// source.audit(Duration(seconds: 5)); + /// + /// source: a------b--c----d--| + /// output: -----a------c--------d| + Stream audit(Duration duration) { + Timer timer; + var shouldClose = false; + T recentData; + + return transform(fromHandlers(handleData: (T data, EventSink sink) { + recentData = data; + timer ??= Timer(duration, () { + sink.add(recentData); + timer = null; + if (shouldClose) { + sink.close(); + } + }); + }, handleDone: (EventSink sink) { + if (timer != null) { + shouldClose = true; + } else { + sink.close(); + } + })); + } + + /// Returns a Stream which collects values and emits when it sees a value on + /// [trigger]. + /// + /// If there are no pending values when [trigger] emits, the next value on the + /// source Stream will immediately flow through. Otherwise, the pending values + /// are released when [trigger] emits. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors from the source stream or the trigger are immediately forwarded to + /// the output. + Stream> buffer(Stream trigger) => + transform(AggregateSample>(trigger, _collect)); +} + +/// Creates a StreamTransformer which only emits when the source stream does not +/// emit for [duration]. +/// +/// Source values will always be delayed by at least [duration], and values +/// which come within this time will replace the old values, only the most +/// recent value will be emitted. +@Deprecated('Use the extension instead') +StreamTransformer debounce(Duration duration) => + _debounceAggregate(duration, _dropPrevious); + +/// Creates a StreamTransformer which collects values until the source stream +/// does not emit for [duration] then emits the collected values. +/// +/// This differs from [debounce] in that values are aggregated instead of +/// skipped. +@Deprecated('Use the extension instead') +StreamTransformer> debounceBuffer(Duration duration) => + _debounceAggregate(duration, _collectToList); + +List _collectToList(T element, List soFar) { + soFar ??= []; + soFar.add(element); + return soFar; +} + +T _dropPrevious(T element, _) => element; + +/// Creates a StreamTransformer which aggregates values until the source stream +/// does not emit for [duration], then emits the aggregated values. +StreamTransformer _debounceAggregate( + Duration duration, R collect(T element, R soFar)) { + Timer timer; + R soFar; + var shouldClose = false; + return fromHandlers(handleData: (T value, EventSink sink) { + timer?.cancel(); + timer = Timer(duration, () { + sink.add(soFar); + if (shouldClose) { + sink.close(); + } + soFar = null; + timer = null; + }); + soFar = collect(value, soFar); + }, handleDone: (EventSink sink) { + if (soFar != null) { + shouldClose = true; + } else { + sink.close(); + } + }); +} + +/// Creates a StreamTransformer which only emits once per [duration], at the +/// beginning of the period. +@Deprecated('Use the extension instead') +StreamTransformer throttle(Duration duration) { + Timer timer; + + return fromHandlers(handleData: (data, sink) { + if (timer == null) { + sink.add(data); + timer = Timer(duration, () { + timer = null; + }); + } + }); +} + +/// Creates a StreamTransformer which only emits once per [duration], at the +/// end of the period. +/// +/// Always introduces a delay of at most [duration]. +/// +/// Differs from `throttle` in that it always emits the most recently received +/// event rather than the first in the period. +/// +/// Differs from `debounce` in that a value will always be emitted after +/// [duration], the output will not be starved by values coming in repeatedly +/// within [duration]. +@Deprecated('Use the extension instead') +StreamTransformer audit(Duration duration) { + Timer timer; + var shouldClose = false; + T recentData; + + return fromHandlers(handleData: (T data, EventSink sink) { + recentData = data; + timer ??= Timer(duration, () { + sink.add(recentData); + timer = null; + if (shouldClose) { + sink.close(); + } + }); + }, handleDone: (EventSink sink) { + if (timer != null) { + shouldClose = true; + } else { + sink.close(); + } + }); +} + +/// Creates a [StreamTransformer] which collects values and emits when it sees a +/// value on [trigger]. +/// +/// If there are no pending values when [trigger] emits, the next value on the +/// source Stream will immediately flow through. Otherwise, the pending values +/// are released when [trigger] emits. +/// +/// Errors from the source stream or the trigger are immediately forwarded to +/// the output. +@Deprecated('Use the extension instead') +StreamTransformer> buffer(Stream trigger) => + AggregateSample>(trigger, _collect); + +List _collect(T event, List soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index be9899e15..bd2073fd6 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -4,14 +4,15 @@ import 'dart:async'; +/// A utility similar to [fold] which emits intermediate accumulations. extension Scan on Stream { /// Like [fold], but instead of producing a single value it yields each /// intermediate accumulation. /// /// If [combine] returns a Future it will not be called again for subsequent - /// events from the source until it completes, therefor the combine callback - /// is always called for elements in order, and the result stream always - /// maintains the same order as the original. + /// events from the source until it completes, therefore [combine] is always + /// called for elements in order, and the result stream always maintains the + /// same order as the original. Stream scan( S initialValue, FutureOr combine(S previousValue, T element)) { var accumulated = initialValue; diff --git a/pkgs/stream_transform/lib/src/start_with.dart b/pkgs/stream_transform/lib/src/start_with.dart deleted file mode 100644 index a9ecaef26..000000000 --- a/pkgs/stream_transform/lib/src/start_with.dart +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -import 'followed_by.dart'; - -extension StartWith on Stream { - /// Returns a stream which emits [initial] before any values from the original - /// stream. - /// - /// If the original stream is a broadcast stream the result will be as well. - Stream startWith(T initial) => - startWithStream(Future.value(initial).asStream()); - - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. - /// - /// If the original stream is a broadcast stream the result will be as well. - /// If the original stream is a broadcast stream it will miss any events which - /// occur before the initial values are all emitted. - Stream startWithMany(Iterable initial) => - startWithStream(Stream.fromIterable(initial)); - - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. - /// - /// If the original stream is a broadcast stream the result will be as well. If - /// the original stream is a broadcast stream it will miss any events which - /// occur before [initial] closes. - Stream startWithStream(Stream initial) { - if (isBroadcast && !initial.isBroadcast) { - initial = initial.asBroadcastStream(); - } - return initial.followedBy(this); - } -} - -/// Emits [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. -@Deprecated('Use the extension instead') -StreamTransformer startWith(T initial) => - startWithStream(Future.value(initial).asStream()); - -/// Emits all values in [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. If -/// the original stream is a broadcast stream it will miss any events which -/// occur before the initial values are all emitted. -@Deprecated('Use the extension instead') -StreamTransformer startWithMany(Iterable initial) => - startWithStream(Stream.fromIterable(initial)); - -/// Emits all values in [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. If -/// the original stream is a broadcast stream it will miss any events which -/// occur before [initial] closes. -@Deprecated('Use the extension instead') -StreamTransformer startWithStream(Stream initial) => - StreamTransformer.fromBind((values) { - if (values.isBroadcast && !initial.isBroadcast) { - initial = initial.asBroadcastStream(); - } - return initial.transform(followedBy(values)); - }); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index e4f47876d..eb58cc578 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -4,6 +4,8 @@ import 'dart:async'; +/// A utility to take events from the most recent sub stream returned by a +/// callback. extension Switch on Stream { /// Maps events to a Stream and emits values from the most recently created /// Stream. @@ -18,6 +20,7 @@ extension Switch on Stream { } } +/// A utility to take events from the most recent sub stream. extension SwitchLatest on Stream> { /// Emits values from the most recently emitted Stream. /// @@ -32,11 +35,11 @@ extension SwitchLatest on Stream> { /// Maps events to a Stream and emits values from the most recently created /// Stream. /// -/// When the source emits a value it will be converted to a [Stream] using [map] -/// and the output will switch to emitting events from that result. +/// When the source emits a value it will be converted to a [Stream] using +/// [convert] and the output will switch to emitting events from that result. /// /// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of the streams produced by [map]. +/// well, regardless of the types of the streams produced by [convert]. @Deprecated('Use the extension instead') StreamTransformer switchMap(Stream convert(S event)) => StreamTransformer.fromBind( diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index d415c2428..862222ede 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -4,8 +4,9 @@ import 'dart:async'; +/// A utility to end a stream based on an external trigger. extension TakeUntil on Stream { - /// Returns a stram which emits values from the source stream until [trigger] + /// Returns a stream which emits values from the source stream until [trigger] /// fires. /// /// Completing [trigger] differs from canceling a subscription in that values diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 61ee1987d..5d8198f2d 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'from_handlers.dart'; +/// A utility to chain extra behavior on a stream. extension Tap on Stream { /// Taps into this stream to allow additional handling on a single-subscriber /// stream without first wrapping as a broadcast stream. diff --git a/pkgs/stream_transform/lib/src/throttle.dart b/pkgs/stream_transform/lib/src/throttle.dart deleted file mode 100644 index bea2980fb..000000000 --- a/pkgs/stream_transform/lib/src/throttle.dart +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -// 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. -import 'dart:async'; - -import 'from_handlers.dart'; - -extension Throttle on Stream { - /// Returns a stream which only emits once per [duration], at the beginning of - /// the period. - /// - /// Events emitted by the source stream within [duration] following an emitted - /// event will be discarded. Errors are always forwarded immediately. - Stream throttle(Duration duration) { - Timer timer; - - return transform(fromHandlers(handleData: (data, sink) { - if (timer == null) { - sink.add(data); - timer = Timer(duration, () { - timer = null; - }); - } - })); - } -} - -/// Creates a StreamTransformer which only emits once per [duration], at the -/// beginning of the period. -@Deprecated('Use the extension instead') -StreamTransformer throttle(Duration duration) { - Timer timer; - - return fromHandlers(handleData: (data, sink) { - if (timer == null) { - sink.add(data); - timer = Timer(duration, () { - timer = null; - }); - } - }); -} diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart index eb79bb507..bfd82be8a 100644 --- a/pkgs/stream_transform/lib/src/where_type.dart +++ b/pkgs/stream_transform/lib/src/where_type.dart @@ -4,6 +4,7 @@ import 'dart:async'; +/// A utility to filter events by type. extension WhereType on Stream { /// Returns a stream which emits only the events which have type [S]. /// diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 557fc82ef..4f7ead87f 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -2,22 +2,16 @@ // 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. -export 'src/async_map_buffer.dart'; +export 'src/async_map.dart'; export 'src/async_where.dart'; -export 'src/audit.dart'; -export 'src/buffer.dart'; export 'src/chain_transformers.dart'; export 'src/combine_latest.dart'; -export 'src/concat.dart'; -export 'src/concurrent_async_map.dart'; -export 'src/debounce.dart'; -export 'src/followed_by.dart'; +export 'src/concatenate.dart'; export 'src/map.dart'; export 'src/merge.dart'; +export 'src/rate_limit.dart'; export 'src/scan.dart'; -export 'src/start_with.dart'; export 'src/switch.dart'; export 'src/take_until.dart'; export 'src/tap.dart'; -export 'src/throttle.dart'; export 'src/where_type.dart'; From b0e2e74003b007e280110cd417e08ed4bcb1c3e0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 18 Oct 2019 16:43:31 -0700 Subject: [PATCH 0589/1215] Merge asyncWhere and whereType to same extension (dart-lang/stream_transform#85) --- .../lib/src/{async_where.dart => where.dart} | 69 +++++++++++++++++- pkgs/stream_transform/lib/src/where_type.dart | 70 ------------------- .../lib/stream_transform.dart | 3 +- 3 files changed, 67 insertions(+), 75 deletions(-) rename pkgs/stream_transform/lib/src/{async_where.dart => where.dart} (54%) delete mode 100644 pkgs/stream_transform/lib/src/where_type.dart diff --git a/pkgs/stream_transform/lib/src/async_where.dart b/pkgs/stream_transform/lib/src/where.dart similarity index 54% rename from pkgs/stream_transform/lib/src/async_where.dart rename to pkgs/stream_transform/lib/src/where.dart index f2fe10888..33c0f7e66 100644 --- a/pkgs/stream_transform/lib/src/async_where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -1,12 +1,24 @@ -// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file // 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. + import 'dart:async'; import 'from_handlers.dart'; -/// An asynchronous [where]. -extension AsyncWhere on Stream { +/// Utilities to filter events. +extension Where on Stream { + /// Returns a stream which emits only the events which have type [S]. + /// + /// If the source stream is a broadcast stream the result will be as well. + /// + /// Errors from the source stream are forwarded directly to the result stream. + /// + /// [S] should be a subtype of the stream's generic type, otherwise nothing of + /// type [S] could possibly be emitted, however there is no static or runtime + /// checking that this is the case. + Stream whereType() => transform(_WhereType()); + /// Like [where] but allows the [test] to return a [Future]. /// /// Events on the result stream will be emitted in the order that [test] @@ -43,6 +55,57 @@ extension AsyncWhere on Stream { } } +/// Emits only the events which have type [R]. +/// +/// If the source stream is a broadcast stream the result will be as well. +/// +/// Errors from the source stream are forwarded directly to the result stream. +/// +/// The static type of the returned transformer takes `Null` so that it can +/// satisfy the subtype requirements for the `stream.transform()` argument on +/// any source stream. The argument to `bind` has been broadened to take +/// `Stream` since it will never be passed a `Stream` at runtime. +/// This is safe to use on any source stream. +/// +/// [R] should be a subtype of the stream's generic type, otherwise nothing of +/// type [R] could possibly be emitted, however there is no static or runtime +/// checking that this is the case. +@Deprecated('Use the extension instead') +StreamTransformer whereType() => _WhereType(); + +class _WhereType extends StreamTransformerBase { + @override + Stream bind(Stream source) { + var controller = source.isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + StreamSubscription subscription; + controller.onListen = () { + assert(subscription == null); + subscription = source.listen( + (value) { + if (value is R) controller.add(value); + }, + onError: controller.addError, + onDone: () { + subscription = null; + controller.close(); + }); + if (!source.isBroadcast) { + controller + ..onPause = subscription.pause + ..onResume = subscription.resume; + } + controller.onCancel = () { + subscription?.cancel(); + subscription = null; + }; + }; + return controller.stream; + } +} + /// Like [Stream.where] but allows the [test] to return a [Future]. /// /// Events on the result stream will be emitted in the order that [test] diff --git a/pkgs/stream_transform/lib/src/where_type.dart b/pkgs/stream_transform/lib/src/where_type.dart deleted file mode 100644 index bfd82be8a..000000000 --- a/pkgs/stream_transform/lib/src/where_type.dart +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// A utility to filter events by type. -extension WhereType on Stream { - /// Returns a stream which emits only the events which have type [S]. - /// - /// If the source stream is a broadcast stream the result will be as well. - /// - /// Errors from the source stream are forwarded directly to the result stream. - /// - /// [S] should be a subtype of the stream's generic type, otherwise nothing of - /// type [S] could possibly be emitted, however there is no static or runtime - /// checking that this is the case. - Stream whereType() => transform(_WhereType()); -} - -/// Emits only the events which have type [R]. -/// -/// If the source stream is a broadcast stream the result will be as well. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// -/// The static type of the returned transformer takes `Null` so that it can -/// satisfy the subtype requirements for the `stream.transform()` argument on -/// any source stream. The argument to `bind` has been broadened to take -/// `Stream` since it will never be passed a `Stream` at runtime. -/// This is safe to use on any source stream. -/// -/// [R] should be a subtype of the stream's generic type, otherwise nothing of -/// type [R] could possibly be emitted, however there is no static or runtime -/// checking that this is the case. -@Deprecated('Use the extension instead') -StreamTransformer whereType() => _WhereType(); - -class _WhereType extends StreamTransformerBase { - @override - Stream bind(Stream source) { - var controller = source.isBroadcast - ? StreamController.broadcast(sync: true) - : StreamController(sync: true); - - StreamSubscription subscription; - controller.onListen = () { - assert(subscription == null); - subscription = source.listen( - (value) { - if (value is R) controller.add(value); - }, - onError: controller.addError, - onDone: () { - subscription = null; - controller.close(); - }); - if (!source.isBroadcast) { - controller - ..onPause = subscription.pause - ..onResume = subscription.resume; - } - controller.onCancel = () { - subscription?.cancel(); - subscription = null; - }; - }; - return controller.stream; - } -} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 4f7ead87f..2f7bf24aa 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. export 'src/async_map.dart'; -export 'src/async_where.dart'; export 'src/chain_transformers.dart'; export 'src/combine_latest.dart'; export 'src/concatenate.dart'; @@ -14,4 +13,4 @@ export 'src/scan.dart'; export 'src/switch.dart'; export 'src/take_until.dart'; export 'src/tap.dart'; -export 'src/where_type.dart'; +export 'src/where.dart'; From eecbabd48d7a69dc2e6172a645b97cf7a0f1ea30 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 5 Nov 2019 10:32:22 -0800 Subject: [PATCH 0590/1215] Add an example (dart-lang/stream_transform#86) Bumps up the score on pub --- pkgs/stream_transform/example/index.html | 11 ++++++++++ pkgs/stream_transform/example/main.dart | 26 ++++++++++++++++++++++++ pkgs/stream_transform/pubspec.yaml | 3 +++ 3 files changed, 40 insertions(+) create mode 100644 pkgs/stream_transform/example/index.html create mode 100644 pkgs/stream_transform/example/main.dart diff --git a/pkgs/stream_transform/example/index.html b/pkgs/stream_transform/example/index.html new file mode 100644 index 000000000..aecdc0957 --- /dev/null +++ b/pkgs/stream_transform/example/index.html @@ -0,0 +1,11 @@ + + + + + +
+
+

+

+ + diff --git a/pkgs/stream_transform/example/main.dart b/pkgs/stream_transform/example/main.dart new file mode 100644 index 000000000..4ed53d834 --- /dev/null +++ b/pkgs/stream_transform/example/main.dart @@ -0,0 +1,26 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:html'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + var firstInput = document.querySelector('#first_input') as InputElement; + var secondInput = document.querySelector('#second_input') as InputElement; + var output = document.querySelector('#output'); + + _inputValues(firstInput) + .combineLatest(_inputValues(secondInput), + (first, second) => 'First: $first, Second: $second') + .tap((v) { + print('Saw: $v'); + }).forEach((v) { + output.text = v; + }); +} + +Stream _inputValues(InputElement element) => element.onKeyUp + .debounce(const Duration(milliseconds: 100)) + .map((_) => element.value); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 75428878f..803cc2e75 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -10,3 +10,6 @@ environment: dev_dependencies: pedantic: ^1.5.0 test: ^1.0.0 + # Example + build_runner: ^1.0.0 + build_web_compilers: ^2.0.0 From 13df7f261d08a8f89353f22a80a0b206079183e7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 5 Nov 2019 13:23:42 -0800 Subject: [PATCH 0591/1215] Prepare to publish (dart-lang/stream_transform#87) --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 52b1c51d0..d9b00498b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.0.20-dev +## 0.0.20 - Add extension methods for most transformers. These should be used in place of the current methods. All current implementations are deprecated and will diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 803cc2e75..8528f2161 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,10 +2,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.20-dev +version: 0.0.20 environment: - sdk: ">=2.6.0-dev.5.0 <3.0.0" + sdk: ">=2.6.0 <3.0.0" dev_dependencies: pedantic: ^1.5.0 From b8da2340f61c97dce1b3a0e6e895aca36ec598c2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 20 Nov 2019 11:27:01 -0800 Subject: [PATCH 0592/1215] Temporarily disable comment_references lint (dart-lang/watcher#76) There was a regression in the SDK and some references that used to be valid, and should still work in Dart doc, are marked invalid. See https://github.com/dart-lang/sdk/issues/39467 --- pkgs/watcher/analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index dd6881e3f..6eccbf845 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -11,7 +11,7 @@ analyzer: linter: rules: - - comment_references + # comment_references # https://github.com/dart-lang/sdk/issues/39467 - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables - unnecessary_const From 085d39579f13f26083a0e4f6bc7944931452d763 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 20 Nov 2019 13:26:02 -0800 Subject: [PATCH 0593/1215] Drop non-extension methods (dart-lang/stream_transform#88) Prepare to publish as `1.0.0` with only the extension method implementations. All deprecated methods are removed. Temporarily drop build_runner. It was only for the example and doesn't have a constraint allowing a breaking change in this package. --- pkgs/stream_transform/CHANGELOG.md | 4 + pkgs/stream_transform/lib/src/async_map.dart | 95 ------------------- .../lib/src/chain_transformers.dart | 24 ----- .../lib/src/combine_latest.dart | 71 -------------- .../stream_transform/lib/src/concatenate.dart | 48 ---------- pkgs/stream_transform/lib/src/map.dart | 21 ---- pkgs/stream_transform/lib/src/merge.dart | 19 ---- pkgs/stream_transform/lib/src/rate_limit.dart | 83 ---------------- pkgs/stream_transform/lib/src/scan.dart | 22 ----- pkgs/stream_transform/lib/src/switch.dart | 23 ----- pkgs/stream_transform/lib/src/take_until.dart | 10 -- pkgs/stream_transform/lib/src/tap.dart | 37 -------- pkgs/stream_transform/lib/src/where.dart | 54 ----------- .../lib/stream_transform.dart | 2 - pkgs/stream_transform/pubspec.yaml | 5 +- 15 files changed, 5 insertions(+), 513 deletions(-) delete mode 100644 pkgs/stream_transform/lib/src/chain_transformers.dart delete mode 100644 pkgs/stream_transform/lib/src/map.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index d9b00498b..99d2786d2 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.0 + +- Remove the top level methods and retain the extensions only. + ## 0.0.20 - Add extension methods for most transformers. These should be used in place diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index c9b263f09..464e49792 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'aggregate_sample.dart'; -import 'chain_transformers.dart'; import 'from_handlers.dart'; import 'rate_limit.dart'; @@ -112,62 +111,6 @@ extension AsyncMap on Stream { } } -/// Like [Stream.asyncMap] but events are buffered until previous events have -/// been processed by [convert]. -/// -/// If the source stream is a broadcast stream the result will be as well. When -/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in -/// that the [convert] function is only called once per event, rather than once -/// per listener per event. -/// -/// The first event from the source stream is always passed to [convert] as a -/// List with a single element. After that events are buffered until the -/// previous Future returned from [convert] has fired. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// Errors during the conversion are also forwarded to the result stream and are -/// considered completing work so the next values are let through. -/// -/// The result stream will not close until the source stream closes and all -/// pending conversions have finished. -@Deprecated('Use the extension instead') -StreamTransformer asyncMapBuffer( - Future Function(List) convert) { - var workFinished = StreamController() - // Let the first event through. - ..add(null); - return chainTransformers( - buffer(workFinished.stream), _asyncMapThen(convert, workFinished.add)); -} - -/// Like [Stream.asyncMap] but events are discarded while work is happening in -/// [convert]. -/// -/// If the source stream is a broadcast stream the result will be as well. When -/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in -/// that the [convert] function is only called once per event, rather than once -/// per listener per event. -/// -/// If no work is happening when an event is emitted it will be immediately -/// passed to [convert]. If there is ongoing work when an event is emitted it -/// will be held until the work is finished. New events emitted will replace a -/// pending event. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// Errors during the conversion are also forwarded to the result stream and are -/// considered completing work so the next values are let through. -/// -/// The result stream will not close until the source stream closes and all -/// pending conversions have finished. -@Deprecated('Use the extension instead') -StreamTransformer asyncMapSample(Future Function(S) convert) { - var workFinished = StreamController() - // Let the first event through. - ..add(null); - return chainTransformers(AggregateSample(workFinished.stream, _dropPrevious), - _asyncMapThen(convert, workFinished.add)); -} - T _dropPrevious(T event, _) => event; /// Like [Stream.asyncMap] but the [convert] is only called once per event, @@ -187,41 +130,3 @@ StreamTransformer _asyncMapThen( } }); } - -/// Like [Stream.asyncMap] but the [convert] callback may be called for an -/// element before processing for the previous element is finished. -/// -/// Events on the result stream will be emitted in the order that [convert] -/// completed which may not match the order of the original stream. -/// -/// If the source stream is a broadcast stream the result will be as well. When -/// used with a broadcast stream behavior also differs from [Stream.asyncMap] in -/// that the [convert] function is only called once per event, rather than once -/// per listener per event. The [convert] callback won't be called for events -/// while a broadcast stream has no listener. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// Errors during the conversion are also forwarded to the result stream. -/// -/// The result stream will not close until the source stream closes and all -/// pending conversions have finished. -@Deprecated('Use the extension instead') -StreamTransformer concurrentAsyncMap(FutureOr convert(S event)) { - var valuesWaiting = 0; - var sourceDone = false; - return fromHandlers(handleData: (element, sink) { - valuesWaiting++; - () async { - try { - sink.add(await convert(element)); - } catch (e, st) { - sink.addError(e, st); - } - valuesWaiting--; - if (valuesWaiting <= 0 && sourceDone) sink.close(); - }(); - }, handleDone: (sink) { - sourceDone = true; - if (valuesWaiting <= 0) sink.close(); - }); -} diff --git a/pkgs/stream_transform/lib/src/chain_transformers.dart b/pkgs/stream_transform/lib/src/chain_transformers.dart deleted file mode 100644 index 1e812d9c3..000000000 --- a/pkgs/stream_transform/lib/src/chain_transformers.dart +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// Combines two transformers into one. -/// -/// This is most useful to keep a reference to the combination and use it in -/// multiple places or give it a descriptive name. For inline uses the directly -/// chained calls to `.transform` should be preferred. -/// -/// For example: -/// -/// ``` -/// /// values.transform(splitDecoded) is identical to -/// /// values.transform(utf8.decoder).transform(const LineSplitter()) -/// final splitDecoded = chainTransformers(utf8.decoder, const LineSplitter()); -/// ``` -@Deprecated('This utility should not be needed with extension methods') -StreamTransformer chainTransformers( - StreamTransformer first, StreamTransformer second) => - StreamTransformer.fromBind( - (values) => values.transform(first).transform(second)); diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 4e35997c1..bacc7d61b 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -76,38 +76,6 @@ extension CombineLatest on Stream { transform(_CombineLatestAll(others)); } -/// Combine the latest value from the source stream with the latest value from -/// [other] using [combine]. -/// -/// No event will be emitted from the result stream until both the source stream -/// and [other] have each emitted at least one event. Once both streams have -/// emitted at least one event, the result stream will emit any time either -/// input stream emits. -/// -/// For example: -/// source.transform(combineLatest(other, (a, b) => a + b)); -/// -/// source: -/// 1--2-----4 -/// other: -/// ------3--- -/// result: -/// ------5--7 -/// -/// The result stream will not close until both the source stream and [other] -/// have closed. -/// -/// Errors thrown by [combine], along with any errors on the source stream or -/// [other], are forwarded to the result stream. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of [other]'s type. If a single subscription stream is -/// combined with a broadcast stream it may never be canceled. -@Deprecated('Use the extension instead') -StreamTransformer combineLatest( - Stream other, FutureOr Function(S, T) combine) => - _CombineLatest(other, combine); - class _CombineLatest extends StreamTransformerBase { final Stream _other; final FutureOr Function(S, T) _combine; @@ -218,45 +186,6 @@ class _CombineLatest extends StreamTransformerBase { } } -/// Combine the latest value emitted from the source stream with the latest -/// values emitted from [others]. -/// -/// [combineLatestAll] subscribes to the source stream and [others] and when -/// any one of the streams emits, the result stream will emit a [List] of -/// the latest values emitted from all streams. -/// -/// The result stream will not emit until all source streams emit at least -/// once. If a source stream emits multiple values before another starts -/// emitting, all but the last value will be lost. -/// -/// The result stream will not close until all source streams have closed. When -/// a source stream closes, the result stream will continue to emit the last -/// value from the closed stream when the other source streams emit until the -/// result stream has closed. If a source stream closes without emitting any -/// value, the result stream will close as well. -/// -/// Errors thrown by any source stream will be forwarded to the result stream. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of [others]. If a single subscription stream -/// is combined with a broadcast source stream, it may never be canceled. -/// -/// ## Example -/// -/// (Suppose first, second, and third are Stream) -/// final combined = first -/// .transform(combineLatestAll([second, third])) -/// .map((data) => data.join()); -/// -/// first: a----b------------------c--------d---| -/// second: --1---------2-----------------| -/// third: -------&----------%---| -/// combined: -------b1&--b2&---b2%---c2%------d2%-| -/// -@Deprecated('Use the extension instead') -StreamTransformer> combineLatestAll(Iterable> others) => - _CombineLatestAll(others); - class _CombineLatestAll extends StreamTransformerBase> { final Iterable> _others; diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index 402a4bc68..f9ba747d1 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -53,21 +53,6 @@ extension Concatenate on Stream { } } -/// Starts emitting values from [next] after the original stream is complete. -/// -/// If the initial stream never finishes, the [next] stream will never be -/// listened to. -/// -/// If a single-subscription follows the a broadcast stream it may be listened -/// to and never canceled. -/// -/// If a broadcast stream follows any other stream it will miss any events which -/// occur before the first stream is done. If a broadcast stream follows a -/// single-subscription stream, pausing the stream while it is listening to the -/// second stream will cause events to be dropped rather than buffered. -@Deprecated('Use the extension instead') -StreamTransformer followedBy(Stream next) => _FollowedBy(next); - class _FollowedBy extends StreamTransformerBase { final Stream _next; @@ -134,36 +119,3 @@ class _FollowedBy extends StreamTransformerBase { return controller.stream; } } - -/// Emits [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. -@Deprecated('Use the extension instead') -StreamTransformer startWith(T initial) => - startWithStream(Future.value(initial).asStream()); - -/// Emits all values in [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. If -/// the original stream is a broadcast stream it will miss any events which -/// occur before the initial values are all emitted. -@Deprecated('Use the extension instead') -StreamTransformer startWithMany(Iterable initial) => - startWithStream(Stream.fromIterable(initial)); - -/// Emits all values in [initial] before any values from the original stream. -/// -/// If the original stream is a broadcast stream the result will be as well. If -/// the original stream is a broadcast stream it will miss any events which -/// occur before [initial] closes. -@Deprecated('Use the extension instead') -StreamTransformer startWithStream(Stream initial) => - StreamTransformer.fromBind((values) { - if (values.isBroadcast && !initial.isBroadcast) { - initial = initial.asBroadcastStream(); - } - return initial.transform(followedBy(values)); - }); - -@Deprecated('Use followedBy instead') -StreamTransformer concat(Stream next) => followedBy(next); diff --git a/pkgs/stream_transform/lib/src/map.dart b/pkgs/stream_transform/lib/src/map.dart deleted file mode 100644 index e1f7137f8..000000000 --- a/pkgs/stream_transform/lib/src/map.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:async'; - -/// Models a [Stream.map] callback as a [StreamTransformer]. -/// -/// This is most useful to pass to functions that take a [StreamTransformer] -/// other than [Stream.transform]. For inline uses [Stream.map] should be -/// preferred. -/// -/// For example: -/// -/// ``` -/// final sinkMapper = new StreamSinkTransformer.fromStreamTransformer( -/// map((v) => '$v')); -/// ``` -@Deprecated('This utility should not be needed with extension methods') -StreamTransformer map(T convert(S event)) => - StreamTransformer.fromBind((stream) => stream.map(convert)); diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 736cde511..bbcf75934 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -56,25 +56,6 @@ extension Merge on Stream { Stream mergeAll(Iterable> others) => transform(_Merge(others)); } -/// Emits values from the source stream and [other] in any order as they arrive. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of [other]'s type. If a single subscription stream is -/// merged into a broadcast stream it may never be canceled. -@Deprecated('Use the extension instead') -StreamTransformer merge(Stream other) => _Merge([other]); - -/// Emits values from the source stream and all streams in [others] in any order -/// as they arrive. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of streams in [others]. If single -/// subscription streams are merged into a broadcast stream they may never be -/// canceled. -@Deprecated('Use the extension instead') -StreamTransformer mergeAll(Iterable> others) => - _Merge(others); - class _Merge extends StreamTransformerBase { final Iterable> _others; diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 91a764866..db6d7df04 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -135,25 +135,6 @@ extension RateLimit on Stream { transform(AggregateSample>(trigger, _collect)); } -/// Creates a StreamTransformer which only emits when the source stream does not -/// emit for [duration]. -/// -/// Source values will always be delayed by at least [duration], and values -/// which come within this time will replace the old values, only the most -/// recent value will be emitted. -@Deprecated('Use the extension instead') -StreamTransformer debounce(Duration duration) => - _debounceAggregate(duration, _dropPrevious); - -/// Creates a StreamTransformer which collects values until the source stream -/// does not emit for [duration] then emits the collected values. -/// -/// This differs from [debounce] in that values are aggregated instead of -/// skipped. -@Deprecated('Use the extension instead') -StreamTransformer> debounceBuffer(Duration duration) => - _debounceAggregate(duration, _collectToList); - List _collectToList(T element, List soFar) { soFar ??= []; soFar.add(element); @@ -189,68 +170,4 @@ StreamTransformer _debounceAggregate( }); } -/// Creates a StreamTransformer which only emits once per [duration], at the -/// beginning of the period. -@Deprecated('Use the extension instead') -StreamTransformer throttle(Duration duration) { - Timer timer; - - return fromHandlers(handleData: (data, sink) { - if (timer == null) { - sink.add(data); - timer = Timer(duration, () { - timer = null; - }); - } - }); -} - -/// Creates a StreamTransformer which only emits once per [duration], at the -/// end of the period. -/// -/// Always introduces a delay of at most [duration]. -/// -/// Differs from `throttle` in that it always emits the most recently received -/// event rather than the first in the period. -/// -/// Differs from `debounce` in that a value will always be emitted after -/// [duration], the output will not be starved by values coming in repeatedly -/// within [duration]. -@Deprecated('Use the extension instead') -StreamTransformer audit(Duration duration) { - Timer timer; - var shouldClose = false; - T recentData; - - return fromHandlers(handleData: (T data, EventSink sink) { - recentData = data; - timer ??= Timer(duration, () { - sink.add(recentData); - timer = null; - if (shouldClose) { - sink.close(); - } - }); - }, handleDone: (EventSink sink) { - if (timer != null) { - shouldClose = true; - } else { - sink.close(); - } - }); -} - -/// Creates a [StreamTransformer] which collects values and emits when it sees a -/// value on [trigger]. -/// -/// If there are no pending values when [trigger] emits, the next value on the -/// source Stream will immediately flow through. Otherwise, the pending values -/// are released when [trigger] emits. -/// -/// Errors from the source stream or the trigger are immediately forwarded to -/// the output. -@Deprecated('Use the extension instead') -StreamTransformer> buffer(Stream trigger) => - AggregateSample>(trigger, _collect); - List _collect(T event, List soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index bd2073fd6..b31b9e767 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -26,25 +26,3 @@ extension Scan on Stream { }); } } - -/// Scan is like fold, but instead of producing a single value it yields -/// each intermediate accumulation. -/// -/// If [combine] returns a Future it will not be called again for subsequent -/// events from the source until it completes, therefor the combine callback is -/// always called for elements in order, and the result stream always maintains -/// the same order as the original. -@Deprecated('Use the extension instead') -StreamTransformer scan( - T initialValue, FutureOr combine(T previousValue, S element)) => - StreamTransformer.fromBind((source) { - var accumulated = initialValue; - return source.asyncMap((value) { - var result = combine(accumulated, value); - if (result is Future) { - return result.then((r) => accumulated = r); - } else { - return accumulated = result as T; - } - }); - }); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index eb58cc578..2e2aebadf 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -32,29 +32,6 @@ extension SwitchLatest on Stream> { Stream switchLatest() => transform(_SwitchTransformer()); } -/// Maps events to a Stream and emits values from the most recently created -/// Stream. -/// -/// When the source emits a value it will be converted to a [Stream] using -/// [convert] and the output will switch to emitting events from that result. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of the streams produced by [convert]. -@Deprecated('Use the extension instead') -StreamTransformer switchMap(Stream convert(S event)) => - StreamTransformer.fromBind( - (source) => source.map(convert).transform(switchLatest())); - -/// Emits values from the most recently emitted Stream. -/// -/// When the source emits a stream the output will switch to emitting events -/// from that stream. -/// -/// If the source stream is a broadcast stream, the result stream will be as -/// well, regardless of the types of streams emitted. -@Deprecated('Use the extension instead') -StreamTransformer, T> switchLatest() => _SwitchTransformer(); - class _SwitchTransformer extends StreamTransformerBase, T> { const _SwitchTransformer(); diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 862222ede..43b35d17d 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -16,16 +16,6 @@ extension TakeUntil on Stream { Stream takeUntil(Future trigger) => transform(_TakeUntil(trigger)); } -/// Emits values from the stream until [trigger] fires. -/// -/// Completing [trigger] differs from canceling a subscription in that values -/// which are emitted before the trigger, but have further asynchronous delays -/// in transformations following the takeUtil, will still go through. Cancelling -/// a subscription immediately stops values. -@Deprecated('Use the extension instead') -StreamTransformer takeUntil(Future trigger) => - _TakeUntil(trigger); - class _TakeUntil extends StreamTransformerBase { final Future _trigger; diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 5d8198f2d..1942b129a 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -44,40 +44,3 @@ extension Tap on Stream { sink.close(); })); } - -/// Taps into a Stream to allow additional handling on a single-subscriber -/// stream without first wrapping as a broadcast stream. -/// -/// The [onValue] callback will be called with every value from the original -/// stream before it is forwarded to listeners on the resulting stream. May be -/// null if only [onError] or [onDone] callbacks are needed. -/// -/// The [onError] callback will be called with every error from the original -/// stream before it is forwarded to listeners on the resulting stream. -/// -/// The [onDone] callback will be called after the original stream closes and -/// before the resulting stream is closed. -/// -/// Errors from any of the callbacks are ignored. -/// -/// The callbacks may not be called until the tapped stream has a listener, and -/// may not be called after the listener has canceled the subscription. -@Deprecated('Use the extension instead') -StreamTransformer tap(void Function(T) onValue, - {void Function(Object, StackTrace) onError, void Function() onDone}) => - fromHandlers(handleData: (value, sink) { - try { - onValue?.call(value); - } catch (_) {/*Ignore*/} - sink.add(value); - }, handleError: (error, stackTrace, sink) { - try { - onError?.call(error, stackTrace); - } catch (_) {/*Ignore*/} - sink.addError(error, stackTrace); - }, handleDone: (sink) { - try { - onDone?.call(); - } catch (_) {/*Ignore*/} - sink.close(); - }); diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 33c0f7e66..70269230f 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -55,24 +55,6 @@ extension Where on Stream { } } -/// Emits only the events which have type [R]. -/// -/// If the source stream is a broadcast stream the result will be as well. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// -/// The static type of the returned transformer takes `Null` so that it can -/// satisfy the subtype requirements for the `stream.transform()` argument on -/// any source stream. The argument to `bind` has been broadened to take -/// `Stream` since it will never be passed a `Stream` at runtime. -/// This is safe to use on any source stream. -/// -/// [R] should be a subtype of the stream's generic type, otherwise nothing of -/// type [R] could possibly be emitted, however there is no static or runtime -/// checking that this is the case. -@Deprecated('Use the extension instead') -StreamTransformer whereType() => _WhereType(); - class _WhereType extends StreamTransformerBase { @override Stream bind(Stream source) { @@ -105,39 +87,3 @@ class _WhereType extends StreamTransformerBase { return controller.stream; } } - -/// Like [Stream.where] but allows the [test] to return a [Future]. -/// -/// Events on the result stream will be emitted in the order that [test] -/// completes which may not match the order of the original stream. -/// -/// If the source stream is a broadcast stream the result will be as well. When -/// used with a broadcast stream behavior also differs from [Stream.where] in -/// that the [test] function is only called once per event, rather than once -/// per listener per event. -/// -/// Errors from the source stream are forwarded directly to the result stream. -/// Errors during the conversion are also forwarded to the result stream. -/// -/// The result stream will not close until the source stream closes and all -/// pending [test] calls have finished. -@Deprecated('Use the extension instead') -StreamTransformer asyncWhere(FutureOr test(T element)) { - var valuesWaiting = 0; - var sourceDone = false; - return fromHandlers(handleData: (element, sink) { - valuesWaiting++; - () async { - try { - if (await test(element)) sink.add(element); - } catch (e, st) { - sink.addError(e, st); - } - valuesWaiting--; - if (valuesWaiting <= 0 && sourceDone) sink.close(); - }(); - }, handleDone: (sink) { - sourceDone = true; - if (valuesWaiting <= 0) sink.close(); - }); -} diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index 2f7bf24aa..d04c4dd77 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.dart @@ -3,10 +3,8 @@ // BSD-style license that can be found in the LICENSE file. export 'src/async_map.dart'; -export 'src/chain_transformers.dart'; export 'src/combine_latest.dart'; export 'src/concatenate.dart'; -export 'src/map.dart'; export 'src/merge.dart'; export 'src/rate_limit.dart'; export 'src/scan.dart'; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 8528f2161..544235736 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 0.0.20 +version: 1.0.0 environment: sdk: ">=2.6.0 <3.0.0" @@ -10,6 +10,3 @@ environment: dev_dependencies: pedantic: ^1.5.0 test: ^1.0.0 - # Example - build_runner: ^1.0.0 - build_web_compilers: ^2.0.0 From 983431b3860e49af1e1b349dae57db333ee45e7a Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Wed, 20 Nov 2019 16:34:46 -0800 Subject: [PATCH 0594/1215] Handle file watcher closed exception (dart-lang/watcher#75) Handle file watcher closed exception on windows --- pkgs/watcher/CHANGELOG.md | 5 +++++ .../lib/src/directory_watcher/windows.dart | 20 +++++++++++++++---- pkgs/watcher/pubspec.yaml | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 44fbda520..2b3cd35b4 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7+13 + +* Catch & forward `FileSystemException` from unexpectedly closed file watchers + on windows; the watcher will also be automatically restarted when this occurs. + # 0.9.7+12 * Catch `FileSystemException` during `existsSync()` on Windows. diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 85fef5f54..8bf664261 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -372,10 +372,22 @@ class _WindowsDirectoryWatcher /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { - // Batch the events together so that we can dedup events. - var innerStream = Directory(path).watch(recursive: true); - _watchSubscription = innerStream.listen(_onEvent, - onError: _eventsController.addError, onDone: _onDone); + // Note: "watcher closed" exceptions do not get sent over the stream + // returned by watch, and must be caught via a zone handler. + runZoned(() { + var innerStream = Directory(path).watch(recursive: true); + _watchSubscription = innerStream.listen(_onEvent, + onError: _eventsController.addError, onDone: _onDone); + }, onError: (error, StackTrace stackTrace) { + if (error is FileSystemException && + error.message.startsWith('Directory watcher closed unexpectedly')) { + _watchSubscription.cancel(); + _eventsController.addError(error, stackTrace); + _startWatch(); + } else { + throw error; + } + }); } /// Starts or restarts listing the watched directory to get an initial picture diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index f999c2a91..f8315bc63 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+12 +version: 0.9.7+13 description: >- A file system watcher. It monitors changes to contents of directories and From 390790f2782b568c3d9372eb3de159929d31de25 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Nov 2019 17:04:08 -0800 Subject: [PATCH 0595/1215] Update .gitignore (dart-lang/watcher#77) --- pkgs/watcher/.gitignore | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/pkgs/watcher/.gitignore b/pkgs/watcher/.gitignore index 7dbf0350d..ac98e87d1 100644 --- a/pkgs/watcher/.gitignore +++ b/pkgs/watcher/.gitignore @@ -1,15 +1,4 @@ # Don’t commit the following directories created by pub. -.buildlog -.pub/ -build/ -packages +.dart_tool .packages - -# Or the files created by dart2js. -*.dart.js -*.js_ -*.js.deps -*.js.map - -# Include when developing application packages. -pubspec.lock \ No newline at end of file +pubspec.lock From 44ed28dfec9be17bfa711e96c73a7e66dd1aa921 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Nov 2019 11:34:02 -0800 Subject: [PATCH 0596/1215] Add concurrentAsyncExpand (dart-lang/stream_transform#90) Closes dart-lang/stream_transform#77 Added with the `Merge` extension, since the behavior is similar to merging streams that are created lazily. Adds a private `StreamTransformer` to merge a `Stream>`. This could be exposed separately as an extension on that type later. In order to allow cancelling and then re-listening on broadcast streams, an sub stream which is single subscription must be converted to broadcast. This can be risky since subscriptions can leak and cause the inner streams to never be canceled. --- pkgs/stream_transform/CHANGELOG.md | 5 + pkgs/stream_transform/README.md | 2 +- pkgs/stream_transform/lib/src/merge.dart | 73 +++++++ pkgs/stream_transform/pubspec.yaml | 2 +- .../test/concurrent_async_expand_test.dart | 187 ++++++++++++++++++ 5 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 pkgs/stream_transform/test/concurrent_async_expand_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 99d2786d2..686f91921 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0 + +- Add `concurrentAsyncExpand` to interleave events emitted by multiple sub + streams created by a callback. + ## 1.0.0 - Remove the top level methods and retain the extensions only. diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 785adf1a9..56d114a7c 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -41,7 +41,7 @@ values that occur within a given duration. Appends the values of a stream after another stream finishes. -## merge, mergeAll +## merge, mergeAll, concurrentAsyncExpand Interleaves events from multiple streams into a single stream. diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index bbcf75934..5d2c8643f 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -54,6 +54,30 @@ extension Merge on Stream { /// events emitted by that stream before the result stream has a subscriber /// will be discarded. Stream mergeAll(Iterable> others) => transform(_Merge(others)); + + /// Like [asyncExpand] but the [convert] callback may be called for an element + /// before the Stream emitted by the previous element has closed. + /// + /// Events on the result stream will be emitted in the order they are emitted + /// by the sub streams, which may not match the order of the original stream. + /// + /// Errors from [convert], the source stream, or any of the sub streams are + /// forwarded to the result stream. + /// + /// The result stream will not close until the source stream closes and all + /// sub streams have closed. + /// + /// If the source stream is a broadcast stream the result will be as well, + /// regardless of the types of streams created by [convert]. In this case, + /// some care should be taken: + /// - If [convert] returns a single subscription stream it may be listened to + /// and never canceled. + /// - For any period of time where there are no listeners on the result + /// stream, any sub streams from previously emitted events will be ignored, + /// regardless of whether they emit further events after a listener is added + /// back. + Stream concurrentAsyncExpand(Stream Function(T) convert) => + map(convert).transform(_MergeExpanded()); } class _Merge extends StreamTransformerBase { @@ -109,3 +133,52 @@ class _Merge extends StreamTransformerBase { return controller.stream; } } + +class _MergeExpanded extends StreamTransformerBase, T> { + @override + Stream bind(Stream> streams) { + final controller = streams.isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + controller.onListen = () { + final subscriptions = >[]; + final outerSubscription = streams.listen((inner) { + if (streams.isBroadcast && !inner.isBroadcast) { + inner = inner.asBroadcastStream(); + } + final subscription = + inner.listen(controller.add, onError: controller.addError); + subscription.onDone(() { + assert(subscriptions.contains(subscription)); + subscriptions.remove(subscription); + if (subscriptions.isEmpty) controller.close(); + }); + subscriptions.add(subscription); + }, onError: controller.addError); + outerSubscription.onDone(() { + assert(subscriptions.contains(outerSubscription)); + subscriptions.remove(outerSubscription); + if (subscriptions.isEmpty) controller.close(); + }); + subscriptions.add(outerSubscription); + if (!streams.isBroadcast) { + controller + ..onPause = () { + for (final subscription in subscriptions) { + subscription.pause(); + } + } + ..onResume = () { + for (final subscription in subscriptions) { + subscription.resume(); + } + }; + } + controller.onCancel = () { + return Future.wait(subscriptions.map((s) => s.cancel())); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 544235736..2d2f59ae1 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 1.0.0 +version: 1.1.0-dev environment: sdk: ">=2.6.0 <3.0.0" diff --git a/pkgs/stream_transform/test/concurrent_async_expand_test.dart b/pkgs/stream_transform/test/concurrent_async_expand_test.dart new file mode 100644 index 000000000..f843c6fff --- /dev/null +++ b/pkgs/stream_transform/test/concurrent_async_expand_test.dart @@ -0,0 +1,187 @@ +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + test('forwards errors from the convert callback', () async { + var errors = []; + var source = Stream.fromIterable([1, 2, 3]); + source.concurrentAsyncExpand((i) { + // ignore: only_throw_errors + throw 'Error: $i'; + }).listen((_) {}, onError: errors.add); + await Future(() {}); + expect(errors, ['Error: 1', 'Error: 2', 'Error: 3']); + }); + + for (var outerType in streamTypes) { + for (var innerType in streamTypes) { + group('concurrentAsyncExpand $outerType to $innerType', () { + StreamController outerController; + bool outerCanceled; + List> innerControllers; + List innerCanceled; + List emittedValues; + bool isDone; + List errors; + Stream transformed; + StreamSubscription subscription; + + setUp(() { + outerController = createController(outerType) + ..onCancel = () { + outerCanceled = true; + }; + outerCanceled = false; + innerControllers = []; + innerCanceled = []; + emittedValues = []; + errors = []; + isDone = false; + transformed = outerController.stream.concurrentAsyncExpand((i) { + var index = innerControllers.length; + innerCanceled.add(false); + innerControllers.add(createController(innerType) + ..onCancel = () { + innerCanceled[index] = true; + }); + return innerControllers.last.stream; + }); + subscription = transformed + .listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + }); + + test('interleaves events from sub streams', () async { + outerController..add(1)..add(2); + await Future(() {}); + expect(emittedValues, isEmpty); + expect(innerControllers, hasLength(2)); + innerControllers[0].add('First'); + innerControllers[1].add('Second'); + innerControllers[0].add('First again'); + await Future(() {}); + expect(emittedValues, ['First', 'Second', 'First again']); + }); + + test('forwards errors from outer stream', () async { + outerController.addError('Error'); + await Future(() {}); + expect(errors, ['Error']); + }); + + test('forwards errors from inner streams', () async { + outerController..add(1)..add(2); + await Future(() {}); + innerControllers[0].addError('Error 1'); + innerControllers[1].addError('Error 2'); + await Future(() {}); + expect(errors, ['Error 1', 'Error 2']); + }); + + test('can continue handling events after an error in outer stream', + () async { + outerController + ..addError('Error') + ..add(1); + await Future(() {}); + innerControllers[0].add('First'); + await Future(() {}); + expect(emittedValues, ['First']); + expect(errors, ['Error']); + }); + + test('cancels outer subscription if output canceled', () async { + await subscription.cancel(); + expect(outerCanceled, true); + }); + + if (outerType != 'broadcast' || innerType != 'single subscription') { + // A single subscription inner stream in a broadcast outer stream is + // not canceled. + test('cancels inner subscriptions if output canceled', () async { + outerController..add(1)..add(2); + await Future(() {}); + await subscription.cancel(); + expect(innerCanceled, [true, true]); + }); + } + + test('stays open if any inner stream is still open', () async { + outerController.add(1); + await outerController.close(); + await Future(() {}); + expect(isDone, false); + }); + + test('stays open if outer stream is still open', () async { + outerController.add(1); + await Future(() {}); + await innerControllers[0].close(); + await Future(() {}); + expect(isDone, false); + }); + + test('closes after all inner streams and outer stream close', () async { + outerController.add(1); + await Future(() {}); + await innerControllers[0].close(); + await outerController.close(); + await Future(() {}); + expect(isDone, true); + }); + + if (outerType == 'broadcast') { + test('multiple listerns all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + outerController.add(1); + await Future(() {}); + innerControllers[0].add('First'); + await Future(() {}); + expect(emittedValues, ['First']); + expect(otherValues, ['First']); + }); + + test('multiple listeners get closed', () async { + var otherDone = false; + transformed.listen(null, onDone: () => otherDone = true); + outerController.add(1); + await Future(() {}); + await innerControllers[0].close(); + await outerController.close(); + await Future(() {}); + expect(isDone, true); + expect(otherDone, true); + }); + + test('can cancel and relisten', () async { + outerController..add(1)..add(2); + await Future(() {}); + innerControllers[0].add('First'); + innerControllers[1].add('Second'); + await Future(() {}); + await subscription.cancel(); + innerControllers[0].add('Ignored'); + await Future(() {}); + subscription = transformed.listen(emittedValues.add); + innerControllers[0].add('Also ignored'); + outerController.add(3); + await Future(() {}); + innerControllers[2].add('More'); + await Future(() {}); + expect(emittedValues, ['First', 'Second', 'More']); + }); + } + }); + } + } +} From 32cda0da2f72d920c2a095beacf7a14eacfa2f03 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Nov 2019 11:34:23 -0800 Subject: [PATCH 0597/1215] Fix travis to fail on analysis lints (dart-lang/stream_transform#91) Fix a case of `unnecessary_this` that was missed. --- pkgs/stream_transform/.travis.yml | 2 +- pkgs/stream_transform/lib/src/async_map.dart | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 0bd0f9c9e..d69c3f7c0 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -11,4 +11,4 @@ dart_task: - test - test -p chrome - dartfmt - - dartanalyzer + - dartanalyzer: --fatal-warnings --fatal-infos . diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index 464e49792..f002667a1 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -41,8 +41,7 @@ extension AsyncMap on Stream { var workFinished = StreamController() // Let the first event through. ..add(null); - return this - .buffer(workFinished.stream) + return buffer(workFinished.stream) .transform(_asyncMapThen(convert, workFinished.add)); } From ad2a637c9fdc061bf85e6b3d0284f2ecf6a07b7c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 27 Nov 2019 14:40:52 -0800 Subject: [PATCH 0598/1215] Refactor tracking of multiple stream subscriptions (dart-lang/stream_transform#92) Instead of using a variable with a bigger scope than the `onListen` handler, and assigning to null in between calls to the callback, scope the variable down. Remove the subscriptions when they are no longer needed and use the size of the list as the subscription count rather than tracking in a separate int variable. Refactor a `..addAll` and a `.map` to use a list literal with a for-loop element. Make more local variables final since the details of which are changed is very relevant to behavior in this code. --- .../lib/src/combine_latest.dart | 55 ++++++++++--------- pkgs/stream_transform/lib/src/merge.dart | 46 +++++++--------- 2 files changed, 50 insertions(+), 51 deletions(-) diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index bacc7d61b..7fee05dce 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -192,22 +192,21 @@ class _CombineLatestAll extends StreamTransformerBase> { _CombineLatestAll(this._others); @override - Stream> bind(Stream source) { - final controller = source.isBroadcast + Stream> bind(Stream first) { + final controller = first.isBroadcast ? StreamController>.broadcast(sync: true) : StreamController>(sync: true); - var allStreams = [source]..addAll(_others); - if (source.isBroadcast) { - allStreams = allStreams - .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) - .toList(); - } - - List> subscriptions; + final allStreams = [ + first, + for (final other in _others) + !first.isBroadcast || other.isBroadcast + ? other + : other.asBroadcastStream(), + ]; controller.onListen = () { - assert(subscriptions == null); + final subscriptions = >[]; final latestData = List(allStreams.length); final hasEmitted = {}; @@ -219,35 +218,39 @@ class _CombineLatestAll extends StreamTransformerBase> { } } - var activeStreamCount = 0; - subscriptions = allStreams.map((stream) { - final index = activeStreamCount; - activeStreamCount++; - return stream.listen((data) => handleData(index, data), - onError: controller.addError, onDone: () { - if (--activeStreamCount <= 0 || !hasEmitted.contains(index)) { + var streamId = 0; + for (final stream in allStreams) { + final index = streamId; + + final subscription = stream.listen((data) => handleData(index, data), + onError: controller.addError); + subscription.onDone(() { + assert(subscriptions.contains(subscription)); + subscriptions.remove(subscription); + if (subscriptions.isEmpty || !hasEmitted.contains(index)) { controller.close(); } }); - }).toList(); - if (!source.isBroadcast) { + subscriptions.add(subscription); + + streamId++; + } + if (!first.isBroadcast) { controller ..onPause = () { - for (var subscription in subscriptions) { + for (final subscription in subscriptions) { subscription.pause(); } } ..onResume = () { - for (var subscription in subscriptions) { + for (final subscription in subscriptions) { subscription.resume(); } }; } controller.onCancel = () { - final toCancel = subscriptions; - subscriptions = null; - if (activeStreamCount <= 0) return null; - return Future.wait(toCancel.map((s) => s.cancel())); + if (subscriptions.isEmpty) return null; + return Future.wait(subscriptions.map((s) => s.cancel())); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 5d2c8643f..99d19c92b 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -87,47 +87,45 @@ class _Merge extends StreamTransformerBase { @override Stream bind(Stream first) { - var controller = first.isBroadcast + final controller = first.isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); - var allStreams = [first]..addAll(_others); - if (first.isBroadcast) { - allStreams = allStreams - .map((s) => s.isBroadcast ? s : s.asBroadcastStream()) - .toList(); - } - - List> subscriptions; + final allStreams = [ + first, + for (final other in _others) + !first.isBroadcast || other.isBroadcast + ? other + : other.asBroadcastStream(), + ]; controller.onListen = () { - assert(subscriptions == null); - var activeStreamCount = 0; - subscriptions = allStreams.map((stream) { - activeStreamCount++; - return stream.listen(controller.add, onError: controller.addError, - onDone: () { - if (--activeStreamCount <= 0) controller.close(); + final subscriptions = >[]; + for (final stream in allStreams) { + final subscription = + stream.listen(controller.add, onError: controller.addError); + subscription.onDone(() { + subscriptions.remove(subscription); + if (subscriptions.isEmpty) controller.close(); }); - }).toList(); + subscriptions.add(subscription); + } if (!first.isBroadcast) { controller ..onPause = () { - for (var subscription in subscriptions) { + for (final subscription in subscriptions) { subscription.pause(); } } ..onResume = () { - for (var subscription in subscriptions) { + for (final subscription in subscriptions) { subscription.resume(); } }; } controller.onCancel = () { - var toCancel = subscriptions; - subscriptions = null; - if (activeStreamCount <= 0) return null; - return Future.wait(toCancel.map((s) => s.cancel())); + if (subscriptions.isEmpty) return null; + return Future.wait(subscriptions.map((s) => s.cancel())); }; }; return controller.stream; @@ -150,14 +148,12 @@ class _MergeExpanded extends StreamTransformerBase, T> { final subscription = inner.listen(controller.add, onError: controller.addError); subscription.onDone(() { - assert(subscriptions.contains(subscription)); subscriptions.remove(subscription); if (subscriptions.isEmpty) controller.close(); }); subscriptions.add(subscription); }, onError: controller.addError); outerSubscription.onDone(() { - assert(subscriptions.contains(outerSubscription)); subscriptions.remove(outerSubscription); if (subscriptions.isEmpty) controller.close(); }); From a6e207e0a6cad6070f75d3dc6a3556d9e07fd89c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Dec 2019 15:08:54 -0800 Subject: [PATCH 0599/1215] Prepare to publish (dart-lang/stream_transform#94) --- pkgs/stream_transform/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 2d2f59ae1..9e263e265 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -2,7 +2,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform -version: 1.1.0-dev +version: 1.1.0 environment: sdk: ">=2.6.0 <3.0.0" From 19df27cdbab2289fbbfe896bcf56c2dd9d536f3c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Dec 2019 15:58:56 -0800 Subject: [PATCH 0600/1215] Remove author from pubspec (dart-lang/stream_transform#95) Upon publish I was notified that this is no longer useful and can be removed. --- pkgs/stream_transform/pubspec.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 9e263e265..5ad672b0a 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,6 +1,5 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. -author: Dart Team homepage: https://www.github.com/dart-lang/stream_transform version: 1.1.0 From b501497c3dca5c6bf1456a9b5a99ed10fc37c7ff Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Dec 2019 11:37:08 -0800 Subject: [PATCH 0601/1215] Fix newly enforced package:pedantic lints (dart-lang/stream_transform#96) - always_declare_return_types - use_function_type_syntax_for_parameters --- pkgs/stream_transform/lib/src/aggregate_sample.dart | 10 +++++----- pkgs/stream_transform/lib/src/async_map.dart | 4 ++-- pkgs/stream_transform/lib/src/concatenate.dart | 6 +++--- pkgs/stream_transform/lib/src/rate_limit.dart | 2 +- pkgs/stream_transform/lib/src/scan.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/lib/src/where.dart | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/start_with_test.dart | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index a069af737..5ddeb1017 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -32,13 +32,13 @@ class AggregateSample extends StreamTransformerBase { StreamSubscription valueSub; StreamSubscription triggerSub; - emit() { + void emit() { controller.add(currentResults); currentResults = null; waitingForTrigger = true; } - onValue(S value) { + void onValue(S value) { currentResults = _aggregate(value, currentResults); if (!waitingForTrigger) emit(); @@ -49,7 +49,7 @@ class AggregateSample extends StreamTransformerBase { } } - onValuesDone() { + void onValuesDone() { isValueDone = true; if (currentResults == null) { triggerSub?.cancel(); @@ -57,7 +57,7 @@ class AggregateSample extends StreamTransformerBase { } } - onTrigger(_) { + void onTrigger(_) { waitingForTrigger = false; if (currentResults != null) emit(); @@ -68,7 +68,7 @@ class AggregateSample extends StreamTransformerBase { } } - onTriggerDone() { + void onTriggerDone() { isTriggerDone = true; if (waitingForTrigger) { valueSub?.cancel(); diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index f002667a1..c5b160b3d 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -89,7 +89,7 @@ extension AsyncMap on Stream { /// /// The result stream will not close until the source stream closes and all /// pending conversions have finished. - Stream concurrentAsyncMap(FutureOr convert(T event)) { + Stream concurrentAsyncMap(FutureOr Function(T) convert) { var valuesWaiting = 0; var sourceDone = false; return transform(fromHandlers(handleData: (element, sink) { @@ -116,7 +116,7 @@ T _dropPrevious(T event, _) => event; /// rather than once per listener, and [then] is called after completing the /// work. StreamTransformer _asyncMapThen( - Future convert(S event), void Function(void) then) { + Future Function(S) convert, void Function(void) then) { Future pendingEvent; return fromHandlers(handleData: (event, sink) { pendingEvent = diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index f9ba747d1..05c977fc3 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -75,17 +75,17 @@ class _FollowedBy extends StreamTransformerBase { Function currentDoneHandler; - listen() { + void listen() { subscription = currentStream.listen(controller.add, onError: controller.addError, onDone: () => currentDoneHandler()); } - onSecondDone() { + void onSecondDone() { secondDone = true; controller.close(); } - onFirstDone() { + void onFirstDone() { firstDone = true; currentStream = next; currentDoneHandler = onSecondDone; diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index db6d7df04..15078b737 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -146,7 +146,7 @@ T _dropPrevious(T element, _) => element; /// Creates a StreamTransformer which aggregates values until the source stream /// does not emit for [duration], then emits the aggregated values. StreamTransformer _debounceAggregate( - Duration duration, R collect(T element, R soFar)) { + Duration duration, R Function(T element, R soFar) collect) { Timer timer; R soFar; var shouldClose = false; diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index b31b9e767..4e022f598 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -14,7 +14,7 @@ extension Scan on Stream { /// called for elements in order, and the result stream always maintains the /// same order as the original. Stream scan( - S initialValue, FutureOr combine(S previousValue, T element)) { + S initialValue, FutureOr Function(S soFar, T element) combine) { var accumulated = initialValue; return asyncMap((value) { var result = combine(accumulated, value); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 2e2aebadf..b30556a8a 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -15,7 +15,7 @@ extension Switch on Stream { /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of the streams produced by [convert]. - Stream switchMap(Stream convert(T event)) { + Stream switchMap(Stream Function(T) convert) { return map(convert).switchLatest(); } } diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 70269230f..850e9a9ab 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -34,7 +34,7 @@ extension Where on Stream { /// /// The result stream will not close until the source stream closes and all /// pending [test] calls have finished. - Stream asyncWhere(FutureOr test(T element)) { + Stream asyncWhere(FutureOr Function(T) test) { var valuesWaiting = 0; var sourceDone = false; return transform(fromHandlers(handleData: (element, sink) { diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 5ad672b0a..1c8d88eed 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.1.0 +version: 1.1.1-dev environment: sdk: ">=2.6.0 <3.0.0" diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 3208903c6..3a5a02550 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -18,7 +18,7 @@ void main() { List emittedValues; bool isDone; - setupForStreamType( + void setupForStreamType( String streamType, Stream Function(Stream) transform) { emittedValues = []; isDone = false; From 69ec2c61ec9cf38c57bb41756f9a34d2065c9fcc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Dec 2019 12:45:27 -0800 Subject: [PATCH 0602/1215] Fix newly enforce package:pedantic lints (dart-lang/stream_channel#48) - use_function_type_syntax_for_parameters - prefer_single_quotes --- .../lib/src/close_guarantee_channel.dart | 4 +- pkgs/stream_channel/lib/src/disconnector.dart | 14 ++-- .../lib/src/guarantee_channel.dart | 14 ++-- .../stream_channel/lib/src/multi_channel.dart | 6 +- .../lib/src/stream_channel_completer.dart | 4 +- pkgs/stream_channel/lib/stream_channel.dart | 8 +- .../test/disconnector_test.dart | 26 +++--- .../test/isolate_channel_test.dart | 34 ++++---- .../test/json_document_transformer_test.dart | 16 ++-- .../test/multi_channel_test.dart | 84 +++++++++---------- .../test/stream_channel_completer_test.dart | 46 +++++----- .../test/stream_channel_controller_test.dart | 32 +++---- .../test/stream_channel_test.dart | 38 ++++----- .../test/with_close_guarantee_test.dart | 8 +- .../test/with_guarantees_test.dart | 52 ++++++------ 15 files changed, 193 insertions(+), 193 deletions(-) diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 33296da43..60916d002 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -48,8 +48,8 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); @override - StreamSubscription listen(void onData(T event), - {Function onError, void onDone(), bool cancelOnError}) { + StreamSubscription listen(void Function(T) onData, + {Function onError, void Function() onDone, bool cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything // but a done event. if (_channel._disconnected) { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 69fbab727..e8835374f 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -87,9 +87,9 @@ class _DisconnectorSink implements StreamSink { @override void add(T data) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_isDisconnected) return; @@ -98,9 +98,9 @@ class _DisconnectorSink implements StreamSink { @override void addError(error, [StackTrace stackTrace]) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_isDisconnected) return; @@ -109,9 +109,9 @@ class _DisconnectorSink implements StreamSink { @override Future addStream(Stream stream) { - if (_closed) throw StateError("Cannot add stream after closing."); + if (_closed) throw StateError('Cannot add stream after closing.'); if (_inAddStream) { - throw StateError("Cannot add stream while adding stream."); + throw StateError('Cannot add stream while adding stream.'); } if (_isDisconnected) return Future.value(); @@ -127,7 +127,7 @@ class _DisconnectorSink implements StreamSink { @override Future close() { if (_inAddStream) { - throw StateError("Cannot close sink while adding stream."); + throw StateError('Cannot close sink while adding stream.'); } _closed = true; diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index d8add39e8..cfee99ee5 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -115,9 +115,9 @@ class _GuaranteeSink implements StreamSink { @override void add(T data) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_disconnected) return; @@ -126,9 +126,9 @@ class _GuaranteeSink implements StreamSink { @override void addError(error, [StackTrace stackTrace]) { - if (_closed) throw StateError("Cannot add event after closing."); + if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { - throw StateError("Cannot add event while adding stream."); + throw StateError('Cannot add event while adding stream.'); } if (_disconnected) return; @@ -158,9 +158,9 @@ class _GuaranteeSink implements StreamSink { @override Future addStream(Stream stream) { - if (_closed) throw StateError("Cannot add stream after closing."); + if (_closed) throw StateError('Cannot add stream after closing.'); if (_inAddStream) { - throw StateError("Cannot add stream while adding stream."); + throw StateError('Cannot add stream while adding stream.'); } if (_disconnected) return Future.value(); @@ -176,7 +176,7 @@ class _GuaranteeSink implements StreamSink { @override Future close() { if (_inAddStream) { - throw StateError("Cannot close sink while adding stream."); + throw StateError('Cannot close sink while adding stream.'); } if (_closed) return done; diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index d729eb7bb..e0982ae19 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -104,11 +104,11 @@ class _MultiChannel extends StreamChannelMixin /// Input IDs of controllers in [_controllers] that we've received messages /// for but that have not yet had a local [virtualChannel] created. - final _pendingIds = Set(); + final _pendingIds = {}; /// Input IDs of virtual channels that used to exist but have since been /// closed. - final _closedIds = Set(); + final _closedIds = {}; /// The next id to use for a local virtual channel. /// @@ -201,7 +201,7 @@ class _MultiChannel extends StreamChannelMixin controller = _controllers[inputId]; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { - throw ArgumentError("A virtual channel with id $id already exists."); + throw ArgumentError('A virtual channel with id $id already exists.'); } else { controller = StreamChannelController(sync: true); _controllers[inputId] = controller; diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index e94eda66e..a14ffde44 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -52,7 +52,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setChannel(StreamChannel channel) { - if (_set) throw StateError("The channel has already been set."); + if (_set) throw StateError('The channel has already been set.'); _set = true; _streamCompleter.setSourceStream(channel.stream); @@ -67,7 +67,7 @@ class StreamChannelCompleter { /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. void setError(error, [StackTrace stackTrace]) { - if (_set) throw StateError("The channel has already been set."); + if (_set) throw StateError('The channel has already been set.'); _set = true; _streamCompleter.setError(error, stackTrace); diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index e99de08f0..c806ec663 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -117,11 +117,11 @@ abstract class StreamChannel { /// Returns a copy of this with [stream] replaced by [change]'s return /// value. - StreamChannel changeStream(Stream change(Stream stream)); + StreamChannel changeStream(Stream Function(Stream) change); /// Returns a copy of this with [sink] replaced by [change]'s return /// value. - StreamChannel changeSink(StreamSink change(StreamSink sink)); + StreamChannel changeSink(StreamSink Function(StreamSink) change); /// Returns a copy of this with the generic type coerced to [S]. /// @@ -167,11 +167,11 @@ abstract class StreamChannelMixin implements StreamChannel { changeSink(transformer.bind); @override - StreamChannel changeStream(Stream change(Stream stream)) => + StreamChannel changeStream(Stream Function(Stream) change) => StreamChannel.withCloseGuarantee(change(stream), sink); @override - StreamChannel changeSink(StreamSink change(StreamSink sink)) => + StreamChannel changeSink(StreamSink Function(StreamSink) change) => StreamChannel.withCloseGuarantee(stream, change(sink)); @override diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index a5ea2ebb5..ec0c64bc0 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -23,8 +23,8 @@ void main() { .transform(disconnector); }); - group("before disconnection", () { - test("forwards events from the sink as normal", () { + group('before disconnection', () { + test('forwards events from the sink as normal', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -33,7 +33,7 @@ void main() { expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards events to the stream as normal", () { + test('forwards events to the stream as normal', () { streamController.add(1); streamController.add(2); streamController.add(3); @@ -47,7 +47,7 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -57,7 +57,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -66,7 +66,7 @@ void main() { }); }); - test("cancels addStream when disconnected", () async { + test('cancels addStream when disconnected', () async { var canceled = false; var controller = StreamController(onCancel: () { canceled = true; @@ -78,7 +78,7 @@ void main() { expect(canceled, isTrue); }); - test("disconnect() returns the close future from the inner sink", () async { + test('disconnect() returns the close future from the inner sink', () async { var streamController = StreamController(); var sinkController = StreamController(); var disconnector = Disconnector(); @@ -104,12 +104,12 @@ void main() { expect(disconnectFutureFired, isTrue); }); - group("after disconnection", () { + group('after disconnection', () { setUp(() { disconnector.disconnect(); }); - test("closes the inner sink and ignores events to the outer sink", () { + test('closes the inner sink and ignores events to the outer sink', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -118,21 +118,21 @@ void main() { expect(sinkController.stream.toList(), completion(isEmpty)); }); - test("closes the stream", () { + test('closes the stream', () { expect(channel.stream.toList(), completion(isEmpty)); }); - test("completes done", () { + test('completes done', () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.done, completes); }); - test("still emits state errors after explicit close", () { + test('still emits state errors after explicit close', () { sinkController.stream.listen(null); // Work around sdk#19095. expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); }); }); } diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index fd14b8407..ab70f749b 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -28,7 +28,7 @@ void main() { channel.sink.close(); }); - test("the channel can send messages", () { + test('the channel can send messages', () { channel.sink.add(1); channel.sink.add(2); channel.sink.add(3); @@ -36,7 +36,7 @@ void main() { expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); }); - test("the channel can receive messages", () { + test('the channel can receive messages', () { sendPort.send(1); sendPort.send(2); sendPort.send(3); @@ -47,7 +47,7 @@ void main() { test("events can't be added to an explicitly-closed sink", () { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -57,7 +57,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -65,10 +65,10 @@ void main() { controller.close(); }); - group("stream channel rules", () { + group('stream channel rules', () { test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { sendPort.send(1); sendPort.send(2); sendPort.send(3); @@ -92,10 +92,10 @@ void main() { expect(receivePort.take(3).toList(), completion(equals([1, 2, 3]))); }); - test("the sink closes as soon as an error is added", () async { - channel.sink.addError("oh no"); + test('the sink closes as soon as an error is added', () async { + channel.sink.addError('oh no'); channel.sink.add(1); - expect(channel.sink.done, throwsA("oh no")); + expect(channel.sink.done, throwsA('oh no')); // Since the sink is closed, the stream should also be closed. expect(channel.stream.isEmpty, completion(isTrue)); @@ -106,7 +106,7 @@ void main() { await pumpEventQueue(); }); - test("the sink closes as soon as an error is added via addStream", + test('the sink closes as soon as an error is added via addStream', () async { var canceled = false; var controller = StreamController(onCancel: () { @@ -116,8 +116,8 @@ void main() { // This future shouldn't get the error, because it's sent to [Sink.done]. expect(channel.sink.addStream(controller.stream), completes); - controller.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + controller.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); await pumpEventQueue(); expect(canceled, isTrue); @@ -127,7 +127,7 @@ void main() { }); }); - group("connect constructors", () { + group('connect constructors', () { ReceivePort connectPort; setUp(() { connectPort = ReceivePort(); @@ -137,7 +137,7 @@ void main() { connectPort.close(); }); - test("create a connected pair of channels", () { + test('create a connected pair of channels', () { var channel1 = IsolateChannel.connectReceive(connectPort); var channel2 = IsolateChannel.connectSend(connectPort.sendPort); @@ -152,10 +152,10 @@ void main() { expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); }); - test("the receiving channel produces an error if it gets the wrong message", + test('the receiving channel produces an error if it gets the wrong message', () { var connectedChannel = IsolateChannel.connectReceive(connectPort); - connectPort.sendPort.send("wrong value"); + connectPort.sendPort.send('wrong value'); expect(connectedChannel.stream.toList(), throwsStateError); expect(connectedChannel.sink.done, completes); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index e6c560ade..3ccce4ead 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -19,26 +19,26 @@ void main() { StreamChannel(streamController.stream, sinkController.sink); }); - test("decodes JSON emitted by the channel", () { + test('decodes JSON emitted by the channel', () { var transformed = channel.transform(jsonDocument); streamController.add('{"foo": "bar"}'); - expect(transformed.stream.first, completion(equals({"foo": "bar"}))); + expect(transformed.stream.first, completion(equals({'foo': 'bar'}))); }); - test("encodes objects added to the channel", () { + test('encodes objects added to the channel', () { var transformed = channel.transform(jsonDocument); - transformed.sink.add({"foo": "bar"}); + transformed.sink.add({'foo': 'bar'}); expect(sinkController.stream.first, - completion(equals(jsonEncode({"foo": "bar"})))); + completion(equals(jsonEncode({'foo': 'bar'})))); }); - test("emits a stream error when incoming JSON is malformed", () { + test('emits a stream error when incoming JSON is malformed', () { var transformed = channel.transform(jsonDocument); - streamController.add("{invalid"); + streamController.add('{invalid'); expect(transformed.stream.first, throwsFormatException); }); - test("synchronously throws if an unencodable object is added", () { + test('synchronously throws if an unencodable object is added', () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(Object()), throwsA(TypeMatcher())); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index b1659a03a..0fa1df9ea 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -16,8 +16,8 @@ void main() { channel2 = MultiChannel(controller.foreign); }); - group("the default virtual channel", () { - test("begins connected", () { + group('the default virtual channel', () { + test('begins connected', () { var first = true; channel2.stream.listen(expectAsync1((message) { if (first) { @@ -32,14 +32,14 @@ void main() { channel1.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(channel2.stream.toList(), completion(isEmpty)); expect(channel2.sink.done, completes); channel1.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(channel1.stream.toList(), completion(isEmpty)); expect(channel1.sink.done, completes); @@ -48,7 +48,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { channel1.sink.done.then(expectAsync1((_) {}, count: 0)); channel1.stream.listen((_) {}).cancel(); @@ -59,8 +59,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () { expect(controller.local.sink.done, completes); expect(controller.foreign.sink.done, completes); @@ -69,7 +69,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -84,7 +84,7 @@ void main() { }); }); - group("a locally-created virtual channel", () { + group('a locally-created virtual channel', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -92,7 +92,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("sends messages only to the other virtual channel", () { + test('sends messages only to the other virtual channel', () { var first = true; virtual2.stream.listen(expectAsync1((message) { if (first) { @@ -114,14 +114,14 @@ void main() { virtual1.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); virtual1.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(virtual1.stream.toList(), completion(isEmpty)); expect(virtual1.sink.done, completes); @@ -130,7 +130,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { virtual1.sink.done.then(expectAsync1((_) {}, count: 0)); virtual1.stream.listen((_) {}).cancel(); @@ -140,8 +140,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () async { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () async { // First close the default channel so we can test the new channel as the // last living virtual channel. unawaited(channel1.sink.close()); @@ -155,7 +155,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -184,7 +184,7 @@ void main() { }); }); - group("a remotely-created virtual channel", () { + group('a remotely-created virtual channel', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -192,7 +192,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("sends messages only to the other virtual channel", () { + test('sends messages only to the other virtual channel', () { var first = true; virtual1.stream.listen(expectAsync1((message) { if (first) { @@ -214,14 +214,14 @@ void main() { virtual2.sink.add(2); }); - test("closes the remote virtual channel when it closes", () { + test('closes the remote virtual channel when it closes', () { expect(virtual1.stream.toList(), completion(isEmpty)); expect(virtual1.sink.done, completes); virtual2.sink.close(); }); - test("closes the local virtual channel when it closes", () { + test('closes the local virtual channel when it closes', () { expect(virtual2.stream.toList(), completion(isEmpty)); expect(virtual2.sink.done, completes); @@ -230,7 +230,7 @@ void main() { test( "doesn't closes the local virtual channel when the stream " - "subscription is canceled", () { + 'subscription is canceled', () { virtual2.sink.done.then(expectAsync1((_) {}, count: 0)); virtual2.stream.listen((_) {}).cancel(); @@ -240,8 +240,8 @@ void main() { }); test( - "closes the underlying channel when it closes without any other " - "virtual channels", () async { + 'closes the underlying channel when it closes without any other ' + 'virtual channels', () async { // First close the default channel so we can test the new channel as the // last living virtual channel. unawaited(channel2.sink.close()); @@ -255,7 +255,7 @@ void main() { test( "doesn't close the underlying channel when it closes with other " - "virtual channels", () { + 'virtual channels', () { controller.local.sink.done.then(expectAsync1((_) {}, count: 0)); controller.foreign.sink.done.then(expectAsync1((_) {}, count: 0)); @@ -270,7 +270,7 @@ void main() { expect(() => channel2.virtualChannel(virtual1.id), throwsArgumentError); }); - test("dispatches events received before the virtual channel is created", + test('dispatches events received before the virtual channel is created', () async { virtual1 = channel1.virtualChannel(); @@ -284,8 +284,8 @@ void main() { }); test( - "dispatches close events received before the virtual channel is " - "created", () async { + 'dispatches close events received before the virtual channel is ' + 'created', () async { virtual1 = channel1.virtualChannel(); unawaited(virtual1.sink.close()); @@ -296,7 +296,7 @@ void main() { }); }); - group("when the underlying stream", () { + group('when the underlying stream', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -304,7 +304,7 @@ void main() { virtual2 = channel2.virtualChannel(virtual1.id); }); - test("closes, all virtual channels close", () { + test('closes, all virtual channels close', () { expect(channel1.stream.toList(), completion(isEmpty)); expect(channel1.sink.done, completes); expect(channel2.stream.toList(), completion(isEmpty)); @@ -317,7 +317,7 @@ void main() { controller.local.sink.close(); }); - test("closes, more virtual channels are created closed", () async { + test('closes, more virtual channels are created closed', () async { unawaited(channel2.sink.close()); unawaited(virtual2.sink.close()); @@ -334,21 +334,21 @@ void main() { expect(virtual.sink.done, completes); }); - test("emits an error, the error is sent only to the default channel", () { + test('emits an error, the error is sent only to the default channel', () { channel1.stream.listen(expectAsync1((_) {}, count: 0), - onError: expectAsync1((error) => expect(error, equals("oh no")))); + onError: expectAsync1((error) => expect(error, equals('oh no')))); virtual1.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync1((_) {}, count: 0)); - controller.foreign.sink.addError("oh no"); + controller.foreign.sink.addError('oh no'); }); }); - group("stream channel rules", () { - group("for the main stream:", () { + group('stream channel rules', () { + group('for the main stream:', () { test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); @@ -359,7 +359,7 @@ void main() { }, count: 1)); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(channel1.sink.close()); // Wait for the done event to be delivered. @@ -405,7 +405,7 @@ void main() { }); }); - group("for a virtual channel:", () { + group('for a virtual channel:', () { VirtualChannel virtual1; VirtualChannel virtual2; setUp(() { @@ -414,8 +414,8 @@ void main() { }); test( - "closing the sink causes the stream to close before it emits any more " - "events", () { + 'closing the sink causes the stream to close before it emits any more ' + 'events', () { virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); @@ -426,7 +426,7 @@ void main() { }, count: 1)); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(virtual1.sink.close()); // Wait for the done event to be delivered. diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 070035e7b..234f956ef 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -20,8 +20,8 @@ void main() { innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); - group("when a channel is set before accessing", () { - test("forwards events through the stream", () { + group('when a channel is set before accessing', () { + test('forwards events through the stream', () { completer.setChannel(innerChannel); expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); @@ -31,7 +31,7 @@ void main() { streamController.close(); }); - test("forwards events through the sink", () { + test('forwards events through the sink', () { completer.setChannel(innerChannel); expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); @@ -41,21 +41,21 @@ void main() { completer.channel.sink.close(); }); - test("forwards an error through the stream", () { - completer.setError("oh no"); - expect(completer.channel.stream.first, throwsA("oh no")); + test('forwards an error through the stream', () { + completer.setError('oh no'); + expect(completer.channel.stream.first, throwsA('oh no')); }); - test("drops sink events", () { - completer.setError("oh no"); + test('drops sink events', () { + completer.setError('oh no'); expect(completer.channel.sink.done, completes); completer.channel.sink.add(1); - completer.channel.sink.addError("oh no"); + completer.channel.sink.addError('oh no'); }); }); - group("when a channel is set after accessing", () { - test("forwards events through the stream", () async { + group('when a channel is set after accessing', () { + test('forwards events through the stream', () async { expect(completer.channel.stream.toList(), completion(equals([1, 2, 3]))); await pumpEventQueue(); @@ -66,7 +66,7 @@ void main() { unawaited(streamController.close()); }); - test("forwards events through the sink", () async { + test('forwards events through the sink', () async { completer.channel.sink.add(1); completer.channel.sink.add(2); completer.channel.sink.add(3); @@ -77,25 +77,25 @@ void main() { expect(sinkController.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards an error through the stream", () async { - expect(completer.channel.stream.first, throwsA("oh no")); + test('forwards an error through the stream', () async { + expect(completer.channel.stream.first, throwsA('oh no')); await pumpEventQueue(); - completer.setError("oh no"); + completer.setError('oh no'); }); - test("drops sink events", () async { + test('drops sink events', () async { expect(completer.channel.sink.done, completes); completer.channel.sink.add(1); - completer.channel.sink.addError("oh no"); + completer.channel.sink.addError('oh no'); await pumpEventQueue(); - completer.setError("oh no"); + completer.setError('oh no'); }); }); - group("forFuture", () { - test("forwards a StreamChannel", () { + group('forFuture', () { + test('forwards a StreamChannel', () { var channel = StreamChannelCompleter.fromFuture(Future.value(innerChannel)); channel.sink.add(1); @@ -107,9 +107,9 @@ void main() { expect(channel.stream.toList(), completion(equals([2]))); }); - test("forwards an error", () { - var channel = StreamChannelCompleter.fromFuture(Future.error("oh no")); - expect(channel.stream.toList(), throwsA("oh no")); + test('forwards an error', () { + var channel = StreamChannelCompleter.fromFuture(Future.error('oh no')); + expect(channel.stream.toList(), throwsA('oh no')); }); }); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 62f883fa5..9b7a851d0 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -6,13 +6,13 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - group("asynchronously", () { + group('asynchronously', () { StreamChannelController controller; setUp(() { controller = StreamChannelController(); }); - test("forwards events from the local sink to the foreign stream", () { + test('forwards events from the local sink to the foreign stream', () { controller.local.sink ..add(1) ..add(2) @@ -21,7 +21,7 @@ void main() { expect(controller.foreign.stream.toList(), completion(equals([1, 2, 3]))); }); - test("forwards events from the foreign sink to the local stream", () { + test('forwards events from the foreign sink to the local stream', () { controller.foreign.sink ..add(1) ..add(2) @@ -31,27 +31,27 @@ void main() { }); test( - "with allowForeignErrors: false, shuts down the connection if an " - "error is added to the foreign channel", () { + 'with allowForeignErrors: false, shuts down the connection if an ' + 'error is added to the foreign channel', () { controller = StreamChannelController(allowForeignErrors: false); - controller.foreign.sink.addError("oh no"); - expect(controller.foreign.sink.done, throwsA("oh no")); + controller.foreign.sink.addError('oh no'); + expect(controller.foreign.sink.done, throwsA('oh no')); expect(controller.foreign.stream.toList(), completion(isEmpty)); expect(controller.local.sink.done, completes); expect(controller.local.stream.toList(), completion(isEmpty)); }); }); - group("synchronously", () { + group('synchronously', () { StreamChannelController controller; setUp(() { controller = StreamChannelController(sync: true); }); test( - "synchronously forwards events from the local sink to the foreign " - "stream", () { + 'synchronously forwards events from the local sink to the foreign ' + 'stream', () { var receivedEvent = false; var receivedError = false; var receivedDone = false; @@ -59,7 +59,7 @@ void main() { expect(event, equals(1)); receivedEvent = true; }), onError: expectAsync1((error) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); receivedError = true; }), onDone: expectAsync0(() { receivedDone = true; @@ -68,7 +68,7 @@ void main() { controller.local.sink.add(1); expect(receivedEvent, isTrue); - controller.local.sink.addError("oh no"); + controller.local.sink.addError('oh no'); expect(receivedError, isTrue); controller.local.sink.close(); @@ -76,8 +76,8 @@ void main() { }); test( - "synchronously forwards events from the foreign sink to the local " - "stream", () { + 'synchronously forwards events from the foreign sink to the local ' + 'stream', () { var receivedEvent = false; var receivedError = false; var receivedDone = false; @@ -85,7 +85,7 @@ void main() { expect(event, equals(1)); receivedEvent = true; }), onError: expectAsync1((error) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); receivedError = true; }), onDone: expectAsync0(() { receivedDone = true; @@ -94,7 +94,7 @@ void main() { controller.foreign.sink.add(1); expect(receivedEvent, isTrue); - controller.foreign.sink.addError("oh no"); + controller.foreign.sink.addError('oh no'); expect(receivedError, isTrue); controller.foreign.sink.close(); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 3f4e896b3..9bd5a86f8 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -41,16 +41,16 @@ void main() { expect(sinkController.stream.toList(), completion(equals([4, 5, 6]))); }); - test("transform() transforms the channel", () async { + test('transform() transforms the channel', () async { var transformed = channel .cast>() .transform(StreamChannelTransformer.fromCodec(utf8)); streamController.add([102, 111, 111, 98, 97, 114]); unawaited(streamController.close()); - expect(await transformed.stream.toList(), equals(["foobar"])); + expect(await transformed.stream.toList(), equals(['foobar'])); - transformed.sink.add("fblthp"); + transformed.sink.add('fblthp'); unawaited(transformed.sink.close()); expect( sinkController.stream.toList(), @@ -59,39 +59,39 @@ void main() { ]))); }); - test("transformStream() transforms only the stream", () async { + test('transformStream() transforms only the stream', () async { var transformed = channel.cast().transformStream(const LineSplitter()); - streamController.add("hello world"); - streamController.add(" what\nis"); - streamController.add("\nup"); + streamController.add('hello world'); + streamController.add(' what\nis'); + streamController.add('\nup'); unawaited(streamController.close()); expect(await transformed.stream.toList(), - equals(["hello world what", "is", "up"])); + equals(['hello world what', 'is', 'up'])); - transformed.sink.add("fbl\nthp"); + transformed.sink.add('fbl\nthp'); unawaited(transformed.sink.close()); - expect(sinkController.stream.toList(), completion(equals(["fbl\nthp"]))); + expect(sinkController.stream.toList(), completion(equals(['fbl\nthp']))); }); - test("transformSink() transforms only the sink", () async { + test('transformSink() transforms only the sink', () async { var transformed = channel.cast().transformSink( StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); - streamController.add("fbl\nthp"); + streamController.add('fbl\nthp'); unawaited(streamController.close()); - expect(await transformed.stream.toList(), equals(["fbl\nthp"])); + expect(await transformed.stream.toList(), equals(['fbl\nthp'])); - transformed.sink.add("hello world"); - transformed.sink.add(" what\nis"); - transformed.sink.add("\nup"); + transformed.sink.add('hello world'); + transformed.sink.add(' what\nis'); + transformed.sink.add('\nup'); unawaited(transformed.sink.close()); expect(sinkController.stream.toList(), - completion(equals(["hello world what", "is", "up"]))); + completion(equals(['hello world what', 'is', 'up']))); }); - test("changeStream() changes the stream", () { + test('changeStream() changes the stream', () { var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); @@ -107,7 +107,7 @@ void main() { expect(changed.stream.toList(), completion(equals([10]))); }); - test("changeSink() changes the sink", () { + test('changeSink() changes the sink', () { var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 803dc61f1..24aef0338 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -35,8 +35,8 @@ void main() { }); test( - "closing the event sink causes the stream to close before it emits any " - "more events", () async { + 'closing the event sink causes the stream to close before it emits any ' + 'more events', () async { controller.local.sink.add(1); controller.local.sink.add(2); controller.local.sink.add(3); @@ -53,8 +53,8 @@ void main() { }); test( - "closing the event sink before events are emitted causes the stream to " - "close immediately", () async { + 'closing the event sink before events are emitted causes the stream to ' + 'close immediately', () async { unawaited(channel.sink.close()); channel.stream.listen(expectAsync1((_) {}, count: 0), onError: expectAsync2((_, __) {}, count: 0), diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index c9ff59f1e..fa49689af 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -19,14 +19,14 @@ void main() { streamController.stream, sinkController.sink); }); - group("with a broadcast stream", () { + group('with a broadcast stream', () { setUp(() { streamController = StreamController.broadcast(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); - test("buffers events", () async { + test('buffers events', () async { streamController.add(1); streamController.add(2); streamController.add(3); @@ -36,15 +36,15 @@ void main() { unawaited(streamController.close()); }); - test("only allows a single subscription", () { + test('only allows a single subscription', () { channel.stream.listen(null); expect(() => channel.stream.listen(null), throwsStateError); }); }); test( - "closing the event sink causes the stream to close before it emits any " - "more events", () { + 'closing the event sink causes the stream to close before it emits any ' + 'more events', () { streamController.add(1); streamController.add(2); streamController.add(3); @@ -58,7 +58,7 @@ void main() { completes); }); - test("after the stream closes, the sink ignores events", () async { + test('after the stream closes, the sink ignores events', () async { unawaited(streamController.close()); // Wait for the done event to be delivered. @@ -105,12 +105,12 @@ void main() { await pumpEventQueue(); }); - test("forwards errors to the other endpoint", () { - channel.sink.addError("error"); - expect(sinkController.stream.first, throwsA("error")); + test('forwards errors to the other endpoint', () { + channel.sink.addError('error'); + expect(sinkController.stream.first, throwsA('error')); }); - test("Sink.done completes once the stream is done", () { + test('Sink.done completes once the stream is done', () { channel.stream.listen(null); expect(channel.sink.done, completes); streamController.close(); @@ -121,7 +121,7 @@ void main() { expect(channel.sink.close(), completes); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); }); @@ -131,7 +131,7 @@ void main() { channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); - expect(() => channel.sink.addError("oh no"), throwsStateError); + expect(() => channel.sink.addError('oh no'), throwsStateError); expect(() => channel.sink.addStream(Stream.fromIterable([])), throwsStateError); expect(() => channel.sink.close(), throwsStateError); @@ -139,7 +139,7 @@ void main() { controller.close(); }); - group("with allowSinkErrors: false", () { + group('with allowSinkErrors: false', () { setUp(() { streamController = StreamController(); sinkController = StreamController(); @@ -148,15 +148,15 @@ void main() { allowSinkErrors: false); }); - test("forwards errors to Sink.done but not the stream", () { - channel.sink.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + test('forwards errors to Sink.done but not the stream', () { + channel.sink.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); sinkController.stream .listen(null, onError: expectAsync1((_) {}, count: 0)); }); - test("adding an error causes the stream to emit a done event", () { - expect(channel.sink.done, throwsA("oh no")); + test('adding an error causes the stream to emit a done event', () { + expect(channel.sink.done, throwsA('oh no')); streamController.add(1); streamController.add(2); @@ -165,21 +165,21 @@ void main() { expect( channel.stream .listen(expectAsync1((event) { - if (event == 2) channel.sink.addError("oh no"); + if (event == 2) channel.sink.addError('oh no'); }, count: 2)) .asFuture(), completes); }); - test("adding an error closes the inner sink", () { - channel.sink.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + test('adding an error closes the inner sink', () { + channel.sink.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); expect(sinkController.stream.toList(), completion(isEmpty)); }); test( - "adding an error via via addStream causes the stream to emit a done " - "event", () async { + 'adding an error via via addStream causes the stream to emit a done ' + 'event', () async { var canceled = false; var controller = StreamController(onCancel: () { canceled = true; @@ -188,8 +188,8 @@ void main() { // This future shouldn't get the error, because it's sent to [Sink.done]. expect(channel.sink.addStream(controller.stream), completes); - controller.addError("oh no"); - expect(channel.sink.done, throwsA("oh no")); + controller.addError('oh no'); + expect(channel.sink.done, throwsA('oh no')); await pumpEventQueue(); expect(canceled, isTrue); From 43c11d2b5385becc8773f811084d4fe33c64b503 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 5 Dec 2019 14:32:41 -0800 Subject: [PATCH 0603/1215] Fix latest pedantic lints, remove deprecated author field in pubspec (dart-lang/string_scanner#17) --- pkgs/string_scanner/analysis_options.yaml | 2 - pkgs/string_scanner/example/example.dart | 8 ++-- .../lib/src/eager_span_scanner.dart | 17 ++++++-- pkgs/string_scanner/lib/src/exception.dart | 1 + pkgs/string_scanner/lib/src/line_scanner.dart | 10 +++-- .../lib/src/relative_span_scanner.dart | 17 +++++++- pkgs/string_scanner/lib/src/span_scanner.dart | 13 +++++- .../lib/src/string_scanner.dart | 12 +++--- pkgs/string_scanner/lib/src/utils.dart | 12 +++--- pkgs/string_scanner/pubspec.yaml | 1 - pkgs/string_scanner/test/error_test.dart | 30 ++++++------- .../test/line_scanner_test.dart | 38 ++++++++--------- .../test/span_scanner_test.dart | 42 +++++++++---------- .../test/string_scanner_test.dart | 40 +++++++++--------- 14 files changed, 139 insertions(+), 104 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 6e8826ba9..c9899f2e2 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -5,7 +5,6 @@ analyzer: linter: rules: - always_declare_return_types - #- annotate_overrides - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - avoid_empty_else @@ -68,7 +67,6 @@ linter: - prefer_is_empty - prefer_is_not_empty - prefer_null_aware_operators - #- prefer_single_quotes - prefer_typing_uninitialized_variables - recursive_getters - slash_for_doc_comments diff --git a/pkgs/string_scanner/example/example.dart b/pkgs/string_scanner/example/example.dart index ddd9d3ead..0358967e4 100644 --- a/pkgs/string_scanner/example/example.dart +++ b/pkgs/string_scanner/example/example.dart @@ -16,18 +16,18 @@ num parseNumber(String source) { // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it // succeeded. It will move the scan pointer past the end of the pattern. - var negative = scanner.scan("-"); + var negative = scanner.scan('-'); // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it // fails. Like [Scanner.scan], it will move the scan pointer forward. - scanner.expect(RegExp(r"\d+")); + scanner.expect(RegExp(r'\d+')); // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. var number = num.parse(scanner.lastMatch[0]); - if (scanner.scan(".")) { - scanner.expect(RegExp(r"\d+")); + if (scanner.scan('.')) { + scanner.expect(RegExp(r'\d+')); var decimal = scanner.lastMatch[0]; number += int.parse(decimal) / math.pow(10, decimal.length); } diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index a2df0f880..d34e4f7c3 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -11,26 +11,30 @@ import 'span_scanner.dart'; // sdk#23770 is fully complete, we should move the shared code into a mixin. /// A regular expression matching newlines across platforms. -final _newlineRegExp = RegExp(r"\r\n?|\n"); +final _newlineRegExp = RegExp(r'\r\n?|\n'); /// A [SpanScanner] that tracks the line and column eagerly, like [LineScanner]. class EagerSpanScanner extends SpanScanner { + @override int get line => _line; int _line = 0; + @override int get column => _column; int _column = 0; + @override LineScannerState get state => _EagerSpanScannerState(this, position, line, column); bool get _betweenCRLF => peekChar(-1) == $cr && peekChar() == $lf; + @override set state(LineScannerState state) { if (state is! _EagerSpanScannerState || !identical((state as _EagerSpanScannerState)._scanner, this)) { - throw ArgumentError("The given LineScannerState was not returned by " - "this LineScanner."); + throw ArgumentError('The given LineScannerState was not returned by ' + 'this LineScanner.'); } super.position = state.position; @@ -38,6 +42,7 @@ class EagerSpanScanner extends SpanScanner { _column = state.column; } + @override set position(int newPosition) { var oldPosition = position; super.position = newPosition; @@ -67,12 +72,14 @@ class EagerSpanScanner extends SpanScanner { EagerSpanScanner(String string, {sourceUrl, int position}) : super(string, sourceUrl: sourceUrl, position: position); + @override bool scanChar(int character) { if (!super.scanChar(character)) return false; _adjustLineAndColumn(character); return true; } + @override int readChar() { var character = super.readChar(); _adjustLineAndColumn(character); @@ -89,6 +96,7 @@ class EagerSpanScanner extends SpanScanner { } } + @override bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; @@ -115,8 +123,11 @@ class EagerSpanScanner extends SpanScanner { /// A class representing the state of an [EagerSpanScanner]. class _EagerSpanScannerState implements LineScannerState { final EagerSpanScanner _scanner; + @override final int position; + @override final int line; + @override final int column; _EagerSpanScannerState(this._scanner, this.position, this.line, this.column); diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index bad08f6e2..8c994b5ae 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -8,6 +8,7 @@ import 'string_scanner.dart'; /// An exception thrown by a [StringScanner] that failed to parse a string. class StringScannerException extends SourceSpanFormatException { + @override String get source => super.source as String; /// The URL of the source file being parsed. diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index e16302a06..180d9239b 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -9,7 +9,7 @@ import 'string_scanner.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. /// A regular expression matching newlines across platforms. -final _newlineRegExp = RegExp(r"\r\n?|\n"); +final _newlineRegExp = RegExp(r'\r\n?|\n'); /// A subclass of [StringScanner] that tracks line and column information. class LineScanner extends StringScanner { @@ -37,8 +37,8 @@ class LineScanner extends StringScanner { set state(LineScannerState state) { if (!identical(state._scanner, this)) { - throw ArgumentError("The given LineScannerState was not returned by " - "this LineScanner."); + throw ArgumentError('The given LineScannerState was not returned by ' + 'this LineScanner.'); } super.position = state.position; @@ -46,6 +46,7 @@ class LineScanner extends StringScanner { _column = state.column; } + @override set position(int newPosition) { var oldPosition = position; super.position = newPosition; @@ -75,12 +76,14 @@ class LineScanner extends StringScanner { LineScanner(String string, {sourceUrl, int position}) : super(string, sourceUrl: sourceUrl, position: position); + @override bool scanChar(int character) { if (!super.scanChar(character)) return false; _adjustLineAndColumn(character); return true; } + @override int readChar() { var character = super.readChar(); _adjustLineAndColumn(character); @@ -97,6 +100,7 @@ class LineScanner extends StringScanner { } } + @override bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index 1a992e41b..096bee3ad 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -27,10 +27,12 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { /// This is used to convert between span-relative and file-relative fields. final FileLocation _startLocation; + @override int get line => _sourceFile.getLine(_startLocation.offset + position) - _startLocation.line; + @override int get column { var line = _sourceFile.getLine(_startLocation.offset + position); var column = @@ -40,24 +42,29 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { : column; } + @override LineScannerState get state => _SpanScannerState(this, position); + @override set state(LineScannerState state) { if (state is! _SpanScannerState || !identical((state as _SpanScannerState)._scanner, this)) { - throw ArgumentError("The given LineScannerState was not returned by " - "this LineScanner."); + throw ArgumentError('The given LineScannerState was not returned by ' + 'this LineScanner.'); } position = state.position; } + @override FileSpan get lastSpan => _lastSpan; FileSpan _lastSpan; + @override FileLocation get location => _sourceFile.location(_startLocation.offset + position); + @override FileSpan get emptySpan => location.pointSpan(); RelativeSpanScanner(FileSpan span) @@ -65,12 +72,14 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { _startLocation = span.start, super(span.text, sourceUrl: span.sourceUrl); + @override FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { var endPosition = endState == null ? position : endState.position; return _sourceFile.span(_startLocation.offset + startState.position, _startLocation.offset + endPosition); } + @override bool matches(Pattern pattern) { if (!super.matches(pattern)) { _lastSpan = null; @@ -82,6 +91,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { return true; } + @override void error(String message, {Match match, int position, int length}) { validateErrorArgs(string, match, position, length); @@ -100,8 +110,11 @@ class _SpanScannerState implements LineScannerState { /// The [SpanScanner] that created this. final RelativeSpanScanner _scanner; + @override final int position; + @override int get line => _scanner._sourceFile.getLine(position); + @override int get column => _scanner._sourceFile.getColumn(position); _SpanScannerState(this._scanner, this.position); diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index d33221626..732a76f18 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -19,16 +19,20 @@ class SpanScanner extends StringScanner implements LineScanner { /// This caches line break information and is used to generate [FileSpan]s. final SourceFile _sourceFile; + @override int get line => _sourceFile.getLine(position); + @override int get column => _sourceFile.getColumn(position); + @override LineScannerState get state => _SpanScannerState(this, position); + @override set state(LineScannerState state) { if (state is! _SpanScannerState || !identical((state as _SpanScannerState)._scanner, this)) { - throw ArgumentError("The given LineScannerState was not returned by " - "this LineScanner."); + throw ArgumentError('The given LineScannerState was not returned by ' + 'this LineScanner.'); } position = state.position; @@ -89,6 +93,7 @@ class SpanScanner extends StringScanner implements LineScanner { return _sourceFile.span(startState.position, endPosition); } + @override bool matches(Pattern pattern) { if (!super.matches(pattern)) { _lastSpan = null; @@ -99,6 +104,7 @@ class SpanScanner extends StringScanner implements LineScanner { return true; } + @override void error(String message, {Match match, int position, int length}) { validateErrorArgs(string, match, position, length); @@ -116,8 +122,11 @@ class _SpanScannerState implements LineScannerState { /// The [SpanScanner] that created this. final SpanScanner _scanner; + @override final int position; + @override int get line => _scanner._sourceFile.getLine(position); + @override int get column => _scanner._sourceFile.getColumn(position); _SpanScannerState(this._scanner, this.position); diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 4a1d10c0c..1739a7cd4 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -24,7 +24,7 @@ class StringScanner { int get position => _position; set position(int position) { if (position < 0 || position > string.length) { - throw ArgumentError("Invalid position $position"); + throw ArgumentError('Invalid position $position'); } _position = position; @@ -68,7 +68,7 @@ class StringScanner { /// This throws a [FormatException] if the string has been fully consumed. It /// doesn't affect [lastMatch]. int readChar() { - if (isDone) _fail("more input"); + if (isDone) _fail('more input'); return string.codeUnitAt(_position++); } @@ -144,10 +144,10 @@ class StringScanner { if (name == null) { if (pattern is RegExp) { var source = pattern.pattern; - name = "/$source/"; + name = '/$source/'; } else { name = - pattern.toString().replaceAll("\\", "\\\\").replaceAll('"', '\\"'); + pattern.toString().replaceAll('\\', '\\\\').replaceAll('"', '\\"'); name = '"$name"'; } } @@ -158,7 +158,7 @@ class StringScanner { /// [FormatException]. void expectDone() { if (isDone) return; - _fail("no more input"); + _fail('no more input'); } /// Returns whether or not [pattern] matches at the current position of the @@ -210,6 +210,6 @@ class StringScanner { /// Throws a [FormatException] describing that [name] is expected at the /// current position in the string. void _fail(String name) { - error("expected $name.", position: position, length: 0); + error('expected $name.', position: position, length: 0); } } diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index df29ba21b..7fe3d5241 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -12,19 +12,19 @@ void validateErrorArgs(String string, Match match, int position, int length) { if (position != null) { if (position < 0) { - throw RangeError("position must be greater than or equal to 0."); + throw RangeError('position must be greater than or equal to 0.'); } else if (position > string.length) { - throw RangeError("position must be less than or equal to the " - "string length."); + throw RangeError('position must be less than or equal to the ' + 'string length.'); } } if (length != null && length < 0) { - throw RangeError("length must be greater than or equal to 0."); + throw RangeError('length must be greater than or equal to 0.'); } if (position != null && length != null && position + length > string.length) { - throw RangeError("position plus length must not go beyond the end of " - "the string."); + throw RangeError('position plus length must not go beyond the end of ' + 'the string.'); } } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 6cba21e76..d5cefceda 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -2,7 +2,6 @@ name: string_scanner version: 1.0.5 description: A class for parsing strings using a sequence of patterns. -author: Dart Team homepage: https://github.com/dart-lang/string_scanner environment: diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index b966b1bca..dfa71755c 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -15,7 +15,7 @@ void main() { expect(() => scanner.error('oh no!'), throwsStringScannerException('bar')); }); - group("with match", () { + group('with match', () { test('supports an earlier match', () { var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); @@ -56,7 +56,7 @@ void main() { }); }); - group("with position and/or length", () { + group('with position and/or length', () { test('defaults to length 0', () { var scanner = StringScanner('foo bar baz'); scanner.expect('foo '); @@ -105,39 +105,39 @@ void main() { }); }); - group("argument errors", () { + group('argument errors', () { StringScanner scanner; setUp(() { scanner = StringScanner('foo bar baz'); scanner.scan('foo'); }); - test("if match is passed with position", () { + test('if match is passed with position', () { expect( - () => scanner.error("oh no!", match: scanner.lastMatch, position: 1), + () => scanner.error('oh no!', match: scanner.lastMatch, position: 1), throwsArgumentError); }); - test("if match is passed with length", () { - expect(() => scanner.error("oh no!", match: scanner.lastMatch, length: 1), + test('if match is passed with length', () { + expect(() => scanner.error('oh no!', match: scanner.lastMatch, length: 1), throwsArgumentError); }); - test("if position is negative", () { - expect(() => scanner.error("oh no!", position: -1), throwsArgumentError); + test('if position is negative', () { + expect(() => scanner.error('oh no!', position: -1), throwsArgumentError); }); - test("if position is outside the string", () { - expect(() => scanner.error("oh no!", position: 100), throwsArgumentError); + test('if position is outside the string', () { + expect(() => scanner.error('oh no!', position: 100), throwsArgumentError); }); - test("if position + length is outside the string", () { - expect(() => scanner.error("oh no!", position: 7, length: 7), + test('if position + length is outside the string', () { + expect(() => scanner.error('oh no!', position: 7, length: 7), throwsArgumentError); }); - test("if length is negative", () { - expect(() => scanner.error("oh no!", length: -1), throwsArgumentError); + test('if length is negative', () { + expect(() => scanner.error('oh no!', length: -1), throwsArgumentError); }); }); } diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 876714271..dc9b8cfd1 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -17,20 +17,20 @@ void main() { expect(scanner.column, equals(0)); }); - group("scan()", () { - test("consuming no newlines increases the column but not the line", () { + group('scan()', () { + test('consuming no newlines increases the column but not the line', () { scanner.scan('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); }); - test("consuming a newline resets the column and increases the line", () { + test('consuming a newline resets the column and increases the line', () { scanner.expect('foo\nba'); expect(scanner.line, equals(1)); expect(scanner.column, equals(2)); }); - test("consuming multiple newlines resets the column and increases the line", + test('consuming multiple newlines resets the column and increases the line', () { scanner.expect('foo\nbar\r\nb'); expect(scanner.line, equals(2)); @@ -48,15 +48,15 @@ void main() { }); }); - group("readChar()", () { - test("on a non-newline character increases the column but not the line", + group('readChar()', () { + test('on a non-newline character increases the column but not the line', () { scanner.readChar(); expect(scanner.line, equals(0)); expect(scanner.column, equals(1)); }); - test("consuming a newline resets the column and increases the line", () { + test('consuming a newline resets the column and increases the line', () { scanner.expect('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); @@ -81,15 +81,15 @@ void main() { }); }); - group("scanChar()", () { - test("on a non-newline character increases the column but not the line", + group('scanChar()', () { + test('on a non-newline character increases the column but not the line', () { scanner.scanChar($f); expect(scanner.line, equals(0)); expect(scanner.column, equals(1)); }); - test("consuming a newline resets the column and increases the line", () { + test('consuming a newline resets the column and increases the line', () { scanner.expect('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); @@ -114,28 +114,28 @@ void main() { }); }); - group("position=", () { - test("forward through newlines sets the line and column", () { + group('position=', () { + test('forward through newlines sets the line and column', () { scanner.position = 10; // "foo\nbar\r\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); - test("forward through no newlines sets the column", () { + test('forward through no newlines sets the column', () { scanner.position = 2; // "fo" expect(scanner.line, equals(0)); expect(scanner.column, equals(2)); }); - test("backward through newlines sets the line and column", () { - scanner.scan("foo\nbar\r\nbaz"); + test('backward through newlines sets the line and column', () { + scanner.scan('foo\nbar\r\nbaz'); scanner.position = 2; // "fo" expect(scanner.line, equals(0)); expect(scanner.column, equals(2)); }); - test("backward through no newlines sets the column", () { - scanner.scan("foo\nbar\r\nbaz"); + test('backward through no newlines sets the column', () { + scanner.scan('foo\nbar\r\nbaz'); scanner.position = 10; // "foo\nbar\r\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); @@ -148,7 +148,7 @@ void main() { }); }); - test("state= restores the line, column, and position", () { + test('state= restores the line, column, and position', () { scanner.scan('foo\nb'); var state = scanner.state; @@ -159,7 +159,7 @@ void main() { expect(scanner.column, equals(1)); }); - test("state= rejects a foreign state", () { + test('state= rejects a foreign state', () { scanner.scan('foo\nb'); expect(() => LineScanner(scanner.string).state = scanner.state, diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 65694eaac..e2570aeff 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -9,15 +9,15 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - testForImplementation("lazy", ([String string]) { + testForImplementation('lazy', ([String string]) { return SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); - testForImplementation("eager", ([String string]) { + testForImplementation('eager', ([String string]) { return SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); }); - group("within", () { + group('within', () { var text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; var startOffset = text.indexOf('foo'); @@ -28,24 +28,24 @@ void main() { SpanScanner.within(file.span(startOffset, text.indexOf(' :after'))); }); - test("string only includes the span text", () { - expect(scanner.string, equals("foo\nbar\nbaz")); + test('string only includes the span text', () { + expect(scanner.string, equals('foo\nbar\nbaz')); }); - test("line and column are span-relative", () { + test('line and column are span-relative', () { expect(scanner.line, equals(0)); expect(scanner.column, equals(0)); - scanner.scan("foo"); + scanner.scan('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); - scanner.scan("\n"); + scanner.scan('\n'); expect(scanner.line, equals(1)); expect(scanner.column, equals(0)); }); - test("tracks the span for the last match", () { + test('tracks the span for the last match', () { scanner.scan('fo'); scanner.scan('o\nba'); @@ -63,7 +63,7 @@ void main() { expect(span.text, equals('o\nba')); }); - test(".spanFrom() returns a span from a previous state", () { + test('.spanFrom() returns a span from a previous state', () { scanner.scan('fo'); var state = scanner.state; scanner.scan('o\nba'); @@ -73,7 +73,7 @@ void main() { expect(span.text, equals('o\nbar\nba')); }); - test(".emptySpan returns an empty span at the current location", () { + test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); var span = scanner.emptySpan; @@ -90,14 +90,14 @@ void main() { expect(span.text, equals('')); }); - test(".error() uses an absolute span", () { - scanner.expect("foo"); + test('.error() uses an absolute span', () { + scanner.expect('foo'); expect( - () => scanner.error('oh no!'), throwsStringScannerException("foo")); + () => scanner.error('oh no!'), throwsStringScannerException('foo')); }); - test(".isDone returns true at the end of the span", () { - scanner.expect("foo\nbar\nbaz"); + test('.isDone returns true at the end of the span', () { + scanner.expect('foo\nbar\nbaz'); expect(scanner.isDone, isTrue); }); }); @@ -105,11 +105,11 @@ void main() { void testForImplementation( String name, SpanScanner Function([String string]) create) { - group("for a $name scanner", () { + group('for a $name scanner', () { SpanScanner scanner; setUp(() => scanner = create()); - test("tracks the span for the last match", () { + test('tracks the span for the last match', () { scanner.scan('fo'); scanner.scan('o\nba'); @@ -127,7 +127,7 @@ void testForImplementation( expect(span.text, equals('o\nba')); }); - test(".spanFrom() returns a span from a previous state", () { + test('.spanFrom() returns a span from a previous state', () { scanner.scan('fo'); var state = scanner.state; scanner.scan('o\nba'); @@ -137,7 +137,7 @@ void testForImplementation( expect(span.text, equals('o\nbar\nba')); }); - test(".spanFrom() handles surrogate pairs correctly", () { + test('.spanFrom() handles surrogate pairs correctly', () { scanner = create('fo\u{12345}o'); scanner.scan('fo'); var state = scanner.state; @@ -146,7 +146,7 @@ void testForImplementation( expect(span.text, equals('\u{12345}o')); }); - test(".emptySpan returns an empty span at the current location", () { + test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); var span = scanner.emptySpan; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 9d6d6b860..e1e5b4eb8 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -72,7 +72,7 @@ void main() { expect(scanner.position, equals(0)); }); - test("substring returns the empty string", () { + test('substring returns the empty string', () { expect(scanner.substring(0), isEmpty); }); @@ -130,38 +130,38 @@ void main() { expect(scanner.position, equals(0)); }); - test("a matching scanChar returns true moves forward", () { + test('a matching scanChar returns true moves forward', () { expect(scanner.scanChar($f), isTrue); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(1)); }); - test("a non-matching scanChar returns false and does nothing", () { + test('a non-matching scanChar returns false and does nothing', () { expect(scanner.scanChar($x), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); - test("a matching expectChar moves forward", () { + test('a matching expectChar moves forward', () { scanner.expectChar($f); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(1)); }); - test("a non-matching expectChar fails", () { + test('a non-matching expectChar fails', () { expect(() => scanner.expectChar($x), throwsFormatException); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); - test("a matching scan returns true and changes the state", () { + test('a matching scan returns true and changes the state', () { expect(scanner.scan(RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); }); - test("a non-matching scan returns false and sets lastMatch to null", () { + test('a non-matching scan returns false and sets lastMatch to null', () { expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch, isNotNull); @@ -171,7 +171,7 @@ void main() { expect(scanner.rest, equals('foo bar')); }); - test("a matching expect changes the state", () { + test('a matching expect changes the state', () { scanner.expect(RegExp('f(..)')); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(3)); @@ -179,8 +179,8 @@ void main() { }); test( - "a non-matching expect throws a FormatException and sets lastMatch to " - "null", () { + 'a non-matching expect throws a FormatException and sets lastMatch to ' + 'null', () { expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch, isNotNull); @@ -190,7 +190,7 @@ void main() { expect(scanner.rest, equals('foo bar')); }); - test("a matching matches returns true and only changes lastMatch", () { + test('a matching matches returns true and only changes lastMatch', () { expect(scanner.matches(RegExp('f(..)')), isTrue); expect(scanner.lastMatch[1], equals('oo')); expect(scanner.position, equals(0)); @@ -205,15 +205,15 @@ void main() { expect(scanner.rest, equals('foo bar')); }); - test("substring from the beginning returns the empty string", () { + test('substring from the beginning returns the empty string', () { expect(scanner.substring(0), isEmpty); }); - test("substring with a custom end returns the substring", () { + test('substring with a custom end returns the substring', () { expect(scanner.substring(0, 3), equals('foo')); }); - test("substring with the string length returns the whole string", () { + test('substring with the string length returns the whole string', () { expect(scanner.substring(0, 7), equals('foo bar')); }); @@ -332,33 +332,33 @@ void main() { expect(scanner.position, equals(7)); }); - test("scan returns false and sets lastMatch to null", () { + test('scan returns false and sets lastMatch to null', () { expect(scanner.scan(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); - test("expect throws a FormatException and sets lastMatch to null", () { + test('expect throws a FormatException and sets lastMatch to null', () { expect(() => scanner.expect(RegExp('.')), throwsFormatException); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); - test("matches returns false sets lastMatch to null", () { + test('matches returns false sets lastMatch to null', () { expect(scanner.matches(RegExp('.')), isFalse); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(7)); }); - test("substring from the beginning returns the whole string", () { + test('substring from the beginning returns the whole string', () { expect(scanner.substring(0), equals('foo bar')); }); - test("substring with a custom start returns a substring from there", () { + test('substring with a custom start returns a substring from there', () { expect(scanner.substring(4), equals('bar')); }); - test("substring with a custom start and end returns that substring", () { + test('substring with a custom start and end returns that substring', () { expect(scanner.substring(3, 5), equals(' b')); }); From 680cc493698b17bb96410766b1085b658b0bb5b6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Dec 2019 13:27:17 -0800 Subject: [PATCH 0604/1215] Fix newly enforced package:pedantic lints (dart-lang/watcher#78) - always_declare_return_types - annotate_overrides - prefer_collection_literals - prefer_conditional_assignment - prefer_final_fields - prefer_if_null_operators - prefer_single_quotes - use_function_type_syntax_for_parameters Bump min SDK to 2.2.0 to allow Set literals. --- pkgs/watcher/.travis.yml | 2 +- pkgs/watcher/benchmark/path_set.dart | 46 +-- pkgs/watcher/example/watch.dart | 4 +- .../src/constructable_file_system_event.dart | 13 + pkgs/watcher/lib/src/directory_watcher.dart | 2 +- .../lib/src/directory_watcher/linux.dart | 21 +- .../lib/src/directory_watcher/mac_os.dart | 21 +- .../lib/src/directory_watcher/polling.dart | 17 +- .../lib/src/directory_watcher/windows.dart | 21 +- pkgs/watcher/lib/src/file_watcher/native.dart | 7 +- .../watcher/lib/src/file_watcher/polling.dart | 7 +- pkgs/watcher/lib/src/path_set.dart | 12 +- pkgs/watcher/lib/src/resubscribable.dart | 4 + pkgs/watcher/lib/src/utils.dart | 5 +- pkgs/watcher/lib/src/watch_event.dart | 10 +- pkgs/watcher/pubspec.yaml | 4 +- .../test/directory_watcher/linux_test.dart | 14 +- .../test/directory_watcher/mac_os_test.dart | 30 +- .../test/directory_watcher/polling_test.dart | 10 +- .../test/directory_watcher/shared.dart | 288 +++++++++--------- .../test/directory_watcher/windows_test.dart | 4 +- .../test/file_watcher/native_test.dart | 2 +- .../test/file_watcher/polling_test.dart | 2 +- pkgs/watcher/test/file_watcher/shared.dart | 70 ++--- .../test/no_subscription/mac_os_test.dart | 2 +- pkgs/watcher/test/no_subscription/shared.dart | 10 +- pkgs/watcher/test/path_set_test.dart | 230 +++++++------- pkgs/watcher/test/utils.dart | 25 +- 28 files changed, 475 insertions(+), 408 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index c15590ba4..9871d25bb 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev -- 2.0.0 +- 2.2.0 dart_task: - test diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index 1ec333626..858df3cc0 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -13,11 +13,11 @@ import 'package:path/path.dart' as p; import 'package:watcher/src/path_set.dart'; -final String root = Platform.isWindows ? r"C:\root" : "/root"; +final String root = Platform.isWindows ? r'C:\root' : '/root'; /// Base class for benchmarks on [PathSet]. abstract class PathSetBenchmark extends BenchmarkBase { - PathSetBenchmark(String method) : super("PathSet.$method"); + PathSetBenchmark(String method) : super('PathSet.$method'); final PathSet pathSet = PathSet(root); @@ -30,14 +30,14 @@ abstract class PathSetBenchmark extends BenchmarkBase { /// /// Each virtual directory contains ten entries: either subdirectories or /// files. - void walkTree(int depth, callback(String path)) { - recurse(String path, remainingDepth) { + void walkTree(int depth, void Function(String) callback) { + void recurse(String path, remainingDepth) { for (var i = 0; i < 10; i++) { var padded = i.toString().padLeft(2, '0'); if (remainingDepth == 0) { - callback(p.join(path, "file_$padded.txt")); + callback(p.join(path, 'file_$padded.txt')); } else { - var subdir = p.join(path, "subdirectory_$padded"); + var subdir = p.join(path, 'subdirectory_$padded'); recurse(subdir, remainingDepth - 1); } } @@ -48,16 +48,18 @@ abstract class PathSetBenchmark extends BenchmarkBase { } class AddBenchmark extends PathSetBenchmark { - AddBenchmark() : super("add()"); + AddBenchmark() : super('add()'); final List paths = []; + @override void setup() { // Make a bunch of paths in about the same order we expect to get them from // Directory.list(). walkTree(3, paths.add); } + @override void run() { for (var path in paths) { pathSet.add(path); @@ -66,10 +68,11 @@ class AddBenchmark extends PathSetBenchmark { } class ContainsBenchmark extends PathSetBenchmark { - ContainsBenchmark() : super("contains()"); + ContainsBenchmark() : super('contains()'); final List paths = []; + @override void setup() { // Add a bunch of paths to the set. walkTree(3, (path) { @@ -80,48 +83,52 @@ class ContainsBenchmark extends PathSetBenchmark { // Add some non-existent paths to test the false case. for (var i = 0; i < 100; i++) { paths.addAll([ - "/nope", - "/root/nope", - "/root/subdirectory_04/nope", - "/root/subdirectory_04/subdirectory_04/nope", - "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope", - "/root/subdirectory_04/subdirectory_04/subdirectory_04/nope/file_04.txt", + '/nope', + '/root/nope', + '/root/subdirectory_04/nope', + '/root/subdirectory_04/subdirectory_04/nope', + '/root/subdirectory_04/subdirectory_04/subdirectory_04/nope', + '/root/subdirectory_04/subdirectory_04/subdirectory_04/nope/file_04.txt', ]); } } + @override void run() { var contained = 0; for (var path in paths) { if (pathSet.contains(path)) contained++; } - if (contained != 10000) throw "Wrong result: $contained"; + if (contained != 10000) throw 'Wrong result: $contained'; } } class PathsBenchmark extends PathSetBenchmark { - PathsBenchmark() : super("toSet()"); + PathsBenchmark() : super('toSet()'); + @override void setup() { walkTree(3, pathSet.add); } + @override void run() { var count = 0; for (var _ in pathSet.paths) { count++; } - if (count != 10000) throw "Wrong result: $count"; + if (count != 10000) throw 'Wrong result: $count'; } } class RemoveBenchmark extends PathSetBenchmark { - RemoveBenchmark() : super("remove()"); + RemoveBenchmark() : super('remove()'); final List paths = []; + @override void setup() { // Make a bunch of paths. Do this here so that we don't spend benchmarked // time synthesizing paths. @@ -136,6 +143,7 @@ class RemoveBenchmark extends PathSetBenchmark { paths.shuffle(random); } + @override void run() { for (var path in paths) { pathSet.remove(path); @@ -143,7 +151,7 @@ class RemoveBenchmark extends PathSetBenchmark { } } -main() { +void main() { AddBenchmark().report(); ContainsBenchmark().report(); PathsBenchmark().report(); diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index 1477e4282..650a4b877 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -8,9 +8,9 @@ library watch; import 'package:path/path.dart' as p; import 'package:watcher/watcher.dart'; -main(List arguments) { +void main(List arguments) { if (arguments.length != 1) { - print("Usage: watch "); + print('Usage: watch '); return; } diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart index 29b7c8ded..0011a8d64 100644 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ b/pkgs/watcher/lib/src/constructable_file_system_event.dart @@ -5,8 +5,11 @@ import 'dart:io'; abstract class _ConstructableFileSystemEvent implements FileSystemEvent { + @override final bool isDirectory; + @override final String path; + @override int get type; _ConstructableFileSystemEvent(this.path, this.isDirectory); @@ -14,45 +17,55 @@ abstract class _ConstructableFileSystemEvent implements FileSystemEvent { class ConstructableFileSystemCreateEvent extends _ConstructableFileSystemEvent implements FileSystemCreateEvent { + @override final type = FileSystemEvent.create; ConstructableFileSystemCreateEvent(String path, bool isDirectory) : super(path, isDirectory); + @override String toString() => "FileSystemCreateEvent('$path')"; } class ConstructableFileSystemDeleteEvent extends _ConstructableFileSystemEvent implements FileSystemDeleteEvent { + @override final type = FileSystemEvent.delete; ConstructableFileSystemDeleteEvent(String path, bool isDirectory) : super(path, isDirectory); + @override String toString() => "FileSystemDeleteEvent('$path')"; } class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent implements FileSystemModifyEvent { + @override final bool contentChanged; + @override final type = FileSystemEvent.modify; ConstructableFileSystemModifyEvent( String path, bool isDirectory, this.contentChanged) : super(path, isDirectory); + @override String toString() => "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; } class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent implements FileSystemMoveEvent { + @override final String destination; + @override final type = FileSystemEvent.move; ConstructableFileSystemMoveEvent( String path, bool isDirectory, this.destination) : super(path, isDirectory); + @override String toString() => "FileSystemMoveEvent('$path', '$destination')"; } diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 8c52ed97a..e0ef3fcc0 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -14,7 +14,7 @@ import 'directory_watcher/polling.dart'; /// in the directory has changed. abstract class DirectoryWatcher implements Watcher { /// The directory whose contents are being monitored. - @Deprecated("Expires in 1.0.0. Use DirectoryWatcher.path instead.") + @Deprecated('Expires in 1.0.0. Use DirectoryWatcher.path instead.') String get directory; /// Creates a new [DirectoryWatcher] monitoring [directory]. diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index f3866c6c6..0a66a1291 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -25,6 +25,7 @@ import '../watch_event.dart'; /// (issue 14424). class LinuxDirectoryWatcher extends ResubscribableWatcher implements DirectoryWatcher { + @override String get directory => path; LinuxDirectoryWatcher(String directory) @@ -33,20 +34,25 @@ class LinuxDirectoryWatcher extends ResubscribableWatcher class _LinuxDirectoryWatcher implements DirectoryWatcher, ManuallyClosedWatcher { + @override String get directory => _files.root; + @override String get path => _files.root; + @override Stream get events => _eventsController.stream; final _eventsController = StreamController.broadcast(); + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); /// A stream group for the [Directory.watch] events of [path] and all its /// subdirectories. - var _nativeEvents = StreamGroup(); + final _nativeEvents = StreamGroup(); /// All known files recursively within [path]. final PathSet _files; @@ -60,7 +66,7 @@ class _LinuxDirectoryWatcher /// /// These are gathered together so that they may all be canceled when the /// watcher is closed. - final _subscriptions = Set(); + final _subscriptions = {}; _LinuxDirectoryWatcher(String path) : _files = PathSet(path) { _nativeEvents.add(Directory(path) @@ -93,6 +99,7 @@ class _LinuxDirectoryWatcher }, cancelOnError: true); } + @override void close() { for (var subscription in _subscriptions) { subscription.cancel(); @@ -128,9 +135,9 @@ class _LinuxDirectoryWatcher /// The callback that's run when a batch of changes comes in. void _onBatch(List batch) { - var files = Set(); - var dirs = Set(); - var changed = Set(); + var files = {}; + var dirs = {}; + var changed = {}; // inotify event batches are ordered by occurrence, so we treat them as a // log of what happened to a file. We only emit events based on the @@ -250,8 +257,8 @@ class _LinuxDirectoryWatcher /// Like [Stream.listen], but automatically adds the subscription to /// [_subscriptions] so that it can be canceled when [close] is called. - void _listen(Stream stream, void onData(T event), - {Function onError, void onDone(), bool cancelOnError}) { + void _listen(Stream stream, void Function(T) onData, + {Function onError, void Function() onDone, bool cancelOnError}) { StreamSubscription subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index f593fbd51..73703cb4d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -24,6 +24,7 @@ import '../watch_event.dart'; /// [Directory.watch]. class MacOSDirectoryWatcher extends ResubscribableWatcher implements DirectoryWatcher { + @override String get directory => path; MacOSDirectoryWatcher(String directory) @@ -32,14 +33,19 @@ class MacOSDirectoryWatcher extends ResubscribableWatcher class _MacOSDirectoryWatcher implements DirectoryWatcher, ManuallyClosedWatcher { + @override String get directory => path; + @override final String path; + @override Stream get events => _eventsController.stream; final _eventsController = StreamController.broadcast(); + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); @@ -64,7 +70,7 @@ class _MacOSDirectoryWatcher /// The subscriptions to [Directory.list] calls for listing the contents of a /// subdirectory that was moved into the watched directory. - final _listSubscriptions = Set>(); + final _listSubscriptions = >{}; /// The timer for tracking how long we wait for an initial batch of bogus /// events (see issue 14373). @@ -85,6 +91,7 @@ class _MacOSDirectoryWatcher .then((_) => _readyCompleter.complete()); } + @override void close() { if (_watchSubscription != null) _watchSubscription.cancel(); if (_initialListSubscription != null) _initialListSubscription.cancel(); @@ -181,19 +188,19 @@ class _MacOSDirectoryWatcher // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return Set(); + if (!event.isDirectory) return {}; if (event is FileSystemMoveEvent) { - return Set.from([event.path, event.destination]); + return {event.path, event.destination}; } - return Set.from([event.path]); + return {event.path}; })); - isInModifiedDirectory(String path) => + bool isInModifiedDirectory(String path) => directories.any((dir) => path != dir && path.startsWith(dir)); - addEvent(String path, FileSystemEvent event) { + void addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - eventsForPaths.putIfAbsent(path, () => Set()).add(event); + eventsForPaths.putIfAbsent(path, () => {}).add(event); } for (var event in batch) { diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index f21a239e9..388f28add 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -15,6 +15,7 @@ import '../watch_event.dart'; /// Periodically polls a directory for changes. class PollingDirectoryWatcher extends ResubscribableWatcher implements DirectoryWatcher { + @override String get directory => path; /// Creates a new polling watcher monitoring [directory]. @@ -25,21 +26,26 @@ class PollingDirectoryWatcher extends ResubscribableWatcher /// and higher CPU usage. Defaults to one second. PollingDirectoryWatcher(String directory, {Duration pollingDelay}) : super(directory, () { - return _PollingDirectoryWatcher(directory, - pollingDelay != null ? pollingDelay : Duration(seconds: 1)); + return _PollingDirectoryWatcher( + directory, pollingDelay ?? Duration(seconds: 1)); }); } class _PollingDirectoryWatcher implements DirectoryWatcher, ManuallyClosedWatcher { + @override String get directory => path; + @override final String path; + @override Stream get events => _events.stream; final _events = StreamController.broadcast(); + @override bool get isReady => _ready.isCompleted; + @override Future get ready => _ready.future; final _ready = Completer(); @@ -50,7 +56,7 @@ class _PollingDirectoryWatcher /// The previous modification times of the files in the directory. /// /// Used to tell which files have been modified. - final _lastModifieds = Map(); + final _lastModifieds = {}; /// The subscription used while [directory] is being listed. /// @@ -70,7 +76,7 @@ class _PollingDirectoryWatcher /// /// Used to tell which files have been removed: files that are in /// [_lastModifieds] but not in here when a poll completes have been removed. - final _polledFiles = Set(); + final _polledFiles = {}; _PollingDirectoryWatcher(this.path, this._pollingDelay) { _filesToProcess = @@ -81,6 +87,7 @@ class _PollingDirectoryWatcher _poll(); } + @override void close() { _events.close(); @@ -99,7 +106,7 @@ class _PollingDirectoryWatcher _filesToProcess.clear(); _polledFiles.clear(); - endListing() { + void endListing() { assert(!_events.isClosed); _listSubscription = null; diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 8bf664261..2a70edced 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -18,6 +18,7 @@ import '../watch_event.dart'; class WindowsDirectoryWatcher extends ResubscribableWatcher implements DirectoryWatcher { + @override String get directory => path; WindowsDirectoryWatcher(String directory) @@ -29,7 +30,7 @@ class _EventBatcher { final List events = []; Timer timer; - void addEvent(FileSystemEvent event, void callback()) { + void addEvent(FileSystemEvent event, void Function() callback) { events.add(event); if (timer != null) { timer.cancel(); @@ -44,14 +45,19 @@ class _EventBatcher { class _WindowsDirectoryWatcher implements DirectoryWatcher, ManuallyClosedWatcher { + @override String get directory => path; + @override final String path; + @override Stream get events => _eventsController.stream; final _eventsController = StreamController.broadcast(); + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); @@ -94,6 +100,7 @@ class _WindowsDirectoryWatcher }); } + @override void close() { if (_watchSubscription != null) _watchSubscription.cancel(); if (_parentWatchSubscription != null) _parentWatchSubscription.cancel(); @@ -222,19 +229,19 @@ class _WindowsDirectoryWatcher // directory's full contents will be examined anyway, so we ignore such // events. Emitting them could cause useless or out-of-order events. var directories = unionAll(batch.map((event) { - if (!event.isDirectory) return Set(); + if (!event.isDirectory) return {}; if (event is FileSystemMoveEvent) { - return Set.from([event.path, event.destination]); + return {event.path, event.destination}; } - return Set.from([event.path]); + return {event.path}; })); - isInModifiedDirectory(String path) => + bool isInModifiedDirectory(String path) => directories.any((dir) => path != dir && path.startsWith(dir)); - addEvent(String path, FileSystemEvent event) { + void addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; - eventsForPaths.putIfAbsent(path, () => Set()).add(event); + eventsForPaths.putIfAbsent(path, () => {}).add(event); } for (var event in batch) { diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index ff25eb74e..7f466af3f 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -19,13 +19,17 @@ class NativeFileWatcher extends ResubscribableWatcher implements FileWatcher { } class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { + @override final String path; + @override Stream get events => _eventsController.stream; final _eventsController = StreamController.broadcast(); + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); @@ -57,7 +61,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); } - _onDone() async { + void _onDone() async { var fileExists = await File(path).exists(); // Check for this after checking whether the file exists because it's @@ -77,6 +81,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { } } + @override void close() { if (_subscription != null) _subscription.cancel(); _subscription = null; diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index e2bf5dd95..11c0c6d9f 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -17,18 +17,22 @@ class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { PollingFileWatcher(String path, {Duration pollingDelay}) : super(path, () { return _PollingFileWatcher( - path, pollingDelay != null ? pollingDelay : Duration(seconds: 1)); + path, pollingDelay ?? Duration(seconds: 1)); }); } class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { + @override final String path; + @override Stream get events => _eventsController.stream; final _eventsController = StreamController.broadcast(); + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); @@ -84,6 +88,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { } } + @override Future close() async { _timer.cancel(); await _eventsController.close(); diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index d6983ffb1..41a0a390b 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -61,7 +61,7 @@ class PathSet { // the next level. var part = parts.removeFirst(); var entry = dir.contents[part]; - if (entry == null || entry.contents.isEmpty) return Set(); + if (entry == null || entry.contents.isEmpty) return {}; partialPath = p.join(partialPath, part); var paths = recurse(entry, partialPath); @@ -75,10 +75,10 @@ class PathSet { // If there's only one component left in [path], we should remove it. var entry = dir.contents.remove(parts.first); - if (entry == null) return Set(); + if (entry == null) return {}; if (entry.contents.isEmpty) { - return Set.from([p.join(root, path)]); + return {p.join(root, path)}; } var set = _explicitPathsWithin(entry, path); @@ -96,8 +96,8 @@ class PathSet { /// /// [dirPath] should be the path to [dir]. Set _explicitPathsWithin(_Entry dir, String dirPath) { - var paths = Set(); - recurse(_Entry dir, String path) { + var paths = {}; + void recurse(_Entry dir, String path) { dir.contents.forEach((name, entry) { var entryPath = p.join(path, name); if (entry.isExplicit) paths.add(p.join(root, entryPath)); @@ -143,7 +143,7 @@ class PathSet { List get paths { var result = []; - recurse(_Entry dir, String path) { + void recurse(_Entry dir, String path) { for (var name in dir.contents.keys) { var entry = dir.contents[name]; var entryPath = p.join(path, name); diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 8de3dfb5a..071909607 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -24,13 +24,17 @@ abstract class ResubscribableWatcher implements Watcher { /// The factory function that produces instances of the inner class. final ManuallyClosedWatcher Function() _factory; + @override final String path; + @override Stream get events => _eventsController.stream; StreamController _eventsController; + @override bool get isReady => _readyCompleter.isCompleted; + @override Future get ready => _readyCompleter.future; var _readyCompleter = Completer(); diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 676ae281b..24b8184c2 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -12,13 +12,13 @@ bool isDirectoryNotFoundException(error) { if (error is! FileSystemException) return false; // See dartbug.com/12461 and tests/standalone/io/directory_error_test.dart. - var notFoundCode = Platform.operatingSystem == "windows" ? 3 : 2; + var notFoundCode = Platform.operatingSystem == 'windows' ? 3 : 2; return error.osError.errorCode == notFoundCode; } /// Returns the union of all elements in each set in [sets]. Set unionAll(Iterable> sets) => - sets.fold(Set(), (union, set) => union.union(set)); + sets.fold({}, (union, set) => union.union(set)); /// A stream transformer that batches all events that are sent at the same time. /// @@ -28,6 +28,7 @@ Set unionAll(Iterable> sets) => /// batches, this collates all the events that are received in "nearby" /// microtasks. class BatchedStreamTransformer extends StreamTransformerBase> { + @override Stream> bind(Stream input) { var batch = Queue(); return StreamTransformer>.fromHandlers( diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart index 94ee5cb89..8b3fabb77 100644 --- a/pkgs/watcher/lib/src/watch_event.dart +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -12,22 +12,24 @@ class WatchEvent { WatchEvent(this.type, this.path); - String toString() => "$type $path"; + @override + String toString() => '$type $path'; } /// Enum for what kind of change has happened to a file. class ChangeType { /// A new file has been added. - static const ADD = ChangeType("add"); + static const ADD = ChangeType('add'); /// A file has been removed. - static const REMOVE = ChangeType("remove"); + static const REMOVE = ChangeType('remove'); /// The contents of a file have changed. - static const MODIFY = ChangeType("modify"); + static const MODIFY = ChangeType('modify'); final String _name; const ChangeType(this._name); + @override String toString() => _name; } diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index f8315bc63..9aa0eaf9f 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+13 +version: 0.9.7+14-dev description: >- A file system watcher. It monitors changes to contents of directories and @@ -8,7 +8,7 @@ author: Dart Team homepage: https://github.com/dart-lang/watcher environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.2.0 <3.0.0' dependencies: async: '>=1.10.0 <3.0.0' diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 0b81919a2..b4745a33f 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -23,21 +23,21 @@ void main() { test('emits events for many nested files moved out then immediately back in', () async { withPermutations( - (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); - await startWatcher(path: "dir"); + (i, j, k) => writeFile('dir/sub/sub-$i/sub-$j/file-$k.txt')); + await startWatcher(path: 'dir'); - renameDir("dir/sub", "sub"); - renameDir("sub", "dir/sub"); + renameDir('dir/sub', 'sub'); + renameDir('sub', 'dir/sub'); await allowEither(() { inAnyOrder(withPermutations( - (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isRemoveEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); inAnyOrder(withPermutations( - (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isAddEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }, () { inAnyOrder(withPermutations( - (i, j, k) => isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isModifyEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 1470f71dc..b100f5970 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -23,35 +23,35 @@ void main() { test( 'does not notify about the watched directory being deleted and ' 'recreated immediately before watching', () async { - createDir("dir"); - writeFile("dir/old.txt"); - deleteDir("dir"); - createDir("dir"); - - await startWatcher(path: "dir"); - writeFile("dir/newer.txt"); - await expectAddEvent("dir/newer.txt"); + createDir('dir'); + writeFile('dir/old.txt'); + deleteDir('dir'); + createDir('dir'); + + await startWatcher(path: 'dir'); + writeFile('dir/newer.txt'); + await expectAddEvent('dir/newer.txt'); }); test('emits events for many nested files moved out then immediately back in', () async { withPermutations( - (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + (i, j, k) => writeFile('dir/sub/sub-$i/sub-$j/file-$k.txt')); - await startWatcher(path: "dir"); + await startWatcher(path: 'dir'); - renameDir("dir/sub", "sub"); - renameDir("sub", "dir/sub"); + renameDir('dir/sub', 'sub'); + renameDir('sub', 'dir/sub'); await allowEither(() { inAnyOrder(withPermutations( - (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isRemoveEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); inAnyOrder(withPermutations( - (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isAddEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }, () { inAnyOrder(withPermutations( - (i, j, k) => isModifyEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isModifyEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }); }); } diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index d64eb0706..261d0e998 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -16,11 +16,11 @@ void main() { sharedTests(); test('does not notify if the modification time did not change', () async { - writeFile("a.txt", contents: "before"); - writeFile("b.txt", contents: "before"); + writeFile('a.txt', contents: 'before'); + writeFile('b.txt', contents: 'before'); await startWatcher(); - writeFile("a.txt", contents: "after", updateModified: false); - writeFile("b.txt", contents: "after"); - await expectModifyEvent("b.txt"); + writeFile('a.txt', contents: 'after', updateModified: false); + writeFile('b.txt', contents: 'after'); + await expectModifyEvent('b.txt'); }); } diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index a302c933e..ebce488db 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -10,130 +10,130 @@ import '../utils.dart'; void sharedTests() { test('does not notify for files that already exist when started', () async { // Make some pre-existing files. - writeFile("a.txt"); - writeFile("b.txt"); + writeFile('a.txt'); + writeFile('b.txt'); await startWatcher(); // Change one after the watcher is running. - writeFile("b.txt", contents: "modified"); + writeFile('b.txt', contents: 'modified'); // We should get a modify event for the changed file, but no add events // for them before this. - await expectModifyEvent("b.txt"); + await expectModifyEvent('b.txt'); }); test('notifies when a file is added', () async { await startWatcher(); - writeFile("file.txt"); - await expectAddEvent("file.txt"); + writeFile('file.txt'); + await expectAddEvent('file.txt'); }); test('notifies when a file is modified', () async { - writeFile("file.txt"); + writeFile('file.txt'); await startWatcher(); - writeFile("file.txt", contents: "modified"); - await expectModifyEvent("file.txt"); + writeFile('file.txt', contents: 'modified'); + await expectModifyEvent('file.txt'); }); test('notifies when a file is removed', () async { - writeFile("file.txt"); + writeFile('file.txt'); await startWatcher(); - deleteFile("file.txt"); - await expectRemoveEvent("file.txt"); + deleteFile('file.txt'); + await expectRemoveEvent('file.txt'); }); test('notifies when a file is modified multiple times', () async { - writeFile("file.txt"); + writeFile('file.txt'); await startWatcher(); - writeFile("file.txt", contents: "modified"); - await expectModifyEvent("file.txt"); - writeFile("file.txt", contents: "modified again"); - await expectModifyEvent("file.txt"); + writeFile('file.txt', contents: 'modified'); + await expectModifyEvent('file.txt'); + writeFile('file.txt', contents: 'modified again'); + await expectModifyEvent('file.txt'); }); test('notifies even if the file contents are unchanged', () async { - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "before"); + writeFile('a.txt', contents: 'same'); + writeFile('b.txt', contents: 'before'); await startWatcher(); - writeFile("a.txt", contents: "same"); - writeFile("b.txt", contents: "after"); - await inAnyOrder([isModifyEvent("a.txt"), isModifyEvent("b.txt")]); + writeFile('a.txt', contents: 'same'); + writeFile('b.txt', contents: 'after'); + await inAnyOrder([isModifyEvent('a.txt'), isModifyEvent('b.txt')]); }); test('when the watched directory is deleted, removes all files', () async { - writeFile("dir/a.txt"); - writeFile("dir/b.txt"); + writeFile('dir/a.txt'); + writeFile('dir/b.txt'); - await startWatcher(path: "dir"); + await startWatcher(path: 'dir'); - deleteDir("dir"); - await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + deleteDir('dir'); + await inAnyOrder([isRemoveEvent('dir/a.txt'), isRemoveEvent('dir/b.txt')]); }); test('when the watched directory is moved, removes all files', () async { - writeFile("dir/a.txt"); - writeFile("dir/b.txt"); + writeFile('dir/a.txt'); + writeFile('dir/b.txt'); - await startWatcher(path: "dir"); + await startWatcher(path: 'dir'); - renameDir("dir", "moved_dir"); - createDir("dir"); - await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + renameDir('dir', 'moved_dir'); + createDir('dir'); + await inAnyOrder([isRemoveEvent('dir/a.txt'), isRemoveEvent('dir/b.txt')]); }); // Regression test for b/30768513. test( "doesn't crash when the directory is moved immediately after a subdir " - "is added", () async { - writeFile("dir/a.txt"); - writeFile("dir/b.txt"); + 'is added', () async { + writeFile('dir/a.txt'); + writeFile('dir/b.txt'); - await startWatcher(path: "dir"); + await startWatcher(path: 'dir'); - createDir("dir/subdir"); - renameDir("dir", "moved_dir"); - createDir("dir"); - await inAnyOrder([isRemoveEvent("dir/a.txt"), isRemoveEvent("dir/b.txt")]); + createDir('dir/subdir'); + renameDir('dir', 'moved_dir'); + createDir('dir'); + await inAnyOrder([isRemoveEvent('dir/a.txt'), isRemoveEvent('dir/b.txt')]); }); - group("moves", () { + group('moves', () { test('notifies when a file is moved within the watched directory', () async { - writeFile("old.txt"); + writeFile('old.txt'); await startWatcher(); - renameFile("old.txt", "new.txt"); + renameFile('old.txt', 'new.txt'); - await inAnyOrder([isAddEvent("new.txt"), isRemoveEvent("old.txt")]); + await inAnyOrder([isAddEvent('new.txt'), isRemoveEvent('old.txt')]); }); test('notifies when a file is moved from outside the watched directory', () async { - writeFile("old.txt"); - createDir("dir"); - await startWatcher(path: "dir"); + writeFile('old.txt'); + createDir('dir'); + await startWatcher(path: 'dir'); - renameFile("old.txt", "dir/new.txt"); - await expectAddEvent("dir/new.txt"); + renameFile('old.txt', 'dir/new.txt'); + await expectAddEvent('dir/new.txt'); }); test('notifies when a file is moved outside the watched directory', () async { - writeFile("dir/old.txt"); - await startWatcher(path: "dir"); + writeFile('dir/old.txt'); + await startWatcher(path: 'dir'); - renameFile("dir/old.txt", "new.txt"); - await expectRemoveEvent("dir/old.txt"); + renameFile('dir/old.txt', 'new.txt'); + await expectRemoveEvent('dir/old.txt'); }); test('notifies when a file is moved onto an existing one', () async { - writeFile("from.txt"); - writeFile("to.txt"); + writeFile('from.txt'); + writeFile('to.txt'); await startWatcher(); - renameFile("from.txt", "to.txt"); - await inAnyOrder([isRemoveEvent("from.txt"), isModifyEvent("to.txt")]); + renameFile('from.txt', 'to.txt'); + await inAnyOrder([isRemoveEvent('from.txt'), isModifyEvent('to.txt')]); }); }); @@ -144,198 +144,198 @@ void sharedTests() { // separate batches, and the watcher will report them as though they occurred // far apart in time, so each of these tests has a "backup case" to allow for // that as well. - group("clustered changes", () { + group('clustered changes', () { test("doesn't notify when a file is created and then immediately removed", () async { - writeFile("test.txt"); + writeFile('test.txt'); await startWatcher(); - writeFile("file.txt"); - deleteFile("file.txt"); + writeFile('file.txt'); + deleteFile('file.txt'); // Backup case. startClosingEventStream(); await allowEvents(() { - expectAddEvent("file.txt"); - expectRemoveEvent("file.txt"); + expectAddEvent('file.txt'); + expectRemoveEvent('file.txt'); }); }); test( - "reports a modification when a file is deleted and then immediately " - "recreated", () async { - writeFile("file.txt"); + 'reports a modification when a file is deleted and then immediately ' + 'recreated', () async { + writeFile('file.txt'); await startWatcher(); - deleteFile("file.txt"); - writeFile("file.txt", contents: "re-created"); + deleteFile('file.txt'); + writeFile('file.txt', contents: 're-created'); await allowEither(() { - expectModifyEvent("file.txt"); + expectModifyEvent('file.txt'); }, () { // Backup case. - expectRemoveEvent("file.txt"); - expectAddEvent("file.txt"); + expectRemoveEvent('file.txt'); + expectAddEvent('file.txt'); }); }); test( - "reports a modification when a file is moved and then immediately " - "recreated", () async { - writeFile("old.txt"); + 'reports a modification when a file is moved and then immediately ' + 'recreated', () async { + writeFile('old.txt'); await startWatcher(); - renameFile("old.txt", "new.txt"); - writeFile("old.txt", contents: "re-created"); + renameFile('old.txt', 'new.txt'); + writeFile('old.txt', contents: 're-created'); await allowEither(() { - inAnyOrder([isModifyEvent("old.txt"), isAddEvent("new.txt")]); + inAnyOrder([isModifyEvent('old.txt'), isAddEvent('new.txt')]); }, () { // Backup case. - expectRemoveEvent("old.txt"); - expectAddEvent("new.txt"); - expectAddEvent("old.txt"); + expectRemoveEvent('old.txt'); + expectAddEvent('new.txt'); + expectAddEvent('old.txt'); }); }); test( - "reports a removal when a file is modified and then immediately " - "removed", () async { - writeFile("file.txt"); + 'reports a removal when a file is modified and then immediately ' + 'removed', () async { + writeFile('file.txt'); await startWatcher(); - writeFile("file.txt", contents: "modified"); - deleteFile("file.txt"); + writeFile('file.txt', contents: 'modified'); + deleteFile('file.txt'); // Backup case. - await allowModifyEvent("file.txt"); + await allowModifyEvent('file.txt'); - await expectRemoveEvent("file.txt"); + await expectRemoveEvent('file.txt'); }); - test("reports an add when a file is added and then immediately modified", + test('reports an add when a file is added and then immediately modified', () async { await startWatcher(); - writeFile("file.txt"); - writeFile("file.txt", contents: "modified"); + writeFile('file.txt'); + writeFile('file.txt', contents: 'modified'); - await expectAddEvent("file.txt"); + await expectAddEvent('file.txt'); // Backup case. startClosingEventStream(); - await allowModifyEvent("file.txt"); + await allowModifyEvent('file.txt'); }); }); - group("subdirectories", () { + group('subdirectories', () { test('watches files in subdirectories', () async { await startWatcher(); - writeFile("a/b/c/d/file.txt"); - await expectAddEvent("a/b/c/d/file.txt"); + writeFile('a/b/c/d/file.txt'); + await expectAddEvent('a/b/c/d/file.txt'); }); test( 'notifies when a subdirectory is moved within the watched directory ' 'and then its contents are modified', () async { - writeFile("old/file.txt"); + writeFile('old/file.txt'); await startWatcher(); - renameDir("old", "new"); + renameDir('old', 'new'); await inAnyOrder( - [isRemoveEvent("old/file.txt"), isAddEvent("new/file.txt")]); + [isRemoveEvent('old/file.txt'), isAddEvent('new/file.txt')]); - writeFile("new/file.txt", contents: "modified"); - await expectModifyEvent("new/file.txt"); + writeFile('new/file.txt', contents: 'modified'); + await expectModifyEvent('new/file.txt'); }); test('notifies when a file is replaced by a subdirectory', () async { - writeFile("new"); - writeFile("old/file.txt"); + writeFile('new'); + writeFile('old/file.txt'); await startWatcher(); - deleteFile("new"); - renameDir("old", "new"); + deleteFile('new'); + renameDir('old', 'new'); await inAnyOrder([ - isRemoveEvent("new"), - isRemoveEvent("old/file.txt"), - isAddEvent("new/file.txt") + isRemoveEvent('new'), + isRemoveEvent('old/file.txt'), + isAddEvent('new/file.txt') ]); }); test('notifies when a subdirectory is replaced by a file', () async { - writeFile("old"); - writeFile("new/file.txt"); + writeFile('old'); + writeFile('new/file.txt'); await startWatcher(); - renameDir("new", "newer"); - renameFile("old", "new"); + renameDir('new', 'newer'); + renameFile('old', 'new'); await inAnyOrder([ - isRemoveEvent("new/file.txt"), - isAddEvent("newer/file.txt"), - isRemoveEvent("old"), - isAddEvent("new") + isRemoveEvent('new/file.txt'), + isAddEvent('newer/file.txt'), + isRemoveEvent('old'), + isAddEvent('new') ]); }, onPlatform: { - "mac-os": Skip("https://github.com/dart-lang/watcher/issues/21") + 'mac-os': Skip('https://github.com/dart-lang/watcher/issues/21') }); test('emits events for many nested files added at once', () async { - withPermutations((i, j, k) => writeFile("sub/sub-$i/sub-$j/file-$k.txt")); + withPermutations((i, j, k) => writeFile('sub/sub-$i/sub-$j/file-$k.txt')); - createDir("dir"); - await startWatcher(path: "dir"); - renameDir("sub", "dir/sub"); + createDir('dir'); + await startWatcher(path: 'dir'); + renameDir('sub', 'dir/sub'); await inAnyOrder(withPermutations( - (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isAddEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }); test('emits events for many nested files removed at once', () async { withPermutations( - (i, j, k) => writeFile("dir/sub/sub-$i/sub-$j/file-$k.txt")); + (i, j, k) => writeFile('dir/sub/sub-$i/sub-$j/file-$k.txt')); - createDir("dir"); - await startWatcher(path: "dir"); + createDir('dir'); + await startWatcher(path: 'dir'); // Rename the directory rather than deleting it because native watchers // report a rename as a single DELETE event for the directory, whereas // they report recursive deletion with DELETE events for every file in the // directory. - renameDir("dir/sub", "sub"); + renameDir('dir/sub', 'sub'); await inAnyOrder(withPermutations( - (i, j, k) => isRemoveEvent("dir/sub/sub-$i/sub-$j/file-$k.txt"))); + (i, j, k) => isRemoveEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }); test('emits events for many nested files moved at once', () async { withPermutations( - (i, j, k) => writeFile("dir/old/sub-$i/sub-$j/file-$k.txt")); + (i, j, k) => writeFile('dir/old/sub-$i/sub-$j/file-$k.txt')); - createDir("dir"); - await startWatcher(path: "dir"); - renameDir("dir/old", "dir/new"); + createDir('dir'); + await startWatcher(path: 'dir'); + renameDir('dir/old', 'dir/new'); await inAnyOrder(unionAll(withPermutations((i, j, k) { - return Set.from([ - isRemoveEvent("dir/old/sub-$i/sub-$j/file-$k.txt"), - isAddEvent("dir/new/sub-$i/sub-$j/file-$k.txt") - ]); + return { + isRemoveEvent('dir/old/sub-$i/sub-$j/file-$k.txt'), + isAddEvent('dir/new/sub-$i/sub-$j/file-$k.txt') + }; }))); }); test( - "emits events for many files added at once in a subdirectory with the " - "same name as a removed file", () async { - writeFile("dir/sub"); - withPermutations((i, j, k) => writeFile("old/sub-$i/sub-$j/file-$k.txt")); - await startWatcher(path: "dir"); + 'emits events for many files added at once in a subdirectory with the ' + 'same name as a removed file', () async { + writeFile('dir/sub'); + withPermutations((i, j, k) => writeFile('old/sub-$i/sub-$j/file-$k.txt')); + await startWatcher(path: 'dir'); - deleteFile("dir/sub"); - renameDir("old", "dir/sub"); + deleteFile('dir/sub'); + renameDir('old', 'dir/sub'); var events = withPermutations( - (i, j, k) => isAddEvent("dir/sub/sub-$i/sub-$j/file-$k.txt")); - events.add(isRemoveEvent("dir/sub")); + (i, j, k) => isAddEvent('dir/sub/sub-$i/sub-$j/file-$k.txt')); + events.add(isRemoveEvent('dir/sub')); await inAnyOrder(events); }); }); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 7931fa819..6ea412f77 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -16,9 +16,9 @@ void main() { // TODO(grouma) - renable when https://github.com/dart-lang/sdk/issues/31760 // is resolved. - group("Shared Tests:", () { + group('Shared Tests:', () { sharedTests(); - }, skip: "SDK issue see - https://github.com/dart-lang/sdk/issues/31760"); + }, skip: 'SDK issue see - https://github.com/dart-lang/sdk/issues/31760'); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { expect(DirectoryWatcher('.'), TypeMatcher()); diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart index 2417dae60..b59d4ed95 100644 --- a/pkgs/watcher/test/file_watcher/native_test.dart +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -14,7 +14,7 @@ void main() { watcherFactory = (file) => NativeFileWatcher(file); setUp(() { - writeFile("file.txt"); + writeFile('file.txt'); }); sharedTests(); diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index 9492f658e..b83d44fd1 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -15,7 +15,7 @@ void main() { PollingFileWatcher(file, pollingDelay: Duration(milliseconds: 100)); setUp(() { - writeFile("file.txt"); + writeFile('file.txt'); }); sharedTests(); diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index eefe5dfc4..c837a2136 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -10,60 +10,60 @@ import '../utils.dart'; void sharedTests() { test("doesn't notify if the file isn't modified", () async { - await startWatcher(path: "file.txt"); + await startWatcher(path: 'file.txt'); await pumpEventQueue(); - deleteFile("file.txt"); - await expectRemoveEvent("file.txt"); + deleteFile('file.txt'); + await expectRemoveEvent('file.txt'); }); - test("notifies when a file is modified", () async { - await startWatcher(path: "file.txt"); - writeFile("file.txt", contents: "modified"); - await expectModifyEvent("file.txt"); + test('notifies when a file is modified', () async { + await startWatcher(path: 'file.txt'); + writeFile('file.txt', contents: 'modified'); + await expectModifyEvent('file.txt'); }); - test("notifies when a file is removed", () async { - await startWatcher(path: "file.txt"); - deleteFile("file.txt"); - await expectRemoveEvent("file.txt"); + test('notifies when a file is removed', () async { + await startWatcher(path: 'file.txt'); + deleteFile('file.txt'); + await expectRemoveEvent('file.txt'); }); - test("notifies when a file is modified multiple times", () async { - await startWatcher(path: "file.txt"); - writeFile("file.txt", contents: "modified"); - await expectModifyEvent("file.txt"); - writeFile("file.txt", contents: "modified again"); - await expectModifyEvent("file.txt"); + test('notifies when a file is modified multiple times', () async { + await startWatcher(path: 'file.txt'); + writeFile('file.txt', contents: 'modified'); + await expectModifyEvent('file.txt'); + writeFile('file.txt', contents: 'modified again'); + await expectModifyEvent('file.txt'); }); - test("notifies even if the file contents are unchanged", () async { - await startWatcher(path: "file.txt"); - writeFile("file.txt"); - await expectModifyEvent("file.txt"); + test('notifies even if the file contents are unchanged', () async { + await startWatcher(path: 'file.txt'); + writeFile('file.txt'); + await expectModifyEvent('file.txt'); }); - test("emits a remove event when the watched file is moved away", () async { - await startWatcher(path: "file.txt"); - renameFile("file.txt", "new.txt"); - await expectRemoveEvent("file.txt"); + test('emits a remove event when the watched file is moved away', () async { + await startWatcher(path: 'file.txt'); + renameFile('file.txt', 'new.txt'); + await expectRemoveEvent('file.txt'); }); test( - "emits a modify event when another file is moved on top of the watched " - "file", () async { - writeFile("old.txt"); - await startWatcher(path: "file.txt"); - renameFile("old.txt", "file.txt"); - await expectModifyEvent("file.txt"); + 'emits a modify event when another file is moved on top of the watched ' + 'file', () async { + writeFile('old.txt'); + await startWatcher(path: 'file.txt'); + renameFile('old.txt', 'file.txt'); + await expectModifyEvent('file.txt'); }); // Regression test for a race condition. - test("closes the watcher immediately after deleting the file", () async { - writeFile("old.txt"); - var watcher = createWatcher(path: "file.txt"); + test('closes the watcher immediately after deleting the file', () async { + writeFile('old.txt'); + var watcher = createWatcher(path: 'file.txt'); var sub = watcher.events.listen(null); - deleteFile("file.txt"); + deleteFile('file.txt'); await Future.delayed(Duration(milliseconds: 10)); await sub.cancel(); }); diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index 5ffb11738..f2270770c 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('mac-os') -@Skip("Flaky due to sdk#23877") +@Skip('Flaky due to sdk#23877') import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index e82692ec4..bcdba5f16 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -19,7 +19,7 @@ void sharedTests() { unawaited(queue.hasNext); var future = - expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "file.txt"))); + expectLater(queue, emits(isWatchEvent(ChangeType.ADD, 'file.txt'))); expect(queue, neverEmits(anything)); await watcher.ready; @@ -32,18 +32,18 @@ void sharedTests() { await queue.cancel(immediate: true); // Now write a file while we aren't listening. - writeFile("unwatched.txt"); + writeFile('unwatched.txt'); queue = StreamQueue(watcher.events); future = - expectLater(queue, emits(isWatchEvent(ChangeType.ADD, "added.txt"))); - expect(queue, neverEmits(isWatchEvent(ChangeType.ADD, "unwatched.txt"))); + expectLater(queue, emits(isWatchEvent(ChangeType.ADD, 'added.txt'))); + expect(queue, neverEmits(isWatchEvent(ChangeType.ADD, 'unwatched.txt'))); // Wait until the watcher is ready to dispatch events again. await watcher.ready; // And add a third file. - writeFile("added.txt"); + writeFile('added.txt'); // Wait until we get an event for the third file. await future; diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index 9ca418180..25cf96943 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -16,210 +16,210 @@ Matcher containsDir(String path) => predicate( void main() { PathSet paths; - setUp(() => paths = PathSet("root")); + setUp(() => paths = PathSet('root')); - group("adding a path", () { - test("stores the path in the set", () { - paths.add("root/path/to/file"); - expect(paths, containsPath("root/path/to/file")); + group('adding a path', () { + test('stores the path in the set', () { + paths.add('root/path/to/file'); + expect(paths, containsPath('root/path/to/file')); }); test("that's a subdir of another path keeps both in the set", () { - paths.add("root/path"); - paths.add("root/path/to/file"); - expect(paths, containsPath("root/path")); - expect(paths, containsPath("root/path/to/file")); + paths.add('root/path'); + paths.add('root/path/to/file'); + expect(paths, containsPath('root/path')); + expect(paths, containsPath('root/path/to/file')); }); test("that's not normalized normalizes the path before storing it", () { - paths.add("root/../root/path/to/../to/././file"); - expect(paths, containsPath("root/path/to/file")); + paths.add('root/../root/path/to/../to/././file'); + expect(paths, containsPath('root/path/to/file')); }); test("that's absolute normalizes the path before storing it", () { - paths.add(p.absolute("root/path/to/file")); - expect(paths, containsPath("root/path/to/file")); + paths.add(p.absolute('root/path/to/file')); + expect(paths, containsPath('root/path/to/file')); }); }); - group("removing a path", () { + group('removing a path', () { test("that's in the set removes and returns that path", () { - paths.add("root/path/to/file"); - expect(paths.remove("root/path/to/file"), - unorderedEquals([p.normalize("root/path/to/file")])); - expect(paths, isNot(containsPath("root/path/to/file"))); + paths.add('root/path/to/file'); + expect(paths.remove('root/path/to/file'), + unorderedEquals([p.normalize('root/path/to/file')])); + expect(paths, isNot(containsPath('root/path/to/file'))); }); test("that's not in the set returns an empty set", () { - paths.add("root/path/to/file"); - expect(paths.remove("root/path/to/nothing"), isEmpty); + paths.add('root/path/to/file'); + expect(paths.remove('root/path/to/nothing'), isEmpty); }); test("that's a directory removes and returns all files beneath it", () { - paths.add("root/outside"); - paths.add("root/path/to/one"); - paths.add("root/path/to/two"); - paths.add("root/path/to/sub/three"); + paths.add('root/outside'); + paths.add('root/path/to/one'); + paths.add('root/path/to/two'); + paths.add('root/path/to/sub/three'); expect( - paths.remove("root/path"), + paths.remove('root/path'), unorderedEquals([ - "root/path/to/one", - "root/path/to/two", - "root/path/to/sub/three" + 'root/path/to/one', + 'root/path/to/two', + 'root/path/to/sub/three' ].map(p.normalize))); - expect(paths, containsPath("root/outside")); - expect(paths, isNot(containsPath("root/path/to/one"))); - expect(paths, isNot(containsPath("root/path/to/two"))); - expect(paths, isNot(containsPath("root/path/to/sub/three"))); + expect(paths, containsPath('root/outside')); + expect(paths, isNot(containsPath('root/path/to/one'))); + expect(paths, isNot(containsPath('root/path/to/two'))); + expect(paths, isNot(containsPath('root/path/to/sub/three'))); }); test( "that's a directory in the set removes and returns it and all files " - "beneath it", () { - paths.add("root/path"); - paths.add("root/path/to/one"); - paths.add("root/path/to/two"); - paths.add("root/path/to/sub/three"); + 'beneath it', () { + paths.add('root/path'); + paths.add('root/path/to/one'); + paths.add('root/path/to/two'); + paths.add('root/path/to/sub/three'); expect( - paths.remove("root/path"), + paths.remove('root/path'), unorderedEquals([ - "root/path", - "root/path/to/one", - "root/path/to/two", - "root/path/to/sub/three" + 'root/path', + 'root/path/to/one', + 'root/path/to/two', + 'root/path/to/sub/three' ].map(p.normalize))); - expect(paths, isNot(containsPath("root/path"))); - expect(paths, isNot(containsPath("root/path/to/one"))); - expect(paths, isNot(containsPath("root/path/to/two"))); - expect(paths, isNot(containsPath("root/path/to/sub/three"))); + expect(paths, isNot(containsPath('root/path'))); + expect(paths, isNot(containsPath('root/path/to/one'))); + expect(paths, isNot(containsPath('root/path/to/two'))); + expect(paths, isNot(containsPath('root/path/to/sub/three'))); }); test("that's not normalized removes and returns the normalized path", () { - paths.add("root/path/to/file"); - expect(paths.remove("root/../root/path/to/../to/./file"), - unorderedEquals([p.normalize("root/path/to/file")])); + paths.add('root/path/to/file'); + expect(paths.remove('root/../root/path/to/../to/./file'), + unorderedEquals([p.normalize('root/path/to/file')])); }); test("that's absolute removes and returns the normalized path", () { - paths.add("root/path/to/file"); - expect(paths.remove(p.absolute("root/path/to/file")), - unorderedEquals([p.normalize("root/path/to/file")])); + paths.add('root/path/to/file'); + expect(paths.remove(p.absolute('root/path/to/file')), + unorderedEquals([p.normalize('root/path/to/file')])); }); }); - group("containsPath()", () { - test("returns false for a non-existent path", () { - paths.add("root/path/to/file"); - expect(paths, isNot(containsPath("root/path/to/nothing"))); + group('containsPath()', () { + test('returns false for a non-existent path', () { + paths.add('root/path/to/file'); + expect(paths, isNot(containsPath('root/path/to/nothing'))); }); test("returns false for a directory that wasn't added explicitly", () { - paths.add("root/path/to/file"); - expect(paths, isNot(containsPath("root/path"))); + paths.add('root/path/to/file'); + expect(paths, isNot(containsPath('root/path'))); }); - test("returns true for a directory that was added explicitly", () { - paths.add("root/path"); - paths.add("root/path/to/file"); - expect(paths, containsPath("root/path")); + test('returns true for a directory that was added explicitly', () { + paths.add('root/path'); + paths.add('root/path/to/file'); + expect(paths, containsPath('root/path')); }); - test("with a non-normalized path normalizes the path before looking it up", + test('with a non-normalized path normalizes the path before looking it up', () { - paths.add("root/path/to/file"); - expect(paths, containsPath("root/../root/path/to/../to/././file")); + paths.add('root/path/to/file'); + expect(paths, containsPath('root/../root/path/to/../to/././file')); }); - test("with an absolute path normalizes the path before looking it up", () { - paths.add("root/path/to/file"); - expect(paths, containsPath(p.absolute("root/path/to/file"))); + test('with an absolute path normalizes the path before looking it up', () { + paths.add('root/path/to/file'); + expect(paths, containsPath(p.absolute('root/path/to/file'))); }); }); - group("containsDir()", () { - test("returns true for a directory that was added implicitly", () { - paths.add("root/path/to/file"); - expect(paths, containsDir("root/path")); - expect(paths, containsDir("root/path/to")); + group('containsDir()', () { + test('returns true for a directory that was added implicitly', () { + paths.add('root/path/to/file'); + expect(paths, containsDir('root/path')); + expect(paths, containsDir('root/path/to')); }); - test("returns true for a directory that was added explicitly", () { - paths.add("root/path"); - paths.add("root/path/to/file"); - expect(paths, containsDir("root/path")); + test('returns true for a directory that was added explicitly', () { + paths.add('root/path'); + paths.add('root/path/to/file'); + expect(paths, containsDir('root/path')); }); test("returns false for a directory that wasn't added", () { - expect(paths, isNot(containsDir("root/nothing"))); + expect(paths, isNot(containsDir('root/nothing'))); }); - test("returns false for a non-directory path that was added", () { - paths.add("root/path/to/file"); - expect(paths, isNot(containsDir("root/path/to/file"))); + test('returns false for a non-directory path that was added', () { + paths.add('root/path/to/file'); + expect(paths, isNot(containsDir('root/path/to/file'))); }); test( - "returns false for a directory that was added implicitly and then " - "removed implicitly", () { - paths.add("root/path/to/file"); - paths.remove("root/path/to/file"); - expect(paths, isNot(containsDir("root/path"))); + 'returns false for a directory that was added implicitly and then ' + 'removed implicitly', () { + paths.add('root/path/to/file'); + paths.remove('root/path/to/file'); + expect(paths, isNot(containsDir('root/path'))); }); test( - "returns false for a directory that was added explicitly whose " - "children were then removed", () { - paths.add("root/path"); - paths.add("root/path/to/file"); - paths.remove("root/path/to/file"); - expect(paths, isNot(containsDir("root/path"))); + 'returns false for a directory that was added explicitly whose ' + 'children were then removed', () { + paths.add('root/path'); + paths.add('root/path/to/file'); + paths.remove('root/path/to/file'); + expect(paths, isNot(containsDir('root/path'))); }); - test("with a non-normalized path normalizes the path before looking it up", + test('with a non-normalized path normalizes the path before looking it up', () { - paths.add("root/path/to/file"); - expect(paths, containsDir("root/../root/path/to/../to/.")); + paths.add('root/path/to/file'); + expect(paths, containsDir('root/../root/path/to/../to/.')); }); - test("with an absolute path normalizes the path before looking it up", () { - paths.add("root/path/to/file"); - expect(paths, containsDir(p.absolute("root/path"))); + test('with an absolute path normalizes the path before looking it up', () { + paths.add('root/path/to/file'); + expect(paths, containsDir(p.absolute('root/path'))); }); }); - group("paths", () { - test("returns paths added to the set", () { - paths.add("root/path"); - paths.add("root/path/to/one"); - paths.add("root/path/to/two"); + group('paths', () { + test('returns paths added to the set', () { + paths.add('root/path'); + paths.add('root/path/to/one'); + paths.add('root/path/to/two'); expect( paths.paths, unorderedEquals([ - "root/path", - "root/path/to/one", - "root/path/to/two", + 'root/path', + 'root/path/to/one', + 'root/path/to/two', ].map(p.normalize))); }); test("doesn't return paths removed from the set", () { - paths.add("root/path/to/one"); - paths.add("root/path/to/two"); - paths.remove("root/path/to/two"); + paths.add('root/path/to/one'); + paths.add('root/path/to/two'); + paths.remove('root/path/to/two'); - expect(paths.paths, unorderedEquals([p.normalize("root/path/to/one")])); + expect(paths.paths, unorderedEquals([p.normalize('root/path/to/one')])); }); }); - group("clear", () { - test("removes all paths from the set", () { - paths.add("root/path"); - paths.add("root/path/to/one"); - paths.add("root/path/to/two"); + group('clear', () { + test('removes all paths from the set', () { + paths.add('root/path'); + paths.add('root/path/to/one'); + paths.add('root/path/to/two'); paths.clear(); expect(paths.paths, isEmpty); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 2e0ad014e..fe86407e2 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -58,7 +58,7 @@ Future startWatcher({String path}) async { path = p.normalize(p.relative(path, from: d.sandbox)); // Make sure we got a path in the sandbox. - assert(p.isRelative(path) && !path.startsWith("..")); + assert(p.isRelative(path) && !path.startsWith('..')); var mtime = _mockFileModificationTimes[path]; return DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); @@ -92,9 +92,9 @@ List _collectedStreamMatchers; /// single stream matcher. /// /// The returned matcher will match each of the collected matchers in order. -StreamMatcher _collectStreamMatcher(block()) { +StreamMatcher _collectStreamMatcher(void Function() block) { var oldStreamMatchers = _collectedStreamMatchers; - _collectedStreamMatchers = List(); + _collectedStreamMatchers = []; try { block(); return emitsInOrder(_collectedStreamMatchers); @@ -128,15 +128,16 @@ Future inAnyOrder(Iterable matchers) { /// will match the emitted events. /// /// If both blocks match, the one that consumed more events will be used. -Future allowEither(block1(), block2()) => _expectOrCollect( - emitsAnyOf([_collectStreamMatcher(block1), _collectStreamMatcher(block2)])); +Future allowEither(void Function() block1, void Function() block2) => + _expectOrCollect(emitsAnyOf( + [_collectStreamMatcher(block1), _collectStreamMatcher(block2)])); /// Allows the expectations established in [block] to match the emitted events. /// /// If the expectations in [block] don't match, no error will be raised and no /// events will be consumed. If this is used at the end of a test, /// [startClosingEventStream] should be called before it. -Future allowEvents(block()) => +Future allowEvents(void Function() block) => _expectOrCollect(mayEmit(_collectStreamMatcher(block))); /// Returns a StreamMatcher that matches a [WatchEvent] with the given [type] @@ -146,7 +147,7 @@ Matcher isWatchEvent(ChangeType type, String path) { return e is WatchEvent && e.type == type && e.path == p.join(d.sandbox, p.normalize(path)); - }, "is $type $path"); + }, 'is $type $path'); } /// Returns a [Matcher] that matches a [WatchEvent] for an add event for [path]. @@ -202,8 +203,8 @@ Future allowRemoveEvent(String path) => /// If [contents] is omitted, creates an empty file. If [updateModified] is /// `false`, the mock file modification time is not changed. void writeFile(String path, {String contents, bool updateModified}) { - if (contents == null) contents = ""; - if (updateModified == null) updateModified = true; + contents ??= ''; + updateModified ??= true; var fullPath = p.join(d.sandbox, path); @@ -260,9 +261,9 @@ void deleteDir(String path) { /// Returns a set of all values returns by [callback]. /// /// [limit] defaults to 3. -Set withPermutations(S callback(int i, int j, int k), {int limit}) { - if (limit == null) limit = 3; - var results = Set(); +Set withPermutations(S Function(int, int, int) callback, {int limit}) { + limit ??= 3; + var results = {}; for (var i = 0; i < limit; i++) { for (var j = 0; j < limit; j++) { for (var k = 0; k < limit; k++) { From fe5d5e4cb9e6deb03707a77247e0f259db81190f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Dec 2019 13:28:14 -0800 Subject: [PATCH 0605/1215] Fix newly enforced package:pedantic lints (dart-lang/timing#13) - use_function_type_syntax_for_parameters Drop author field from pubspec --- pkgs/timing/lib/src/clock.dart | 2 +- pkgs/timing/pubspec.yaml | 3 +-- pkgs/timing/test/timing_test.dart | 7 ++++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/timing/lib/src/clock.dart b/pkgs/timing/lib/src/clock.dart index ae1f25fcc..2fdfc7c6b 100644 --- a/pkgs/timing/lib/src/clock.dart +++ b/pkgs/timing/lib/src/clock.dart @@ -16,5 +16,5 @@ const _zoneKey = #timing_Clock; DateTime now() => (Zone.current[_zoneKey] as _Clock ?? _defaultClock)(); /// Runs [f], with [clock] scoped whenever [now] is called. -T scopeClock(DateTime clock(), T f()) => +T scopeClock(DateTime Function() clock, T Function() f) => runZoned(f, zoneValues: {_zoneKey: clock}); diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 0b451234a..0b9b4e496 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,9 +1,8 @@ name: timing -version: 0.1.1+2 +version: 0.1.1+3-dev description: >- A simple package for tracking the performance of synchronous and asynchronous actions. -author: Dart Team homepage: https://github.com/dart-lang/timing environment: diff --git a/pkgs/timing/test/timing_test.dart b/pkgs/timing/test/timing_test.dart index b2ea8dad8..56f5f98de 100644 --- a/pkgs/timing/test/timing_test.dart +++ b/pkgs/timing/test/timing_test.dart @@ -20,13 +20,14 @@ void main() { TimeTracker tracker; TimeTracker nestedTracker; - T scopedTrack(T f()) => scopeClock(fakeClock, () => tracker.track(f)); + T scopedTrack(T Function() f) => + scopeClock(fakeClock, () => tracker.track(f)); setUp(() { time = startTime; }); - void canHandleSync([additionalExpects() = _noop]) { + void canHandleSync([void Function() additionalExpects = _noop]) { test('Can track sync code', () { expect(tracker.isStarted, false); expect(tracker.isTracking, false); @@ -94,7 +95,7 @@ void main() { }); } - void canHandleAsync([additionalExpects() = _noop]) { + void canHandleAsync([void Function() additionalExpects = _noop]) { test('Can track async code', () async { expect(tracker.isStarted, false); expect(tracker.isTracking, false); From 78adc2b4ac74fe32c56ca361e8c66069fed26759 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 9 Dec 2019 17:27:35 -0800 Subject: [PATCH 0606/1215] Run dartfmt --fix (dart-lang/term_glyph#8) Drops optional new and const. --- pkgs/term_glyph/lib/term_glyph.dart | 4 ++-- pkgs/term_glyph/tool/generate.dart | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/pkgs/term_glyph/lib/term_glyph.dart b/pkgs/term_glyph/lib/term_glyph.dart index 57c762e55..b7361be6d 100644 --- a/pkgs/term_glyph/lib/term_glyph.dart +++ b/pkgs/term_glyph/lib/term_glyph.dart @@ -10,10 +10,10 @@ import 'src/generated/glyph_set.dart'; import 'src/generated/unicode_glyph_set.dart'; /// A [GlyphSet] that always returns ASCII glyphs. -const GlyphSet asciiGlyphs = const AsciiGlyphSet(); +const GlyphSet asciiGlyphs = AsciiGlyphSet(); /// A [GlyphSet] that always returns Unicode glyphs. -const GlyphSet unicodeGlyphs = const UnicodeGlyphSet(); +const GlyphSet unicodeGlyphs = UnicodeGlyphSet(); /// Returns [asciiGlyphs] if [ascii] is `true` or [unicodeGlyphs] otherwise. /// diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index b4b3e431c..370994f96 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -8,13 +8,13 @@ import 'package:csv/csv.dart'; import 'package:meta/meta.dart'; void main() { - var csv = new CsvCodec(eol: "\n"); - var data = csv.decoder.convert(new File("data.csv").readAsStringSync()); + var csv = CsvCodec(eol: "\n"); + var data = csv.decoder.convert(File("data.csv").readAsStringSync()); // Remove comments and empty lines. data.removeWhere((row) => row.length < 3); - new Directory("lib/src/generated").createSync(recursive: true); + Directory("lib/src/generated").createSync(recursive: true); _writeGlyphSetInterface(data); _writeGlyphSet(data, ascii: false); @@ -29,8 +29,8 @@ void main() { /// Writes `lib/src/generated/glyph_set.dart`. void _writeGlyphSetInterface(List data) { - var file = new File("lib/src/generated/glyph_set.dart") - .openSync(mode: FileMode.write); + var file = + File("lib/src/generated/glyph_set.dart").openSync(mode: FileMode.write); file.writeStringSync(r""" // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -84,9 +84,9 @@ void _writeGlyphSetInterface(List data) { /// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes /// the Unicode glyph set. void _writeGlyphSet(List data, {@required bool ascii}) { - var file = new File( - "lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart") - .openSync(mode: FileMode.write); + var file = + File("lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart") + .openSync(mode: FileMode.write); var className = "${ascii ? "Ascii" : "Unicode"}GlyphSet"; file.writeStringSync(""" @@ -126,8 +126,8 @@ void _writeGlyphSet(List data, {@required bool ascii}) { /// Writes `lib/src/generated/top_level.dart`. void _writeTopLevel(List data) { - var file = new File("lib/src/generated/top_level.dart") - .openSync(mode: FileMode.write); + var file = + File("lib/src/generated/top_level.dart").openSync(mode: FileMode.write); file.writeStringSync(""" // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file From b1a5507ed3dd26ee9dcb402ecfca85503f4f3f3a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 9 Dec 2019 17:39:36 -0800 Subject: [PATCH 0607/1215] Enforce and fix package:pedantic lints (dart-lang/term_glyph#9) - annotate_overrides - prefer_single_quotes Update `tool/generate.dart` to prefer single quotes and add override annotations. Regenerate files. Fix other cases by hand. --- pkgs/term_glyph/analysis_options.yaml | 1 + .../lib/src/generated/ascii_glyph_set.dart | 269 ++++++++++------ .../lib/src/generated/glyph_set.dart | 16 +- .../lib/src/generated/unicode_glyph_set.dart | 301 +++++++++++------- pkgs/term_glyph/test/symbol_test.dart | 48 +-- pkgs/term_glyph/tool/generate.dart | 64 ++-- 6 files changed, 412 insertions(+), 287 deletions(-) create mode 100644 pkgs/term_glyph/analysis_options.yaml diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml new file mode 100644 index 000000000..108d1058a --- /dev/null +++ b/pkgs/term_glyph/analysis_options.yaml @@ -0,0 +1 @@ +include: package:pedantic/analysis_options.yaml diff --git a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart index f470fe4a0..c233bf510 100644 --- a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart @@ -12,311 +12,372 @@ class AsciiGlyphSet implements GlyphSet { /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] /// otherwise. + @override String glyphOrAscii(String glyph, String alternative) => alternative; /// A bullet point. /// - /// Always "*" for [this]. - String get bullet => "*"; + /// Always '*' for [this]. + @override + String get bullet => '*'; /// A left-pointing arrow. /// /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// - /// Always "<" for [this]. - String get leftArrow => "<"; + /// Always '<' for [this]. + @override + String get leftArrow => '<'; /// A right-pointing arrow. /// /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// - /// Always ">" for [this]. - String get rightArrow => ">"; + /// Always '>' for [this]. + @override + String get rightArrow => '>'; /// An upwards-pointing arrow. /// - /// Always "^" for [this]. - String get upArrow => "^"; + /// Always '^' for [this]. + @override + String get upArrow => '^'; /// A downwards-pointing arrow. /// - /// Always "v" for [this]. - String get downArrow => "v"; + /// Always 'v' for [this]. + @override + String get downArrow => 'v'; /// A two-character left-pointing arrow. /// - /// Always "<=" for [this]. - String get longLeftArrow => "<="; + /// Always '<=' for [this]. + @override + String get longLeftArrow => '<='; /// A two-character right-pointing arrow. /// - /// Always "=>" for [this]. - String get longRightArrow => "=>"; + /// Always '=>' for [this]. + @override + String get longRightArrow => '=>'; /// A horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLine => "-"; + /// Always '-' for [this]. + @override + String get horizontalLine => '-'; /// A vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLine => "|"; + /// Always '|' for [this]. + @override + String get verticalLine => '|'; /// The upper left-hand corner of a box. /// - /// Always "," for [this]. - String get topLeftCorner => ","; + /// Always ',' for [this]. + @override + String get topLeftCorner => ','; /// The upper right-hand corner of a box. /// - /// Always "," for [this]. - String get topRightCorner => ","; + /// Always ',' for [this]. + @override + String get topRightCorner => ','; /// The lower left-hand corner of a box. /// /// Always "'" for [this]. + @override String get bottomLeftCorner => "'"; /// The lower right-hand corner of a box. /// /// Always "'" for [this]. + @override String get bottomRightCorner => "'"; /// An intersection of vertical and horizontal box lines. /// - /// Always "+" for [this]. - String get cross => "+"; + /// Always '+' for [this]. + @override + String get cross => '+'; /// A horizontal box line with a vertical line going up from the middle. /// - /// Always "+" for [this]. - String get teeUp => "+"; + /// Always '+' for [this]. + @override + String get teeUp => '+'; /// A horizontal box line with a vertical line going down from the middle. /// - /// Always "+" for [this]. - String get teeDown => "+"; + /// Always '+' for [this]. + @override + String get teeDown => '+'; /// A vertical box line with a horizontal line going left from the middle. /// - /// Always "+" for [this]. - String get teeLeft => "+"; + /// Always '+' for [this]. + @override + String get teeLeft => '+'; /// A vertical box line with a horizontal line going right from the middle. /// - /// Always "+" for [this]. - String get teeRight => "+"; + /// Always '+' for [this]. + @override + String get teeRight => '+'; /// The top half of a vertical box line. /// /// Always "'" for [this]. + @override String get upEnd => "'"; /// The bottom half of a vertical box line. /// - /// Always "," for [this]. - String get downEnd => ","; + /// Always ',' for [this]. + @override + String get downEnd => ','; /// The left half of a horizontal box line. /// - /// Always "-" for [this]. - String get leftEnd => "-"; + /// Always '-' for [this]. + @override + String get leftEnd => '-'; /// The right half of a horizontal box line. /// - /// Always "-" for [this]. - String get rightEnd => "-"; + /// Always '-' for [this]. + @override + String get rightEnd => '-'; /// A bold horizontal line that can be used to draw a box. /// - /// Always "=" for [this]. - String get horizontalLineBold => "="; + /// Always '=' for [this]. + @override + String get horizontalLineBold => '='; /// A bold vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineBold => "|"; + /// Always '|' for [this]. + @override + String get verticalLineBold => '|'; /// The bold upper left-hand corner of a box. /// - /// Always "," for [this]. - String get topLeftCornerBold => ","; + /// Always ',' for [this]. + @override + String get topLeftCornerBold => ','; /// The bold upper right-hand corner of a box. /// - /// Always "," for [this]. - String get topRightCornerBold => ","; + /// Always ',' for [this]. + @override + String get topRightCornerBold => ','; /// The bold lower left-hand corner of a box. /// /// Always "'" for [this]. + @override String get bottomLeftCornerBold => "'"; /// The bold lower right-hand corner of a box. /// /// Always "'" for [this]. + @override String get bottomRightCornerBold => "'"; /// An intersection of bold vertical and horizontal box lines. /// - /// Always "+" for [this]. - String get crossBold => "+"; + /// Always '+' for [this]. + @override + String get crossBold => '+'; /// A bold horizontal box line with a vertical line going up from the middle. /// - /// Always "+" for [this]. - String get teeUpBold => "+"; + /// Always '+' for [this]. + @override + String get teeUpBold => '+'; /// A bold horizontal box line with a vertical line going down from the middle. /// - /// Always "+" for [this]. - String get teeDownBold => "+"; + /// Always '+' for [this]. + @override + String get teeDownBold => '+'; /// A bold vertical box line with a horizontal line going left from the middle. /// - /// Always "+" for [this]. - String get teeLeftBold => "+"; + /// Always '+' for [this]. + @override + String get teeLeftBold => '+'; /// A bold vertical box line with a horizontal line going right from the middle. /// - /// Always "+" for [this]. - String get teeRightBold => "+"; + /// Always '+' for [this]. + @override + String get teeRightBold => '+'; /// The top half of a bold vertical box line. /// /// Always "'" for [this]. + @override String get upEndBold => "'"; /// The bottom half of a bold vertical box line. /// - /// Always "," for [this]. - String get downEndBold => ","; + /// Always ',' for [this]. + @override + String get downEndBold => ','; /// The left half of a bold horizontal box line. /// - /// Always "-" for [this]. - String get leftEndBold => "-"; + /// Always '-' for [this]. + @override + String get leftEndBold => '-'; /// The right half of a bold horizontal box line. /// - /// Always "-" for [this]. - String get rightEndBold => "-"; + /// Always '-' for [this]. + @override + String get rightEndBold => '-'; /// A double horizontal line that can be used to draw a box. /// - /// Always "=" for [this]. - String get horizontalLineDouble => "="; + /// Always '=' for [this]. + @override + String get horizontalLineDouble => '='; /// A double vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineDouble => "|"; + /// Always '|' for [this]. + @override + String get verticalLineDouble => '|'; /// The double upper left-hand corner of a box. /// - /// Always "," for [this]. - String get topLeftCornerDouble => ","; + /// Always ',' for [this]. + @override + String get topLeftCornerDouble => ','; /// The double upper right-hand corner of a box. /// - /// Always "," for [this]. - String get topRightCornerDouble => ","; + /// Always ',' for [this]. + @override + String get topRightCornerDouble => ','; /// The double lower left-hand corner of a box. /// /// Always '"' for [this]. + @override String get bottomLeftCornerDouble => '"'; /// The double lower right-hand corner of a box. /// /// Always '"' for [this]. + @override String get bottomRightCornerDouble => '"'; /// An intersection of double vertical and horizontal box lines. /// - /// Always "+" for [this]. - String get crossDouble => "+"; + /// Always '+' for [this]. + @override + String get crossDouble => '+'; /// A double horizontal box line with a vertical line going up from the middle. /// - /// Always "+" for [this]. - String get teeUpDouble => "+"; + /// Always '+' for [this]. + @override + String get teeUpDouble => '+'; /// A double horizontal box line with a vertical line going down from the middle. /// - /// Always "+" for [this]. - String get teeDownDouble => "+"; + /// Always '+' for [this]. + @override + String get teeDownDouble => '+'; /// A double vertical box line with a horizontal line going left from the middle. /// - /// Always "+" for [this]. - String get teeLeftDouble => "+"; + /// Always '+' for [this]. + @override + String get teeLeftDouble => '+'; /// A double vertical box line with a horizontal line going right from the middle. /// - /// Always "+" for [this]. - String get teeRightDouble => "+"; + /// Always '+' for [this]. + @override + String get teeRightDouble => '+'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineDoubleDash => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineDoubleDash => '-'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineDoubleDashBold => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineDoubleDashBold => '-'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineDoubleDash => "|"; + /// Always '|' for [this]. + @override + String get verticalLineDoubleDash => '|'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineDoubleDashBold => "|"; + /// Always '|' for [this]. + @override + String get verticalLineDoubleDashBold => '|'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineTripleDash => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineTripleDash => '-'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineTripleDashBold => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineTripleDashBold => '-'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineTripleDash => "|"; + /// Always '|' for [this]. + @override + String get verticalLineTripleDash => '|'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineTripleDashBold => "|"; + /// Always '|' for [this]. + @override + String get verticalLineTripleDashBold => '|'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineQuadrupleDash => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineQuadrupleDash => '-'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "-" for [this]. - String get horizontalLineQuadrupleDashBold => "-"; + /// Always '-' for [this]. + @override + String get horizontalLineQuadrupleDashBold => '-'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineQuadrupleDash => "|"; + /// Always '|' for [this]. + @override + String get verticalLineQuadrupleDash => '|'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "|" for [this]. - String get verticalLineQuadrupleDashBold => "|"; + /// Always '|' for [this]. + @override + String get verticalLineQuadrupleDashBold => '|'; } diff --git a/pkgs/term_glyph/lib/src/generated/glyph_set.dart b/pkgs/term_glyph/lib/src/generated/glyph_set.dart index 93676db9a..941da4f00 100644 --- a/pkgs/term_glyph/lib/src/generated/glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/glyph_set.dart @@ -14,17 +14,17 @@ /// /// /// Adds a vertical line to the left of [text]. /// /// -/// /// If [ascii] is `true`, this uses plain ASCII for the line. If it's -/// /// `false`, this uses Unicode characters. If it's `null`, it defaults -/// /// to [glyph.ascii]. -/// void addVerticalLine(String text, {bool ascii}) { +/// /// If [unicode] is `true`, this uses Unicode for the line. If it's +/// /// `false`, this uses plain ASCII characters. If it's `null`, it +/// /// defaults to [glyph.ascii]. +/// void addVerticalLine(String text, {bool unicode}) { /// var glyphs = -/// (ascii ?? glyph.ascii) ? glyph.asciiGlyphs : glyph.unicodeGlyphs; +/// (unicode ?? !glyph.ascii) ? glyph.unicodeGlyphs : glyph.asciiGlyphs; /// /// return text -/// .split("\n") -/// .map((line) => "${glyphs.verticalLine} $line") -/// .join("\n"); +/// .split('\n') +/// .map((line) => '${glyphs.verticalLine} $line') +/// .join('\n'); /// } /// ``` abstract class GlyphSet { diff --git a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart index 4e54068ac..bc6ad3348 100644 --- a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart @@ -12,311 +12,372 @@ class UnicodeGlyphSet implements GlyphSet { /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] /// otherwise. + @override String glyphOrAscii(String glyph, String alternative) => glyph; /// A bullet point. /// - /// Always "•" for [this]. - String get bullet => "•"; + /// Always '•' for [this]. + @override + String get bullet => '•'; /// A left-pointing arrow. /// /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// - /// Always "←" for [this]. - String get leftArrow => "←"; + /// Always '←' for [this]. + @override + String get leftArrow => '←'; /// A right-pointing arrow. /// /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// - /// Always "→" for [this]. - String get rightArrow => "→"; + /// Always '→' for [this]. + @override + String get rightArrow => '→'; /// An upwards-pointing arrow. /// - /// Always "↑" for [this]. - String get upArrow => "↑"; + /// Always '↑' for [this]. + @override + String get upArrow => '↑'; /// A downwards-pointing arrow. /// - /// Always "↓" for [this]. - String get downArrow => "↓"; + /// Always '↓' for [this]. + @override + String get downArrow => '↓'; /// A two-character left-pointing arrow. /// - /// Always "◀━" for [this]. - String get longLeftArrow => "◀━"; + /// Always '◀━' for [this]. + @override + String get longLeftArrow => '◀━'; /// A two-character right-pointing arrow. /// - /// Always "━▶" for [this]. - String get longRightArrow => "━▶"; + /// Always '━▶' for [this]. + @override + String get longRightArrow => '━▶'; /// A horizontal line that can be used to draw a box. /// - /// Always "─" for [this]. - String get horizontalLine => "─"; + /// Always '─' for [this]. + @override + String get horizontalLine => '─'; /// A vertical line that can be used to draw a box. /// - /// Always "│" for [this]. - String get verticalLine => "│"; + /// Always '│' for [this]. + @override + String get verticalLine => '│'; /// The upper left-hand corner of a box. /// - /// Always "┌" for [this]. - String get topLeftCorner => "┌"; + /// Always '┌' for [this]. + @override + String get topLeftCorner => '┌'; /// The upper right-hand corner of a box. /// - /// Always "┐" for [this]. - String get topRightCorner => "┐"; + /// Always '┐' for [this]. + @override + String get topRightCorner => '┐'; /// The lower left-hand corner of a box. /// - /// Always "└" for [this]. - String get bottomLeftCorner => "└"; + /// Always '└' for [this]. + @override + String get bottomLeftCorner => '└'; /// The lower right-hand corner of a box. /// - /// Always "┘" for [this]. - String get bottomRightCorner => "┘"; + /// Always '┘' for [this]. + @override + String get bottomRightCorner => '┘'; /// An intersection of vertical and horizontal box lines. /// - /// Always "┼" for [this]. - String get cross => "┼"; + /// Always '┼' for [this]. + @override + String get cross => '┼'; /// A horizontal box line with a vertical line going up from the middle. /// - /// Always "┴" for [this]. - String get teeUp => "┴"; + /// Always '┴' for [this]. + @override + String get teeUp => '┴'; /// A horizontal box line with a vertical line going down from the middle. /// - /// Always "┬" for [this]. - String get teeDown => "┬"; + /// Always '┬' for [this]. + @override + String get teeDown => '┬'; /// A vertical box line with a horizontal line going left from the middle. /// - /// Always "┤" for [this]. - String get teeLeft => "┤"; + /// Always '┤' for [this]. + @override + String get teeLeft => '┤'; /// A vertical box line with a horizontal line going right from the middle. /// - /// Always "├" for [this]. - String get teeRight => "├"; + /// Always '├' for [this]. + @override + String get teeRight => '├'; /// The top half of a vertical box line. /// - /// Always "╵" for [this]. - String get upEnd => "╵"; + /// Always '╵' for [this]. + @override + String get upEnd => '╵'; /// The bottom half of a vertical box line. /// - /// Always "╷" for [this]. - String get downEnd => "╷"; + /// Always '╷' for [this]. + @override + String get downEnd => '╷'; /// The left half of a horizontal box line. /// - /// Always "╴" for [this]. - String get leftEnd => "╴"; + /// Always '╴' for [this]. + @override + String get leftEnd => '╴'; /// The right half of a horizontal box line. /// - /// Always "╶" for [this]. - String get rightEnd => "╶"; + /// Always '╶' for [this]. + @override + String get rightEnd => '╶'; /// A bold horizontal line that can be used to draw a box. /// - /// Always "━" for [this]. - String get horizontalLineBold => "━"; + /// Always '━' for [this]. + @override + String get horizontalLineBold => '━'; /// A bold vertical line that can be used to draw a box. /// - /// Always "┃" for [this]. - String get verticalLineBold => "┃"; + /// Always '┃' for [this]. + @override + String get verticalLineBold => '┃'; /// The bold upper left-hand corner of a box. /// - /// Always "┏" for [this]. - String get topLeftCornerBold => "┏"; + /// Always '┏' for [this]. + @override + String get topLeftCornerBold => '┏'; /// The bold upper right-hand corner of a box. /// - /// Always "┓" for [this]. - String get topRightCornerBold => "┓"; + /// Always '┓' for [this]. + @override + String get topRightCornerBold => '┓'; /// The bold lower left-hand corner of a box. /// - /// Always "┗" for [this]. - String get bottomLeftCornerBold => "┗"; + /// Always '┗' for [this]. + @override + String get bottomLeftCornerBold => '┗'; /// The bold lower right-hand corner of a box. /// - /// Always "┛" for [this]. - String get bottomRightCornerBold => "┛"; + /// Always '┛' for [this]. + @override + String get bottomRightCornerBold => '┛'; /// An intersection of bold vertical and horizontal box lines. /// - /// Always "╋" for [this]. - String get crossBold => "╋"; + /// Always '╋' for [this]. + @override + String get crossBold => '╋'; /// A bold horizontal box line with a vertical line going up from the middle. /// - /// Always "┻" for [this]. - String get teeUpBold => "┻"; + /// Always '┻' for [this]. + @override + String get teeUpBold => '┻'; /// A bold horizontal box line with a vertical line going down from the middle. /// - /// Always "┳" for [this]. - String get teeDownBold => "┳"; + /// Always '┳' for [this]. + @override + String get teeDownBold => '┳'; /// A bold vertical box line with a horizontal line going left from the middle. /// - /// Always "┫" for [this]. - String get teeLeftBold => "┫"; + /// Always '┫' for [this]. + @override + String get teeLeftBold => '┫'; /// A bold vertical box line with a horizontal line going right from the middle. /// - /// Always "┣" for [this]. - String get teeRightBold => "┣"; + /// Always '┣' for [this]. + @override + String get teeRightBold => '┣'; /// The top half of a bold vertical box line. /// - /// Always "╹" for [this]. - String get upEndBold => "╹"; + /// Always '╹' for [this]. + @override + String get upEndBold => '╹'; /// The bottom half of a bold vertical box line. /// - /// Always "╻" for [this]. - String get downEndBold => "╻"; + /// Always '╻' for [this]. + @override + String get downEndBold => '╻'; /// The left half of a bold horizontal box line. /// - /// Always "╸" for [this]. - String get leftEndBold => "╸"; + /// Always '╸' for [this]. + @override + String get leftEndBold => '╸'; /// The right half of a bold horizontal box line. /// - /// Always "╺" for [this]. - String get rightEndBold => "╺"; + /// Always '╺' for [this]. + @override + String get rightEndBold => '╺'; /// A double horizontal line that can be used to draw a box. /// - /// Always "═" for [this]. - String get horizontalLineDouble => "═"; + /// Always '═' for [this]. + @override + String get horizontalLineDouble => '═'; /// A double vertical line that can be used to draw a box. /// - /// Always "║" for [this]. - String get verticalLineDouble => "║"; + /// Always '║' for [this]. + @override + String get verticalLineDouble => '║'; /// The double upper left-hand corner of a box. /// - /// Always "╔" for [this]. - String get topLeftCornerDouble => "╔"; + /// Always '╔' for [this]. + @override + String get topLeftCornerDouble => '╔'; /// The double upper right-hand corner of a box. /// - /// Always "╗" for [this]. - String get topRightCornerDouble => "╗"; + /// Always '╗' for [this]. + @override + String get topRightCornerDouble => '╗'; /// The double lower left-hand corner of a box. /// - /// Always "╚" for [this]. - String get bottomLeftCornerDouble => "╚"; + /// Always '╚' for [this]. + @override + String get bottomLeftCornerDouble => '╚'; /// The double lower right-hand corner of a box. /// - /// Always "╝" for [this]. - String get bottomRightCornerDouble => "╝"; + /// Always '╝' for [this]. + @override + String get bottomRightCornerDouble => '╝'; /// An intersection of double vertical and horizontal box lines. /// - /// Always "╬" for [this]. - String get crossDouble => "╬"; + /// Always '╬' for [this]. + @override + String get crossDouble => '╬'; /// A double horizontal box line with a vertical line going up from the middle. /// - /// Always "╩" for [this]. - String get teeUpDouble => "╩"; + /// Always '╩' for [this]. + @override + String get teeUpDouble => '╩'; /// A double horizontal box line with a vertical line going down from the middle. /// - /// Always "╦" for [this]. - String get teeDownDouble => "╦"; + /// Always '╦' for [this]. + @override + String get teeDownDouble => '╦'; /// A double vertical box line with a horizontal line going left from the middle. /// - /// Always "╣" for [this]. - String get teeLeftDouble => "╣"; + /// Always '╣' for [this]. + @override + String get teeLeftDouble => '╣'; /// A double vertical box line with a horizontal line going right from the middle. /// - /// Always "╠" for [this]. - String get teeRightDouble => "╠"; + /// Always '╠' for [this]. + @override + String get teeRightDouble => '╠'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "╌" for [this]. - String get horizontalLineDoubleDash => "╌"; + /// Always '╌' for [this]. + @override + String get horizontalLineDoubleDash => '╌'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "╍" for [this]. - String get horizontalLineDoubleDashBold => "╍"; + /// Always '╍' for [this]. + @override + String get horizontalLineDoubleDashBold => '╍'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "╎" for [this]. - String get verticalLineDoubleDash => "╎"; + /// Always '╎' for [this]. + @override + String get verticalLineDoubleDash => '╎'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "╏" for [this]. - String get verticalLineDoubleDashBold => "╏"; + /// Always '╏' for [this]. + @override + String get verticalLineDoubleDashBold => '╏'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "┄" for [this]. - String get horizontalLineTripleDash => "┄"; + /// Always '┄' for [this]. + @override + String get horizontalLineTripleDash => '┄'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "┅" for [this]. - String get horizontalLineTripleDashBold => "┅"; + /// Always '┅' for [this]. + @override + String get horizontalLineTripleDashBold => '┅'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "┆" for [this]. - String get verticalLineTripleDash => "┆"; + /// Always '┆' for [this]. + @override + String get verticalLineTripleDash => '┆'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "┇" for [this]. - String get verticalLineTripleDashBold => "┇"; + /// Always '┇' for [this]. + @override + String get verticalLineTripleDashBold => '┇'; /// A dashed horizontal line that can be used to draw a box. /// - /// Always "┈" for [this]. - String get horizontalLineQuadrupleDash => "┈"; + /// Always '┈' for [this]. + @override + String get horizontalLineQuadrupleDash => '┈'; /// A bold dashed horizontal line that can be used to draw a box. /// - /// Always "┉" for [this]. - String get horizontalLineQuadrupleDashBold => "┉"; + /// Always '┉' for [this]. + @override + String get horizontalLineQuadrupleDashBold => '┉'; /// A dashed vertical line that can be used to draw a box. /// - /// Always "┊" for [this]. - String get verticalLineQuadrupleDash => "┊"; + /// Always '┊' for [this]. + @override + String get verticalLineQuadrupleDash => '┊'; /// A bold dashed vertical line that can be used to draw a box. /// - /// Always "┋" for [this]. - String get verticalLineQuadrupleDashBold => "┋"; + /// Always '┋' for [this]. + @override + String get verticalLineQuadrupleDashBold => '┋'; } diff --git a/pkgs/term_glyph/test/symbol_test.dart b/pkgs/term_glyph/test/symbol_test.dart index 1e665e80c..22993a737 100644 --- a/pkgs/term_glyph/test/symbol_test.dart +++ b/pkgs/term_glyph/test/symbol_test.dart @@ -7,55 +7,55 @@ import 'package:test/test.dart'; import 'package:term_glyph/term_glyph.dart' as glyph; void main() { - group("with ascii = false", () { + group('with ascii = false', () { setUpAll(() { glyph.ascii = false; }); - test("glyph getters return Unicode versions", () { - expect(glyph.topLeftCorner, equals("┌")); - expect(glyph.teeUpBold, equals("┻")); - expect(glyph.longLeftArrow, equals("◀━")); + test('glyph getters return Unicode versions', () { + expect(glyph.topLeftCorner, equals('┌')); + expect(glyph.teeUpBold, equals('┻')); + expect(glyph.longLeftArrow, equals('◀━')); }); - test("glyphOrAscii returns the first argument", () { - expect(glyph.glyphOrAscii("A", "B"), equals("A")); + test('glyphOrAscii returns the first argument', () { + expect(glyph.glyphOrAscii('A', 'B'), equals('A')); }); - test("glyphs returns unicodeGlyphs", () { + test('glyphs returns unicodeGlyphs', () { expect(glyph.glyphs, equals(glyph.unicodeGlyphs)); }); - test("asciiGlyphs still returns ASCII characters", () { - expect(glyph.asciiGlyphs.topLeftCorner, equals(",")); - expect(glyph.asciiGlyphs.teeUpBold, equals("+")); - expect(glyph.asciiGlyphs.longLeftArrow, equals("<=")); + test('asciiGlyphs still returns ASCII characters', () { + expect(glyph.asciiGlyphs.topLeftCorner, equals(',')); + expect(glyph.asciiGlyphs.teeUpBold, equals('+')); + expect(glyph.asciiGlyphs.longLeftArrow, equals('<=')); }); }); - group("with ascii = true", () { + group('with ascii = true', () { setUpAll(() { glyph.ascii = true; }); - test("glyphs return ASCII versions", () { - expect(glyph.topLeftCorner, equals(",")); - expect(glyph.teeUpBold, equals("+")); - expect(glyph.longLeftArrow, equals("<=")); + test('glyphs return ASCII versions', () { + expect(glyph.topLeftCorner, equals(',')); + expect(glyph.teeUpBold, equals('+')); + expect(glyph.longLeftArrow, equals('<=')); }); - test("glyphOrAscii returns the second argument", () { - expect(glyph.glyphOrAscii("A", "B"), equals("B")); + test('glyphOrAscii returns the second argument', () { + expect(glyph.glyphOrAscii('A', 'B'), equals('B')); }); - test("glyphs returns asciiGlyphs", () { + test('glyphs returns asciiGlyphs', () { expect(glyph.glyphs, equals(glyph.asciiGlyphs)); }); - test("unicodeGlyphs still returns Unicode characters", () { - expect(glyph.unicodeGlyphs.topLeftCorner, equals("┌")); - expect(glyph.unicodeGlyphs.teeUpBold, equals("┻")); - expect(glyph.unicodeGlyphs.longLeftArrow, equals("◀━")); + test('unicodeGlyphs still returns Unicode characters', () { + expect(glyph.unicodeGlyphs.topLeftCorner, equals('┌')); + expect(glyph.unicodeGlyphs.teeUpBold, equals('┻')); + expect(glyph.unicodeGlyphs.longLeftArrow, equals('◀━')); }); }); } diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 370994f96..04a919b1f 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -8,13 +8,13 @@ import 'package:csv/csv.dart'; import 'package:meta/meta.dart'; void main() { - var csv = CsvCodec(eol: "\n"); - var data = csv.decoder.convert(File("data.csv").readAsStringSync()); + var csv = CsvCodec(eol: '\n'); + var data = csv.decoder.convert(File('data.csv').readAsStringSync()); // Remove comments and empty lines. data.removeWhere((row) => row.length < 3); - Directory("lib/src/generated").createSync(recursive: true); + Directory('lib/src/generated').createSync(recursive: true); _writeGlyphSetInterface(data); _writeGlyphSet(data, ascii: false); @@ -22,7 +22,7 @@ void main() { _writeTopLevel(data); var result = Process.runSync( - "pub", ["run", "dart_style:format", "-w", "lib/src/generated"]); + 'pub', ['run', 'dart_style:format', '-w', 'lib/src/generated']); print(result.stderr); exit(result.exitCode); } @@ -30,8 +30,8 @@ void main() { /// Writes `lib/src/generated/glyph_set.dart`. void _writeGlyphSetInterface(List data) { var file = - File("lib/src/generated/glyph_set.dart").openSync(mode: FileMode.write); - file.writeStringSync(r""" + File('lib/src/generated/glyph_set.dart').openSync(mode: FileMode.write); + file.writeStringSync(r''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. @@ -56,26 +56,26 @@ void _writeGlyphSetInterface(List data) { /// (unicode ?? !glyph.ascii) ? glyph.unicodeGlyphs : glyph.asciiGlyphs; /// /// return text - /// .split("\n") - /// .map((line) => "${glyphs.verticalLine} $line") - /// .join("\n"); + /// .split('\n') + /// .map((line) => '${glyphs.verticalLine} $line') + /// .join('\n'); /// } /// ``` abstract class GlyphSet { /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] /// otherwise. String glyphOrAscii(String glyph, String alternative); - """); + '''); for (var glyph in data) { - for (var line in glyph[3].split("\n")) { - file.writeStringSync("/// $line\n"); + for (var line in glyph[3].split('\n')) { + file.writeStringSync('/// $line\n'); } - file.writeStringSync("String get ${glyph[0]};"); + file.writeStringSync('String get ${glyph[0]};'); } - file.writeStringSync("}"); + file.writeStringSync('}'); file.closeSync(); } @@ -85,11 +85,11 @@ void _writeGlyphSetInterface(List data) { /// the Unicode glyph set. void _writeGlyphSet(List data, {@required bool ascii}) { var file = - File("lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart") + File('lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart') .openSync(mode: FileMode.write); - var className = "${ascii ? "Ascii" : "Unicode"}GlyphSet"; - file.writeStringSync(""" + var className = '${ascii ? "Ascii" : "Unicode"}GlyphSet'; + file.writeStringSync(''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. @@ -103,33 +103,35 @@ void _writeGlyphSet(List data, {@required bool ascii}) { const $className(); /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] /// otherwise. + @override String glyphOrAscii(String glyph, String alternative) => ${ascii ? "alternative" : "glyph"}; - """); + '''); var index = ascii ? 2 : 1; for (var glyph in data) { - for (var line in glyph[3].split("\n")) { - file.writeStringSync("/// $line\n"); + for (var line in glyph[3].split('\n')) { + file.writeStringSync('/// $line\n'); } - file.writeStringSync(""" + file.writeStringSync(''' /// /// Always ${_quote(glyph[index])} for [this]. + @override String get ${glyph[0]} => ${_quote(glyph[index])}; - """); + '''); } - file.writeStringSync("}"); + file.writeStringSync('}'); file.closeSync(); } /// Writes `lib/src/generated/top_level.dart`. void _writeTopLevel(List data) { var file = - File("lib/src/generated/top_level.dart").openSync(mode: FileMode.write); + File('lib/src/generated/top_level.dart').openSync(mode: FileMode.write); - file.writeStringSync(""" + file.writeStringSync(''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // 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. @@ -137,22 +139,22 @@ void _writeTopLevel(List data) { // Don't modify this file by hand! It's generated by tool/generate.dart. import '../../term_glyph.dart' as glyph; - """); + '''); for (var glyph in data) { - for (var line in glyph[3].split("\n")) { - file.writeStringSync("/// $line\n"); + for (var line in glyph[3].split('\n')) { + file.writeStringSync('/// $line\n'); } - file.writeStringSync(""" + file.writeStringSync(''' /// /// If [ascii] is `false`, this is "${glyph[1]}". If it's `true`, this is /// "${glyph[2]}" instead. String get ${glyph[0]} => glyph.glyphs.${glyph[0]}; - """); + '''); } file.closeSync(); } -String _quote(String input) => input.contains('"') ? "'$input'" : '"$input"'; +String _quote(String input) => input.contains("'") ? '"$input"' : "'$input'"; From 9cac3aebab3477eb6ee574b5bfa3a327567996f6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 11 Dec 2019 12:43:46 -0800 Subject: [PATCH 0608/1215] Handle `null` returns from cancelled subscriptions (dart-lang/stream_transform#97) A call to `StreamSubscription.cancel` is allowed to return `null`, though it never does using the `StreamController` from the SDK. If a custom Stream implementation does synchronously cancel and return `null` it could cause problems in a number of transformers which would attempt to `Future.wait` on the results of the cancels. - Update the places using `Future.wait` to filter out null results first. - Refactor some places to use collection literals and conditional elements. - Filter out nulls first, and if every canceled subscription was synchronous skip the call to `Future.wait` entirely. - Add a custom Stream implementation which always returns `null` when it's subscription is canceled as a test utility. - Add tests that would fail without the null filtering on each implementation that was updated. --- pkgs/stream_transform/CHANGELOG.md | 7 ++++++ .../lib/src/aggregate_sample.dart | 6 +++-- .../lib/src/combine_latest.dart | 14 +++++++---- pkgs/stream_transform/lib/src/merge.dart | 15 ++++++++--- pkgs/stream_transform/lib/src/switch.dart | 21 ++++++---------- pkgs/stream_transform/pubspec.yaml | 3 ++- .../test/async_map_sample_test.dart | 9 +++++++ pkgs/stream_transform/test/buffer_test.dart | 9 +++++++ .../test/combine_latest_all_test.dart | 12 +++++++++ .../test/combine_latest_test.dart | 13 ++++++++++ .../test/concurrent_async_expand_test.dart | 15 +++++++++++ pkgs/stream_transform/test/merge_test.dart | 13 ++++++++++ pkgs/stream_transform/test/switch_test.dart | 13 ++++++++++ pkgs/stream_transform/test/utils.dart | 25 +++++++++++++++++++ 14 files changed, 150 insertions(+), 25 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 686f91921..5342392cc 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.1.1 + +- Fix a bug in `asyncMapSample`, `buffer`, `combineLatest`, + `combineLatestAll`, `merge`, and `mergeAll` which would cause an exception + when cancelling a subscription after using the transformer if the original + stream(s) returned `null` from cancelling their subscriptions. + ## 1.1.0 - Add `concurrentAsyncExpand` to interleave events emitted by multiple sub diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index 5ddeb1017..88fc4909a 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -107,8 +107,10 @@ class AggregateSample extends StreamTransformerBase { } else { triggerSub.pause(); } - if (toCancel.isEmpty) return null; - return Future.wait(toCancel.map((s) => s.cancel())); + var cancels = + toCancel.map((s) => s.cancel()).where((f) => f != null).toList(); + if (cancels.isEmpty) return null; + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 7fee05dce..303b16a4a 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -175,11 +175,11 @@ class _CombineLatest extends StreamTransformerBase { }; } controller.onCancel = () { - var cancelSource = sourceSubscription.cancel(); - var cancelOther = otherSubscription.cancel(); + var cancels = [sourceSubscription.cancel(), otherSubscription.cancel()] + .where((f) => f != null); sourceSubscription = null; otherSubscription = null; - return Future.wait([cancelSource, cancelOther]); + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; @@ -249,8 +249,12 @@ class _CombineLatestAll extends StreamTransformerBase> { }; } controller.onCancel = () { - if (subscriptions.isEmpty) return null; - return Future.wait(subscriptions.map((s) => s.cancel())); + var cancels = subscriptions + .map((s) => s.cancel()) + .where((f) => f != null) + .toList(); + if (cancels.isEmpty) return null; + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 99d19c92b..f654d35a5 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -124,8 +124,12 @@ class _Merge extends StreamTransformerBase { }; } controller.onCancel = () { - if (subscriptions.isEmpty) return null; - return Future.wait(subscriptions.map((s) => s.cancel())); + var cancels = subscriptions + .map((s) => s.cancel()) + .where((f) => f != null) + .toList(); + if (cancels.isEmpty) return null; + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; @@ -172,7 +176,12 @@ class _MergeExpanded extends StreamTransformerBase, T> { }; } controller.onCancel = () { - return Future.wait(subscriptions.map((s) => s.cancel())); + var cancels = subscriptions + .map((s) => s.cancel()) + .where((f) => f != null) + .toList(); + if (cancels.isEmpty) return null; + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index b30556a8a..5125d576b 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -41,15 +41,11 @@ class _SwitchTransformer extends StreamTransformerBase, T> { ? StreamController.broadcast(sync: true) : StreamController(sync: true); - StreamSubscription> outerSubscription; - controller.onListen = () { - assert(outerSubscription == null); - StreamSubscription innerSubscription; var outerStreamDone = false; - outerSubscription = outer.listen( + final outerSubscription = outer.listen( (innerStream) { innerSubscription?.cancel(); innerSubscription = innerStream.listen(controller.add, @@ -75,15 +71,12 @@ class _SwitchTransformer extends StreamTransformerBase, T> { }; } controller.onCancel = () { - var toCancel = >[]; - if (!outerStreamDone) toCancel.add(outerSubscription); - if (innerSubscription != null) { - toCancel.add(innerSubscription); - } - outerSubscription = null; - innerSubscription = null; - if (toCancel.isEmpty) return null; - return Future.wait(toCancel.map((s) => s.cancel())); + var cancels = [ + if (!outerStreamDone) outerSubscription.cancel(), + if (innerSubscription != null) innerSubscription.cancel(), + ].where((f) => f != null); + if (cancels.isEmpty) return null; + return Future.wait(cancels).then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 1c8d88eed..62a7fa627 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,11 +1,12 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.1.1-dev +version: 1.1.1 environment: sdk: ">=2.6.0 <3.0.0" dev_dependencies: + async: ^2.0.0 pedantic: ^1.5.0 test: ^1.0.0 diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 119e0c85e..9c37cd491 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -200,4 +200,13 @@ void main() { } }); } + test('handles null response from cancel', () async { + var controller = StreamController(); + + var subscription = NullOnCancelStream(controller.stream) + .asyncMapSample((_) async {}) + .listen(null); + + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 580058600..80a793cbc 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -243,4 +243,13 @@ void main() { ]); }); } + + test('handles null response from cancel', () async { + var controller = StreamController(); + var trigger = StreamController(); + var subscription = NullOnCancelStream(controller.stream) + .buffer(trigger.stream) + .listen(null); + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart index 2943449fd..d57d61852 100644 --- a/pkgs/stream_transform/test/combine_latest_all_test.dart +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -8,6 +8,8 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + Future tick() => Future(() {}); void main() { @@ -164,4 +166,14 @@ void main() { }); }); }); + + test('handles null response from cancel', () async { + var source = StreamController(); + var other = StreamController(); + + var subscription = NullOnCancelStream(source.stream) + .combineLatestAll([NullOnCancelStream(other.stream)]).listen(null); + + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index 2b35e2c21..4ea94994d 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -9,6 +9,8 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { group('combineLatest', () { test('flows through combine callback', () async { @@ -168,6 +170,17 @@ void main() { }); }); }); + + test('handles null response from cancel', () async { + var source = StreamController(); + var other = StreamController(); + + var subscription = NullOnCancelStream(source.stream) + .combineLatest(NullOnCancelStream(other.stream), (a, b) => null) + .listen(null); + + await subscription.cancel(); + }); } class _NumberedException implements Exception { diff --git a/pkgs/stream_transform/test/concurrent_async_expand_test.dart b/pkgs/stream_transform/test/concurrent_async_expand_test.dart index f843c6fff..9ed02d036 100644 --- a/pkgs/stream_transform/test/concurrent_async_expand_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_expand_test.dart @@ -184,4 +184,19 @@ void main() { }); } } + + test('hendles null response from cancel', () async { + var source = StreamController(); + var other = StreamController(); + + var subscription = NullOnCancelStream(source.stream) + .concurrentAsyncExpand((_) => NullOnCancelStream(other.stream)) + .listen(null); + + source.add(1); + + await Future(() {}); + + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 24cd76b16..2eef5d1a5 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -8,6 +8,8 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'utils.dart'; + void main() { group('merge', () { test('includes all values', () async { @@ -138,4 +140,15 @@ void main() { expect(secondListenerValues, [1, 2, 3, 4, 5, 6]); }); }); + + test('handles null response rom cancel', () async { + var source = StreamController(); + var other = StreamController(); + + var subscription = NullOnCancelStream(source.stream) + .merge(NullOnCancelStream(other.stream)) + .listen(null); + + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index ba265033b..40030f0d2 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -146,4 +146,17 @@ void main() { expect(transformed.isBroadcast, true); }); }); + + test('handles null response from cancel', () async { + var outer = StreamController>(); + var inner = StreamController(); + + var subscription = + NullOnCancelStream(outer.stream).switchLatest().listen(null); + + outer.add(NullOnCancelStream(inner.stream)); + await Future(() {}); + + await subscription.cancel(); + }); } diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart index b6196d687..4aa583751 100644 --- a/pkgs/stream_transform/test/utils.dart +++ b/pkgs/stream_transform/test/utils.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:async/async.dart'; + /// Cycle the event loop to ensure timers are started, then wait for a delay /// longer than [milliseconds] to allow for the timer to fire. Future waitForTimer(int milliseconds) => @@ -23,3 +25,26 @@ StreamController createController(String streamType) { } const streamTypes = ['single subscription', 'broadcast']; + +class NullOnCancelStream extends StreamView { + final Stream _stream; + + NullOnCancelStream(this._stream) : super(_stream); + + @override + StreamSubscription listen(void Function(T) onData, + {Function onError, void Function() onDone, bool cancelOnError}) => + _NullOnCancelSubscription(_stream.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError)); +} + +class _NullOnCancelSubscription extends DelegatingStreamSubscription { + final StreamSubscription _subscription; + _NullOnCancelSubscription(this._subscription) : super(_subscription); + + @override + Future cancel() { + _subscription.cancel(); + return null; + } +} From af16ef10241425d54fc17a9657a6ec8508a255cb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 11 Dec 2019 17:17:53 -0800 Subject: [PATCH 0609/1215] Drop the doc comments on overrides (dart-lang/term_glyph#10) These classes are not public and so the docs don't show up on the pub site. Even if they did show up the comments as is only duplicate the information from the interface (which dartdoc would show anyway) and the implementation (which dartdoc also shows). --- .../lib/src/generated/ascii_glyph_set.dart | 246 ------------------ .../lib/src/generated/unicode_glyph_set.dart | 246 ------------------ pkgs/term_glyph/pubspec.yaml | 2 +- pkgs/term_glyph/tool/generate.dart | 6 - 4 files changed, 1 insertion(+), 499 deletions(-) diff --git a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart index c233bf510..e0c3a4994 100644 --- a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart @@ -14,370 +14,124 @@ class AsciiGlyphSet implements GlyphSet { /// otherwise. @override String glyphOrAscii(String glyph, String alternative) => alternative; - - /// A bullet point. - /// - /// Always '*' for [this]. @override String get bullet => '*'; - - /// A left-pointing arrow. - /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. - /// - /// Always '<' for [this]. @override String get leftArrow => '<'; - - /// A right-pointing arrow. - /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. - /// - /// Always '>' for [this]. @override String get rightArrow => '>'; - - /// An upwards-pointing arrow. - /// - /// Always '^' for [this]. @override String get upArrow => '^'; - - /// A downwards-pointing arrow. - /// - /// Always 'v' for [this]. @override String get downArrow => 'v'; - - /// A two-character left-pointing arrow. - /// - /// Always '<=' for [this]. @override String get longLeftArrow => '<='; - - /// A two-character right-pointing arrow. - /// - /// Always '=>' for [this]. @override String get longRightArrow => '=>'; - - /// A horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLine => '-'; - - /// A vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLine => '|'; - - /// The upper left-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topLeftCorner => ','; - - /// The upper right-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topRightCorner => ','; - - /// The lower left-hand corner of a box. - /// - /// Always "'" for [this]. @override String get bottomLeftCorner => "'"; - - /// The lower right-hand corner of a box. - /// - /// Always "'" for [this]. @override String get bottomRightCorner => "'"; - - /// An intersection of vertical and horizontal box lines. - /// - /// Always '+' for [this]. @override String get cross => '+'; - - /// A horizontal box line with a vertical line going up from the middle. - /// - /// Always '+' for [this]. @override String get teeUp => '+'; - - /// A horizontal box line with a vertical line going down from the middle. - /// - /// Always '+' for [this]. @override String get teeDown => '+'; - - /// A vertical box line with a horizontal line going left from the middle. - /// - /// Always '+' for [this]. @override String get teeLeft => '+'; - - /// A vertical box line with a horizontal line going right from the middle. - /// - /// Always '+' for [this]. @override String get teeRight => '+'; - - /// The top half of a vertical box line. - /// - /// Always "'" for [this]. @override String get upEnd => "'"; - - /// The bottom half of a vertical box line. - /// - /// Always ',' for [this]. @override String get downEnd => ','; - - /// The left half of a horizontal box line. - /// - /// Always '-' for [this]. @override String get leftEnd => '-'; - - /// The right half of a horizontal box line. - /// - /// Always '-' for [this]. @override String get rightEnd => '-'; - - /// A bold horizontal line that can be used to draw a box. - /// - /// Always '=' for [this]. @override String get horizontalLineBold => '='; - - /// A bold vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineBold => '|'; - - /// The bold upper left-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topLeftCornerBold => ','; - - /// The bold upper right-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topRightCornerBold => ','; - - /// The bold lower left-hand corner of a box. - /// - /// Always "'" for [this]. @override String get bottomLeftCornerBold => "'"; - - /// The bold lower right-hand corner of a box. - /// - /// Always "'" for [this]. @override String get bottomRightCornerBold => "'"; - - /// An intersection of bold vertical and horizontal box lines. - /// - /// Always '+' for [this]. @override String get crossBold => '+'; - - /// A bold horizontal box line with a vertical line going up from the middle. - /// - /// Always '+' for [this]. @override String get teeUpBold => '+'; - - /// A bold horizontal box line with a vertical line going down from the middle. - /// - /// Always '+' for [this]. @override String get teeDownBold => '+'; - - /// A bold vertical box line with a horizontal line going left from the middle. - /// - /// Always '+' for [this]. @override String get teeLeftBold => '+'; - - /// A bold vertical box line with a horizontal line going right from the middle. - /// - /// Always '+' for [this]. @override String get teeRightBold => '+'; - - /// The top half of a bold vertical box line. - /// - /// Always "'" for [this]. @override String get upEndBold => "'"; - - /// The bottom half of a bold vertical box line. - /// - /// Always ',' for [this]. @override String get downEndBold => ','; - - /// The left half of a bold horizontal box line. - /// - /// Always '-' for [this]. @override String get leftEndBold => '-'; - - /// The right half of a bold horizontal box line. - /// - /// Always '-' for [this]. @override String get rightEndBold => '-'; - - /// A double horizontal line that can be used to draw a box. - /// - /// Always '=' for [this]. @override String get horizontalLineDouble => '='; - - /// A double vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineDouble => '|'; - - /// The double upper left-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topLeftCornerDouble => ','; - - /// The double upper right-hand corner of a box. - /// - /// Always ',' for [this]. @override String get topRightCornerDouble => ','; - - /// The double lower left-hand corner of a box. - /// - /// Always '"' for [this]. @override String get bottomLeftCornerDouble => '"'; - - /// The double lower right-hand corner of a box. - /// - /// Always '"' for [this]. @override String get bottomRightCornerDouble => '"'; - - /// An intersection of double vertical and horizontal box lines. - /// - /// Always '+' for [this]. @override String get crossDouble => '+'; - - /// A double horizontal box line with a vertical line going up from the middle. - /// - /// Always '+' for [this]. @override String get teeUpDouble => '+'; - - /// A double horizontal box line with a vertical line going down from the middle. - /// - /// Always '+' for [this]. @override String get teeDownDouble => '+'; - - /// A double vertical box line with a horizontal line going left from the middle. - /// - /// Always '+' for [this]. @override String get teeLeftDouble => '+'; - - /// A double vertical box line with a horizontal line going right from the middle. - /// - /// Always '+' for [this]. @override String get teeRightDouble => '+'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineDoubleDash => '-'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineDoubleDashBold => '-'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineDoubleDash => '|'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineDoubleDashBold => '|'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineTripleDash => '-'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineTripleDashBold => '-'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineTripleDash => '|'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineTripleDashBold => '|'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineQuadrupleDash => '-'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '-' for [this]. @override String get horizontalLineQuadrupleDashBold => '-'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineQuadrupleDash => '|'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '|' for [this]. @override String get verticalLineQuadrupleDashBold => '|'; } diff --git a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart index bc6ad3348..1737b391b 100644 --- a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart @@ -14,370 +14,124 @@ class UnicodeGlyphSet implements GlyphSet { /// otherwise. @override String glyphOrAscii(String glyph, String alternative) => glyph; - - /// A bullet point. - /// - /// Always '•' for [this]. @override String get bullet => '•'; - - /// A left-pointing arrow. - /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. - /// - /// Always '←' for [this]. @override String get leftArrow => '←'; - - /// A right-pointing arrow. - /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. - /// - /// Always '→' for [this]. @override String get rightArrow => '→'; - - /// An upwards-pointing arrow. - /// - /// Always '↑' for [this]. @override String get upArrow => '↑'; - - /// A downwards-pointing arrow. - /// - /// Always '↓' for [this]. @override String get downArrow => '↓'; - - /// A two-character left-pointing arrow. - /// - /// Always '◀━' for [this]. @override String get longLeftArrow => '◀━'; - - /// A two-character right-pointing arrow. - /// - /// Always '━▶' for [this]. @override String get longRightArrow => '━▶'; - - /// A horizontal line that can be used to draw a box. - /// - /// Always '─' for [this]. @override String get horizontalLine => '─'; - - /// A vertical line that can be used to draw a box. - /// - /// Always '│' for [this]. @override String get verticalLine => '│'; - - /// The upper left-hand corner of a box. - /// - /// Always '┌' for [this]. @override String get topLeftCorner => '┌'; - - /// The upper right-hand corner of a box. - /// - /// Always '┐' for [this]. @override String get topRightCorner => '┐'; - - /// The lower left-hand corner of a box. - /// - /// Always '└' for [this]. @override String get bottomLeftCorner => '└'; - - /// The lower right-hand corner of a box. - /// - /// Always '┘' for [this]. @override String get bottomRightCorner => '┘'; - - /// An intersection of vertical and horizontal box lines. - /// - /// Always '┼' for [this]. @override String get cross => '┼'; - - /// A horizontal box line with a vertical line going up from the middle. - /// - /// Always '┴' for [this]. @override String get teeUp => '┴'; - - /// A horizontal box line with a vertical line going down from the middle. - /// - /// Always '┬' for [this]. @override String get teeDown => '┬'; - - /// A vertical box line with a horizontal line going left from the middle. - /// - /// Always '┤' for [this]. @override String get teeLeft => '┤'; - - /// A vertical box line with a horizontal line going right from the middle. - /// - /// Always '├' for [this]. @override String get teeRight => '├'; - - /// The top half of a vertical box line. - /// - /// Always '╵' for [this]. @override String get upEnd => '╵'; - - /// The bottom half of a vertical box line. - /// - /// Always '╷' for [this]. @override String get downEnd => '╷'; - - /// The left half of a horizontal box line. - /// - /// Always '╴' for [this]. @override String get leftEnd => '╴'; - - /// The right half of a horizontal box line. - /// - /// Always '╶' for [this]. @override String get rightEnd => '╶'; - - /// A bold horizontal line that can be used to draw a box. - /// - /// Always '━' for [this]. @override String get horizontalLineBold => '━'; - - /// A bold vertical line that can be used to draw a box. - /// - /// Always '┃' for [this]. @override String get verticalLineBold => '┃'; - - /// The bold upper left-hand corner of a box. - /// - /// Always '┏' for [this]. @override String get topLeftCornerBold => '┏'; - - /// The bold upper right-hand corner of a box. - /// - /// Always '┓' for [this]. @override String get topRightCornerBold => '┓'; - - /// The bold lower left-hand corner of a box. - /// - /// Always '┗' for [this]. @override String get bottomLeftCornerBold => '┗'; - - /// The bold lower right-hand corner of a box. - /// - /// Always '┛' for [this]. @override String get bottomRightCornerBold => '┛'; - - /// An intersection of bold vertical and horizontal box lines. - /// - /// Always '╋' for [this]. @override String get crossBold => '╋'; - - /// A bold horizontal box line with a vertical line going up from the middle. - /// - /// Always '┻' for [this]. @override String get teeUpBold => '┻'; - - /// A bold horizontal box line with a vertical line going down from the middle. - /// - /// Always '┳' for [this]. @override String get teeDownBold => '┳'; - - /// A bold vertical box line with a horizontal line going left from the middle. - /// - /// Always '┫' for [this]. @override String get teeLeftBold => '┫'; - - /// A bold vertical box line with a horizontal line going right from the middle. - /// - /// Always '┣' for [this]. @override String get teeRightBold => '┣'; - - /// The top half of a bold vertical box line. - /// - /// Always '╹' for [this]. @override String get upEndBold => '╹'; - - /// The bottom half of a bold vertical box line. - /// - /// Always '╻' for [this]. @override String get downEndBold => '╻'; - - /// The left half of a bold horizontal box line. - /// - /// Always '╸' for [this]. @override String get leftEndBold => '╸'; - - /// The right half of a bold horizontal box line. - /// - /// Always '╺' for [this]. @override String get rightEndBold => '╺'; - - /// A double horizontal line that can be used to draw a box. - /// - /// Always '═' for [this]. @override String get horizontalLineDouble => '═'; - - /// A double vertical line that can be used to draw a box. - /// - /// Always '║' for [this]. @override String get verticalLineDouble => '║'; - - /// The double upper left-hand corner of a box. - /// - /// Always '╔' for [this]. @override String get topLeftCornerDouble => '╔'; - - /// The double upper right-hand corner of a box. - /// - /// Always '╗' for [this]. @override String get topRightCornerDouble => '╗'; - - /// The double lower left-hand corner of a box. - /// - /// Always '╚' for [this]. @override String get bottomLeftCornerDouble => '╚'; - - /// The double lower right-hand corner of a box. - /// - /// Always '╝' for [this]. @override String get bottomRightCornerDouble => '╝'; - - /// An intersection of double vertical and horizontal box lines. - /// - /// Always '╬' for [this]. @override String get crossDouble => '╬'; - - /// A double horizontal box line with a vertical line going up from the middle. - /// - /// Always '╩' for [this]. @override String get teeUpDouble => '╩'; - - /// A double horizontal box line with a vertical line going down from the middle. - /// - /// Always '╦' for [this]. @override String get teeDownDouble => '╦'; - - /// A double vertical box line with a horizontal line going left from the middle. - /// - /// Always '╣' for [this]. @override String get teeLeftDouble => '╣'; - - /// A double vertical box line with a horizontal line going right from the middle. - /// - /// Always '╠' for [this]. @override String get teeRightDouble => '╠'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '╌' for [this]. @override String get horizontalLineDoubleDash => '╌'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '╍' for [this]. @override String get horizontalLineDoubleDashBold => '╍'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '╎' for [this]. @override String get verticalLineDoubleDash => '╎'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '╏' for [this]. @override String get verticalLineDoubleDashBold => '╏'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '┄' for [this]. @override String get horizontalLineTripleDash => '┄'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '┅' for [this]. @override String get horizontalLineTripleDashBold => '┅'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '┆' for [this]. @override String get verticalLineTripleDash => '┆'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '┇' for [this]. @override String get verticalLineTripleDashBold => '┇'; - - /// A dashed horizontal line that can be used to draw a box. - /// - /// Always '┈' for [this]. @override String get horizontalLineQuadrupleDash => '┈'; - - /// A bold dashed horizontal line that can be used to draw a box. - /// - /// Always '┉' for [this]. @override String get horizontalLineQuadrupleDashBold => '┉'; - - /// A dashed vertical line that can be used to draw a box. - /// - /// Always '┊' for [this]. @override String get verticalLineQuadrupleDash => '┊'; - - /// A bold dashed vertical line that can be used to draw a box. - /// - /// Always '┋' for [this]. @override String get verticalLineQuadrupleDashBold => '┋'; } diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 29ea7d6b6..9c650e3f1 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.1.0 +version: 1.1.1-dev description: Useful Unicode glyphs and ASCII substitutes. author: Dart Team diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 04a919b1f..6e18536f0 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -110,13 +110,7 @@ void _writeGlyphSet(List data, {@required bool ascii}) { var index = ascii ? 2 : 1; for (var glyph in data) { - for (var line in glyph[3].split('\n')) { - file.writeStringSync('/// $line\n'); - } - file.writeStringSync(''' - /// - /// Always ${_quote(glyph[index])} for [this]. @override String get ${glyph[0]} => ${_quote(glyph[index])}; '''); From 58e0f742c287a03aff27fb9882f04888c83affcc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 3 Jan 2020 14:02:43 -0800 Subject: [PATCH 0610/1215] Drop the _WhereType transformer definition (dart-lang/stream_transform#98) This was only required because of the challenges of being exposed as a `StreamTransformer` and the subtyping rules for the generic arguments. Now that we aren't exposing it as `StreamTransformer` we don't need extra complications. --- pkgs/stream_transform/lib/src/where.dart | 35 +----------------------- pkgs/stream_transform/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 850e9a9ab..8917cb4de 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -17,7 +17,7 @@ extension Where on Stream { /// [S] should be a subtype of the stream's generic type, otherwise nothing of /// type [S] could possibly be emitted, however there is no static or runtime /// checking that this is the case. - Stream whereType() => transform(_WhereType()); + Stream whereType() => where((e) => e is S).cast(); /// Like [where] but allows the [test] to return a [Future]. /// @@ -54,36 +54,3 @@ extension Where on Stream { })); } } - -class _WhereType extends StreamTransformerBase { - @override - Stream bind(Stream source) { - var controller = source.isBroadcast - ? StreamController.broadcast(sync: true) - : StreamController(sync: true); - - StreamSubscription subscription; - controller.onListen = () { - assert(subscription == null); - subscription = source.listen( - (value) { - if (value is R) controller.add(value); - }, - onError: controller.addError, - onDone: () { - subscription = null; - controller.close(); - }); - if (!source.isBroadcast) { - controller - ..onPause = subscription.pause - ..onResume = subscription.resume; - } - controller.onCancel = () { - subscription?.cancel(); - subscription = null; - }; - }; - return controller.stream; - } -} diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 62a7fa627..9f98a7129 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.1.1 +version: 1.1.2-dev environment: sdk: ">=2.6.0 <3.0.0" From 364b71fa00dc3ee711b09d74f74b38c0ea93792a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 14 Jan 2020 13:35:10 -0800 Subject: [PATCH 0611/1215] Fix implicit casts (dart-lang/stream_channel#49) - Add some explicit casts. - Cast a `Stream` to `Stream` since we always expect to get a List out. --- pkgs/stream_channel/CHANGELOG.md | 2 +- pkgs/stream_channel/analysis_options.yaml | 2 ++ pkgs/stream_channel/lib/src/multi_channel.dart | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4f345106a..842129238 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.1.0 +## 2.1.0-dev * Require Dart `2.2.0` or later. diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index df4128a17..b36c8749b 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,5 +1,7 @@ include: package:pedantic/analysis_options.yaml analyzer: + strong-mode: + implicit-casts: false # These are errors when building in Google errors: unused_import: error diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e0982ae19..79f247e08 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -140,8 +140,8 @@ class _MultiChannel extends StreamChannelMixin (message) => _inner.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _inner.stream.listen((message) { - var id = message[0]; + _innerStreamSubscription = _inner.stream.cast().listen((message) { + var id = message[0] as int; // If the channel was closed before an incoming message was processed, // ignore that message. @@ -156,7 +156,7 @@ class _MultiChannel extends StreamChannelMixin }); if (message.length > 1) { - controller.local.sink.add(message[1]); + controller.local.sink.add(message[1] as T); } else { // A message without data indicates that the channel has been closed. We // can just close the sink here without doing any more cleanup, because From 75f49eee3bd6ecd60d016ee106b38c7a8f9f1415 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 14 Jan 2020 15:11:08 -0800 Subject: [PATCH 0612/1215] Drop usages of Delegating*.typed (dart-lang/stream_channel#50) --- pkgs/stream_channel/lib/stream_channel.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index c806ec663..56937929a 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -176,5 +176,5 @@ abstract class StreamChannelMixin implements StreamChannel { @override StreamChannel cast() => StreamChannel( - DelegatingStream.typed(stream), DelegatingStreamSink.typed(sink)); + stream.cast(), StreamController(sync: true)..stream.cast().pipe(sink)); } From 10ef1f6b2eb0d880c3dbcce935b6325094659d53 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 16 Jan 2020 17:42:54 -0800 Subject: [PATCH 0613/1215] Fix test related to latest version of source_span (dart-lang/pubspec_parse#55) Bump min SDK to ensure tested SDKs support latest source_span Cleanup analysis_options.yaml --- pkgs/pubspec_parse/.travis.yml | 4 ++-- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/analysis_options.yaml | 8 ++------ pkgs/pubspec_parse/pubspec.yaml | 4 ++-- pkgs/pubspec_parse/test/dependency_test.dart | 8 ++++---- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index ccb1cafa5..66bff3db8 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - - 2.2.0 + - 2.6.0 - dev dart_task: @@ -16,7 +16,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.2.0 + - dart: 2.6.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index f2c254244..df5c0e827 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.6-dev + +- Update SDK requirement to `>=2.6.0 <3.0.0`. + ## 0.1.5 - Update SDK requirement to `>=2.2.0 <3.0.0`. diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index f983bb3b8..649460aea 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -1,13 +1,9 @@ include: package:pedantic/analysis_options.yaml + analyzer: strong-mode: implicit-casts: false - errors: - dead_code: error - override_on_non_overriding_method: error - unused_element: error - unused_import: error - unused_local_variable: error + linter: rules: - always_declare_return_types diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index fc54d1240..785630507 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,12 +2,12 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.5 +version: 0.1.6-dev homepage: https://github.com/dart-lang/pubspec_parse author: Dart Team environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.6.0 <3.0.0' dependencies: checked_yaml: ^1.0.0 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index d3bf3ad70..35ac6b67c 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -139,10 +139,10 @@ line 5, column 15: Unsupported value for "version". Could not parse version "not 'not_supported': null }, r''' line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git, path, hosted] - ╷ -10│ "not_supported": null - │ ^^^^^^^^^^^^^^^ - ╵'''); + ╷ +10 │ "not_supported": null + │ ^^^^^^^^^^^^^^^ + ╵'''); }); test('map w/ version and hosted as String', () { From 82db7f19e74873e8bfb9fb378775f1756fe27730 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 13 Feb 2020 11:19:25 -0800 Subject: [PATCH 0614/1215] Fix the description of debounce (dart-lang/stream_transform#101) It is the most recent, or "last" event in a series that is emitted. See discussion in dart-lang/stream_transform#100 Change the word "period" to "series of closely spaced events" since there is no fixed length of time. --- pkgs/stream_transform/CHANGELOG.md | 2 ++ pkgs/stream_transform/lib/src/rate_limit.dart | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 5342392cc..3cada22b1 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.1.2-dev + ## 1.1.1 - Fix a bug in `asyncMapSample`, `buffer`, `combineLatest`, diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 15078b737..40b77ef02 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -9,8 +9,10 @@ import 'from_handlers.dart'; /// Utilities to rate limit events. /// -/// - [debounce] - emit the _first_ event at the _end_ of the period. -/// - [debounceBuffer] - emit _all_ events at the _end_ of the period. +/// - [debounce] - emit the _last_ event at the _end_ of a series of closely +/// spaced events. +/// - [debounceBuffer] - emit _all_ events at the _end_ of a series of closely +/// spaced events. /// - [throttle] - emit the _first_ event at the _beginning_ of the period. /// - [audit] - emit the _last_ event at the _end_ of the period. /// - [buffer] - emit _all_ events on a _trigger_. From f07261f56eb001a7e9d82fe293b8ffd17a002d55 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 14 Feb 2020 09:27:43 -0800 Subject: [PATCH 0615/1215] Remove redundant pedantic lints --- pkgs/pubspec_parse/analysis_options.yaml | 37 ------------------------ 1 file changed, 37 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 649460aea..92e1bec21 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -6,24 +6,15 @@ analyzer: linter: rules: - - always_declare_return_types - - annotate_overrides - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - - avoid_empty_else - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - avoid_renaming_method_parameters - - avoid_return_types_on_setters - avoid_returning_null - avoid_returning_null_for_future - avoid_returning_null_for_void - avoid_returning_this - - avoid_shadowing_type_parameters - avoid_single_cascade_in_expression_statements - - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - await_only_futures - camel_case_types @@ -33,8 +24,6 @@ linter: - constant_identifier_names - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - empty_statements - file_names - hash_and_equals @@ -42,54 +31,28 @@ linter: - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment - - library_names - - library_prefixes - list_remove_unrelated_type - literal_only_boolean_expressions - no_adjacent_strings_in_list - - no_duplicate_case_values - non_constant_identifier_names - - null_closures - - omit_local_variable_types - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - prefer_final_locals - - prefer_generic_function_type_aliases - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - prefer_null_aware_operators - - prefer_single_quotes - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - - unawaited_futures - unnecessary_await_in_return - unnecessary_brace_in_string_interps - - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_function_type_syntax_for_parameters - - use_rethrow_when_possible - - valid_regexps - void_checks From 7f9401085be8999350c9d0b87826e20e175809d1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 14 Feb 2020 09:29:55 -0800 Subject: [PATCH 0616/1215] enable some useful lints --- pkgs/pubspec_parse/analysis_options.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 92e1bec21..581ed8a2f 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -7,8 +7,11 @@ analyzer: linter: rules: - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors - avoid_classes_with_only_static_members - avoid_function_literals_in_foreach_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values - avoid_renaming_method_parameters - avoid_returning_null - avoid_returning_null_for_future @@ -16,6 +19,7 @@ linter: - avoid_returning_this - avoid_single_cascade_in_expression_statements - avoid_unused_constructor_parameters + - avoid_void_async - await_only_futures - camel_case_types - cancel_subscriptions @@ -31,21 +35,34 @@ linter: - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment + - lines_longer_than_80_chars - list_remove_unrelated_type - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list + - no_runtimeType_toString - non_constant_identifier_names - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names + - prefer_asserts_in_initializer_lists - prefer_const_constructors + - prefer_const_declarations + # Need to update json_serializable to generate an ignore for this lint + #- prefer_expression_function_bodies - prefer_final_locals + - prefer_function_declarations_over_variables - prefer_initializing_formals + - prefer_inlined_adds - prefer_interpolation_to_compose_strings + - prefer_is_not_operator - prefer_null_aware_operators + - prefer_relative_imports - prefer_typing_uninitialized_variables + - prefer_void_to_null + - sort_pub_dependencies - test_types_in_equals - throw_in_finally - unnecessary_await_in_return @@ -53,6 +70,8 @@ linter: - unnecessary_getters_setters - unnecessary_lambdas - unnecessary_null_aware_assignments + - unnecessary_overrides - unnecessary_parenthesis - unnecessary_statements + - unnecessary_string_interpolations - void_checks From 0a210abdd32164af56398c523fb191242674bd65 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 20 Feb 2020 14:02:35 -0800 Subject: [PATCH 0617/1215] Strengthen Travis checks (dart-lang/stream_transform#102) - Restore checks on the earliest supported SDK. - Tests and analyzer with warnings and errors are run on both SDKs. - Dartfmt, and analyzer with lints are run on only the dev SDK. - Add test order randomization. --- pkgs/stream_transform/.travis.yml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index d69c3f7c0..596c0c618 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,12 +3,21 @@ branches: only: [master] dart: - dev - # 2.2.0 + - 2.6.0 cache: directories: - $HOME/.pub-cache dart_task: - - test - - test -p chrome - - dartfmt - - dartanalyzer: --fatal-warnings --fatal-infos . + - test --test-randomize-ordering-seed=random + - test -p chrome --test-randomize-ordering-seed=random + +matrix: + include: + - dart: dev + dart_task: dartfmt + - dart: dev + dart_task: + dartanalyzer: --fatal-warnings --fatal-infos . + - dart: 2.6.0 + dart_task: + dartanalyzer: --fatal-warnings . From c4ab1940e53667f6e6cc85ca828245341272cd3f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 25 Feb 2020 17:02:23 -0800 Subject: [PATCH 0618/1215] Add leading and trailing support to debounce (dart-lang/stream_transform#103) Closes dart-lang/stream_transform#100 Add support for immediately emitting the leading event of a series of closely spaced events. By default continue to only emit the trailing events. --- pkgs/stream_transform/CHANGELOG.md | 4 +- pkgs/stream_transform/lib/src/rate_limit.dart | 65 +++++++++---- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/debounce_test.dart | 92 ++++++++++++++++++- 4 files changed, 144 insertions(+), 19 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 3cada22b1..f235df10d 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.1.2-dev +## 1.2.0-dev + +- Add support for emitting the "leading" event in `debounce`. ## 1.1.1 diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 40b77ef02..6341c3e77 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -9,7 +9,7 @@ import 'from_handlers.dart'; /// Utilities to rate limit events. /// -/// - [debounce] - emit the _last_ event at the _end_ of a series of closely +/// - [debounce] - emit the the _first_ or _last_ event of a series of closely /// spaced events. /// - [debounceBuffer] - emit _all_ events at the _end_ of a series of closely /// spaced events. @@ -17,24 +17,47 @@ import 'from_handlers.dart'; /// - [audit] - emit the _last_ event at the _end_ of the period. /// - [buffer] - emit _all_ events on a _trigger_. extension RateLimit on Stream { - /// Returns a Stream which only emits when the source stream does not emit for - /// [duration]. + /// Returns a Stream which suppresses events with less inter-event spacing + /// than [duration]. /// - /// Values will always be delayed by at least [duration], and values which - /// come within this time will replace the old values, only the most - /// recent value will be emitted. + /// Events which are emitted with less than [duration] elapsed between them + /// are considered to be part of the same "series". If [leading] is `true`, + /// the first event of this series is emitted immediately. If [trailing] is + /// `true` the last event of this series is emitted with a delay of at least + /// [duration]. By default only trailing events are emitted, both arguments + /// must be specified with `leading: true, trailing: false` to emit only + /// leading events. /// /// If the source stream is a broadcast stream, the result will be as well. /// Errors are forwarded immediately. /// - /// If there is an event waiting during the debounce period when the source - /// stream closes the returned stream will wait to emit it following the - /// debounce period before closing. If there is no pending debounced event + /// If there is a trailing event waiting during the debounce period when the + /// source stream closes the returned stream will wait to emit it following + /// the debounce period before closing. If there is no pending debounced event /// when the source stream closes the returned stream will close immediately. /// + /// For example: + /// + /// source.debouce(Duration(seconds: 1)); + /// + /// source: 1-2-3---4---5-6-| + /// result: ------3---4-----6| + /// + /// source.debouce(Duration(seconds: 1), leading: true, trailing: false); + /// + /// source: 1-2-3---4---5-6-| + /// result: 1-------4---5---| + /// + /// source.debouce(Duration(seconds: 1), leading: true); + /// + /// source: 1-2-3---4---5-6-| + /// result: 1-----3-4---5---6| + /// /// To collect values emitted during the debounce period see [debounceBuffer]. - Stream debounce(Duration duration) => - transform(_debounceAggregate(duration, _dropPrevious)); + Stream debounce(Duration duration, + {bool leading = false, bool trailing = true}) => + transform(_debounceAggregate(duration, _dropPrevious, + leading: leading, trailing: trailing)); /// Returns a Stream which collects values until the source stream does not /// emit for [duration] then emits the collected values. @@ -53,7 +76,8 @@ extension RateLimit on Stream { /// To keep only the most recent event during the debounce perios see /// [debounce]. Stream> debounceBuffer(Duration duration) => - transform(_debounceAggregate(duration, _collectToList)); + transform(_debounceAggregate(duration, _collectToList, + leading: false, trailing: true)); /// Returns a stream which only emits once per [duration], at the beginning of /// the period. @@ -148,25 +172,34 @@ T _dropPrevious(T element, _) => element; /// Creates a StreamTransformer which aggregates values until the source stream /// does not emit for [duration], then emits the aggregated values. StreamTransformer _debounceAggregate( - Duration duration, R Function(T element, R soFar) collect) { + Duration duration, R Function(T element, R soFar) collect, + {bool leading, bool trailing}) { Timer timer; R soFar; var shouldClose = false; + var emittedLatestAsLeading = false; return fromHandlers(handleData: (T value, EventSink sink) { timer?.cancel(); - timer = Timer(duration, () { + soFar = collect(value, soFar); + if (timer == null && leading) { + emittedLatestAsLeading = true; sink.add(soFar); + } else { + emittedLatestAsLeading = false; + } + timer = Timer(duration, () { + if (trailing && !emittedLatestAsLeading) sink.add(soFar); if (shouldClose) { sink.close(); } soFar = null; timer = null; }); - soFar = collect(value, soFar); }, handleDone: (EventSink sink) { - if (soFar != null) { + if (soFar != null && trailing) { shouldClose = true; } else { + timer?.cancel(); sink.close(); } }); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 9f98a7129..c1d6298d4 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.1.2-dev +version: 1.2.0-dev environment: sdk: ">=2.6.0 <3.0.0" diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index cb027c58b..de6b74020 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -12,7 +12,7 @@ import 'utils.dart'; void main() { for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - group('debounce', () { + group('debounce - trailing', () { StreamController values; List emittedValues; bool valuesCanceled; @@ -88,6 +88,96 @@ void main() { } }); + group('debounce - leading', () { + StreamController values; + List emittedValues; + Stream transformed; + bool isDone; + + setUp(() async { + values = createController(streamType); + emittedValues = []; + isDone = false; + transformed = values.stream.debounce(const Duration(milliseconds: 5), + leading: true, trailing: false) + ..listen(emittedValues.add, onDone: () { + isDone = true; + }); + }); + + test('swallows values that come faster than duration', () async { + values..add(1)..add(2); + await values.close(); + expect(emittedValues, [1]); + }); + + test('outputs multiple values spaced further than duration', () async { + values.add(1); + await waitForTimer(5); + values.add(2); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values..add(1)..add(2); + await waitForTimer(5); + expect(emittedValues, [1]); + expect(otherValues, [1]); + }); + } + + test('closes output immediately if not waiting for trailing value', + () async { + values.add(1); + await values.close(); + expect(isDone, true); + }); + }); + + group('debounce - leading and trailing', () { + StreamController values; + List emittedValues; + Stream transformed; + + setUp(() async { + values = createController(streamType); + emittedValues = []; + transformed = values.stream.debounce(const Duration(milliseconds: 5), + leading: true, trailing: true) + ..listen(emittedValues.add); + }); + + test('swallows values that come faster than duration', () async { + values..add(1)..add(2)..add(3); + await values.close(); + await waitForTimer(5); + expect(emittedValues, [1, 3]); + }); + + test('outputs multiple values spaced further than duration', () async { + values.add(1); + await waitForTimer(5); + values.add(2); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values..add(1)..add(2); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + expect(otherValues, [1, 2]); + }); + } + }); + group('debounceBuffer', () { StreamController values; List> emittedValues; From 61232120b8a95e005343aa885a0cd621f879831e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 08:50:15 -0800 Subject: [PATCH 0619/1215] Fix URLs throughout the package (dart-lang/pubspec_parse#58) --- pkgs/pubspec_parse/README.md | 10 ++-------- pkgs/pubspec_parse/build.yaml | 2 +- pkgs/pubspec_parse/lib/src/pubspec.dart | 4 +--- pkgs/pubspec_parse/pubspec.yaml | 1 - 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index a95459c6f..7287d5f4e 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,13 +1,7 @@ [![Build Status](https://travis-ci.org/dart-lang/pubspec_parse.svg?branch=master)](https://travis-ci.org/dart-lang/pubspec_parse) +[![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/pubspec_parse) Supports parsing `pubspec.yaml` files with robust error reporting and support for most of the documented features. -Read more about the -[pubspec format](https://www.dartlang.org/tools/pub/pubspec). - -## Features and bugs - -Please file feature requests and bugs at the [issue tracker]. - -[issue tracker]: https://github.com/dart-lang/pubspec_parse/issues +Read more about the [pubspec format](https://dart.dev/tools/pub/pubspec). diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 1525ab832..874c975da 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -1,4 +1,4 @@ -# Read about `build.yaml` at https://pub.dartlang.org/packages/build_config +# Read about `build.yaml` at https://pub.dev/packages/build_config # To update generated code, run `pub run build_runner build` targets: $default: diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 735838907..e3dbac14f 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -28,9 +28,7 @@ class Pubspec { /// /// Accepted values: `null`, `'none'` or an `http` or `https` URL. /// - /// If not specified, the pub client defaults to `https://pub.dartlang.org`. - /// - /// [More information](https://www.dartlang.org/tools/pub/pubspec#publish_to). + /// [More information](https://dart.dev/tools/pub/pubspec#publish_to). final String publishTo; /// Optional field to specify the source code repository of the package. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 785630507..a148e7f69 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -4,7 +4,6 @@ description: >- error reporting. version: 0.1.6-dev homepage: https://github.com/dart-lang/pubspec_parse -author: Dart Team environment: sdk: '>=2.6.0 <3.0.0' From 1683d54e5ca4399df9919dc2b6eb2a4a338ac2b5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Feb 2020 09:01:10 -0800 Subject: [PATCH 0620/1215] Enable and some lints (dart-lang/pubspec_parse#57) Ignored violations in generated code --- pkgs/pubspec_parse/analysis_options.yaml | 5 +++-- pkgs/pubspec_parse/build.yaml | 7 +++++++ pkgs/pubspec_parse/lib/src/dependency.g.dart | 2 ++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 ++ pkgs/pubspec_parse/pubspec.yaml | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 581ed8a2f..39be54abb 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -50,8 +50,7 @@ linter: - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - # Need to update json_serializable to generate an ignore for this lint - #- prefer_expression_function_bodies + - prefer_expression_function_bodies - prefer_final_locals - prefer_function_declarations_over_variables - prefer_initializing_formals @@ -62,6 +61,7 @@ linter: - prefer_relative_imports - prefer_typing_uninitialized_variables - prefer_void_to_null + - provide_deprecation_message - sort_pub_dependencies - test_types_in_equals - throw_in_finally @@ -74,4 +74,5 @@ linter: - unnecessary_parenthesis - unnecessary_statements - unnecessary_string_interpolations + - use_string_buffers - void_checks diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 874c975da..aa3ea69ec 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -12,3 +12,10 @@ targets: checked: true create_to_json: false field_rename: snake + + # The end-user of a builder which applies "source_gen|combining_builder" + # may configure the builder to ignore specific lints for their project + source_gen|combining_builder: + options: + ignore_for_file: + - prefer_expression_function_bodies diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 4e137fad7..37352b37f 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -1,5 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: prefer_expression_function_bodies + part of 'dependency.dart'; // ************************************************************************** diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index eb062b8fd..c29a221d3 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -1,5 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: prefer_expression_function_bodies + part of 'pubspec.dart'; // ************************************************************************** diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index a148e7f69..2940ce3f9 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -21,6 +21,8 @@ dev_dependencies: json_serializable: ^3.0.0 path: ^1.5.1 pedantic: ^1.4.0 + # Needed because we are configuring `combining_builder` + source_gen: ^0.9.5 stack_trace: ^1.9.2 test: ^1.0.0 test_descriptor: ^1.0.3 From 8ea51b3b95101570818ee153881553aab1749714 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 26 Feb 2020 11:07:43 -0800 Subject: [PATCH 0621/1215] Prepare to publish (dart-lang/stream_transform#104) --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index f235df10d..f4cf39509 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.2.0-dev +## 1.2.0 - Add support for emitting the "leading" event in `debounce`. diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c1d6298d4..c336b81ce 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.2.0-dev +version: 1.2.0 environment: sdk: ">=2.6.0 <3.0.0" From c1a13133966bfb9feb405e6d70ade9ff75ccbeef Mon Sep 17 00:00:00 2001 From: Jonas Termansen Date: Fri, 6 Mar 2020 17:53:46 +0100 Subject: [PATCH 0622/1215] Check for FileSystemEntityType.notFound (dart-lang/watcher#80) The Dart breaking change will change the timestamps on the notFound object from null to the epoch timestamp. --- pkgs/watcher/lib/src/stat.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 6430d0b56..fb157a571 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -28,5 +28,6 @@ Future modificationTime(String path) async { } final stat = await FileStat.stat(path); + if (stat.type == FileSystemEntityType.notFound) return null; return stat.modified; } From 51c389da0aeb645666c784a6271e2fac896334bd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 6 Mar 2020 09:31:04 -0800 Subject: [PATCH 0623/1215] Prepare to publish, tighten pub constraints (dart-lang/watcher#81) - Add a changelog entry. - Remove unused author key from pubspec. - Tighten the constraints on dependencies for any which had a lower major version bound than the package versions which support Dart 2. --- pkgs/watcher/CHANGELOG.md | 5 +++++ pkgs/watcher/pubspec.yaml | 9 ++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 2b3cd35b4..65ab5dfaf 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7+14 + +* Prepare for breaking change in SDK where modified times for not found files + becomes meaningless instead of null. + # 0.9.7+13 * Catch & forward `FileSystemException` from unexpectedly closed file watchers diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 9aa0eaf9f..3982775c1 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,21 +1,20 @@ name: watcher -version: 0.9.7+14-dev +version: 0.9.7+14 description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. -author: Dart Team homepage: https://github.com/dart-lang/watcher environment: sdk: '>=2.2.0 <3.0.0' dependencies: - async: '>=1.10.0 <3.0.0' - path: '>=0.9.0 <2.0.0' + async: ^2.0.0 + path: ^1.0.0 pedantic: ^1.1.0 dev_dependencies: benchmark_harness: ^1.0.4 - test: '>=0.12.42 <2.0.0' + test: ^1.0.0 test_descriptor: ^1.0.0 From c9b3111a830ecdab4cd7018bbcc7f982db1ac342 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 9 Mar 2020 12:21:41 -0700 Subject: [PATCH 0624/1215] Remove lints duplicated in pkg:pedantic --- pkgs/string_scanner/analysis_options.yaml | 37 ++--------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index c9899f2e2..7684be711 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -1,26 +1,20 @@ include: package:pedantic/analysis_options.yaml + analyzer: strong-mode: implicit-casts: false + linter: rules: - - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - - avoid_empty_else - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - avoid_renaming_method_parameters - - avoid_return_types_on_setters #- avoid_returning_null - avoid_returning_null_for_future - avoid_returning_null_for_void - avoid_returning_this - - avoid_shadowing_type_parameters - avoid_single_cascade_in_expression_statements - - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - await_only_futures - camel_case_types @@ -30,8 +24,6 @@ linter: - constant_identifier_names - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - empty_statements - file_names - hash_and_equals @@ -39,53 +31,28 @@ linter: - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment - - library_names - - library_prefixes - list_remove_unrelated_type - literal_only_boolean_expressions - no_adjacent_strings_in_list - - no_duplicate_case_values - non_constant_identifier_names - - null_closures - - omit_local_variable_types - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields #- prefer_final_locals - - prefer_generic_function_type_aliases - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - prefer_null_aware_operators - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - - unawaited_futures - unnecessary_await_in_return - unnecessary_brace_in_string_interps - - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_function_type_syntax_for_parameters - - use_rethrow_when_possible - - valid_regexps - void_checks From 2f624e5d4687dd8b29033d1cccad4d25a950072b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 9 Mar 2020 12:28:05 -0700 Subject: [PATCH 0625/1215] Enable and fix a number of lints --- pkgs/string_scanner/analysis_options.yaml | 24 +++++++++-- pkgs/string_scanner/example/example.dart | 6 +-- .../lib/src/eager_span_scanner.dart | 12 +++--- pkgs/string_scanner/lib/src/line_scanner.dart | 12 +++--- .../lib/src/relative_span_scanner.dart | 8 ++-- pkgs/string_scanner/lib/src/span_scanner.dart | 8 ++-- .../lib/src/string_scanner.dart | 10 ++--- pkgs/string_scanner/test/error_test.dart | 32 +++++++-------- .../test/line_scanner_test.dart | 2 +- .../test/span_scanner_test.dart | 40 ++++++++++--------- .../test/string_scanner_test.dart | 4 +- 11 files changed, 89 insertions(+), 69 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 7684be711..60abe63e6 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -7,19 +7,21 @@ analyzer: linter: rules: - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors - avoid_classes_with_only_static_members - avoid_function_literals_in_foreach_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values - avoid_renaming_method_parameters - #- avoid_returning_null - avoid_returning_null_for_future - avoid_returning_null_for_void - avoid_returning_this - avoid_single_cascade_in_expression_statements - avoid_unused_constructor_parameters + - avoid_void_async - await_only_futures - camel_case_types - cancel_subscriptions - #- cascade_invocations - comment_references - constant_identifier_names - control_flow_in_finally @@ -31,21 +33,34 @@ linter: - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment + - lines_longer_than_80_chars - list_remove_unrelated_type - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list + - no_runtimeType_toString - non_constant_identifier_names - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names + - prefer_asserts_in_initializer_lists - prefer_const_constructors - #- prefer_final_locals + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_locals + - prefer_function_declarations_over_variables - prefer_initializing_formals + - prefer_inlined_adds - prefer_interpolation_to_compose_strings + - prefer_is_not_operator - prefer_null_aware_operators + - prefer_relative_imports - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - sort_pub_dependencies - test_types_in_equals - throw_in_finally - unnecessary_await_in_return @@ -53,6 +68,9 @@ linter: - unnecessary_getters_setters - unnecessary_lambdas - unnecessary_null_aware_assignments + - unnecessary_overrides - unnecessary_parenthesis - unnecessary_statements + - unnecessary_string_interpolations + - use_string_buffers - void_checks diff --git a/pkgs/string_scanner/example/example.dart b/pkgs/string_scanner/example/example.dart index 0358967e4..e92677f1c 100644 --- a/pkgs/string_scanner/example/example.dart +++ b/pkgs/string_scanner/example/example.dart @@ -12,11 +12,11 @@ void main(List args) { num parseNumber(String source) { // Scan a number ("1", "1.5", "-3"). - var scanner = StringScanner(source); + final scanner = StringScanner(source); // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it // succeeded. It will move the scan pointer past the end of the pattern. - var negative = scanner.scan('-'); + final negative = scanner.scan('-'); // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it // fails. Like [Scanner.scan], it will move the scan pointer forward. @@ -28,7 +28,7 @@ num parseNumber(String source) { if (scanner.scan('.')) { scanner.expect(RegExp(r'\d+')); - var decimal = scanner.lastMatch[0]; + final decimal = scanner.lastMatch[0]; number += int.parse(decimal) / math.pow(10, decimal.length); } diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index d34e4f7c3..848cb72c4 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -44,11 +44,11 @@ class EagerSpanScanner extends SpanScanner { @override set position(int newPosition) { - var oldPosition = position; + final oldPosition = position; super.position = newPosition; if (newPosition > oldPosition) { - var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + final newlines = _newlinesIn(string.substring(oldPosition, newPosition)); _line += newlines.length; if (newlines.isEmpty) { _column += newPosition - oldPosition; @@ -56,7 +56,7 @@ class EagerSpanScanner extends SpanScanner { _column = newPosition - newlines.last.end; } } else { - var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + final newlines = _newlinesIn(string.substring(newPosition, oldPosition)); if (_betweenCRLF) newlines.removeLast(); _line -= newlines.length; @@ -81,7 +81,7 @@ class EagerSpanScanner extends SpanScanner { @override int readChar() { - var character = super.readChar(); + final character = super.readChar(); _adjustLineAndColumn(character); return character; } @@ -100,7 +100,7 @@ class EagerSpanScanner extends SpanScanner { bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - var newlines = _newlinesIn(lastMatch[0]); + final newlines = _newlinesIn(lastMatch[0]); _line += newlines.length; if (newlines.isEmpty) { _column += lastMatch[0].length; @@ -114,7 +114,7 @@ class EagerSpanScanner extends SpanScanner { /// Returns a list of [Match]es describing all the newlines in [text], which /// is assumed to end at [position]. List _newlinesIn(String text) { - var newlines = _newlineRegExp.allMatches(text).toList(); + final newlines = _newlineRegExp.allMatches(text).toList(); if (_betweenCRLF) newlines.removeLast(); return newlines; } diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 180d9239b..9e7d918fa 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -48,11 +48,11 @@ class LineScanner extends StringScanner { @override set position(int newPosition) { - var oldPosition = position; + final oldPosition = position; super.position = newPosition; if (newPosition > oldPosition) { - var newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + final newlines = _newlinesIn(string.substring(oldPosition, newPosition)); _line += newlines.length; if (newlines.isEmpty) { _column += newPosition - oldPosition; @@ -60,7 +60,7 @@ class LineScanner extends StringScanner { _column = newPosition - newlines.last.end; } } else { - var newlines = _newlinesIn(string.substring(newPosition, oldPosition)); + final newlines = _newlinesIn(string.substring(newPosition, oldPosition)); if (_betweenCRLF) newlines.removeLast(); _line -= newlines.length; @@ -85,7 +85,7 @@ class LineScanner extends StringScanner { @override int readChar() { - var character = super.readChar(); + final character = super.readChar(); _adjustLineAndColumn(character); return character; } @@ -104,7 +104,7 @@ class LineScanner extends StringScanner { bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - var newlines = _newlinesIn(lastMatch[0]); + final newlines = _newlinesIn(lastMatch[0]); _line += newlines.length; if (newlines.isEmpty) { _column += lastMatch[0].length; @@ -118,7 +118,7 @@ class LineScanner extends StringScanner { /// Returns a list of [Match]es describing all the newlines in [text], which /// is assumed to end at [position]. List _newlinesIn(String text) { - var newlines = _newlineRegExp.allMatches(text).toList(); + final newlines = _newlineRegExp.allMatches(text).toList(); if (_betweenCRLF) newlines.removeLast(); return newlines; } diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index 096bee3ad..a7a035abb 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -34,8 +34,8 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { @override int get column { - var line = _sourceFile.getLine(_startLocation.offset + position); - var column = + final line = _sourceFile.getLine(_startLocation.offset + position); + final column = _sourceFile.getColumn(_startLocation.offset + position, line: line); return line == _startLocation.line ? column - _startLocation.column @@ -74,7 +74,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { @override FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { - var endPosition = endState == null ? position : endState.position; + final endPosition = endState == null ? position : endState.position; return _sourceFile.span(_startLocation.offset + startState.position, _startLocation.offset + endPosition); } @@ -99,7 +99,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { position ??= match == null ? this.position : match.start; length ??= match == null ? 1 : match.end - match.start; - var span = _sourceFile.span(_startLocation.offset + position, + final span = _sourceFile.span(_startLocation.offset + position, _startLocation.offset + position + length); throw StringScannerException(message, span, string); } diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 732a76f18..1a8ca2ade 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -82,14 +82,14 @@ class SpanScanner extends StringScanner implements LineScanner { /// /// This scans through [span]`.text, but emits new spans from [span]`.file` in /// their appropriate relative positions. The [string] field contains only - /// [span]`.text`, and [position], [line], and [column] are all relative to the - /// span. + /// [span]`.text`, and [position], [line], and [column] are all relative to + /// the span. factory SpanScanner.within(FileSpan span) = RelativeSpanScanner; /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { - var endPosition = endState == null ? position : endState.position; + final endPosition = endState == null ? position : endState.position; return _sourceFile.span(startState.position, endPosition); } @@ -112,7 +112,7 @@ class SpanScanner extends StringScanner implements LineScanner { position ??= match == null ? this.position : match.start; length ??= match == null ? 0 : match.end - match.start; - var span = _sourceFile.span(position, position + length); + final span = _sourceFile.span(position, position + length); throw StringScannerException(message, span, string); } } diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 1739a7cd4..55ff17d3a 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -81,7 +81,7 @@ class StringScanner { /// affect [lastMatch]. int peekChar([int offset]) { offset ??= 0; - var index = position + offset; + final index = position + offset; if (index < 0 || index >= string.length) return null; return string.codeUnitAt(index); } @@ -123,7 +123,7 @@ class StringScanner { /// /// Returns whether or not [pattern] matched. bool scan(Pattern pattern) { - var success = matches(pattern); + final success = matches(pattern); if (success) { _position = _lastMatch.end; _lastMatchPosition = _position; @@ -143,7 +143,7 @@ class StringScanner { if (name == null) { if (pattern is RegExp) { - var source = pattern.pattern; + final source = pattern.pattern; name = '/$source/'; } else { name = @@ -201,8 +201,8 @@ class StringScanner { position ??= match == null ? this.position : match.start; length ??= match == null ? 0 : match.end - match.start; - var sourceFile = SourceFile.fromString(string, url: sourceUrl); - var span = sourceFile.span(position, position + length); + final sourceFile = SourceFile.fromString(string, url: sourceUrl); + final span = sourceFile.span(position, position + length); throw StringScannerException(message, span, string); } diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index dfa71755c..617304070 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -9,7 +9,7 @@ import 'utils.dart'; void main() { test('defaults to the last match', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); scanner.expect('bar'); expect(() => scanner.error('oh no!'), throwsStringScannerException('bar')); @@ -17,39 +17,39 @@ void main() { group('with match', () { test('supports an earlier match', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); - var match = scanner.lastMatch; + final match = scanner.lastMatch; scanner.expect('bar'); expect(() => scanner.error('oh no!', match: match), throwsStringScannerException('foo ')); }); test('supports a match on a previous line', () { - var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); + final scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo '); scanner.expect('re'); - var match = scanner.lastMatch; + final match = scanner.lastMatch; scanner.expect(' mi\nearth '); expect(() => scanner.error('oh no!', match: match), throwsStringScannerException('re')); }); test('supports a multiline match', () { - var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); + final scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar '); scanner.expect('baz\ndo'); - var match = scanner.lastMatch; + final match = scanner.lastMatch; scanner.expect(' re mi'); expect(() => scanner.error('oh no!', match: match), throwsStringScannerException('baz\ndo')); }); test('supports a match after position', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); scanner.expect('bar'); - var match = scanner.lastMatch; + final match = scanner.lastMatch; scanner.position = 0; expect(() => scanner.error('oh no!', match: match), throwsStringScannerException('bar')); @@ -58,48 +58,48 @@ void main() { group('with position and/or length', () { test('defaults to length 0', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1), throwsStringScannerException('')); }); test('defaults to the current position', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', length: 3), throwsStringScannerException('bar')); }); test('supports an earlier position', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); scanner.expect('foo '); expect(() => scanner.error('oh no!', position: 1, length: 2), throwsStringScannerException('oo')); }); test('supports a position on a previous line', () { - var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); + final scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 15, length: 2), throwsStringScannerException('re')); }); test('supports a multiline length', () { - var scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); + final scanner = StringScanner('foo bar baz\ndo re mi\nearth fire water'); scanner.expect('foo bar baz\ndo re mi\nearth'); expect(() => scanner.error('oh no!', position: 8, length: 8), throwsStringScannerException('baz\ndo r')); }); test('supports a position after the current one', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); expect(() => scanner.error('oh no!', position: 4, length: 3), throwsStringScannerException('bar')); }); test('supports a length of zero', () { - var scanner = StringScanner('foo bar baz'); + final scanner = StringScanner('foo bar baz'); expect(() => scanner.error('oh no!', position: 4, length: 0), throwsStringScannerException('')); }); diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index dc9b8cfd1..aafc74a07 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -150,7 +150,7 @@ void main() { test('state= restores the line, column, and position', () { scanner.scan('foo\nb'); - var state = scanner.state; + final state = scanner.state; scanner.scan('ar\nba'); scanner.state = state; diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index e2570aeff..2034d0a8d 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -9,21 +9,23 @@ import 'package:test/test.dart'; import 'utils.dart'; void main() { - testForImplementation('lazy', ([String string]) { - return SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); - }); + testForImplementation( + 'lazy', + ([String string]) => + SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source')); - testForImplementation('eager', ([String string]) { - return SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source'); - }); + testForImplementation( + 'eager', + ([String string]) => + SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source')); group('within', () { - var text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; - var startOffset = text.indexOf('foo'); + const text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; + final startOffset = text.indexOf('foo'); SpanScanner scanner; setUp(() { - var file = SourceFile.fromString(text, url: 'source'); + final file = SourceFile.fromString(text, url: 'source'); scanner = SpanScanner.within(file.span(startOffset, text.indexOf(' :after'))); }); @@ -49,7 +51,7 @@ void main() { scanner.scan('fo'); scanner.scan('o\nba'); - var span = scanner.lastSpan; + final span = scanner.lastSpan; expect(span.start.offset, equals(startOffset + 2)); expect(span.start.line, equals(1)); expect(span.start.column, equals(10)); @@ -65,18 +67,18 @@ void main() { test('.spanFrom() returns a span from a previous state', () { scanner.scan('fo'); - var state = scanner.state; + final state = scanner.state; scanner.scan('o\nba'); scanner.scan('r\nba'); - var span = scanner.spanFrom(state); + final span = scanner.spanFrom(state); expect(span.text, equals('o\nbar\nba')); }); test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); - var span = scanner.emptySpan; + final span = scanner.emptySpan; expect(span.start.offset, equals(startOffset + 6)); expect(span.start.line, equals(2)); expect(span.start.column, equals(2)); @@ -113,7 +115,7 @@ void testForImplementation( scanner.scan('fo'); scanner.scan('o\nba'); - var span = scanner.lastSpan; + final span = scanner.lastSpan; expect(span.start.offset, equals(2)); expect(span.start.line, equals(0)); expect(span.start.column, equals(2)); @@ -129,27 +131,27 @@ void testForImplementation( test('.spanFrom() returns a span from a previous state', () { scanner.scan('fo'); - var state = scanner.state; + final state = scanner.state; scanner.scan('o\nba'); scanner.scan('r\nba'); - var span = scanner.spanFrom(state); + final span = scanner.spanFrom(state); expect(span.text, equals('o\nbar\nba')); }); test('.spanFrom() handles surrogate pairs correctly', () { scanner = create('fo\u{12345}o'); scanner.scan('fo'); - var state = scanner.state; + final state = scanner.state; scanner.scan('\u{12345}o'); - var span = scanner.spanFrom(state); + final span = scanner.spanFrom(state); expect(span.text, equals('\u{12345}o')); }); test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); - var span = scanner.emptySpan; + final span = scanner.emptySpan; expect(span.start.offset, equals(6)); expect(span.start.line, equals(1)); expect(span.start.column, equals(2)); diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index e1e5b4eb8..9dee9d123 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -374,7 +374,7 @@ void main() { }); test('setting and resetting position clears lastMatch', () { - var oldPosition = scanner.position; + final oldPosition = scanner.position; scanner.position = 1; scanner.position = oldPosition; expect(scanner.lastMatch, isNull); @@ -395,7 +395,7 @@ void main() { group('a scanner constructed with a custom position', () { test('starts scanning from that position', () { - var scanner = StringScanner('foo bar', position: 1); + final scanner = StringScanner('foo bar', position: 1); expect(scanner.position, equals(1)); expect(scanner.rest, equals('oo bar')); From cf713fe332b2508eb6bde464a54ba0747448bf24 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 9 Mar 2020 12:28:23 -0700 Subject: [PATCH 0626/1215] Fix readme Align with example/example.dart --- pkgs/string_scanner/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/string_scanner/README.md b/pkgs/string_scanner/README.md index 15aa24261..6427218c2 100644 --- a/pkgs/string_scanner/README.md +++ b/pkgs/string_scanner/README.md @@ -2,29 +2,29 @@ This package exposes a `StringScanner` type that makes it easy to parse a string using a series of `Pattern`s. For example: ```dart -import 'dart:math'; +import 'dart:math' as math; import 'package:string_scanner/string_scanner.dart'; num parseNumber(String source) { // Scan a number ("1", "1.5", "-3"). - var scanner = StringScanner(source); + final scanner = StringScanner(source); // [Scanner.scan] tries to consume a [Pattern] and returns whether or not it // succeeded. It will move the scan pointer past the end of the pattern. - var negative = scanner.scan("-"); + final negative = scanner.scan('-'); // [Scanner.expect] consumes a [Pattern] and throws a [FormatError] if it // fails. Like [Scanner.scan], it will move the scan pointer forward. - scanner.expect(RegExp(r"\d+")); + scanner.expect(RegExp(r'\d+')); // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. var number = num.parse(scanner.lastMatch[0]); - if (scanner.scan(".")) { - scanner.expect(RegExp(r"\d+")); - var decimal = scanner.lastMatch[0]; + if (scanner.scan('.')) { + scanner.expect(RegExp(r'\d+')); + final decimal = scanner.lastMatch[0]; number += int.parse(decimal) / math.pow(10, decimal.length); } From 8358111d7856a31ac41d98831defd1379c4d43b3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 18 Mar 2020 13:13:45 -0700 Subject: [PATCH 0627/1215] Close send channel in test (dart-lang/stream_channel#54) Without closing this channel the VM will not exit. Refactor to `async/await` so that we can close the channel only after receiving the expected items. This allows running the test directly in the VM without the test runner. --- pkgs/stream_channel/test/isolate_channel_test.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index ab70f749b..ec26fb647 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -137,19 +137,21 @@ void main() { connectPort.close(); }); - test('create a connected pair of channels', () { + test('create a connected pair of channels', () async { var channel1 = IsolateChannel.connectReceive(connectPort); var channel2 = IsolateChannel.connectSend(connectPort.sendPort); channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); - expect(channel2.stream.take(3).toList(), completion(equals([1, 2, 3]))); + expect(await channel2.stream.take(3).toList(), equals([1, 2, 3])); channel2.sink.add(4); channel2.sink.add(5); channel2.sink.add(6); - expect(channel1.stream.take(3).toList(), completion(equals([4, 5, 6]))); + expect(await channel1.stream.take(3).toList(), equals([4, 5, 6])); + + await channel2.sink.close(); }); test('the receiving channel produces an error if it gets the wrong message', From 1512a1ee966ec62c9a3f39a924d3fc3fb3bb1ba1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 27 Mar 2020 12:04:52 -0700 Subject: [PATCH 0628/1215] Refactor to avoid `.cast()` (dart-lang/stream_transform#105) Keeps us at a single type check with `event is S`. --- pkgs/stream_transform/CHANGELOG.md | 2 ++ pkgs/stream_transform/lib/src/where.dart | 5 ++++- pkgs/stream_transform/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index f4cf39509..5a5ea2a8c 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.1-dev + ## 1.2.0 - Add support for emitting the "leading" event in `debounce`. diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 8917cb4de..97ec57b30 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -17,7 +17,10 @@ extension Where on Stream { /// [S] should be a subtype of the stream's generic type, otherwise nothing of /// type [S] could possibly be emitted, however there is no static or runtime /// checking that this is the case. - Stream whereType() => where((e) => e is S).cast(); + Stream whereType() => + transform(StreamTransformer.fromHandlers(handleData: (event, sink) { + if (event is S) sink.add(event); + })); /// Like [where] but allows the [test] to return a [Future]. /// diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c336b81ce..8279c44fa 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://www.github.com/dart-lang/stream_transform -version: 1.2.0 +version: 1.2.1-dev environment: sdk: ">=2.6.0 <3.0.0" From eb109aef39742e86328a6d50b763b853484600a4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 2 Apr 2020 10:25:21 -0700 Subject: [PATCH 0629/1215] Rewrite doc comment to refer to TypeError (dart-lang/stream_channel#57) This will be the type going forward. Keep a reference to `CastError` for now, we can drop it after a few SDK releases. --- pkgs/stream_channel/lib/stream_channel.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 56937929a..4722aa39c 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -126,8 +126,9 @@ abstract class StreamChannel { /// Returns a copy of this with the generic type coerced to [S]. /// /// If any events emitted by [stream] aren't of type [S], they're converted - /// into [CastError] events. Similarly, if any events are added to [sink] that - /// aren't of type [S], a [CastError] is thrown. + /// into [TypeError] events (`CastError` on some SDK versions). Similarly, if + /// any events are added to [sink] that aren't of type [S], a [TypeError] is + /// thrown. StreamChannel cast(); } From 056a79259a018db9560564c714e90cee39fbad8a Mon Sep 17 00:00:00 2001 From: Sinegovsky Ivan Date: Sat, 11 Apr 2020 03:30:36 +0300 Subject: [PATCH 0630/1215] Add support for Firefox anonymous stackTraces (dart-lang/stack_trace#55) Co-authored-by: Sinegovsky Ivan --- pkgs/stack_trace/CHANGELOG.md | 4 +++ pkgs/stack_trace/lib/src/frame.dart | 27 ++++++++++++++++ pkgs/stack_trace/lib/src/trace.dart | 11 ++++++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 46 +++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index d4bfa07ec..faf6eebc7 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.4-dev + +* Added support for firefox anonymous stack traces + ## 1.9.3 * Set max SDK version to `<3.0.0`. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index bbe5c79e6..53ae61999 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -30,6 +30,11 @@ final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); final _v8EvalLocation = new RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); +// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 +// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 +final _firefoxEvalLocation = + new RegExp(r"(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+"); + // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 @@ -205,11 +210,33 @@ class Frame { /// be retrieved. factory Frame.parseIE(String frame) => new Frame.parseV8(frame); + /// Parses a string representation of a Firefox 'eval' or 'function' stack frame. + /// + /// for example: + /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 + /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 + factory Frame._parseFirefoxEval(String frame) => + _catchFormatException(frame, () { + final match = _firefoxEvalLocation.firstMatch(frame); + if (match == null) return new UnparsedFrame(frame); + var member = match[1].replaceAll('/<', ''); + final uri = _uriOrPathToUri(match[2]); + final line = int.parse(match[3]); + if (member.isEmpty || member == 'anonymous') { + member = ''; + } + return new Frame(uri, line, null, member); + }); + /// Parses a string representation of a Firefox stack frame. factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { var match = _firefoxSafariFrame.firstMatch(frame); if (match == null) return new UnparsedFrame(frame); + if (match[3].contains(' line ')) { + return Frame._parseFirefoxEval(frame); + } + // Normally this is a URI, but in a jsshell trace it can be a path. var uri = _uriOrPathToUri(match[3]); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 972c33e4c..9baff1c70 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -27,6 +27,14 @@ final _v8Trace = new RegExp(r"\n ?at "); /// though it is possible for the message to match this as well. final _v8TraceLine = new RegExp(r" ?at "); +/// A RegExp to match Firefox's eval and Function stack traces. +/// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack +/// These stack traces looks like: +/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 +/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 +final _firefoxEvalTrace = + new RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); + /// A RegExp to match Firefox and Safari's stack traces. /// /// Firefox and Safari have very similar stack trace formats, so we use the same @@ -120,7 +128,8 @@ class Trace implements StackTrace { if (trace.isEmpty) return new Trace([]); if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); if (trace.contains("\tat ")) return new Trace.parseJSCore(trace); - if (trace.contains(_firefoxSafariTrace)) { + if (trace.contains(_firefoxSafariTrace) || + trace.contains(_firefoxEvalTrace)) { return new Trace.parseFirefox(trace); } if (trace.contains(chainGap)) return new Chain.parse(trace).toTrace(); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 6774615c9..8715eae11 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -7,7 +7,7 @@ name: stack_trace # # When the major version is upgraded, you *must* update that version constraint # in pub to stay in sync with this. -version: 1.9.3 +version: 1.9.4-dev description: A package for manipulating stack traces and printing them readably. author: 'Dart Team ' diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 42df4cddf..1ec3c995d 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -236,6 +236,52 @@ void main() { }); group('.parseFirefox/.parseSafari', () { + test('parses a Firefox stack trace with anonymous function', () { + var trace = new Trace.parse(''' +Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 +anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 +baz@http://pub.dartlang.org/buz.js:56355:55 + '''); + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[0].line, equals(18056)); + expect(trace.frames[0].column, equals(12)); + expect(trace.frames[0].member, equals("Foo._bar")); + expect(trace.frames[1].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[1].line, equals(693)); + expect(trace.frames[1].column, isNull); + expect(trace.frames[1].member, equals("")); + expect(trace.frames[2].uri, + equals(Uri.parse("http://pub.dartlang.org/buz.js"))); + expect(trace.frames[2].line, equals(56355)); + expect(trace.frames[2].column, equals(55)); + expect(trace.frames[2].member, equals("baz")); + }); + + test( + 'parses a Firefox stack trace with nested evals in anonymous function correctly', + () { + var trace = new Trace.parse(''' + Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 + anonymous@file:///C:/example.html line 7 > eval line 1 > eval:1:1 + anonymous@file:///C:/example.html line 45 > Function:1:1 + '''); + expect(trace.frames[0].uri, + equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + expect(trace.frames[0].line, equals(18056)); + expect(trace.frames[0].column, equals(12)); + expect(trace.frames[0].member, equals("Foo._bar")); + expect(trace.frames[1].uri, equals(Uri.parse("file:///C:/example.html"))); + expect(trace.frames[1].line, equals(7)); + expect(trace.frames[1].column, isNull); + expect(trace.frames[1].member, equals("")); + expect(trace.frames[2].uri, equals(Uri.parse("file:///C:/example.html"))); + expect(trace.frames[2].line, equals(45)); + expect(trace.frames[2].column, isNull); + expect(trace.frames[2].member, equals("")); + }); + test('parses a simple stack frame correctly', () { var frame = new Frame.parseFirefox( ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); From 9de1bbb10891c57f811f740972ec1dd035102f94 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 12 Apr 2020 20:24:25 -0700 Subject: [PATCH 0631/1215] Clean up pubspec (dart-lang/stack_trace#58) - Remove stale comment about barback. Pub no longer forces tight constraints on this package. - Remove unused author field. - Remove some unnecessary newlines. --- pkgs/stack_trace/pubspec.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 8715eae11..070d3e743 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,16 +1,6 @@ name: stack_trace - -# Note! This version number is referenced directly in the pub source code in -# lib/src/barback.dart. Pub implicitly places a version constraint on -# stack_trace to ensure users only select a version of stack_trace that works -# with their current version of pub. -# -# When the major version is upgraded, you *must* update that version constraint -# in pub to stay in sync with this. version: 1.9.4-dev - description: A package for manipulating stack traces and printing them readably. -author: 'Dart Team ' homepage: https://github.com/dart-lang/stack_trace environment: From ddcc164f89f721db68d81e6b27086b4e30b49753 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 12 Apr 2020 20:24:44 -0700 Subject: [PATCH 0632/1215] Reflow comments to 80 characters (dart-lang/stack_trace#59) - Find comment lines longer than 80 characters and reflow to under than 80 characters. Leave URLs as is. - Remove some noise words "string representation" from a doc comment - the signature tells us it is a `String`. - Add some blank lines to reformat a doc comment. Indent example stack traces lines like a code block. - Remove the noise word "correctly" from a test case so it fits under 80 characters. - Remove an unnecessary trailing whitespace. --- pkgs/stack_trace/lib/src/frame.dart | 31 ++++++++++++++------------- pkgs/stack_trace/lib/src/trace.dart | 10 +++++---- pkgs/stack_trace/test/frame_test.dart | 5 ++--- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 53ae61999..23909f8f0 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -134,8 +134,8 @@ class Frame { /// Parses a string representation of a Dart VM stack frame. factory Frame.parseVM(String frame) => _catchFormatException(frame, () { - // The VM sometimes folds multiple stack frames together and replaces them - // with "...". + // The VM sometimes folds multiple stack frames together and replaces + // them with "...". if (frame == '...') { return new Frame(new Uri(), null, null, '...'); } @@ -163,8 +163,8 @@ class Frame { var match = _v8Frame.firstMatch(frame); if (match == null) return new UnparsedFrame(frame); - // v8 location strings can be arbitrarily-nested, since it adds a layer of - // nesting for each eval performed on that line. + // v8 location strings can be arbitrarily-nested, since it adds a layer + // of nesting for each eval performed on that line. parseLocation(location, member) { var evalMatch = _v8EvalLocation.firstMatch(location); while (evalMatch != null) { @@ -185,9 +185,9 @@ class Frame { // V8 stack frames can be in two forms. if (match[2] != null) { - // The first form looks like " at FUNCTION (LOCATION)". V8 proper lists - // anonymous functions within eval as "", while IE10 lists them - // as "Anonymous function". + // The first form looks like " at FUNCTION (LOCATION)". V8 proper + // lists anonymous functions within eval as "", while IE10 + // lists them as "Anonymous function". return parseLocation( match[2], match[1] @@ -195,8 +195,8 @@ class Frame { .replaceAll("Anonymous function", "") .replaceAll("(anonymous function)", "")); } else { - // The second form looks like " at LOCATION", and is used for anonymous - // functions. + // The second form looks like " at LOCATION", and is used for + // anonymous functions. return parseLocation(match[3], ""); } }); @@ -210,7 +210,7 @@ class Frame { /// be retrieved. factory Frame.parseIE(String frame) => new Frame.parseV8(frame); - /// Parses a string representation of a Firefox 'eval' or 'function' stack frame. + /// Parses a Firefox 'eval' or 'function' stack frame. /// /// for example: /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 @@ -247,8 +247,8 @@ class Frame { new List.filled('/'.allMatches(match[2]).length, ".").join(); if (member == '') member = ''; - // Some Firefox members have initial dots. We remove them for consistency - // with other platforms. + // Some Firefox members have initial dots. We remove them for + // consistency with other platforms. member = member.replaceFirst(_initialDot, ''); } else { member = ''; @@ -279,12 +279,13 @@ class Frame { "Couldn't parse package:stack_trace stack trace line '$frame'."); } // Fake truncated data urls generated by the friendly stack trace format - // cause Uri.parse to throw an exception so we have to special case them. + // cause Uri.parse to throw an exception so we have to special case + // them. var uri = match[1] == 'data:...' ? new Uri.dataFromString('') : Uri.parse(match[1]); - // If there's no scheme, this is a relative URI. We should interpret it as - // relative to the current working directory. + // If there's no scheme, this is a relative URI. We should interpret it + // as relative to the current working directory. if (uri.scheme == '') { uri = path.toUri(path.absolute(path.fromUri(uri))); } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 9baff1c70..09c1ca1c8 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -28,10 +28,12 @@ final _v8Trace = new RegExp(r"\n ?at "); final _v8TraceLine = new RegExp(r" ?at "); /// A RegExp to match Firefox's eval and Function stack traces. +/// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack +/// /// These stack traces looks like: -/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 -/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 +/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 +/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 final _firefoxEvalTrace = new RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); @@ -172,8 +174,8 @@ class Trace implements StackTrace { trace .split("\n") .skip(1) - // It's possible that an Exception's description contains a line that - // looks like a V8 trace line, which will screw this up. + // It's possible that an Exception's description contains a line + // that looks like a V8 trace line, which will screw this up. // Unfortunately, that's impossible to detect. .skipWhile((line) => !line.startsWith(_v8TraceLine)) .map((line) => new Frame.parseV8(line)), diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 1ec3c995d..4e46a559c 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -259,13 +259,12 @@ baz@http://pub.dartlang.org/buz.js:56355:55 expect(trace.frames[2].member, equals("baz")); }); - test( - 'parses a Firefox stack trace with nested evals in anonymous function correctly', + test('parses a Firefox stack trace with nested evals in anonymous function', () { var trace = new Trace.parse(''' Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 anonymous@file:///C:/example.html line 7 > eval line 1 > eval:1:1 - anonymous@file:///C:/example.html line 45 > Function:1:1 + anonymous@file:///C:/example.html line 45 > Function:1:1 '''); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); From a82704fd5d3d999fdf1f662d8df173d05e9c8b9c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Sun, 12 Apr 2020 20:38:09 -0700 Subject: [PATCH 0633/1215] Test on oldest supported SDK (dart-lang/stack_trace#57) - Bump min SDK to 2.0.0 - Run tests and analyzer `--fatal-warnings` on `2.0.0`. - Run tests, dartfmt check, and analyzer `--fatal-infos` on the dev SDK. - Switch from `isInstanceOf` to `TypeMatcher` to fix deprecation warning. --- pkgs/stack_trace/.travis.yml | 9 +++++++-- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 6 +++--- pkgs/stack_trace/test/chain/dart2js_test.dart | 4 ++-- pkgs/stack_trace/test/chain/vm_test.dart | 4 ++-- pkgs/stack_trace/test/frame_test.dart | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 8ddade509..f3c200daf 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev - - stable + - 2.0.0 dart_task: - test: -p vm @@ -12,9 +12,14 @@ dart_task: matrix: include: # Only validate formatting using the dev release - # Formatted with 1.23.0+ which has (good) changes since 1.22.1 - dart: dev dart_task: dartfmt + - dart: dev + dart_task: + dartanalyzer: --fatal-infos --fatal-warnings . + - dart: 2.0.0 + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 070d3e743..3ddf071ba 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -4,7 +4,7 @@ description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: - sdk: '>=1.23.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: path: ^1.2.0 diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 26b04a158..9de7d53b8 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -44,7 +44,7 @@ void main() { return new Future.error("oh no"); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); })); }); @@ -55,7 +55,7 @@ void main() { future.then(expectAsync1((_) {}, count: 0)); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); })); }); @@ -80,7 +80,7 @@ void main() { return new Future.error("oh no"); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); }), when: false); }); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index df3d07bd9..8cceded31 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -151,7 +151,7 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); expect(chain.traces, hasLength(2)); completer.complete(); } catch (error, stackTrace) { @@ -171,7 +171,7 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); expect(chain.traces, hasLength(2)); completer.complete(); } catch (error, stackTrace) { diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index f84d1d2c7..4f8aa957c 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -246,7 +246,7 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); expect(chain.traces[1].frames, contains(frameMember(startsWith('inMicrotask')))); completer.complete(); @@ -267,7 +267,7 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, new isInstanceOf()); + expect(chain, TypeMatcher()); expect(chain.traces[1].frames, contains(frameMember(startsWith('inMicrotask')))); completer.complete(); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 4e46a559c..22e931885 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -658,6 +658,6 @@ baz@http://pub.dartlang.org/buz.js:56355:55 void expectIsUnparsed(Frame constructor(String text), String text) { var frame = constructor(text); - expect(frame, new isInstanceOf()); + expect(frame, TypeMatcher()); expect(frame.toString(), equals(text)); } From 973e37d0604d438db9bc1c200c4599662b2312d5 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 13 Apr 2020 09:55:13 -0700 Subject: [PATCH 0634/1215] Run dartfmt --fix (dart-lang/stack_trace#60) - Use function type syntax for typedefs. - Use `=` for argument default values. - Drop optional `new` and `const`. - Use triple slash for doc comments. --- pkgs/stack_trace/analysis_options.yaml | 7 + pkgs/stack_trace/lib/src/chain.dart | 53 +++-- pkgs/stack_trace/lib/src/frame.dart | 72 +++--- pkgs/stack_trace/lib/src/lazy_chain.dart | 8 +- pkgs/stack_trace/lib/src/lazy_trace.dart | 10 +- .../lib/src/stack_zone_specification.dart | 33 ++- pkgs/stack_trace/lib/src/trace.dart | 74 +++--- pkgs/stack_trace/lib/src/unparsed_frame.dart | 2 +- pkgs/stack_trace/lib/src/vm_trace.dart | 2 +- pkgs/stack_trace/lib/stack_trace.dart | 36 ++- pkgs/stack_trace/test/chain/chain_test.dart | 101 ++++----- pkgs/stack_trace/test/chain/dart2js_test.dart | 45 ++-- pkgs/stack_trace/test/chain/utils.dart | 32 ++- pkgs/stack_trace/test/chain/vm_test.dart | 44 ++-- pkgs/stack_trace/test/frame_test.dart | 214 +++++++++--------- pkgs/stack_trace/test/trace_test.dart | 126 +++++------ pkgs/stack_trace/test/utils.dart | 2 +- pkgs/stack_trace/test/vm_test.dart | 20 +- 18 files changed, 434 insertions(+), 447 deletions(-) create mode 100644 pkgs/stack_trace/analysis_options.yaml diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml new file mode 100644 index 000000000..7472eb06b --- /dev/null +++ b/pkgs/stack_trace/analysis_options.yaml @@ -0,0 +1,7 @@ +linter: + rules: + - prefer_equal_for_default_values + - prefer_generic_function_type_aliases + - slash_for_doc_comments + - unnecessary_const + - unnecessary_new diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 8685a9ee9..da6fb6f06 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -13,10 +13,10 @@ import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. @Deprecated("Will be removed in stack_trace 2.0.0.") -typedef void ChainHandler(error, Chain chain); +typedef ChainHandler = void Function(dynamic error, Chain chain); /// An opaque key used to track the current [StackZoneSpecification]. -final _specKey = new Object(); +final _specKey = Object(); /// A chain of stack traces. /// @@ -73,10 +73,10 @@ class Chain implements StackTrace { /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T callback(), {void onError(error, Chain chain), - bool when: true, - bool errorZone: true}) { + bool when = true, + bool errorZone = true}) { if (!errorZone && onError != null) { - throw new ArgumentError.value( + throw ArgumentError.value( onError, "onError", "must be null if errorZone is false"); } @@ -87,15 +87,15 @@ class Chain implements StackTrace { onError( error, stackTrace == null - ? new Chain.current() - : new Chain.forTrace(stackTrace)); + ? Chain.current() + : Chain.forTrace(stackTrace)); }; } return runZoned(callback, onError: newOnError); } - var spec = new StackZoneSpecification(onError, errorZone: errorZone); + var spec = StackZoneSpecification(onError, errorZone: errorZone); return runZoned(() { try { return callback(); @@ -113,7 +113,7 @@ class Chain implements StackTrace { /// [callback] in a [Zone] in which chain capturing is disabled. /// /// If [callback] returns a value, it will be returned by [disable] as well. - static T disable(T callback(), {bool when: true}) { + static T disable(T callback(), {bool when = true}) { var zoneValues = when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null; @@ -139,14 +139,13 @@ class Chain implements StackTrace { factory Chain.current([int level = 0]) { if (_currentSpec != null) return _currentSpec.currentChain(level + 1); - var chain = new Chain.forTrace(StackTrace.current); - return new LazyChain(() { + var chain = Chain.forTrace(StackTrace.current); + return LazyChain(() { // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - var first = new Trace( - chain.traces.first.frames.skip(level + (inJS ? 2 : 1)), + var first = Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1)), original: chain.traces.first.original.toString()); - return new Chain([first]..addAll(chain.traces.skip(1))); + return Chain([first]..addAll(chain.traces.skip(1))); }); } @@ -161,8 +160,8 @@ class Chain implements StackTrace { factory Chain.forTrace(StackTrace trace) { if (trace is Chain) return trace; if (_currentSpec != null) return _currentSpec.chainFor(trace); - if (trace is Trace) return new Chain([trace]); - return new LazyChain(() => new Chain.parse(trace.toString())); + if (trace is Trace) return Chain([trace]); + return LazyChain(() => Chain.parse(trace.toString())); } /// Parses a string representation of a stack chain. @@ -171,19 +170,19 @@ class Chain implements StackTrace { /// as a full stack chain. Otherwise, it will be parsed as in [Trace.parse] /// and returned as a single-trace chain. factory Chain.parse(String chain) { - if (chain.isEmpty) return new Chain([]); + if (chain.isEmpty) return Chain([]); if (chain.contains(vmChainGap)) { - return new Chain( - chain.split(vmChainGap).map((trace) => new Trace.parseVM(trace))); + return Chain( + chain.split(vmChainGap).map((trace) => Trace.parseVM(trace))); } - if (!chain.contains(chainGap)) return new Chain([new Trace.parse(chain)]); + if (!chain.contains(chainGap)) return Chain([Trace.parse(chain)]); - return new Chain( - chain.split(chainGap).map((trace) => new Trace.parseFriendly(trace))); + return Chain( + chain.split(chainGap).map((trace) => Trace.parseFriendly(trace))); } /// Returns a new [Chain] comprised of [traces]. - Chain(Iterable traces) : traces = new List.unmodifiable(traces); + Chain(Iterable traces) : traces = List.unmodifiable(traces); /// Returns a terser version of [this]. /// @@ -211,7 +210,7 @@ class Chain implements StackTrace { /// If [terse] is true, this will also fold together frames from the core /// library or from this package, and simplify core library frames as in /// [Trace.terse]. - Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) { + Chain foldFrames(bool predicate(Frame frame), {bool terse = false}) { var foldedTraces = traces.map((trace) => trace.foldFrames(predicate, terse: terse)); var nonEmptyTraces = foldedTraces.where((trace) { @@ -229,17 +228,17 @@ class Chain implements StackTrace { // If all the traces contain only internal processing, preserve the last // (top-most) one so that the chain isn't empty. if (nonEmptyTraces.isEmpty && foldedTraces.isNotEmpty) { - return new Chain([foldedTraces.last]); + return Chain([foldedTraces.last]); } - return new Chain(nonEmptyTraces); + return Chain(nonEmptyTraces); } /// Converts [this] to a [Trace]. /// /// The trace version of a chain is just the concatenation of all the traces /// in the chain. - Trace toTrace() => new Trace(traces.expand((trace) => trace.frames)); + Trace toTrace() => Trace(traces.expand((trace) => trace.frames)); String toString() { // Figure out the longest path so we know how much to pad. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 23909f8f0..752dcb73d 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -10,7 +10,7 @@ import 'unparsed_frame.dart'; // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21) // #1 Foo._bar (file:///home/nweiz/code/stuff.dart:42) // #1 Foo._bar (file:///home/nweiz/code/stuff.dart) -final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); +final _vmFrame = RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // at Object.stringify (native) // at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) @@ -18,29 +18,29 @@ final _vmFrame = new RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) // at http://pub.dartlang.org/stuff.dart.js:560:28 final _v8Frame = - new RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); + RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // http://pub.dartlang.org/stuff.dart.js:560:28 -final _v8UrlLocation = new RegExp(r'^(.*):(\d+):(\d+)|native$'); +final _v8UrlLocation = RegExp(r'^(.*):(\d+):(\d+)|native$'); // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28 // eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) // eval as function (eval as otherFunction // (http://pub.dartlang.org/stuff.dart.js:560:28)) final _v8EvalLocation = - new RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); + RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); // anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 // anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 final _firefoxEvalLocation = - new RegExp(r"(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+"); + RegExp(r"(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+"); // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36 // http://pub.dartlang.org/stuff.dart.js:560 -final _firefoxSafariFrame = new RegExp(r'^' +final _firefoxSafariFrame = RegExp(r'^' r'(?:' // Member description. Not present in some Safari frames. r'([^@(/]*)' // The actual name of the member. r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. @@ -59,13 +59,13 @@ final _firefoxSafariFrame = new RegExp(r'^' // foo/bar.dart 10:11 (anonymous function).dart.fn // http://dartlang.org/foo/bar.dart Foo._bar // data:... 10:11 Foo._bar -final _friendlyFrame = new RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); +final _friendlyFrame = RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); /// A regular expression that matches asynchronous member names generated by the /// VM. -final _asyncBody = new RegExp(r'<(|[^>]+)_async_body>'); +final _asyncBody = RegExp(r'<(|[^>]+)_async_body>'); -final _initialDot = new RegExp(r"^\."); +final _initialDot = RegExp(r"^\."); /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { @@ -125,11 +125,11 @@ class Frame { /// higher than `1`, it will return higher frames. factory Frame.caller([int level = 1]) { if (level < 0) { - throw new ArgumentError("Argument [level] must be greater than or equal " + throw ArgumentError("Argument [level] must be greater than or equal " "to 0."); } - return new Trace.current(level + 1).frames.first; + return Trace.current(level + 1).frames.first; } /// Parses a string representation of a Dart VM stack frame. @@ -137,11 +137,11 @@ class Frame { // The VM sometimes folds multiple stack frames together and replaces // them with "...". if (frame == '...') { - return new Frame(new Uri(), null, null, '...'); + return Frame(Uri(), null, null, '...'); } var match = _vmFrame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); + if (match == null) return UnparsedFrame(frame); // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. @@ -155,13 +155,13 @@ class Frame { lineAndColumn.length > 1 ? int.parse(lineAndColumn[1]) : null; var column = lineAndColumn.length > 2 ? int.parse(lineAndColumn[2]) : null; - return new Frame(uri, line, column, member); + return Frame(uri, line, column, member); }); /// Parses a string representation of a Chrome/V8 stack frame. factory Frame.parseV8(String frame) => _catchFormatException(frame, () { var match = _v8Frame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); + if (match == null) return UnparsedFrame(frame); // v8 location strings can be arbitrarily-nested, since it adds a layer // of nesting for each eval performed on that line. @@ -173,13 +173,13 @@ class Frame { } if (location == 'native') { - return new Frame(Uri.parse('native'), null, null, member); + return Frame(Uri.parse('native'), null, null, member); } var urlMatch = _v8UrlLocation.firstMatch(location); - if (urlMatch == null) return new UnparsedFrame(frame); + if (urlMatch == null) return UnparsedFrame(frame); - return new Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]), + return Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]), int.parse(urlMatch[3]), member); } @@ -202,13 +202,13 @@ class Frame { }); /// Parses a string representation of a JavaScriptCore stack trace. - factory Frame.parseJSCore(String frame) => new Frame.parseV8(frame); + factory Frame.parseJSCore(String frame) => Frame.parseV8(frame); /// Parses a string representation of an IE stack frame. /// /// IE10+ frames look just like V8 frames. Prior to IE10, stack traces can't /// be retrieved. - factory Frame.parseIE(String frame) => new Frame.parseV8(frame); + factory Frame.parseIE(String frame) => Frame.parseV8(frame); /// Parses a Firefox 'eval' or 'function' stack frame. /// @@ -218,20 +218,20 @@ class Frame { factory Frame._parseFirefoxEval(String frame) => _catchFormatException(frame, () { final match = _firefoxEvalLocation.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); + if (match == null) return UnparsedFrame(frame); var member = match[1].replaceAll('/<', ''); final uri = _uriOrPathToUri(match[2]); final line = int.parse(match[3]); if (member.isEmpty || member == 'anonymous') { member = ''; } - return new Frame(uri, line, null, member); + return Frame(uri, line, null, member); }); /// Parses a string representation of a Firefox stack frame. factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { var match = _firefoxSafariFrame.firstMatch(frame); - if (match == null) return new UnparsedFrame(frame); + if (match == null) return UnparsedFrame(frame); if (match[3].contains(' line ')) { return Frame._parseFirefoxEval(frame); @@ -244,7 +244,7 @@ class Frame { if (match[1] != null) { member = match[1]; member += - new List.filled('/'.allMatches(match[2]).length, ".").join(); + List.filled('/'.allMatches(match[2]).length, ".").join(); if (member == '') member = ''; // Some Firefox members have initial dots. We remove them for @@ -257,32 +257,32 @@ class Frame { var line = match[4] == '' ? null : int.parse(match[4]); var column = match[5] == null || match[5] == '' ? null : int.parse(match[5]); - return new Frame(uri, line, column, member); + return Frame(uri, line, column, member); }); /// Parses a string representation of a Safari 6.0 stack frame. @Deprecated("Use Frame.parseSafari instead.") - factory Frame.parseSafari6_0(String frame) => new Frame.parseFirefox(frame); + factory Frame.parseSafari6_0(String frame) => Frame.parseFirefox(frame); /// Parses a string representation of a Safari 6.1+ stack frame. @Deprecated("Use Frame.parseSafari instead.") - factory Frame.parseSafari6_1(String frame) => new Frame.parseFirefox(frame); + factory Frame.parseSafari6_1(String frame) => Frame.parseFirefox(frame); /// Parses a string representation of a Safari stack frame. - factory Frame.parseSafari(String frame) => new Frame.parseFirefox(frame); + factory Frame.parseSafari(String frame) => Frame.parseFirefox(frame); /// Parses this package's string representation of a stack frame. factory Frame.parseFriendly(String frame) => _catchFormatException(frame, () { var match = _friendlyFrame.firstMatch(frame); if (match == null) { - throw new FormatException( + throw FormatException( "Couldn't parse package:stack_trace stack trace line '$frame'."); } // Fake truncated data urls generated by the friendly stack trace format // cause Uri.parse to throw an exception so we have to special case // them. var uri = match[1] == 'data:...' - ? new Uri.dataFromString('') + ? Uri.dataFromString('') : Uri.parse(match[1]); // If there's no scheme, this is a relative URI. We should interpret it // as relative to the current working directory. @@ -292,14 +292,14 @@ class Frame { var line = match[2] == null ? null : int.parse(match[2]); var column = match[3] == null ? null : int.parse(match[3]); - return new Frame(uri, line, column, match[4]); + return Frame(uri, line, column, match[4]); }); /// A regular expression matching an absolute URI. - static final _uriRegExp = new RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); + static final _uriRegExp = RegExp(r'^[a-zA-Z][-+.a-zA-Z\d]*://'); /// A regular expression matching a Windows path. - static final _windowsRegExp = new RegExp(r'^([a-zA-Z]:[\\/]|\\\\)'); + static final _windowsRegExp = RegExp(r'^([a-zA-Z]:[\\/]|\\\\)'); /// Converts [uriOrPath], which can be a URI, a Windows path, or a Posix path, /// to a URI (absolute if possible). @@ -307,9 +307,9 @@ class Frame { if (uriOrPath.contains(_uriRegExp)) { return Uri.parse(uriOrPath); } else if (uriOrPath.contains(_windowsRegExp)) { - return new Uri.file(uriOrPath, windows: true); + return Uri.file(uriOrPath, windows: true); } else if (uriOrPath.startsWith('/')) { - return new Uri.file(uriOrPath, windows: false); + return Uri.file(uriOrPath, windows: false); } // As far as I've seen, Firefox and V8 both always report absolute paths in @@ -327,7 +327,7 @@ class Frame { try { return body(); } on FormatException catch (_) { - return new UnparsedFrame(text); + return UnparsedFrame(text); } } diff --git a/pkgs/stack_trace/lib/src/lazy_chain.dart b/pkgs/stack_trace/lib/src/lazy_chain.dart index 55b98974a..5dbe1c01f 100644 --- a/pkgs/stack_trace/lib/src/lazy_chain.dart +++ b/pkgs/stack_trace/lib/src/lazy_chain.dart @@ -8,7 +8,7 @@ import 'lazy_trace.dart'; import 'trace.dart'; /// A thunk for lazily constructing a [Chain]. -typedef Chain ChainThunk(); +typedef ChainThunk = Chain Function(); /// A wrapper around a [ChainThunk]. This works around issue 9579 by avoiding /// the conversion of native [StackTrace]s to strings until it's absolutely @@ -26,8 +26,8 @@ class LazyChain implements Chain { List get traces => _chain.traces; Chain get terse => _chain.terse; - Chain foldFrames(bool predicate(Frame frame), {bool terse: false}) => - new LazyChain(() => _chain.foldFrames(predicate, terse: terse)); - Trace toTrace() => new LazyTrace(() => _chain.toTrace()); + Chain foldFrames(bool predicate(Frame frame), {bool terse = false}) => + LazyChain(() => _chain.foldFrames(predicate, terse: terse)); + Trace toTrace() => LazyTrace(() => _chain.toTrace()); String toString() => _chain.toString(); } diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index a31b75fde..9cd53ee94 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -6,7 +6,7 @@ import 'frame.dart'; import 'trace.dart'; /// A thunk for lazily constructing a [Trace]. -typedef Trace TraceThunk(); +typedef TraceThunk = Trace Function(); /// A wrapper around a [TraceThunk]. This works around issue 9579 by avoiding /// the conversion of native [StackTrace]s to strings until it's absolutely @@ -25,11 +25,11 @@ class LazyTrace implements Trace { List get frames => _trace.frames; StackTrace get original => _trace.original; StackTrace get vmTrace => _trace.vmTrace; - Trace get terse => new LazyTrace(() => _trace.terse); - Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) => - new LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); + Trace get terse => LazyTrace(() => _trace.terse); + Trace foldFrames(bool predicate(Frame frame), {bool terse = false}) => + LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); String toString() => _trace.toString(); // Work around issue 14075. - set frames(_) => throw new UnimplementedError(); + set frames(_) => throw UnimplementedError(); } diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 6c31d1280..4ef4eae3c 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -11,7 +11,7 @@ import 'trace.dart'; import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. -typedef void _ChainHandler(error, Chain chain); +typedef _ChainHandler = void Function(dynamic error, Chain chain); /// A class encapsulating the zone specification for a [Chain.capture] zone. /// @@ -37,7 +37,7 @@ class StackZoneSpecification { /// zone. /// /// If `Zone.current[disableKey]` is `true`, no stack chains will be tracked. - static final disableKey = new Object(); + static final disableKey = Object(); /// Whether chain-tracking is disabled in the current zone. bool get _disabled => Zone.current[disableKey] == true; @@ -50,7 +50,7 @@ class StackZoneSpecification { /// /// The chain associated with a given stack trace doesn't contain a node for /// that stack trace. - final _chains = new Expando<_Node>("stack chains"); + final _chains = Expando<_Node>("stack chains"); /// The error handler for the zone. /// @@ -64,12 +64,12 @@ class StackZoneSpecification { /// Whether this is an error zone. final bool _errorZone; - StackZoneSpecification(this._onError, {bool errorZone: true}) + StackZoneSpecification(this._onError, {bool errorZone = true}) : _errorZone = errorZone; /// Converts [this] to a real [ZoneSpecification]. ZoneSpecification toSpec() { - return new ZoneSpecification( + return ZoneSpecification( handleUncaughtError: _errorZone ? _handleUncaughtError : null, registerCallback: _registerCallback, registerUnaryCallback: _registerUnaryCallback, @@ -98,15 +98,15 @@ class StackZoneSpecification { // If there's no [_currentNode], we're running synchronously beneath // [Chain.capture] and we should fall back to the VM's stack chaining. We // can't use [Chain.from] here because it'll just call [chainFor] again. - if (trace is Trace) return new Chain([trace]); - return new LazyChain(() => new Chain.parse(trace.toString())); + if (trace is Trace) return Chain([trace]); + return LazyChain(() => Chain.parse(trace.toString())); } else { if (trace is! Trace) { var original = trace; - trace = new LazyTrace(() => new Trace.parse(_trimVMChain(original))); + trace = LazyTrace(() => Trace.parse(_trimVMChain(original))); } - return new _Node(trace, previous).toChain(); + return _Node(trace, previous).toChain(); } } @@ -184,7 +184,7 @@ class StackZoneSpecification { } var asyncError = parent.errorCallback(zone, error, stackTrace); - return asyncError == null ? new AsyncError(error, stackTrace) : asyncError; + return asyncError == null ? AsyncError(error, stackTrace) : asyncError; } /// Creates a [_Node] with the current stack trace and linked to @@ -194,7 +194,7 @@ class StackZoneSpecification { /// [_createNode] is called. If [level] is passed, the first trace will start /// that many frames up instead. _Node _createNode([int level = 0]) => - new _Node(_currentTrace(level + 1), _currentNode); + _Node(_currentTrace(level + 1), _currentNode); // TODO(nweiz): use a more robust way of detecting and tracking errors when // issue 15105 is fixed. @@ -223,13 +223,12 @@ class StackZoneSpecification { Trace _currentTrace([int level]) { level ??= 0; var stackTrace = StackTrace.current; - return new LazyTrace(() { + return LazyTrace(() { var text = _trimVMChain(stackTrace); - var trace = new Trace.parse(text); + var trace = Trace.parse(text); // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), - original: text); + return Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: text); }); } @@ -250,7 +249,7 @@ class _Node { /// The previous node in the chain. final _Node previous; - _Node(StackTrace trace, [this.previous]) : trace = new Trace.from(trace); + _Node(StackTrace trace, [this.previous]) : trace = Trace.from(trace); /// Converts this to a [Chain]. Chain toChain() { @@ -260,6 +259,6 @@ class _Node { nodes.add(node.trace); node = node.previous; } - return new Chain(nodes); + return Chain(nodes); } } diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 09c1ca1c8..4a908746e 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -11,7 +11,7 @@ import 'unparsed_frame.dart'; import 'utils.dart'; import 'vm_trace.dart'; -final _terseRegExp = new RegExp(r"(-patch)?([/\\].*)?$"); +final _terseRegExp = RegExp(r"(-patch)?([/\\].*)?$"); /// A RegExp to match V8's stack traces. /// @@ -19,13 +19,13 @@ final _terseRegExp = new RegExp(r"(-patch)?([/\\].*)?$"); /// description of the exception that occurred. That description can be multiple /// lines, so we just look for any line other than the first that begins with /// three or four spaces and "at". -final _v8Trace = new RegExp(r"\n ?at "); +final _v8Trace = RegExp(r"\n ?at "); /// A RegExp to match indidual lines of V8's stack traces. /// /// This is intended to filter out the leading exception details of the trace /// though it is possible for the message to match this as well. -final _v8TraceLine = new RegExp(r" ?at "); +final _v8TraceLine = RegExp(r" ?at "); /// A RegExp to match Firefox's eval and Function stack traces. /// @@ -34,8 +34,7 @@ final _v8TraceLine = new RegExp(r" ?at "); /// These stack traces looks like: /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 -final _firefoxEvalTrace = - new RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); +final _firefoxEvalTrace = RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); /// A RegExp to match Firefox and Safari's stack traces. /// @@ -50,7 +49,7 @@ final _firefoxEvalTrace = /// "@", and they always have both the line and column number (or just a /// trailing colon if no column number is available). They can also contain /// empty lines or lines consisting only of `[native code]`. -final _firefoxSafariTrace = new RegExp( +final _firefoxSafariTrace = RegExp( r"^" r"(" // Member description. Not present in some Safari frames. r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. @@ -63,7 +62,7 @@ final _firefoxSafariTrace = new RegExp( /// A RegExp to match this package's stack traces. final _friendlyTrace = - new RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); + RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { @@ -77,8 +76,8 @@ class Trace implements StackTrace { /// set, this folds together multiple stack frames from the Dart core /// libraries, so that only the core library method directly called from user /// code is visible (see [Trace.terse]). - static String format(StackTrace stackTrace, {bool terse: true}) { - var trace = new Trace.from(stackTrace); + static String format(StackTrace stackTrace, {bool terse = true}) { + var trace = Trace.from(stackTrace); if (terse) trace = trace.terse; return trace.toString(); } @@ -90,15 +89,15 @@ class Trace implements StackTrace { /// many frames up instead. factory Trace.current([int level = 0]) { if (level < 0) { - throw new ArgumentError("Argument [level] must be greater than or equal " + throw ArgumentError("Argument [level] must be greater than or equal " "to 0."); } - var trace = new Trace.from(StackTrace.current); - return new LazyTrace(() { + var trace = Trace.from(StackTrace.current); + return LazyTrace(() { // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - return new Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + return Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: trace.original.toString()); }); } @@ -112,12 +111,12 @@ class Trace implements StackTrace { // the natural failure will only occur when the LazyTrace is materialized, // and we want to provide an error that's more local to the actual problem. if (trace == null) { - throw new ArgumentError("Cannot create a Trace from null."); + throw ArgumentError("Cannot create a Trace from null."); } if (trace is Trace) return trace; if (trace is Chain) return trace.toTrace(); - return new LazyTrace(() => new Trace.parse(trace.toString())); + return LazyTrace(() => Trace.parse(trace.toString())); } /// Parses a string representation of a stack trace. @@ -127,24 +126,24 @@ class Trace implements StackTrace { /// of [Chain.toTrace]. factory Trace.parse(String trace) { try { - if (trace.isEmpty) return new Trace([]); - if (trace.contains(_v8Trace)) return new Trace.parseV8(trace); - if (trace.contains("\tat ")) return new Trace.parseJSCore(trace); + if (trace.isEmpty) return Trace([]); + if (trace.contains(_v8Trace)) return Trace.parseV8(trace); + if (trace.contains("\tat ")) return Trace.parseJSCore(trace); if (trace.contains(_firefoxSafariTrace) || trace.contains(_firefoxEvalTrace)) { - return new Trace.parseFirefox(trace); + return Trace.parseFirefox(trace); } - if (trace.contains(chainGap)) return new Chain.parse(trace).toTrace(); + if (trace.contains(chainGap)) return Chain.parse(trace).toTrace(); if (trace.contains(_friendlyTrace)) { - return new Trace.parseFriendly(trace); + return Trace.parseFriendly(trace); } // Default to parsing the stack trace as a VM trace. This is also hit on // IE and Safari, where the stack trace is just an empty string (issue // 11257). - return new Trace.parseVM(trace); + return Trace.parseVM(trace); } on FormatException catch (error) { - throw new FormatException('${error.message}\nStack trace:\n$trace'); + throw FormatException('${error.message}\nStack trace:\n$trace'); } } @@ -157,12 +156,12 @@ class Trace implements StackTrace { var lines = trace.trim().replaceAll(vmChainGap, '').split("\n"); var frames = lines .take(lines.length - 1) - .map((line) => new Frame.parseVM(line)) + .map((line) => Frame.parseVM(line)) .toList(); // TODO(nweiz): Remove this when issue 23614 is fixed. if (!lines.last.endsWith(".da")) { - frames.add(new Frame.parseVM(lines.last)); + frames.add(Frame.parseVM(lines.last)); } return frames; @@ -178,7 +177,7 @@ class Trace implements StackTrace { // that looks like a V8 trace line, which will screw this up. // Unfortunately, that's impossible to detect. .skipWhile((line) => !line.startsWith(_v8TraceLine)) - .map((line) => new Frame.parseV8(line)), + .map((line) => Frame.parseV8(line)), original: trace); /// Parses a string representation of a JavaScriptCore stack trace. @@ -187,7 +186,7 @@ class Trace implements StackTrace { trace .split("\n") .where((line) => line != "\tat ") - .map((line) => new Frame.parseV8(line)), + .map((line) => Frame.parseV8(line)), original: trace); /// Parses a string representation of an Internet Explorer stack trace. @@ -203,7 +202,7 @@ class Trace implements StackTrace { .trim() .split("\n") .where((line) => line.isNotEmpty && line != '[native code]') - .map((line) => new Frame.parseFirefox(line)), + .map((line) => Frame.parseFirefox(line)), original: trace); /// Parses a string representation of a Safari stack trace. @@ -221,7 +220,7 @@ class Trace implements StackTrace { .trim() .split("\n") .where((line) => line != '[native code]') - .map((line) => new Frame.parseFirefox(line)), + .map((line) => Frame.parseFirefox(line)), original: trace); /// Parses this package's string representation of a stack trace. @@ -237,20 +236,20 @@ class Trace implements StackTrace { .split("\n") // Filter out asynchronous gaps from [Chain]s. .where((line) => !line.startsWith('=====')) - .map((line) => new Frame.parseFriendly(line)), + .map((line) => Frame.parseFriendly(line)), original: trace); /// Returns a new [Trace] comprised of [frames]. Trace(Iterable frames, {String original}) - : frames = new List.unmodifiable(frames), - original = new StackTrace.fromString(original); + : frames = List.unmodifiable(frames), + original = StackTrace.fromString(original); /// Returns a VM-style [StackTrace] object. /// /// The return value's [toString] method will always return a string /// representation in the Dart VM's stack trace format, regardless of what /// platform is being used. - StackTrace get vmTrace => new VMTrace(frames); + StackTrace get vmTrace => VMTrace(frames); /// Returns a terser version of [this]. /// @@ -281,7 +280,7 @@ class Trace implements StackTrace { /// If [terse] is true, this will also fold together frames from the core /// library or from this package, simplify core library frames, and /// potentially remove the outermost frame as in [Trace.terse]. - Trace foldFrames(bool predicate(Frame frame), {bool terse: false}) { + Trace foldFrames(bool predicate(Frame frame), {bool terse = false}) { if (terse) { var oldPredicate = predicate; predicate = (frame) { @@ -307,8 +306,7 @@ class Trace implements StackTrace { if (frame is UnparsedFrame || !predicate(frame)) { newFrames.add(frame); } else if (newFrames.isEmpty || !predicate(newFrames.last)) { - newFrames - .add(new Frame(frame.uri, frame.line, frame.column, frame.member)); + newFrames.add(Frame(frame.uri, frame.line, frame.column, frame.member)); } } @@ -316,7 +314,7 @@ class Trace implements StackTrace { newFrames = newFrames.map((frame) { if (frame is UnparsedFrame || !predicate(frame)) return frame; var library = frame.library.replaceAll(_terseRegExp, ''); - return new Frame(Uri.parse(library), null, null, frame.member); + return Frame(Uri.parse(library), null, null, frame.member); }).toList(); if (newFrames.length > 1 && predicate(newFrames.first)) { @@ -324,7 +322,7 @@ class Trace implements StackTrace { } } - return new Trace(newFrames.reversed, original: this.original.toString()); + return Trace(newFrames.reversed, original: this.original.toString()); } /// Returns a human-readable string representation of [this]. diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index 78ac738e8..3f7ffe2d1 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -8,7 +8,7 @@ import 'frame.dart'; /// /// The [member] property contains the original frame's contents. class UnparsedFrame implements Frame { - final Uri uri = new Uri(path: "unparsed"); + final Uri uri = Uri(path: "unparsed"); final int line = null; final int column = null; final bool isCore = false; diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 7086df700..74ffbcad6 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -20,7 +20,7 @@ class VMTrace implements StackTrace { return frames.map((frame) { var number = "#${i++}".padRight(8); var member = frame.member - .replaceAllMapped(new RegExp(r"[^.]+\."), + .replaceAllMapped(RegExp(r"[^.]+\."), (match) => "${match[1]}.<${match[1]}_async_body>") .replaceAll("", ""); var line = frame.line == null ? 0 : frame.line; diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index 1e6f0b01e..8a6ba9b51 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -2,25 +2,23 @@ // 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. -/** - * Stack trace generation and parsing. - * - * ## Installing ## - * - * Use [pub][] to install this package. Add the following to your `pubspec.yaml` - * file. - * - * dependencies: - * stack_trace: any - * - * Then run `pub install`. - * - * For more information, see the - * [stack_trace package on pub.dartlang.org][pkg]. - * - * [pub]: http://pub.dartlang.org - * [pkg]: http://pub.dartlang.org/packages/stack_trace - */ +/// Stack trace generation and parsing. +/// +/// ## Installing ## +/// +/// Use [pub][] to install this package. Add the following to your `pubspec.yaml` +/// file. +/// +/// dependencies: +/// stack_trace: any +/// +/// Then run `pub install`. +/// +/// For more information, see the +/// [stack_trace package on pub.dartlang.org][pkg]. +/// +/// [pub]: http://pub.dartlang.org +/// [pkg]: http://pub.dartlang.org/packages/stack_trace export 'src/chain.dart'; export 'src/frame.dart'; export 'src/trace.dart'; diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 9de7d53b8..40c2954dd 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -10,26 +10,26 @@ import 'package:test/test.dart'; import 'utils.dart'; -typedef void ChainErrorCallback(stack, Chain chain); +typedef ChainErrorCallback = void Function(dynamic stack, Chain chain); void main() { group('Chain.parse()', () { test('parses a real Chain', () { return captureFuture(() => inMicrotask(() => throw 'error')) .then((chain) { - expect(new Chain.parse(chain.toString()).toString(), - equals(chain.toString())); + expect( + Chain.parse(chain.toString()).toString(), equals(chain.toString())); }); }); test('parses an empty string', () { - var chain = new Chain.parse(''); + var chain = Chain.parse(''); expect(chain.traces, isEmpty); }); test('parses a chain containing empty traces', () { var chain = - new Chain.parse('===== asynchronous gap ===========================\n' + Chain.parse('===== asynchronous gap ===========================\n' '===== asynchronous gap ===========================\n'); expect(chain.traces, hasLength(3)); expect(chain.traces[0].frames, isEmpty); @@ -41,7 +41,7 @@ void main() { group("Chain.capture()", () { test("with onError blocks errors", () { Chain.capture(() { - return new Future.error("oh no"); + return Future.error("oh no"); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); expect(chain, TypeMatcher()); @@ -50,8 +50,7 @@ void main() { test("with no onError blocks errors", () { runZoned(() { - var future = - Chain.capture(() => new Future.error("oh no"), when: false); + var future = Chain.capture(() => Future.error("oh no"), when: false); future.then(expectAsync1((_) {}, count: 0)); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); @@ -60,7 +59,7 @@ void main() { }); test("with errorZone: false doesn't block errors", () { - expect(Chain.capture(() => new Future.error("oh no"), errorZone: false), + expect(Chain.capture(() => Future.error("oh no"), errorZone: false), throwsA("oh no")); }); @@ -71,13 +70,13 @@ void main() { group("with when: false", () { test("with no onError doesn't block errors", () { - expect(Chain.capture(() => new Future.error("oh no"), when: false), + expect(Chain.capture(() => Future.error("oh no"), when: false), throwsA("oh no")); }); test("with onError blocks errors", () { Chain.capture(() { - return new Future.error("oh no"); + return Future.error("oh no"); }, onError: expectAsync2((error, chain) { expect(error, equals("oh no")); expect(chain, TypeMatcher()); @@ -87,9 +86,9 @@ void main() { test("doesn't enable chain-tracking", () { return Chain.disable(() { return Chain.capture(() { - var completer = new Completer(); + var completer = Completer(); inMicrotask(() { - completer.complete(new Chain.current()); + completer.complete(Chain.current()); }); return completer.future.then((chain) { @@ -104,8 +103,8 @@ void main() { group("Chain.disable()", () { test("disables chain-tracking", () { return Chain.disable(() { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + var completer = Completer(); + inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { expect(chain.traces, hasLength(1)); @@ -116,8 +115,8 @@ void main() { test("Chain.capture() re-enables chain-tracking", () { return Chain.disable(() { return Chain.capture(() { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + var completer = Completer(); + inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { expect(chain.traces, hasLength(2)); @@ -151,8 +150,8 @@ void main() { test("with when: false doesn't disable", () { return Chain.capture(() { return Chain.disable(() { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + var completer = Completer(); + inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { expect(chain.traces, hasLength(2)); @@ -163,9 +162,9 @@ void main() { }); test("toString() ensures that all traces are aligned", () { - var chain = new Chain([ - new Trace.parse('short 10:11 Foo.bar\n'), - new Trace.parse('loooooooooooong 10:11 Zop.zoop') + var chain = Chain([ + Trace.parse('short 10:11 Foo.bar\n'), + Trace.parse('loooooooooooong 10:11 Zop.zoop') ]); expect( @@ -178,13 +177,13 @@ void main() { var userSlashCode = p.join('user', 'code.dart'); group('Chain.terse', () { test('makes each trace terse', () { - var chain = new Chain([ - new Trace.parse('dart:core 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('dart:core 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz\n' 'user/code.dart 10:11 Bang.qux\n' 'dart:core 10:11 Zip.zap\n' 'dart:core 10:11 Zop.zoop'), - new Trace.parse('user/code.dart 10:11 Bang.qux\n' + Trace.parse('user/code.dart 10:11 Bang.qux\n' 'dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap\n' @@ -202,13 +201,13 @@ void main() { }); test('eliminates internal-only traces', () { - var chain = new Chain([ - new Trace.parse('user/code.dart 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz'), - new Trace.parse('dart:core 10:11 Foo.bar\n' + Trace.parse('dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap'), - new Trace.parse('user/code.dart 10:11 Foo.bar\n' + Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz') ]); @@ -220,11 +219,11 @@ void main() { }); test("doesn't return an empty chain", () { - var chain = new Chain([ - new Trace.parse('dart:core 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('dart:core 10:11 Foo.bar\n' 'package:stack_trace/stack_trace.dart 10:11 Bar.baz\n' 'dart:core 10:11 Zip.zap'), - new Trace.parse('dart:core 10:11 A.b\n' + Trace.parse('dart:core 10:11 A.b\n' 'package:stack_trace/stack_trace.dart 10:11 C.d\n' 'dart:core 10:11 E.f') ]); @@ -234,10 +233,10 @@ void main() { // Regression test for #9 test("doesn't crash on empty traces", () { - var chain = new Chain([ - new Trace.parse('user/code.dart 10:11 Bang.qux'), - new Trace([]), - new Trace.parse('user/code.dart 10:11 Bang.qux') + var chain = Chain([ + Trace.parse('user/code.dart 10:11 Bang.qux'), + Trace([]), + Trace.parse('user/code.dart 10:11 Bang.qux') ]); expect( @@ -250,13 +249,13 @@ void main() { group('Chain.foldFrames', () { test('folds each trace', () { - var chain = new Chain([ - new Trace.parse('a.dart 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'b.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' 'a.dart 10:11 Zop.zoop'), - new Trace.parse('a.dart 10:11 Foo.bar\n' + Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'a.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' @@ -275,13 +274,13 @@ void main() { }); test('with terse: true, folds core frames as well', () { - var chain = new Chain([ - new Trace.parse('a.dart 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('a.dart 10:11 Foo.bar\n' 'dart:async-patch/future.dart 10:11 Zip.zap\n' 'b.dart 10:11 Bang.qux\n' 'dart:core 10:11 Bar.baz\n' 'a.dart 10:11 Zop.zoop'), - new Trace.parse('a.dart 10:11 Foo.bar\n' + Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bar.baz\n' 'a.dart 10:11 Bang.qux\n' 'a.dart 10:11 Zip.zap\n' @@ -300,12 +299,12 @@ void main() { }); test('eliminates completely-folded traces', () { - var chain = new Chain([ - new Trace.parse('a.dart 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('a.dart 10:11 Foo.bar\n' 'b.dart 10:11 Bang.qux'), - new Trace.parse('a.dart 10:11 Foo.bar\n' + Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bang.qux'), - new Trace.parse('a.dart 10:11 Zip.zap\n' + Trace.parse('a.dart 10:11 Zip.zap\n' 'b.dart 10:11 Zop.zoop') ]); @@ -320,8 +319,8 @@ void main() { }); test("doesn't return an empty trace", () { - var chain = new Chain([ - new Trace.parse('a.dart 10:11 Foo.bar\n' + var chain = Chain([ + Trace.parse('a.dart 10:11 Foo.bar\n' 'a.dart 10:11 Bang.qux') ]); @@ -331,10 +330,10 @@ void main() { }); test('Chain.toTrace eliminates asynchronous gaps', () { - var trace = new Chain([ - new Trace.parse('user/code.dart 10:11 Foo.bar\n' + var trace = Chain([ + Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz'), - new Trace.parse('user/code.dart 10:11 Foo.bar\n' + Trace.parse('user/code.dart 10:11 Foo.bar\n' 'dart:core 10:11 Bar.baz') ]).toTrace(); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index 8cceded31..fbbad5611 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -73,7 +73,7 @@ void main() { }); test('multiple times', () { - var completer = new Completer(); + var completer = Completer(); var first = true; Chain.capture(() { @@ -99,7 +99,7 @@ void main() { }); test('passed to a completer', () async { - var trace = new Trace.current(); + var trace = Trace.current(); var chain = await captureFuture(() { inMicrotask(() => completerErrorFuture(trace)); }); @@ -120,7 +120,7 @@ void main() { }); test('passed to a stream controller', () async { - var trace = new Trace.current(); + var trace = Trace.current(); var chain = await captureFuture(() { inMicrotask(() => controllerErrorStream(trace).listen(null)); }); @@ -138,7 +138,7 @@ void main() { }); test('and relays them to the parent zone', () { - var completer = new Completer(); + var completer = Completer(); runZoned(() { Chain.capture(() { @@ -164,7 +164,7 @@ void main() { }); test('capture() without onError passes exceptions to parent zone', () { - var completer = new Completer(); + var completer = Completer(); runZoned(() { Chain.capture(() => inMicrotask(() => throw 'error')); @@ -184,9 +184,9 @@ void main() { group('current() within capture()', () { test('called in a microtask', () async { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inMicrotask(() => completer.complete(new Chain.current())); + inMicrotask(() => completer.complete(Chain.current())); }); var chain = await completer.future; @@ -194,9 +194,9 @@ void main() { }); test('called in a one-shot timer', () async { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inOneShotTimer(() => completer.complete(new Chain.current())); + inOneShotTimer(() => completer.complete(Chain.current())); }); var chain = await completer.future; @@ -204,9 +204,9 @@ void main() { }); test('called in a periodic timer', () async { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inPeriodicTimer(() => completer.complete(new Chain.current())); + inPeriodicTimer(() => completer.complete(Chain.current())); }); var chain = await completer.future; @@ -214,11 +214,11 @@ void main() { }); test('called in a nested series of asynchronous operations', () async { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() { inOneShotTimer(() { - inMicrotask(() => completer.complete(new Chain.current())); + inMicrotask(() => completer.complete(Chain.current())); }); }); }); @@ -228,9 +228,9 @@ void main() { }); test('called in a long future chain', () async { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inFutureChain(() => completer.complete(new Chain.current())); + inFutureChain(() => completer.complete(Chain.current())); }); var chain = await completer.future; @@ -243,8 +243,8 @@ void main() { 'trace', () { // The test runner runs all tests with chains enabled. return Chain.disable(() async { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + var completer = Completer(); + inMicrotask(() => completer.complete(Chain.current())); var chain = await completer.future; // Since the chain wasn't loaded within [Chain.capture], the full stack @@ -311,13 +311,13 @@ void main() { throw 'error'; } catch (_, stackTrace) { trace = stackTrace; - return new Chain.forTrace(stackTrace); + return Chain.forTrace(stackTrace); } }); expect(chain.traces, hasLength(1)); - expect(chain.traces.first.toString(), - equals(new Trace.from(trace).toString())); + expect( + chain.traces.first.toString(), equals(Trace.from(trace).toString())); }); }); @@ -330,12 +330,11 @@ void main() { throw 'error'; } catch (_, stackTrace) { trace = stackTrace; - return new Chain.forTrace(stackTrace); + return Chain.forTrace(stackTrace); } }); expect(chain.traces, hasLength(1)); - expect(chain.traces.first.toString(), - equals(new Trace.from(trace).toString())); + expect(chain.traces.first.toString(), equals(Trace.from(trace).toString())); }); } diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 0c5c98372..c1f98e400 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -16,7 +16,7 @@ void inOneShotTimer(callback()) => Timer.run(callback); /// Runs [callback] once in a periodic timer callback. void inPeriodicTimer(callback()) { var count = 0; - new Timer.periodic(new Duration(milliseconds: 1), (timer) { + Timer.periodic(Duration(milliseconds: 1), (timer) { count++; if (count != 5) return; timer.cancel(); @@ -26,28 +26,28 @@ void inPeriodicTimer(callback()) { /// Runs [callback] within a long asynchronous Future chain. void inFutureChain(callback()) { - new Future(() {}) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) - .then((_) => new Future(() {})) + Future(() {}) + .then((_) => Future(() {})) + .then((_) => Future(() {})) + .then((_) => Future(() {})) + .then((_) => Future(() {})) .then((_) => callback()) - .then((_) => new Future(() {})); + .then((_) => Future(() {})); } void inNewFuture(callback()) { - new Future(callback); + Future(callback); } void inSyncFuture(callback()) { - new Future.sync(callback); + Future.sync(callback); } /// Returns a Future that completes to an error using a completer. /// /// If [trace] is passed, it's used as the stack trace for the error. Future completerErrorFuture([StackTrace trace]) { - var completer = new Completer(); + var completer = Completer(); completer.completeError('error', trace); return completer.future; } @@ -56,7 +56,7 @@ Future completerErrorFuture([StackTrace trace]) { /// /// If [trace] is passed, it's used as the stack trace for the error. Stream controllerErrorStream([StackTrace trace]) { - var controller = new StreamController(); + var controller = StreamController(); controller.addError('error', trace); return controller.stream; } @@ -64,19 +64,17 @@ Stream controllerErrorStream([StackTrace trace]) { /// Runs [callback] within [asyncFn], then converts any errors raised into a /// [Chain] with [Chain.forTrace]. Future chainForTrace(asyncFn(callback()), callback()) { - var completer = new Completer(); + var completer = Completer(); asyncFn(() { // We use `new Future.value().then(...)` here as opposed to [new Future] or // [new Future.sync] because those methods don't pass the exception through // the zone specification before propagating it, so there's no chance to // attach a chain to its stack trace. See issue 15105. - new Future.value() - .then((_) => callback()) - .catchError(completer.completeError); + Future.value().then((_) => callback()).catchError(completer.completeError); }); return completer.future - .catchError((_, stackTrace) => new Chain.forTrace(stackTrace)); + .catchError((_, stackTrace) => Chain.forTrace(stackTrace)); } /// Runs [callback] in a [Chain.capture] zone and returns a Future that @@ -84,7 +82,7 @@ Future chainForTrace(asyncFn(callback()), callback()) { /// /// [callback] is expected to throw the string `"error"`. Future captureFuture(callback()) { - var completer = new Completer(); + var completer = Completer(); Chain.capture(callback, onError: (error, chain) { expect(error, equals('error')); completer.complete(chain); diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 4f8aa957c..c006d8894 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -31,8 +31,8 @@ void main() { // Because there's no chain context for a synchronous error, we fall back // on the VM's stack chain tracking. - expect(chain.toString(), - equals(new Chain.parse(vmTrace.toString()).toString())); + expect( + chain.toString(), equals(Chain.parse(vmTrace.toString()).toString())); }); test('thrown in a microtask', () { @@ -137,7 +137,7 @@ void main() { }); test('multiple times', () { - var completer = new Completer(); + var completer = Completer(); var first = true; Chain.capture(() { @@ -165,7 +165,7 @@ void main() { }); test('passed to a completer', () { - var trace = new Trace.current(); + var trace = Trace.current(); return captureFuture(() { inMicrotask(() => completerErrorFuture(trace)); }).then((chain) { @@ -206,7 +206,7 @@ void main() { }); test('passed to a stream controller', () { - var trace = new Trace.current(); + var trace = Trace.current(); return captureFuture(() { inMicrotask(() => controllerErrorStream(trace).listen(null)); }).then((chain) { @@ -232,7 +232,7 @@ void main() { }); test('and relays them to the parent zone', () { - var completer = new Completer(); + var completer = Completer(); runZoned(() { Chain.capture(() { @@ -260,7 +260,7 @@ void main() { }); test('capture() without onError passes exceptions to parent zone', () { - var completer = new Completer(); + var completer = Completer(); runZoned(() { Chain.capture(() => inMicrotask(() => throw 'error')); @@ -281,9 +281,9 @@ void main() { group('current() within capture()', () { test('called in a microtask', () { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inMicrotask(() => completer.complete(new Chain.current())); + inMicrotask(() => completer.complete(Chain.current())); }); return completer.future.then((chain) { @@ -295,9 +295,9 @@ void main() { }); test('called in a one-shot timer', () { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inOneShotTimer(() => completer.complete(new Chain.current())); + inOneShotTimer(() => completer.complete(Chain.current())); }); return completer.future.then((chain) { @@ -309,9 +309,9 @@ void main() { }); test('called in a periodic timer', () { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inPeriodicTimer(() => completer.complete(new Chain.current())); + inPeriodicTimer(() => completer.complete(Chain.current())); }); return completer.future.then((chain) { @@ -323,11 +323,11 @@ void main() { }); test('called in a nested series of asynchronous operations', () { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() { inOneShotTimer(() { - inMicrotask(() => completer.complete(new Chain.current())); + inMicrotask(() => completer.complete(Chain.current())); }); }); }); @@ -345,9 +345,9 @@ void main() { }); test('called in a long future chain', () { - var completer = new Completer(); + var completer = Completer(); Chain.capture(() { - inFutureChain(() => completer.complete(new Chain.current())); + inFutureChain(() => completer.complete(Chain.current())); }); return completer.future.then((chain) { @@ -364,8 +364,8 @@ void main() { 'trace', () { // The test runner runs all tests with chains enabled. return Chain.disable(() { - var completer = new Completer(); - inMicrotask(() => completer.complete(new Chain.current())); + var completer = Completer(); + inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { // Since the chain wasn't loaded within [Chain.capture], the full stack @@ -463,7 +463,7 @@ void main() { throw 'error'; } catch (_, stackTrace) { trace = stackTrace; - return new Chain.forTrace(stackTrace); + return Chain.forTrace(stackTrace); } }); @@ -472,7 +472,7 @@ void main() { // Assert that we've trimmed the VM's stack chains here to avoid // duplication. expect(chain.traces.first.toString(), - equals(new Chain.parse(trace.toString()).traces.first.toString())); + equals(Chain.parse(trace.toString()).traces.first.toString())); }); }); @@ -490,7 +490,7 @@ void main() { } }); - var chain = new Chain.forTrace(trace); + var chain = Chain.forTrace(trace); expect(chain.traces, hasLength(vmChainGap.allMatches(trace.toString()).length + 1)); expect( diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 22e931885..685603e31 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -9,7 +9,7 @@ import 'package:test/test.dart'; void main() { group('.parseVM', () { test('parses a stack frame with column correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " + var frame = Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:42:21)"); expect( frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); @@ -19,7 +19,7 @@ void main() { }); test('parses a stack frame without column correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " + var frame = Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart:24)"); expect( frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); @@ -30,7 +30,7 @@ void main() { // This can happen with async stack traces. See issue 22009. test('parses a stack frame without line or column correctly', () { - var frame = new Frame.parseVM("#1 Foo._bar " + var frame = Frame.parseVM("#1 Foo._bar " "(file:///home/nweiz/code/stuff.dart)"); expect( frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); @@ -41,7 +41,7 @@ void main() { test('converts "" to ""', () { String parsedMember(String member) => - new Frame.parseVM('#0 $member (foo:0:0)').member; + Frame.parseVM('#0 $member (foo:0:0)').member; expect(parsedMember('Foo.'), equals('Foo.')); expect(parsedMember('..bar'), @@ -49,22 +49,21 @@ void main() { }); test('converts "<_async_body>" to ""', () { - var frame = new Frame.parseVM( - '#0 Foo.<_async_body> (foo:0:0)'); + var frame = + Frame.parseVM('#0 Foo.<_async_body> (foo:0:0)'); expect(frame.member, equals('Foo.')); }); test('converts "" to ""', () { - var frame = - new Frame.parseVM('#0 Foo. (foo:0:0)'); + var frame = Frame.parseVM('#0 Foo. (foo:0:0)'); expect(frame.member, equals('Foo.')); }); test('parses a folded frame correctly', () { - var frame = new Frame.parseVM('...'); + var frame = Frame.parseVM('...'); expect(frame.member, equals('...')); - expect(frame.uri, equals(new Uri())); + expect(frame.uri, equals(Uri())); expect(frame.line, isNull); expect(frame.column, isNull); }); @@ -72,17 +71,17 @@ void main() { group('.parseV8', () { test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => new Frame.parseV8(text), ''); - expectIsUnparsed((text) => new Frame.parseV8(text), '#1'); - expectIsUnparsed((text) => new Frame.parseV8(text), '#1 Foo'); - expectIsUnparsed((text) => new Frame.parseV8(text), + expectIsUnparsed((text) => Frame.parseV8(text), ''); + expectIsUnparsed((text) => Frame.parseV8(text), '#1'); + expectIsUnparsed((text) => Frame.parseV8(text), '#1 Foo'); + expectIsUnparsed((text) => Frame.parseV8(text), '#1 (dart:async/future.dart:10:15)'); - expectIsUnparsed((text) => new Frame.parseV8(text), - 'Foo (dart:async/future.dart:10:15)'); + expectIsUnparsed( + (text) => Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); }); test('parses a stack frame correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " "(http://pub.dartlang.org/stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -92,7 +91,7 @@ void main() { }); test('parses a stack frame with an absolute POSIX path correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " "(/path/to/stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -101,7 +100,7 @@ void main() { }); test('parses a stack frame with an absolute Windows path correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " r"(C:\path\to\stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -110,7 +109,7 @@ void main() { }); test('parses a stack frame with a Windows UNC path correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " r"(\\mount\path\to\stuff.dart.js:560:28)"); expect( frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); @@ -120,7 +119,7 @@ void main() { }); test('parses a stack frame with a relative POSIX path correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " "(path/to/stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -129,7 +128,7 @@ void main() { }); test('parses a stack frame with a relative Windows path correctly', () { - var frame = new Frame.parseV8(" at VW.call\$0 " + var frame = Frame.parseV8(" at VW.call\$0 " r"(path\to\stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -138,8 +137,8 @@ void main() { }); test('parses an anonymous stack frame correctly', () { - var frame = new Frame.parseV8( - " at http://pub.dartlang.org/stuff.dart.js:560:28"); + var frame = + Frame.parseV8(" at http://pub.dartlang.org/stuff.dart.js:560:28"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -148,7 +147,7 @@ void main() { }); test('parses a native stack frame correctly', () { - var frame = new Frame.parseV8(" at Object.stringify (native)"); + var frame = Frame.parseV8(" at Object.stringify (native)"); expect(frame.uri, Uri.parse('native')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -158,7 +157,7 @@ void main() { test('parses a stack frame with [as ...] correctly', () { // Ignore "[as ...]", since other stack trace formats don't support a // similar construct. - var frame = new Frame.parseV8(" at VW.call\$0 [as call\$4] " + var frame = Frame.parseV8(" at VW.call\$0 [as call\$4] " "(http://pub.dartlang.org/stuff.dart.js:560:28)"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -168,7 +167,7 @@ void main() { }); test('parses a basic eval stack frame correctly', () { - var frame = new Frame.parseV8(" at eval (eval at " + var frame = Frame.parseV8(" at eval (eval at " "(http://pub.dartlang.org/stuff.dart.js:560:28))"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -178,7 +177,7 @@ void main() { }); test('parses an IE10 eval stack frame correctly', () { - var frame = new Frame.parseV8(" at eval (eval at Anonymous function " + var frame = Frame.parseV8(" at eval (eval at Anonymous function " "(http://pub.dartlang.org/stuff.dart.js:560:28))"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -188,7 +187,7 @@ void main() { }); test('parses an eval stack frame with inner position info correctly', () { - var frame = new Frame.parseV8(" at eval (eval at " + var frame = Frame.parseV8(" at eval (eval at " "(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -198,7 +197,7 @@ void main() { }); test('parses a nested eval stack frame correctly', () { - var frame = new Frame.parseV8(" at eval (eval at " + var frame = Frame.parseV8(" at eval (eval at " "(eval at sub (http://pub.dartlang.org/stuff.dart.js:560:28)))"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -209,7 +208,7 @@ void main() { test('converts "" to ""', () { String parsedMember(String member) => - new Frame.parseV8(' at $member (foo:0:0)').member; + Frame.parseV8(' at $member (foo:0:0)').member; expect(parsedMember('Foo.'), equals('Foo.')); expect( @@ -217,27 +216,27 @@ void main() { }); test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => new Frame.parseV8(text), ''); - expectIsUnparsed((text) => new Frame.parseV8(text), ' at'); - expectIsUnparsed((text) => new Frame.parseV8(text), ' at Foo'); - expectIsUnparsed((text) => new Frame.parseV8(text), - ' at Foo (dart:async/future.dart)'); - expectIsUnparsed((text) => new Frame.parseV8(text), + expectIsUnparsed((text) => Frame.parseV8(text), ''); + expectIsUnparsed((text) => Frame.parseV8(text), ' at'); + expectIsUnparsed((text) => Frame.parseV8(text), ' at Foo'); + expectIsUnparsed( + (text) => Frame.parseV8(text), ' at Foo (dart:async/future.dart)'); + expectIsUnparsed((text) => Frame.parseV8(text), ' at (dart:async/future.dart:10:15)'); - expectIsUnparsed((text) => new Frame.parseV8(text), - 'Foo (dart:async/future.dart:10:15)'); expectIsUnparsed( - (text) => new Frame.parseV8(text), ' at dart:async/future.dart'); - expectIsUnparsed((text) => new Frame.parseV8(text), - ' at dart:async/future.dart:10'); + (text) => Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); + expectIsUnparsed( + (text) => Frame.parseV8(text), ' at dart:async/future.dart'); expectIsUnparsed( - (text) => new Frame.parseV8(text), 'dart:async/future.dart:10:15'); + (text) => Frame.parseV8(text), ' at dart:async/future.dart:10'); + expectIsUnparsed( + (text) => Frame.parseV8(text), 'dart:async/future.dart:10:15'); }); }); group('.parseFirefox/.parseSafari', () { test('parses a Firefox stack trace with anonymous function', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 baz@http://pub.dartlang.org/buz.js:56355:55 @@ -261,7 +260,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a Firefox stack trace with nested evals in anonymous function', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 anonymous@file:///C:/example.html line 7 > eval line 1 > eval:1:1 anonymous@file:///C:/example.html line 45 > Function:1:1 @@ -282,7 +281,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a simple stack frame correctly', () { - var frame = new Frame.parseFirefox( + var frame = Frame.parseFirefox( ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -292,8 +291,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with an absolute POSIX path correctly', () { - var frame = - new Frame.parseFirefox(".VW.call\$0@/path/to/stuff.dart.js:560"); + var frame = Frame.parseFirefox(".VW.call\$0@/path/to/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -302,7 +300,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with an absolute Windows path correctly', () { var frame = - new Frame.parseFirefox(r".VW.call$0@C:\path\to\stuff.dart.js:560"); + Frame.parseFirefox(r".VW.call$0@C:\path\to\stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -310,8 +308,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with a Windows UNC path correctly', () { - var frame = new Frame.parseFirefox( - r".VW.call$0@\\mount\path\to\stuff.dart.js:560"); + var frame = + Frame.parseFirefox(r".VW.call$0@\\mount\path\to\stuff.dart.js:560"); expect( frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -320,8 +318,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with a relative POSIX path correctly', () { - var frame = - new Frame.parseFirefox(".VW.call\$0@path/to/stuff.dart.js:560"); + var frame = Frame.parseFirefox(".VW.call\$0@path/to/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -329,8 +326,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with a relative Windows path correctly', () { - var frame = - new Frame.parseFirefox(r".VW.call$0@path\to\stuff.dart.js:560"); + var frame = Frame.parseFirefox(r".VW.call$0@path\to\stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -339,7 +335,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a simple anonymous stack frame correctly', () { var frame = - new Frame.parseFirefox("@http://pub.dartlang.org/stuff.dart.js:560"); + Frame.parseFirefox("@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -348,7 +344,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a nested anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( + var frame = Frame.parseFirefox( ".foo/<@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -356,8 +352,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 expect(frame.column, isNull); expect(frame.member, equals("foo.")); - frame = new Frame.parseFirefox( - ".foo/@http://pub.dartlang.org/stuff.dart.js:560"); + frame = + Frame.parseFirefox(".foo/@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); expect(frame.line, equals(560)); @@ -366,7 +362,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a named nested anonymous stack frame correctly', () { - var frame = new Frame.parseFirefox( + var frame = Frame.parseFirefox( ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -374,7 +370,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 expect(frame.column, isNull); expect(frame.member, equals("foo.")); - frame = new Frame.parseFirefox( + frame = Frame.parseFirefox( ".foo/.name@http://pub.dartlang.org/stuff.dart.js:560"); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -384,7 +380,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with parameters correctly', () { - var frame = new Frame.parseFirefox( + var frame = Frame.parseFirefox( '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -394,7 +390,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a nested anonymous stack frame with parameters correctly', () { - var frame = new Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' + var frame = Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' 'http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); @@ -406,9 +402,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test( 'parses a deeply-nested anonymous stack frame with parameters ' 'correctly', () { - var frame = - new Frame.parseFirefox('.convertDartClosureToJS/\$function new Frame.parseFirefox(text), ''); - expectIsUnparsed((text) => new Frame.parseFirefox(text), '.foo'); - expectIsUnparsed((text) => new Frame.parseFirefox(text), - '.foo@dart:async/future.dart'); - expectIsUnparsed((text) => new Frame.parseFirefox(text), + expectIsUnparsed((text) => Frame.parseFirefox(text), ''); + expectIsUnparsed((text) => Frame.parseFirefox(text), '.foo'); + expectIsUnparsed( + (text) => Frame.parseFirefox(text), '.foo@dart:async/future.dart'); + expectIsUnparsed((text) => Frame.parseFirefox(text), '.foo(@dart:async/future.dart:10'); expectIsUnparsed( - (text) => new Frame.parseFirefox(text), '@dart:async/future.dart'); + (text) => Frame.parseFirefox(text), '@dart:async/future.dart'); }); test('parses a simple stack frame correctly', () { - var frame = new Frame.parseFirefox( - "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); + var frame = + Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -437,8 +432,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses an anonymous stack frame correctly', () { - var frame = - new Frame.parseFirefox("http://dartlang.org/foo/bar.dart:10:11"); + var frame = Frame.parseFirefox("http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -446,8 +440,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with no line correctly', () { - var frame = new Frame.parseFirefox( - "foo\$bar@http://dartlang.org/foo/bar.dart::11"); + var frame = + Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart::11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, isNull); expect(frame.column, equals(11)); @@ -455,8 +449,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with no column correctly', () { - var frame = new Frame.parseFirefox( - "foo\$bar@http://dartlang.org/foo/bar.dart:10:"); + var frame = + Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); expect(frame.column, isNull); @@ -464,8 +458,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with no line or column correctly', () { - var frame = new Frame.parseFirefox( - "foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); + var frame = + Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -475,7 +469,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 group('.parseFriendly', () { test('parses a simple stack frame correctly', () { - var frame = new Frame.parseFriendly( + var frame = Frame.parseFriendly( "http://dartlang.org/foo/bar.dart 10:11 Foo..bar"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); @@ -484,8 +478,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with no line or column correctly', () { - var frame = new Frame.parseFriendly( - "http://dartlang.org/foo/bar.dart Foo..bar"); + var frame = + Frame.parseFriendly("http://dartlang.org/foo/bar.dart Foo..bar"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, isNull); expect(frame.column, isNull); @@ -493,7 +487,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with no column correctly', () { - var frame = new Frame.parseFriendly( + var frame = Frame.parseFriendly( "http://dartlang.org/foo/bar.dart 10 Foo..bar"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, equals(10)); @@ -502,7 +496,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with a relative path correctly', () { - var frame = new Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); + var frame = Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); expect(frame.uri, equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); expect(frame.line, equals(10)); @@ -511,14 +505,14 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => new Frame.parseFriendly(text), ''); - expectIsUnparsed((text) => new Frame.parseFriendly(text), 'foo/bar.dart'); + expectIsUnparsed((text) => Frame.parseFriendly(text), ''); + expectIsUnparsed((text) => Frame.parseFriendly(text), 'foo/bar.dart'); expectIsUnparsed( - (text) => new Frame.parseFriendly(text), 'foo/bar.dart 10:11'); + (text) => Frame.parseFriendly(text), 'foo/bar.dart 10:11'); }); test('parses a data url stack frame with no line or column correctly', () { - var frame = new Frame.parseFriendly("data:... main"); + var frame = Frame.parseFriendly("data:... main"); expect(frame.uri.scheme, equals('data')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -526,7 +520,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a data url stack frame correctly', () { - var frame = new Frame.parseFriendly("data:... 10:11 main"); + var frame = Frame.parseFriendly("data:... 10:11 main"); expect(frame.uri.scheme, equals('data')); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -534,7 +528,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a stack frame with spaces in the member name correctly', () { - var frame = new Frame.parseFriendly( + var frame = Frame.parseFriendly( "foo/bar.dart 10:11 (anonymous function).dart.fn"); expect(frame.uri, equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); @@ -546,7 +540,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test( 'parses a stack frame with spaces in the member name and no line or ' 'column correctly', () { - var frame = new Frame.parseFriendly( + var frame = Frame.parseFriendly( "http://dartlang.org/foo/bar.dart (anonymous function).dart.fn"); expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); expect(frame.line, isNull); @@ -557,7 +551,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('only considers dart URIs to be core', () { bool isCore(String library) => - new Frame.parseVM('#0 Foo ($library:0:0)').isCore; + Frame.parseVM('#0 Foo ($library:0:0)').isCore; expect(isCore('dart:core'), isTrue); expect(isCore('dart:async'), isTrue); @@ -571,22 +565,22 @@ baz@http://pub.dartlang.org/buz.js:56355:55 group('.library', () { test('returns the URI string for non-file URIs', () { - expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, + expect(Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').library, equals('dart:async/future.dart')); expect( - new Frame.parseVM('#0 Foo ' + Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)') .library, equals('http://dartlang.org/stuff/thing.dart')); }); test('returns the relative path for file URIs', () { - expect(new Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, + expect(Frame.parseVM('#0 Foo (foo/bar.dart:0:0)').library, equals(path.join('foo', 'bar.dart'))); }); test('truncates data: URIs', () { - var frame = new Frame.parseVM( + var frame = Frame.parseVM( '#0 Foo (data:application/dart;charset=utf-8,blah:0:0)'); expect(frame.library, equals('data:...')); }); @@ -597,30 +591,30 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'returns the library and line/column numbers for non-core ' 'libraries', () { expect( - new Frame.parseVM('#0 Foo ' + Frame.parseVM('#0 Foo ' '(http://dartlang.org/thing.dart:5:10)') .location, equals('http://dartlang.org/thing.dart 5:10')); - expect(new Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, + expect(Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); }); group('.package', () { test('returns null for non-package URIs', () { - expect(new Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, - isNull); expect( - new Frame.parseVM('#0 Foo ' + Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, isNull); + expect( + Frame.parseVM('#0 Foo ' '(http://dartlang.org/stuff/thing.dart:0:0)') .package, isNull); }); test('returns the package name for package: URIs', () { - expect(new Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package, + expect(Frame.parseVM('#0 Foo (package:foo/foo.dart:0:0)').package, equals('foo')); - expect(new Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package, + expect(Frame.parseVM('#0 Foo (package:foo/zap/bar.dart:0:0)').package, equals('foo')); }); }); @@ -630,27 +624,27 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'returns the library and line/column numbers for non-core ' 'libraries', () { expect( - new Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') + Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') .toString(), equals('http://dartlang.org/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { expect( - new Frame.parseVM('#0 Foo. ' + Frame.parseVM('#0 Foo. ' '(dart:core/uri.dart:5:10)') .toString(), equals('dart:core/uri.dart 5:10 in Foo.')); }); test('prints a frame without a column correctly', () { - expect(new Frame.parseVM('#0 Foo (dart:core/uri.dart:5)').toString(), + expect(Frame.parseVM('#0 Foo (dart:core/uri.dart:5)').toString(), equals('dart:core/uri.dart 5 in Foo')); }); test('prints relative paths as relative', () { var relative = path.normalize('relative/path/to/foo.dart'); - expect(new Frame.parseFriendly('$relative 5:10 Foo').toString(), + expect(Frame.parseFriendly('$relative 5:10 Foo').toString(), equals('$relative 5:10 in Foo')); }); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 33d4f4ee8..61abe5dc3 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -6,17 +6,17 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -Trace getCurrentTrace([int level]) => new Trace.current(level); +Trace getCurrentTrace([int level]) => Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { // This just shouldn't crash. - test('a native stack trace is parseable', () => new Trace.current()); + test('a native stack trace is parseable', () => Trace.current()); group('.parse', () { test('.parse parses a VM stack trace correctly', () { - var trace = new Trace.parse( + var trace = Trace.parse( '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' '#1 zip..zap (dart:async/future.dart:0:2)\n' '#2 zip..zap (http://pub.dartlang.org/thing.' @@ -30,7 +30,7 @@ void main() { }); test('parses a V8 stack trace correctly', () { - var trace = new Trace.parse('Error\n' + var trace = Trace.parse('Error\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' @@ -43,7 +43,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse("Exception: foo\n" + trace = Trace.parse("Exception: foo\n" ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' @@ -56,7 +56,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse('Exception: foo\n' + trace = Trace.parse('Exception: foo\n' ' bar\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' @@ -70,7 +70,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse('Exception: foo\n' + trace = Trace.parse('Exception: foo\n' ' bar\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' @@ -90,11 +90,11 @@ void main() { // JavaScriptCore traces are just like V8, except that it doesn't have a // header and it starts with a tab rather than spaces. test('parses a JavaScriptCore stack trace correctly', () { - var trace = new Trace.parse( - '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - '\tat http://pub.dartlang.org/stuff.js:0:2\n' - '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + var trace = + Trace.parse('\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + '\tat http://pub.dartlang.org/stuff.js:0:2\n' + '\tat zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -103,11 +103,11 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( - '\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - '\tat \n' - '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + trace = + Trace.parse('\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' + '\tat \n' + '\tat zip..zap ' + '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -116,10 +116,9 @@ void main() { }); test('parses a Firefox/Safari stack trace correctly', () { - var trace = - new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -128,7 +127,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse('zip/<@http://pub.dartlang.org/stuff.js:0\n' + trace = Trace.parse('zip/<@http://pub.dartlang.org/stuff.js:0\n' 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); @@ -139,7 +138,7 @@ void main() { expect(trace.frames[2].uri, equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - trace = new Trace.parse( + trace = Trace.parse( 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); @@ -154,11 +153,10 @@ void main() { test('parses a Firefox/Safari stack trace containing native code correctly', () { - var trace = - new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' - '[native code]'); + var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + '[native code]'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -171,7 +169,7 @@ void main() { test('parses a Firefox/Safari stack trace without a method name correctly', () { - var trace = new Trace.parse('http://pub.dartlang.org/stuff.js:42\n' + var trace = Trace.parse('http://pub.dartlang.org/stuff.js:42\n' 'zip/<@http://pub.dartlang.org/stuff.js:0\n' 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); @@ -186,11 +184,10 @@ void main() { test('parses a Firefox/Safari stack trace with an empty line correctly', () { - var trace = - new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - '\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + '\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -202,10 +199,9 @@ void main() { test('parses a Firefox/Safari stack trace with a column number correctly', () { - var trace = - new Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' + 'zip/<@http://pub.dartlang.org/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); @@ -218,9 +214,9 @@ void main() { }); test('parses a package:stack_trace stack trace correctly', () { - var trace = new Trace.parse( - 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/baz.dart Foo..bar'); + var trace = + Trace.parse('http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/baz.dart Foo..bar'); expect(trace.frames[0].uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); @@ -229,12 +225,12 @@ void main() { }); test('parses a package:stack_trace stack chain correctly', () { - var trace = new Trace.parse( - 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/baz.dart Foo..bar\n' - '===== asynchronous gap ===========================\n' - 'http://dartlang.org/foo/bang.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/quux.dart Foo..bar'); + var trace = + Trace.parse('http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/baz.dart Foo..bar\n' + '===== asynchronous gap ===========================\n' + 'http://dartlang.org/foo/bang.dart 10:11 Foo..bar\n' + 'http://dartlang.org/foo/quux.dart Foo..bar'); expect(trace.frames[0].uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); @@ -247,19 +243,19 @@ void main() { }); test('parses a real package:stack_trace stack trace correctly', () { - var traceString = new Trace.current().toString(); - expect(new Trace.parse(traceString).toString(), equals(traceString)); + var traceString = Trace.current().toString(); + expect(Trace.parse(traceString).toString(), equals(traceString)); }); test('parses an empty string correctly', () { - var trace = new Trace.parse(''); + var trace = Trace.parse(''); expect(trace.frames, isEmpty); expect(trace.toString(), equals('')); }); }); test('.toString() nicely formats the stack trace', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 Foo._bar (foo/bar.dart:42:21) #1 zip..zap (dart:async/future.dart:0:2) #2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) @@ -274,10 +270,10 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap test('.vmTrace returns a native-style trace', () { var uri = path.toUri(path.absolute('foo')); - var trace = new Trace([ - new Frame(uri, 10, 20, 'Foo.'), - new Frame(Uri.parse('http://dartlang.org/foo.dart'), null, null, 'bar'), - new Frame(Uri.parse('dart:async'), 15, null, 'baz'), + var trace = Trace([ + Frame(uri, 10, 20, 'Foo.'), + Frame(Uri.parse('http://dartlang.org/foo.dart'), null, null, 'bar'), + Frame(Uri.parse('dart:async'), 15, null, 'baz'), ]); expect( @@ -290,7 +286,7 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap group("folding", () { group(".terse", () { test('folds core frames together bottom-up', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) #0 notCore (foo.dart:42:21) @@ -308,7 +304,7 @@ bar.dart 10:20 alsoNotCore }); test('folds empty async frames', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 top (dart:async/future.dart:0:2) #1 empty.<_async_body> (bar.dart) #2 bottom (dart:async-patch/future.dart:9:11) @@ -322,7 +318,7 @@ foo.dart 42:21 notCore }); test('removes the bottom-most async frame', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 notCore (foo.dart:42:21) #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) @@ -336,7 +332,7 @@ foo.dart 42:21 notCore }); test("won't make a trace empty", () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #1 top (dart:async/future.dart:0:2) #2 bottom (dart:core/uri.dart:1:100) '''); @@ -347,13 +343,13 @@ dart:core bottom }); test("won't panic on an empty trace", () { - expect(new Trace.parse("").terse.toString(), equals("")); + expect(Trace.parse("").terse.toString(), equals("")); }); }); group(".foldFrames", () { test('folds frames together bottom-up', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (foo.dart:1:100) @@ -373,7 +369,7 @@ dart:async-patch/future.dart 9:11 fooBottom }); test('will never fold unparsed frames', () { - var trace = new Trace.parse(r''' + var trace = Trace.parse(r''' .g"cs$#:b";a#>sw{*{ul$"$xqwr`p %+j-?uppx<([j@#nu{{>*+$%x-={`{ !e($b{nj)zs?cgr%!;bmw.+$j+pfj~ @@ -388,7 +384,7 @@ dart:async-patch/future.dart 9:11 fooBottom group("with terse: true", () { test('folds core frames as well', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 coreBottom (dart:async/future.dart:0:2) @@ -408,7 +404,7 @@ bar.dart 10:20 alsoNotFoo }); test('shortens folded frames', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #0 notFoo (foo.dart:42:21) #1 fooTop (bar.dart:0:2) #2 fooBottom (package:foo/bar.dart:0:2) @@ -431,7 +427,7 @@ bar.dart 20:20 againNotFoo }); test('removes the bottom-most folded frame', () { - var trace = new Trace.parse(''' + var trace = Trace.parse(''' #2 fooTop (package:foo/bar.dart:0:2) #3 notFoo (bar.dart:10:20) #5 fooBottom (foo/bar.dart:9:11) diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index 0241b3737..41a79c6eb 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -18,7 +18,7 @@ Matcher frameLibrary(matcher) => /// [description] should be a noun phrase that describes the relation of the /// output of [transformation] to its input. Matcher transform(transformation(value), matcher, String description) => - new _TransformMatcher(transformation, wrapMatcher(matcher), description); + _TransformMatcher(transformation, wrapMatcher(matcher), description); class _TransformMatcher extends Matcher { final Function _transformation; diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 1b5345837..9d5e77b78 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -19,13 +19,13 @@ String getStackTraceString() => StackTrace.current.toString(); StackTrace getStackTraceObject() => StackTrace.current; Frame getCaller([int level]) { - if (level == null) return new Frame.caller(); - return new Frame.caller(level); + if (level == null) return Frame.caller(); + return Frame.caller(level); } Frame nestedGetCaller(int level) => getCaller(level); -Trace getCurrentTrace([int level]) => new Trace.current(level); +Trace getCurrentTrace([int level]) => Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); @@ -33,14 +33,14 @@ void main() { group('Trace', () { test('.parse parses a real stack trace correctly', () { var string = getStackTraceString(); - var trace = new Trace.parse(string); + var trace = Trace.parse(string); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceString')); }); test('converts from a native stack trace correctly', () { - var trace = new Trace.from(getStackTraceObject()); + var trace = Trace.from(getStackTraceObject()); expect(path.url.basename(trace.frames.first.uri.path), equals('vm_test.dart')); expect(trace.frames.first.member, equals('getStackTraceObject')); @@ -53,7 +53,7 @@ void main() { try { overflow(); } catch (_, stackTrace) { - trace = new Trace.from(stackTrace); + trace = Trace.from(stackTrace); } expect(trace.frames.first.member, equals('main...overflow')); @@ -62,12 +62,12 @@ void main() { group('.current()', () { test('with no argument returns a trace starting at the current frame', () { - var trace = new Trace.current(); + var trace = Trace.current(); expect(trace.frames.first.member, equals('main...')); }); test('at level 0 returns a trace starting at the current frame', () { - var trace = new Trace.current(0); + var trace = Trace.current(0); expect(trace.frames.first.member, equals('main...')); }); @@ -82,7 +82,7 @@ void main() { }); test('throws an ArgumentError for negative levels', () { - expect(() => new Trace.current(-1), throwsArgumentError); + expect(() => Trace.current(-1), throwsArgumentError); }); }); }); @@ -105,7 +105,7 @@ void main() { }); test('throws an ArgumentError for negative levels', () { - expect(() => new Frame.caller(-1), throwsArgumentError); + expect(() => Frame.caller(-1), throwsArgumentError); }); }); } From 6e7c07478bd039aabd8e2696a0b50ea7146d2e3e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 13 Apr 2020 11:11:31 -0700 Subject: [PATCH 0635/1215] Disable implicit casts (dart-lang/stack_trace#61) --- pkgs/stack_trace/analysis_options.yaml | 3 +++ pkgs/stack_trace/lib/src/chain.dart | 5 +++-- pkgs/stack_trace/lib/src/frame.dart | 4 ++-- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/test/chain/dart2js_test.dart | 4 ++-- pkgs/stack_trace/test/chain/utils.dart | 2 +- pkgs/stack_trace/test/chain/vm_test.dart | 2 +- 7 files changed, 13 insertions(+), 9 deletions(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 7472eb06b..3384ee624 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,3 +1,6 @@ +analyzer: + strong-mode: + implicit-casts: false linter: rules: - prefer_equal_for_default_values diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index da6fb6f06..3397f34c9 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -47,7 +47,8 @@ class Chain implements StackTrace { final List traces; /// The [StackZoneSpecification] for the current zone. - static StackZoneSpecification get _currentSpec => Zone.current[_specKey]; + static StackZoneSpecification get _currentSpec => + Zone.current[_specKey] as StackZoneSpecification; /// If [when] is `true`, runs [callback] in a [Zone] in which the current /// stack chain is tracked and automatically associated with (most) errors. @@ -81,7 +82,7 @@ class Chain implements StackTrace { } if (!when) { - var newOnError; + void Function(Object, StackTrace) newOnError; if (onError != null) { newOnError = (error, stackTrace) { onError( diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 752dcb73d..ae191820a 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -165,7 +165,7 @@ class Frame { // v8 location strings can be arbitrarily-nested, since it adds a layer // of nesting for each eval performed on that line. - parseLocation(location, member) { + Frame parseLocation(String location, String member) { var evalMatch = _v8EvalLocation.firstMatch(location); while (evalMatch != null) { location = evalMatch[1]; @@ -240,7 +240,7 @@ class Frame { // Normally this is a URI, but in a jsshell trace it can be a path. var uri = _uriOrPathToUri(match[3]); - var member; + String member; if (match[1] != null) { member = match[1]; member += diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 4ef4eae3c..7420e0aa3 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -133,7 +133,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. ZoneBinaryCallback _registerBinaryCallback( - Zone self, ZoneDelegate parent, Zone zone, Function f) { + Zone self, ZoneDelegate parent, Zone zone, R Function(T1, T2) f) { if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); var node = _createNode(1); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index fbbad5611..827c45940 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -305,7 +305,7 @@ void main() { test( 'called for an unregistered stack trace returns a chain wrapping that ' 'trace', () { - var trace; + StackTrace trace; var chain = Chain.capture(() { try { throw 'error'; @@ -324,7 +324,7 @@ void main() { test( 'forTrace() outside of capture() returns a chain wrapping the given ' 'trace', () { - var trace; + StackTrace trace; var chain = Chain.capture(() { try { throw 'error'; diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index c1f98e400..790693a49 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -74,7 +74,7 @@ Future chainForTrace(asyncFn(callback()), callback()) { }); return completer.future - .catchError((_, stackTrace) => Chain.forTrace(stackTrace)); + .catchError((_, StackTrace stackTrace) => Chain.forTrace(stackTrace)); } /// Runs [callback] in a [Chain.capture] zone and returns a Future that diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index c006d8894..842f0a078 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -481,7 +481,7 @@ void main() { 'chain', () { // Disable the test package's chain-tracking. return Chain.disable(() async { - var trace; + StackTrace trace; await Chain.capture(() async { try { throw 'error'; From 7500d6225f0e7715e313f93cadf52b22fe09a923 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 13 Apr 2020 12:02:36 -0700 Subject: [PATCH 0636/1215] Enable and fix package:pedantic lints (dart-lang/stack_trace#62) - always_declare_return_types - annotate_overrides - prefer_conditional_assignment - prefer_if_null_operators - prefer_single_quotes - unnecessary_this - use_function_type_syntax_for_parameters Remove local lint config which duplicates enabled rules. Ignore `prefer_spread_collections` for now. We should publish once more before bumping the min SDK. --- pkgs/stack_trace/analysis_options.yaml | 10 +- pkgs/stack_trace/lib/src/chain.dart | 17 +- pkgs/stack_trace/lib/src/frame.dart | 31 +-- pkgs/stack_trace/lib/src/lazy_chain.dart | 12 +- pkgs/stack_trace/lib/src/lazy_trace.dart | 13 +- .../lib/src/stack_zone_specification.dart | 10 +- pkgs/stack_trace/lib/src/trace.dart | 62 ++--- pkgs/stack_trace/lib/src/unparsed_frame.dart | 15 +- pkgs/stack_trace/lib/src/vm_trace.dart | 15 +- pkgs/stack_trace/pubspec.yaml | 1 + pkgs/stack_trace/test/chain/chain_test.dart | 42 ++-- pkgs/stack_trace/test/chain/utils.dart | 17 +- pkgs/stack_trace/test/frame_test.dart | 226 +++++++++--------- pkgs/stack_trace/test/trace_test.dart | 110 ++++----- pkgs/stack_trace/test/utils.dart | 5 +- pkgs/stack_trace/test/vm_test.dart | 2 +- 16 files changed, 303 insertions(+), 285 deletions(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 3384ee624..2762c70f2 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,10 +1,6 @@ +include: package:pedantic/analysis_options.yaml analyzer: strong-mode: implicit-casts: false -linter: - rules: - - prefer_equal_for_default_values - - prefer_generic_function_type_aliases - - slash_for_doc_comments - - unnecessary_const - - unnecessary_new + errors: + prefer_spread_collections: ignore diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 3397f34c9..602b90c09 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -12,7 +12,7 @@ import 'trace.dart'; import 'utils.dart'; /// A function that handles errors in the zone wrapped by [Chain.capture]. -@Deprecated("Will be removed in stack_trace 2.0.0.") +@Deprecated('Will be removed in stack_trace 2.0.0.') typedef ChainHandler = void Function(dynamic error, Chain chain); /// An opaque key used to track the current [StackZoneSpecification]. @@ -72,13 +72,13 @@ class Chain implements StackTrace { /// `false`, [onError] must be `null`. /// /// If [callback] returns a value, it will be returned by [capture] as well. - static T capture(T callback(), - {void onError(error, Chain chain), + static T capture(T Function() callback, + {void Function(Object error, Chain) onError, bool when = true, bool errorZone = true}) { if (!errorZone && onError != null) { throw ArgumentError.value( - onError, "onError", "must be null if errorZone is false"); + onError, 'onError', 'must be null if errorZone is false'); } if (!when) { @@ -114,7 +114,7 @@ class Chain implements StackTrace { /// [callback] in a [Zone] in which chain capturing is disabled. /// /// If [callback] returns a value, it will be returned by [disable] as well. - static T disable(T callback(), {bool when = true}) { + static T disable(T Function() callback, {bool when = true}) { var zoneValues = when ? {_specKey: null, StackZoneSpecification.disableKey: true} : null; @@ -126,8 +126,8 @@ class Chain implements StackTrace { /// Prior to Dart 1.7, this was necessary to ensure that stack traces for /// exceptions reported with [Completer.completeError] and /// [StreamController.addError] were tracked correctly. - @Deprecated("Chain.track is not necessary in Dart 1.7+.") - static track(futureOrStream) => futureOrStream; + @Deprecated('Chain.track is not necessary in Dart 1.7+.') + static dynamic track(futureOrStream) => futureOrStream; /// Returns the current stack chain. /// @@ -211,7 +211,7 @@ class Chain implements StackTrace { /// If [terse] is true, this will also fold together frames from the core /// library or from this package, and simplify core library frames as in /// [Trace.terse]. - Chain foldFrames(bool predicate(Frame frame), {bool terse = false}) { + Chain foldFrames(bool Function(Frame) predicate, {bool terse = false}) { var foldedTraces = traces.map((trace) => trace.foldFrames(predicate, terse: terse)); var nonEmptyTraces = foldedTraces.where((trace) { @@ -241,6 +241,7 @@ class Chain implements StackTrace { /// in the chain. Trace toTrace() => Trace(traces.expand((trace) => trace.frames)); + @override String toString() { // Figure out the longest path so we know how much to pad. var longest = traces.map((trace) { diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index ae191820a..34108f3cf 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -33,7 +33,7 @@ final _v8EvalLocation = // anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 // anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 final _firefoxEvalLocation = - RegExp(r"(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+"); + RegExp(r'(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+'); // .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 // .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 @@ -65,7 +65,7 @@ final _friendlyFrame = RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); /// VM. final _asyncBody = RegExp(r'<(|[^>]+)_async_body>'); -final _initialDot = RegExp(r"^\."); +final _initialDot = RegExp(r'^\.'); /// A single stack frame. Each frame points to a precise location in Dart code. class Frame { @@ -100,7 +100,7 @@ class Frame { /// This will usually be the string form of [uri], but a relative URI will be /// used if possible. Data URIs will be truncated. String get library { - if (uri.scheme == 'data') return "data:..."; + if (uri.scheme == 'data') return 'data:...'; return path.prettyUri(uri); } @@ -125,8 +125,8 @@ class Frame { /// higher than `1`, it will return higher frames. factory Frame.caller([int level = 1]) { if (level < 0) { - throw ArgumentError("Argument [level] must be greater than or equal " - "to 0."); + throw ArgumentError('Argument [level] must be greater than or equal ' + 'to 0.'); } return Trace.current(level + 1).frames.first; @@ -146,8 +146,8 @@ class Frame { // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. var member = match[1] - .replaceAll(_asyncBody, "") - .replaceAll("", ""); + .replaceAll(_asyncBody, '') + .replaceAll('', ''); var uri = Uri.parse(match[2]); var lineAndColumn = match[3].split(':'); @@ -191,13 +191,13 @@ class Frame { return parseLocation( match[2], match[1] - .replaceAll("", "") - .replaceAll("Anonymous function", "") - .replaceAll("(anonymous function)", "")); + .replaceAll('', '') + .replaceAll('Anonymous function', '') + .replaceAll('(anonymous function)', '')); } else { // The second form looks like " at LOCATION", and is used for // anonymous functions. - return parseLocation(match[3], ""); + return parseLocation(match[3], ''); } }); @@ -244,7 +244,7 @@ class Frame { if (match[1] != null) { member = match[1]; member += - List.filled('/'.allMatches(match[2]).length, ".").join(); + List.filled('/'.allMatches(match[2]).length, '.').join(); if (member == '') member = ''; // Some Firefox members have initial dots. We remove them for @@ -261,11 +261,11 @@ class Frame { }); /// Parses a string representation of a Safari 6.0 stack frame. - @Deprecated("Use Frame.parseSafari instead.") + @Deprecated('Use Frame.parseSafari instead.') factory Frame.parseSafari6_0(String frame) => Frame.parseFirefox(frame); /// Parses a string representation of a Safari 6.1+ stack frame. - @Deprecated("Use Frame.parseSafari instead.") + @Deprecated('Use Frame.parseSafari instead.') factory Frame.parseSafari6_1(String frame) => Frame.parseFirefox(frame); /// Parses a string representation of a Safari stack frame. @@ -323,7 +323,7 @@ class Frame { /// /// If [body] throws a [FormatException], returns an [UnparsedFrame] with /// [text] instead. - static Frame _catchFormatException(String text, Frame body()) { + static Frame _catchFormatException(String text, Frame Function() body) { try { return body(); } on FormatException catch (_) { @@ -333,5 +333,6 @@ class Frame { Frame(this.uri, this.line, this.column, this.member); + @override String toString() => '$location in $member'; } diff --git a/pkgs/stack_trace/lib/src/lazy_chain.dart b/pkgs/stack_trace/lib/src/lazy_chain.dart index 5dbe1c01f..12dbacea2 100644 --- a/pkgs/stack_trace/lib/src/lazy_chain.dart +++ b/pkgs/stack_trace/lib/src/lazy_chain.dart @@ -19,15 +19,17 @@ class LazyChain implements Chain { LazyChain(this._thunk); - Chain get _chain { - if (_inner == null) _inner = _thunk(); - return _inner; - } + Chain get _chain => _inner ??= _thunk(); + @override List get traces => _chain.traces; + @override Chain get terse => _chain.terse; - Chain foldFrames(bool predicate(Frame frame), {bool terse = false}) => + @override + Chain foldFrames(bool Function(Frame) predicate, {bool terse = false}) => LazyChain(() => _chain.foldFrames(predicate, terse: terse)); + @override Trace toTrace() => LazyTrace(() => _chain.toTrace()); + @override String toString() => _chain.toString(); } diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 9cd53ee94..917d20ed2 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -17,17 +17,20 @@ class LazyTrace implements Trace { LazyTrace(this._thunk); - Trace get _trace { - if (_inner == null) _inner = _thunk(); - return _inner; - } + Trace get _trace => _inner ??= _thunk(); + @override List get frames => _trace.frames; + @override StackTrace get original => _trace.original; + @override StackTrace get vmTrace => _trace.vmTrace; + @override Trace get terse => LazyTrace(() => _trace.terse); - Trace foldFrames(bool predicate(Frame frame), {bool terse = false}) => + @override + Trace foldFrames(bool Function(Frame) predicate, {bool terse = false}) => LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); + @override String toString() => _trace.toString(); // Work around issue 14075. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 7420e0aa3..4ac660408 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -50,7 +50,7 @@ class StackZoneSpecification { /// /// The chain associated with a given stack trace doesn't contain a node for /// that stack trace. - final _chains = Expando<_Node>("stack chains"); + final _chains = Expando<_Node>('stack chains'); /// The error handler for the zone. /// @@ -113,7 +113,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. ZoneCallback _registerCallback( - Zone self, ZoneDelegate parent, Zone zone, R f()) { + Zone self, ZoneDelegate parent, Zone zone, R Function() f) { if (f == null || _disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); @@ -122,7 +122,7 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentChain] when /// [f] is run. ZoneUnaryCallback _registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, R f(T arg)) { + Zone self, ZoneDelegate parent, Zone zone, R Function(T) f) { if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { @@ -184,7 +184,7 @@ class StackZoneSpecification { } var asyncError = parent.errorCallback(zone, error, stackTrace); - return asyncError == null ? AsyncError(error, stackTrace) : asyncError; + return asyncError ?? AsyncError(error, stackTrace); } /// Creates a [_Node] with the current stack trace and linked to @@ -202,7 +202,7 @@ class StackZoneSpecification { /// /// If [f] throws an error, this associates [node] with that error's stack /// trace. - T _run(T f(), _Node node) { + T _run(T Function() f, _Node node) { var previousNode = _currentNode; _currentNode = node; try { diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 4a908746e..df5d455bf 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -11,7 +11,7 @@ import 'unparsed_frame.dart'; import 'utils.dart'; import 'vm_trace.dart'; -final _terseRegExp = RegExp(r"(-patch)?([/\\].*)?$"); +final _terseRegExp = RegExp(r'(-patch)?([/\\].*)?$'); /// A RegExp to match V8's stack traces. /// @@ -19,13 +19,13 @@ final _terseRegExp = RegExp(r"(-patch)?([/\\].*)?$"); /// description of the exception that occurred. That description can be multiple /// lines, so we just look for any line other than the first that begins with /// three or four spaces and "at". -final _v8Trace = RegExp(r"\n ?at "); +final _v8Trace = RegExp(r'\n ?at '); /// A RegExp to match indidual lines of V8's stack traces. /// /// This is intended to filter out the leading exception details of the trace /// though it is possible for the message to match this as well. -final _v8TraceLine = RegExp(r" ?at "); +final _v8TraceLine = RegExp(r' ?at '); /// A RegExp to match Firefox's eval and Function stack traces. /// @@ -34,7 +34,7 @@ final _v8TraceLine = RegExp(r" ?at "); /// These stack traces looks like: /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 -final _firefoxEvalTrace = RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); +final _firefoxEvalTrace = RegExp(r'@\S+ line \d+ >.* (Function|eval):\d+:\d+'); /// A RegExp to match Firefox and Safari's stack traces. /// @@ -50,19 +50,19 @@ final _firefoxEvalTrace = RegExp(r"@\S+ line \d+ >.* (Function|eval):\d+:\d+"); /// trailing colon if no column number is available). They can also contain /// empty lines or lines consisting only of `[native code]`. final _firefoxSafariTrace = RegExp( - r"^" - r"(" // Member description. Not present in some Safari frames. - r"([.0-9A-Za-z_$/<]|\(.*\))*" // Member name and arguments. - r"@" - r")?" - r"[^\s]*" // Frame URL. - r":\d*" // Line or column number. Some older frames only have a line number. - r"$", + r'^' + r'(' // Member description. Not present in some Safari frames. + r'([.0-9A-Za-z_$/<]|\(.*\))*' // Member name and arguments. + r'@' + r')?' + r'[^\s]*' // Frame URL. + r':\d*' // Line or column number. Some older frames only have a line number. + r'$', multiLine: true); /// A RegExp to match this package's stack traces. final _friendlyTrace = - RegExp(r"^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$", multiLine: true); + RegExp(r'^[^\s<][^\s]*( \d+(:\d+)?)?[ \t]+[^\s]+$', multiLine: true); /// A stack trace, comprised of a list of stack frames. class Trace implements StackTrace { @@ -89,8 +89,8 @@ class Trace implements StackTrace { /// many frames up instead. factory Trace.current([int level = 0]) { if (level < 0) { - throw ArgumentError("Argument [level] must be greater than or equal " - "to 0."); + throw ArgumentError('Argument [level] must be greater than or equal ' + 'to 0.'); } var trace = Trace.from(StackTrace.current); @@ -111,7 +111,7 @@ class Trace implements StackTrace { // the natural failure will only occur when the LazyTrace is materialized, // and we want to provide an error that's more local to the actual problem. if (trace == null) { - throw ArgumentError("Cannot create a Trace from null."); + throw ArgumentError('Cannot create a Trace from null.'); } if (trace is Trace) return trace; @@ -128,7 +128,7 @@ class Trace implements StackTrace { try { if (trace.isEmpty) return Trace([]); if (trace.contains(_v8Trace)) return Trace.parseV8(trace); - if (trace.contains("\tat ")) return Trace.parseJSCore(trace); + if (trace.contains('\tat ')) return Trace.parseJSCore(trace); if (trace.contains(_firefoxSafariTrace) || trace.contains(_firefoxEvalTrace)) { return Trace.parseFirefox(trace); @@ -153,14 +153,14 @@ class Trace implements StackTrace { static List _parseVM(String trace) { // Ignore [vmChainGap]. This matches the behavior of // `Chain.parse().toTrace()`. - var lines = trace.trim().replaceAll(vmChainGap, '').split("\n"); + var lines = trace.trim().replaceAll(vmChainGap, '').split('\n'); var frames = lines .take(lines.length - 1) .map((line) => Frame.parseVM(line)) .toList(); // TODO(nweiz): Remove this when issue 23614 is fixed. - if (!lines.last.endsWith(".da")) { + if (!lines.last.endsWith('.da')) { frames.add(Frame.parseVM(lines.last)); } @@ -171,7 +171,7 @@ class Trace implements StackTrace { Trace.parseV8(String trace) : this( trace - .split("\n") + .split('\n') .skip(1) // It's possible that an Exception's description contains a line // that looks like a V8 trace line, which will screw this up. @@ -184,8 +184,8 @@ class Trace implements StackTrace { Trace.parseJSCore(String trace) : this( trace - .split("\n") - .where((line) => line != "\tat ") + .split('\n') + .where((line) => line != '\tat ') .map((line) => Frame.parseV8(line)), original: trace); @@ -200,7 +200,7 @@ class Trace implements StackTrace { : this( trace .trim() - .split("\n") + .split('\n') .where((line) => line.isNotEmpty && line != '[native code]') .map((line) => Frame.parseFirefox(line)), original: trace); @@ -209,16 +209,16 @@ class Trace implements StackTrace { Trace.parseSafari(String trace) : this.parseFirefox(trace); /// Parses a string representation of a Safari 6.1+ stack trace. - @Deprecated("Use Trace.parseSafari instead.") + @Deprecated('Use Trace.parseSafari instead.') Trace.parseSafari6_1(String trace) : this.parseSafari(trace); /// Parses a string representation of a Safari 6.0 stack trace. - @Deprecated("Use Trace.parseSafari instead.") + @Deprecated('Use Trace.parseSafari instead.') Trace.parseSafari6_0(String trace) : this( trace .trim() - .split("\n") + .split('\n') .where((line) => line != '[native code]') .map((line) => Frame.parseFirefox(line)), original: trace); @@ -233,7 +233,7 @@ class Trace implements StackTrace { ? [] : trace .trim() - .split("\n") + .split('\n') // Filter out asynchronous gaps from [Chain]s. .where((line) => !line.startsWith('=====')) .map((line) => Frame.parseFriendly(line)), @@ -280,7 +280,7 @@ class Trace implements StackTrace { /// If [terse] is true, this will also fold together frames from the core /// library or from this package, simplify core library frames, and /// potentially remove the outermost frame as in [Trace.terse]. - Trace foldFrames(bool predicate(Frame frame), {bool terse = false}) { + Trace foldFrames(bool Function(Frame) predicate, {bool terse = false}) { if (terse) { var oldPredicate = predicate; predicate = (frame) { @@ -322,10 +322,10 @@ class Trace implements StackTrace { } } - return Trace(newFrames.reversed, original: this.original.toString()); + return Trace(newFrames.reversed, original: original.toString()); } - /// Returns a human-readable string representation of [this]. + @override String toString() { // Figure out the longest path so we know how much to pad. var longest = @@ -333,7 +333,7 @@ class Trace implements StackTrace { // Print out the stack trace nicely formatted. return frames.map((frame) { - if (frame is UnparsedFrame) return "$frame\n"; + if (frame is UnparsedFrame) return '$frame\n'; return '${frame.location.padRight(longest)} ${frame.member}\n'; }).join(); } diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index 3f7ffe2d1..31d017996 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -8,17 +8,26 @@ import 'frame.dart'; /// /// The [member] property contains the original frame's contents. class UnparsedFrame implements Frame { - final Uri uri = Uri(path: "unparsed"); + @override + final Uri uri = Uri(path: 'unparsed'); + @override final int line = null; + @override final int column = null; + @override final bool isCore = false; - final String library = "unparsed"; + @override + final String library = 'unparsed'; + @override final String package = null; - final String location = "unparsed"; + @override + final String location = 'unparsed'; + @override final String member; UnparsedFrame(this.member); + @override String toString() => member; } diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 74ffbcad6..3ba73b9fb 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -15,17 +15,18 @@ class VMTrace implements StackTrace { VMTrace(this.frames); + @override String toString() { var i = 1; return frames.map((frame) { - var number = "#${i++}".padRight(8); + var number = '#${i++}'.padRight(8); var member = frame.member - .replaceAllMapped(RegExp(r"[^.]+\."), - (match) => "${match[1]}.<${match[1]}_async_body>") - .replaceAll("", ""); - var line = frame.line == null ? 0 : frame.line; - var column = frame.column == null ? 0 : frame.column; - return "$number$member (${frame.uri}:$line:$column)\n"; + .replaceAllMapped(RegExp(r'[^.]+\.'), + (match) => '${match[1]}.<${match[1]}_async_body>') + .replaceAll('', ''); + var line = frame.line ?? 0; + var column = frame.column ?? 0; + return '$number$member (${frame.uri}:$line:$column)\n'; }).join(); } } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3ddf071ba..d16cbf979 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -10,4 +10,5 @@ dependencies: path: ^1.2.0 dev_dependencies: + pedantic: ^1.0.0 test: '>=0.12.17 <2.0.0' diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 40c2954dd..b6ad33e03 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -38,29 +38,29 @@ void main() { }); }); - group("Chain.capture()", () { - test("with onError blocks errors", () { + group('Chain.capture()', () { + test('with onError blocks errors', () { Chain.capture(() { - return Future.error("oh no"); + return Future.error('oh no'); }, onError: expectAsync2((error, chain) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); expect(chain, TypeMatcher()); })); }); - test("with no onError blocks errors", () { + test('with no onError blocks errors', () { runZoned(() { - var future = Chain.capture(() => Future.error("oh no"), when: false); + var future = Chain.capture(() => Future.error('oh no'), when: false); future.then(expectAsync1((_) {}, count: 0)); }, onError: expectAsync2((error, chain) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); expect(chain, TypeMatcher()); })); }); test("with errorZone: false doesn't block errors", () { - expect(Chain.capture(() => Future.error("oh no"), errorZone: false), - throwsA("oh no")); + expect(Chain.capture(() => Future.error('oh no'), errorZone: false), + throwsA('oh no')); }); test("doesn't allow onError and errorZone: false", () { @@ -68,17 +68,17 @@ void main() { throwsArgumentError); }); - group("with when: false", () { + group('with when: false', () { test("with no onError doesn't block errors", () { - expect(Chain.capture(() => Future.error("oh no"), when: false), - throwsA("oh no")); + expect(Chain.capture(() => Future.error('oh no'), when: false), + throwsA('oh no')); }); - test("with onError blocks errors", () { + test('with onError blocks errors', () { Chain.capture(() { - return Future.error("oh no"); + return Future.error('oh no'); }, onError: expectAsync2((error, chain) { - expect(error, equals("oh no")); + expect(error, equals('oh no')); expect(chain, TypeMatcher()); }), when: false); }); @@ -100,8 +100,8 @@ void main() { }); }); - group("Chain.disable()", () { - test("disables chain-tracking", () { + group('Chain.disable()', () { + test('disables chain-tracking', () { return Chain.disable(() { var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); @@ -112,7 +112,7 @@ void main() { }); }); - test("Chain.capture() re-enables chain-tracking", () { + test('Chain.capture() re-enables chain-tracking', () { return Chain.disable(() { return Chain.capture(() { var completer = Completer(); @@ -125,7 +125,7 @@ void main() { }); }); - test("preserves parent zones of the capture zone", () { + test('preserves parent zones of the capture zone', () { // The outer disable call turns off the test package's chain-tracking. return Chain.disable(() { return runZoned(() { @@ -136,7 +136,7 @@ void main() { }); }); - test("preserves child zones of the capture zone", () { + test('preserves child zones of the capture zone', () { // The outer disable call turns off the test package's chain-tracking. return Chain.disable(() { return Chain.capture(() { @@ -161,7 +161,7 @@ void main() { }); }); - test("toString() ensures that all traces are aligned", () { + test('toString() ensures that all traces are aligned', () { var chain = Chain([ Trace.parse('short 10:11 Foo.bar\n'), Trace.parse('loooooooooooong 10:11 Zop.zoop') diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 790693a49..0711108cb 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -8,13 +8,13 @@ import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; /// Runs [callback] in a microtask callback. -void inMicrotask(callback()) => scheduleMicrotask(callback); +void inMicrotask(void Function() callback) => scheduleMicrotask(callback); /// Runs [callback] in a one-shot timer callback. -void inOneShotTimer(callback()) => Timer.run(callback); +void inOneShotTimer(void Function() callback) => Timer.run(callback); /// Runs [callback] once in a periodic timer callback. -void inPeriodicTimer(callback()) { +void inPeriodicTimer(void Function() callback) { var count = 0; Timer.periodic(Duration(milliseconds: 1), (timer) { count++; @@ -25,7 +25,7 @@ void inPeriodicTimer(callback()) { } /// Runs [callback] within a long asynchronous Future chain. -void inFutureChain(callback()) { +void inFutureChain(void Function() callback) { Future(() {}) .then((_) => Future(() {})) .then((_) => Future(() {})) @@ -35,11 +35,11 @@ void inFutureChain(callback()) { .then((_) => Future(() {})); } -void inNewFuture(callback()) { +void inNewFuture(void Function() callback) { Future(callback); } -void inSyncFuture(callback()) { +void inSyncFuture(void Function() callback) { Future.sync(callback); } @@ -63,7 +63,8 @@ Stream controllerErrorStream([StackTrace trace]) { /// Runs [callback] within [asyncFn], then converts any errors raised into a /// [Chain] with [Chain.forTrace]. -Future chainForTrace(asyncFn(callback()), callback()) { +Future chainForTrace( + void Function(void Function()) asyncFn, void Function() callback) { var completer = Completer(); asyncFn(() { // We use `new Future.value().then(...)` here as opposed to [new Future] or @@ -81,7 +82,7 @@ Future chainForTrace(asyncFn(callback()), callback()) { /// completes to the stack chain for an error thrown by [callback]. /// /// [callback] is expected to throw the string `"error"`. -Future captureFuture(callback()) { +Future captureFuture(void Function() callback) { var completer = Completer(); Chain.capture(callback, onError: (error, chain) { expect(error, equals('error')); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 685603e31..25487c9e7 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -9,20 +9,20 @@ import 'package:test/test.dart'; void main() { group('.parseVM', () { test('parses a stack frame with column correctly', () { - var frame = Frame.parseVM("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart:42:21)"); + var frame = Frame.parseVM('#1 Foo._bar ' + '(file:///home/nweiz/code/stuff.dart:42:21)'); expect( - frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + frame.uri, equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); expect(frame.line, equals(42)); expect(frame.column, equals(21)); expect(frame.member, equals('Foo._bar')); }); test('parses a stack frame without column correctly', () { - var frame = Frame.parseVM("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart:24)"); + var frame = Frame.parseVM('#1 Foo._bar ' + '(file:///home/nweiz/code/stuff.dart:24)'); expect( - frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + frame.uri, equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); expect(frame.line, equals(24)); expect(frame.column, null); expect(frame.member, equals('Foo._bar')); @@ -30,10 +30,10 @@ void main() { // This can happen with async stack traces. See issue 22009. test('parses a stack frame without line or column correctly', () { - var frame = Frame.parseVM("#1 Foo._bar " - "(file:///home/nweiz/code/stuff.dart)"); + var frame = Frame.parseVM('#1 Foo._bar ' + '(file:///home/nweiz/code/stuff.dart)'); expect( - frame.uri, equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); + frame.uri, equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('Foo._bar')); @@ -81,56 +81,56 @@ void main() { }); test('parses a stack frame correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - "(http://pub.dartlang.org/stuff.dart.js:560:28)"); + var frame = Frame.parseV8(' at VW.call\$0 ' + '(http://pub.dartlang.org/stuff.dart.js:560:28)'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with an absolute POSIX path correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - "(/path/to/stuff.dart.js:560:28)"); - expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); + var frame = Frame.parseV8(' at VW.call\$0 ' + '(/path/to/stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('file:///path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with an absolute Windows path correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - r"(C:\path\to\stuff.dart.js:560:28)"); - expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); + var frame = Frame.parseV8(' at VW.call\$0 ' + r'(C:\path\to\stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('file:///C:/path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a Windows UNC path correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - r"(\\mount\path\to\stuff.dart.js:560:28)"); + var frame = Frame.parseV8(' at VW.call\$0 ' + r'(\\mount\path\to\stuff.dart.js:560:28)'); expect( - frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + frame.uri, equals(Uri.parse('file://mount/path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a relative POSIX path correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - "(path/to/stuff.dart.js:560:28)"); - expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + var frame = Frame.parseV8(' at VW.call\$0 ' + '(path/to/stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a relative Windows path correctly', () { - var frame = Frame.parseV8(" at VW.call\$0 " - r"(path\to\stuff.dart.js:560:28)"); - expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + var frame = Frame.parseV8(' at VW.call\$0 ' + r'(path\to\stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); @@ -138,16 +138,16 @@ void main() { test('parses an anonymous stack frame correctly', () { var frame = - Frame.parseV8(" at http://pub.dartlang.org/stuff.dart.js:560:28"); + Frame.parseV8(' at http://pub.dartlang.org/stuff.dart.js:560:28'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('')); }); test('parses a native stack frame correctly', () { - var frame = Frame.parseV8(" at Object.stringify (native)"); + var frame = Frame.parseV8(' at Object.stringify (native)'); expect(frame.uri, Uri.parse('native')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -157,50 +157,50 @@ void main() { test('parses a stack frame with [as ...] correctly', () { // Ignore "[as ...]", since other stack trace formats don't support a // similar construct. - var frame = Frame.parseV8(" at VW.call\$0 [as call\$4] " - "(http://pub.dartlang.org/stuff.dart.js:560:28)"); + var frame = Frame.parseV8(' at VW.call\$0 [as call\$4] ' + '(http://pub.dartlang.org/stuff.dart.js:560:28)'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); }); test('parses a basic eval stack frame correctly', () { - var frame = Frame.parseV8(" at eval (eval at " - "(http://pub.dartlang.org/stuff.dart.js:560:28))"); + var frame = Frame.parseV8(' at eval (eval at ' + '(http://pub.dartlang.org/stuff.dart.js:560:28))'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); }); test('parses an IE10 eval stack frame correctly', () { - var frame = Frame.parseV8(" at eval (eval at Anonymous function " - "(http://pub.dartlang.org/stuff.dart.js:560:28))"); + var frame = Frame.parseV8(' at eval (eval at Anonymous function ' + '(http://pub.dartlang.org/stuff.dart.js:560:28))'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); }); test('parses an eval stack frame with inner position info correctly', () { - var frame = Frame.parseV8(" at eval (eval at " - "(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)"); + var frame = Frame.parseV8(' at eval (eval at ' + '(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); }); test('parses a nested eval stack frame correctly', () { - var frame = Frame.parseV8(" at eval (eval at " - "(eval at sub (http://pub.dartlang.org/stuff.dart.js:560:28)))"); + var frame = Frame.parseV8(' at eval (eval at ' + '(eval at sub (http://pub.dartlang.org/stuff.dart.js:560:28)))'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); @@ -242,20 +242,20 @@ anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 baz@http://pub.dartlang.org/buz.js:56355:55 '''); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[0].line, equals(18056)); expect(trace.frames[0].column, equals(12)); - expect(trace.frames[0].member, equals("Foo._bar")); + expect(trace.frames[0].member, equals('Foo._bar')); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].line, equals(693)); expect(trace.frames[1].column, isNull); - expect(trace.frames[1].member, equals("")); + expect(trace.frames[1].member, equals('')); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/buz.js"))); + equals(Uri.parse('http://pub.dartlang.org/buz.js'))); expect(trace.frames[2].line, equals(56355)); expect(trace.frames[2].column, equals(55)); - expect(trace.frames[2].member, equals("baz")); + expect(trace.frames[2].member, equals('baz')); }); test('parses a Firefox stack trace with nested evals in anonymous function', @@ -266,33 +266,33 @@ baz@http://pub.dartlang.org/buz.js:56355:55 anonymous@file:///C:/example.html line 45 > Function:1:1 '''); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[0].line, equals(18056)); expect(trace.frames[0].column, equals(12)); - expect(trace.frames[0].member, equals("Foo._bar")); - expect(trace.frames[1].uri, equals(Uri.parse("file:///C:/example.html"))); + expect(trace.frames[0].member, equals('Foo._bar')); + expect(trace.frames[1].uri, equals(Uri.parse('file:///C:/example.html'))); expect(trace.frames[1].line, equals(7)); expect(trace.frames[1].column, isNull); - expect(trace.frames[1].member, equals("")); - expect(trace.frames[2].uri, equals(Uri.parse("file:///C:/example.html"))); + expect(trace.frames[1].member, equals('')); + expect(trace.frames[2].uri, equals(Uri.parse('file:///C:/example.html'))); expect(trace.frames[2].line, equals(45)); expect(trace.frames[2].column, isNull); - expect(trace.frames[2].member, equals("")); + expect(trace.frames[2].member, equals('')); }); test('parses a simple stack frame correctly', () { var frame = Frame.parseFirefox( - ".VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560"); + '.VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with an absolute POSIX path correctly', () { - var frame = Frame.parseFirefox(".VW.call\$0@/path/to/stuff.dart.js:560"); - expect(frame.uri, equals(Uri.parse("file:///path/to/stuff.dart.js"))); + var frame = Frame.parseFirefox('.VW.call\$0@/path/to/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('file:///path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); @@ -300,8 +300,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with an absolute Windows path correctly', () { var frame = - Frame.parseFirefox(r".VW.call$0@C:\path\to\stuff.dart.js:560"); - expect(frame.uri, equals(Uri.parse("file:///C:/path/to/stuff.dart.js"))); + Frame.parseFirefox(r'.VW.call$0@C:\path\to\stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('file:///C:/path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); @@ -309,25 +309,25 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with a Windows UNC path correctly', () { var frame = - Frame.parseFirefox(r".VW.call$0@\\mount\path\to\stuff.dart.js:560"); + Frame.parseFirefox(r'.VW.call$0@\\mount\path\to\stuff.dart.js:560'); expect( - frame.uri, equals(Uri.parse("file://mount/path/to/stuff.dart.js"))); + frame.uri, equals(Uri.parse('file://mount/path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a relative POSIX path correctly', () { - var frame = Frame.parseFirefox(".VW.call\$0@path/to/stuff.dart.js:560"); - expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + var frame = Frame.parseFirefox('.VW.call\$0@path/to/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); }); test('parses a stack frame with a relative Windows path correctly', () { - var frame = Frame.parseFirefox(r".VW.call$0@path\to\stuff.dart.js:560"); - expect(frame.uri, equals(Uri.parse("path/to/stuff.dart.js"))); + var frame = Frame.parseFirefox(r'.VW.call$0@path\to\stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('path/to/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); @@ -335,68 +335,68 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a simple anonymous stack frame correctly', () { var frame = - Frame.parseFirefox("@http://pub.dartlang.org/stuff.dart.js:560"); + Frame.parseFirefox('@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("")); + expect(frame.member, equals('')); }); test('parses a nested anonymous stack frame correctly', () { var frame = Frame.parseFirefox( - ".foo/<@http://pub.dartlang.org/stuff.dart.js:560"); + '.foo/<@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo.")); + expect(frame.member, equals('foo.')); frame = - Frame.parseFirefox(".foo/@http://pub.dartlang.org/stuff.dart.js:560"); + Frame.parseFirefox('.foo/@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo.")); + expect(frame.member, equals('foo.')); }); test('parses a named nested anonymous stack frame correctly', () { var frame = Frame.parseFirefox( - ".foo/.name<@http://pub.dartlang.org/stuff.dart.js:560"); + '.foo/.name<@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo.")); + expect(frame.member, equals('foo.')); frame = Frame.parseFirefox( - ".foo/.name@http://pub.dartlang.org/stuff.dart.js:560"); + '.foo/.name@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo.")); + expect(frame.member, equals('foo.')); }); test('parses a stack frame with parameters correctly', () { var frame = Frame.parseFirefox( '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo")); + expect(frame.member, equals('foo')); }); test('parses a nested anonymous stack frame with parameters correctly', () { var frame = Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' 'http://pub.dartlang.org/stuff.dart.js:560'); expect(frame.uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.dart.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); - expect(frame.member, equals("foo.")); + expect(frame.member, equals('foo.')); }); test( @@ -405,10 +405,10 @@ baz@http://pub.dartlang.org/buz.js:56355:55 var frame = Frame.parseFirefox('.convertDartClosureToJS/\$function.")); + expect(frame.member, equals('convertDartClosureToJS..')); }); test('returns an UnparsedFrame for malformed frames', () { @@ -424,16 +424,16 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a simple stack frame correctly', () { var frame = - Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); }); test('parses an anonymous stack frame correctly', () { - var frame = Frame.parseFirefox("http://dartlang.org/foo/bar.dart:10:11"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + var frame = Frame.parseFirefox('http://dartlang.org/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('')); @@ -441,8 +441,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line correctly', () { var frame = - Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart::11"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart::11'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); @@ -450,8 +450,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no column correctly', () { var frame = - Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, isNull); expect(frame.member, equals('foo\$bar')); @@ -459,8 +459,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line or column correctly', () { var frame = - Frame.parseFirefox("foo\$bar@http://dartlang.org/foo/bar.dart:10:11"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); @@ -470,8 +470,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 group('.parseFriendly', () { test('parses a simple stack frame correctly', () { var frame = Frame.parseFriendly( - "http://dartlang.org/foo/bar.dart 10:11 Foo..bar"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('Foo..bar')); @@ -479,8 +479,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line or column correctly', () { var frame = - Frame.parseFriendly("http://dartlang.org/foo/bar.dart Foo..bar"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + Frame.parseFriendly('http://dartlang.org/foo/bar.dart Foo..bar'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('Foo..bar')); @@ -488,15 +488,15 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no column correctly', () { var frame = Frame.parseFriendly( - "http://dartlang.org/foo/bar.dart 10 Foo..bar"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + 'http://dartlang.org/foo/bar.dart 10 Foo..bar'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, isNull); expect(frame.member, equals('Foo..bar')); }); test('parses a stack frame with a relative path correctly', () { - var frame = Frame.parseFriendly("foo/bar.dart 10:11 Foo..bar"); + var frame = Frame.parseFriendly('foo/bar.dart 10:11 Foo..bar'); expect(frame.uri, equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); expect(frame.line, equals(10)); @@ -512,7 +512,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a data url stack frame with no line or column correctly', () { - var frame = Frame.parseFriendly("data:... main"); + var frame = Frame.parseFriendly('data:... main'); expect(frame.uri.scheme, equals('data')); expect(frame.line, isNull); expect(frame.column, isNull); @@ -520,7 +520,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a data url stack frame correctly', () { - var frame = Frame.parseFriendly("data:... 10:11 main"); + var frame = Frame.parseFriendly('data:... 10:11 main'); expect(frame.uri.scheme, equals('data')); expect(frame.line, equals(10)); expect(frame.column, equals(11)); @@ -529,7 +529,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with spaces in the member name correctly', () { var frame = Frame.parseFriendly( - "foo/bar.dart 10:11 (anonymous function).dart.fn"); + 'foo/bar.dart 10:11 (anonymous function).dart.fn'); expect(frame.uri, equals(path.toUri(path.absolute(path.join('foo', 'bar.dart'))))); expect(frame.line, equals(10)); @@ -541,8 +541,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'parses a stack frame with spaces in the member name and no line or ' 'column correctly', () { var frame = Frame.parseFriendly( - "http://dartlang.org/foo/bar.dart (anonymous function).dart.fn"); - expect(frame.uri, equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + 'http://dartlang.org/foo/bar.dart (anonymous function).dart.fn'); + expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('(anonymous function).dart.fn')); @@ -650,7 +650,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); } -void expectIsUnparsed(Frame constructor(String text), String text) { +void expectIsUnparsed(Frame Function(String) constructor, String text) { var frame = constructor(text); expect(frame, TypeMatcher()); expect(frame.toString(), equals(text)); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 61abe5dc3..33a077dae 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -23,10 +23,10 @@ void main() { 'dart:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("file:///home/nweiz/code/stuff.dart"))); - expect(trace.frames[1].uri, equals(Uri.parse("dart:async/future.dart"))); + equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); + expect(trace.frames[1].uri, equals(Uri.parse('dart:async/future.dart'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.dart"))); + equals(Uri.parse('http://pub.dartlang.org/thing.dart'))); }); test('parses a V8 stack trace correctly', () { @@ -37,24 +37,24 @@ void main() { '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); - trace = Trace.parse("Exception: foo\n" + trace = Trace.parse('Exception: foo\n' ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' ' at http://pub.dartlang.org/stuff.js:0:2\n' ' at zip..zap ' '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); trace = Trace.parse('Exception: foo\n' ' bar\n' @@ -64,11 +64,11 @@ void main() { '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); trace = Trace.parse('Exception: foo\n' ' bar\n' @@ -78,13 +78,13 @@ void main() { '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); - expect(trace.frames[1].member, equals("")); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + expect(trace.frames[1].member, equals('')); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); - expect(trace.frames[2].member, equals(".zip.zap")); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + expect(trace.frames[2].member, equals('.zip.zap')); }); // JavaScriptCore traces are just like V8, except that it doesn't have a @@ -97,11 +97,11 @@ void main() { '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); trace = Trace.parse('\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' @@ -110,9 +110,9 @@ void main() { '(http://pub.dartlang.org/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); }); test('parses a Firefox/Safari stack trace correctly', () { @@ -121,22 +121,22 @@ void main() { 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); trace = Trace.parse('zip/<@http://pub.dartlang.org/stuff.js:0\n' 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); trace = Trace.parse( 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' @@ -144,11 +144,11 @@ void main() { 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); }); test('parses a Firefox/Safari stack trace containing native code correctly', @@ -159,11 +159,11 @@ void main() { '[native code]'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); expect(trace.frames.length, equals(3)); }); @@ -174,12 +174,12 @@ void main() { 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[0].member, equals('')); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); }); test('parses a Firefox/Safari stack trace with an empty line correctly', @@ -190,11 +190,11 @@ void main() { 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); }); test('parses a Firefox/Safari stack trace with a column number correctly', @@ -204,13 +204,13 @@ void main() { 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[0].line, equals(42)); expect(trace.frames[0].column, equals(2)); expect(trace.frames[1].uri, - equals(Uri.parse("http://pub.dartlang.org/stuff.js"))); + equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://pub.dartlang.org/thing.js"))); + equals(Uri.parse('http://pub.dartlang.org/thing.js'))); }); test('parses a package:stack_trace stack trace correctly', () { @@ -219,9 +219,9 @@ void main() { 'http://dartlang.org/foo/baz.dart Foo..bar'); expect(trace.frames[0].uri, - equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://dartlang.org/foo/baz.dart"))); + equals(Uri.parse('http://dartlang.org/foo/baz.dart'))); }); test('parses a package:stack_trace stack chain correctly', () { @@ -233,13 +233,13 @@ void main() { 'http://dartlang.org/foo/quux.dart Foo..bar'); expect(trace.frames[0].uri, - equals(Uri.parse("http://dartlang.org/foo/bar.dart"))); + equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); expect(trace.frames[1].uri, - equals(Uri.parse("http://dartlang.org/foo/baz.dart"))); + equals(Uri.parse('http://dartlang.org/foo/baz.dart'))); expect(trace.frames[2].uri, - equals(Uri.parse("http://dartlang.org/foo/bang.dart"))); + equals(Uri.parse('http://dartlang.org/foo/bang.dart'))); expect(trace.frames[3].uri, - equals(Uri.parse("http://dartlang.org/foo/quux.dart"))); + equals(Uri.parse('http://dartlang.org/foo/quux.dart'))); }); test('parses a real package:stack_trace stack trace correctly', () { @@ -283,8 +283,8 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap '#3 baz (dart:async:15:0)\n')); }); - group("folding", () { - group(".terse", () { + group('folding', () { + group('.terse', () { test('folds core frames together bottom-up', () { var trace = Trace.parse(''' #1 top (dart:async/future.dart:0:2) @@ -343,11 +343,11 @@ dart:core bottom }); test("won't panic on an empty trace", () { - expect(Trace.parse("").terse.toString(), equals("")); + expect(Trace.parse('').terse.toString(), equals('')); }); }); - group(".foldFrames", () { + group('.foldFrames', () { test('folds frames together bottom-up', () { var trace = Trace.parse(''' #0 notFoo (foo.dart:42:21) @@ -382,7 +382,7 @@ dart:async-patch/future.dart 9:11 fooBottom ''')); }); - group("with terse: true", () { + group('with terse: true', () { test('folds core frames as well', () { var trace = Trace.parse(''' #0 notFoo (foo.dart:42:21) diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index 41a79c6eb..38950c16a 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -17,7 +17,8 @@ Matcher frameLibrary(matcher) => /// /// [description] should be a noun phrase that describes the relation of the /// output of [transformation] to its input. -Matcher transform(transformation(value), matcher, String description) => +Matcher transform( + void Function(dynamic) transformation, matcher, String description) => _TransformMatcher(transformation, wrapMatcher(matcher), description); class _TransformMatcher extends Matcher { @@ -27,9 +28,11 @@ class _TransformMatcher extends Matcher { _TransformMatcher(this._transformation, this._matcher, this._description); + @override bool matches(item, Map matchState) => _matcher.matches(_transformation(item), matchState); + @override Description describe(Description description) => description.add(_description).add(' ').addDescriptionOf(_matcher); } diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 9d5e77b78..4ad3de2cd 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -47,7 +47,7 @@ void main() { }); test('.from handles a stack overflow trace correctly', () { - overflow() => overflow(); + void overflow() => overflow(); var trace; try { From 7f7a57da3093cf501d2bd3a05fca10aa4ac44e6b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 13 Apr 2020 12:02:54 -0700 Subject: [PATCH 0637/1215] Drop a workaround for a resolved issue (dart-lang/stack_trace#63) https://github.com/dart-lang/sdk/issues/14075 has been closed for a long time. This class in not in the public interface for the package so it should not be breaking to remove the throwing setter. --- pkgs/stack_trace/lib/src/lazy_trace.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 917d20ed2..0fa2af18b 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -32,7 +32,4 @@ class LazyTrace implements Trace { LazyTrace(() => _trace.foldFrames(predicate, terse: terse)); @override String toString() => _trace.toString(); - - // Work around issue 14075. - set frames(_) => throw UnimplementedError(); } From 5fa9c9b66fb7f1ccdb61353826b30cbc609766d7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 13 Apr 2020 13:31:17 -0700 Subject: [PATCH 0638/1215] Loosen argument type in callback (dart-lang/stack_trace#65) The type was technically changed when refactoring to function type syntax, restore the `dynamic` but make it explicit. This surfaces as a static problem in the null safety branch. Fix it on the master branch as well for consistency. --- pkgs/stack_trace/lib/src/chain.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 602b90c09..48ac2d9d6 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -73,7 +73,7 @@ class Chain implements StackTrace { /// /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T Function() callback, - {void Function(Object error, Chain) onError, + {void Function(dynamic error, Chain) onError, bool when = true, bool errorZone = true}) { if (!errorZone && onError != null) { From 2b3cbd263fc9e1b505f3c34a03768507f7a5c5d2 Mon Sep 17 00:00:00 2001 From: Max Lapides Date: Wed, 15 Apr 2020 16:14:34 -0700 Subject: [PATCH 0639/1215] docs: fix spelling of debounce (dart-lang/stream_transform#107) --- pkgs/stream_transform/lib/src/rate_limit.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 6341c3e77..e42f8f43f 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -38,17 +38,17 @@ extension RateLimit on Stream { /// /// For example: /// - /// source.debouce(Duration(seconds: 1)); + /// source.debounce(Duration(seconds: 1)); /// /// source: 1-2-3---4---5-6-| /// result: ------3---4-----6| /// - /// source.debouce(Duration(seconds: 1), leading: true, trailing: false); + /// source.debounce(Duration(seconds: 1), leading: true, trailing: false); /// /// source: 1-2-3---4---5-6-| /// result: 1-------4---5---| /// - /// source.debouce(Duration(seconds: 1), leading: true); + /// source.debounce(Duration(seconds: 1), leading: true); /// /// source: 1-2-3---4---5-6-| /// result: 1-----3-4---5---6| From 303f88d2ff444468df8a408173ed780557e07aef Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 15 Apr 2020 17:38:26 -0700 Subject: [PATCH 0640/1215] Fix missing events for files with directory prefix (dart-lang/watcher#84) Fixes dart-lang/watcher#83 If any event had the same leading characters as a directory that was also changed it would get filtered out. For example if both `lib/b/` and `lib/b.dart` have change events we'd lose the events for `lib/b.dart` because it shared a prefix with a directory, even though it isn't contained within that directory. --- pkgs/watcher/CHANGELOG.md | 5 +++++ pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 4 +++- pkgs/watcher/lib/src/directory_watcher/windows.dart | 2 +- pkgs/watcher/pubspec.yaml | 2 +- pkgs/watcher/test/directory_watcher/mac_os_test.dart | 11 +++++++++++ 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 65ab5dfaf..74565902a 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +# 0.9.7+15-dev + +* Fix a bug on Mac where modifying a directory with a path exactly matching a + prefix of a modified file would suppress change events for that file. + # 0.9.7+14 * Prepare for breaking change in SDK where modified times for not found files diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 73703cb4d..0aa056635 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -5,6 +5,8 @@ import 'dart:async'; import 'dart:io'; +import 'package:path/path.dart' as p; + import '../directory_watcher.dart'; import '../constructable_file_system_event.dart'; import '../path_set.dart'; @@ -196,7 +198,7 @@ class _MacOSDirectoryWatcher })); bool isInModifiedDirectory(String path) => - directories.any((dir) => path != dir && path.startsWith(dir)); + directories.any((dir) => path != dir && p.isWithin(dir, path)); void addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 2a70edced..9a7de5f37 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -237,7 +237,7 @@ class _WindowsDirectoryWatcher })); bool isInModifiedDirectory(String path) => - directories.any((dir) => path != dir && path.startsWith(dir)); + directories.any((dir) => path != dir && p.isWithin(dir, path)); void addEvent(String path, FileSystemEvent event) { if (isInModifiedDirectory(path)) return; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 3982775c1..230b00b2c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+14 +version: 0.9.7+15-dev description: >- A file system watcher. It monitors changes to contents of directories and diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index b100f5970..58ba31aaa 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -54,4 +54,15 @@ void main() { (i, j, k) => isModifyEvent('dir/sub/sub-$i/sub-$j/file-$k.txt'))); }); }); + test('does not suppress files with the same prefix as a directory', () async { + // Regression test for https://github.com/dart-lang/watcher/issues/83 + writeFile('some_name.txt'); + + await startWatcher(); + + writeFile('some_name/some_name.txt'); + deleteFile('some_name.txt'); + + await expectRemoveEvent('some_name.txt'); + }); } From 82476532a57e78564e8edf1b90a4490ae1754cd0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 15 Apr 2020 17:38:49 -0700 Subject: [PATCH 0641/1215] Use ?. over explicit null check (dart-lang/watcher#85) --- pkgs/watcher/lib/src/directory_watcher/linux.dart | 2 +- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 6 +++--- pkgs/watcher/lib/src/directory_watcher/polling.dart | 2 +- pkgs/watcher/lib/src/directory_watcher/windows.dart | 12 +++++------- pkgs/watcher/lib/src/file_watcher/native.dart | 2 +- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 0a66a1291..7348cb45f 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -262,7 +262,7 @@ class _LinuxDirectoryWatcher StreamSubscription subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); - if (onDone != null) onDone(); + onDone?.call(); }, cancelOnError: cancelOnError); _subscriptions.add(subscription); } diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 0aa056635..4408ff1eb 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -95,8 +95,8 @@ class _MacOSDirectoryWatcher @override void close() { - if (_watchSubscription != null) _watchSubscription.cancel(); - if (_initialListSubscription != null) _initialListSubscription.cancel(); + _watchSubscription?.cancel(); + _initialListSubscription?.cancel(); _watchSubscription = null; _initialListSubscription = null; @@ -365,7 +365,7 @@ class _MacOSDirectoryWatcher /// of its state. Future _listDir() { assert(!isReady); - if (_initialListSubscription != null) _initialListSubscription.cancel(); + _initialListSubscription?.cancel(); _files.clear(); var completer = Completer(); diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 388f28add..902e8b861 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -92,7 +92,7 @@ class _PollingDirectoryWatcher _events.close(); // If we're in the middle of listing the directory, stop. - if (_listSubscription != null) _listSubscription.cancel(); + _listSubscription?.cancel(); // Don't process any remaining files. _filesToProcess.clear(); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 9a7de5f37..f5093c5dc 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -32,9 +32,7 @@ class _EventBatcher { void addEvent(FileSystemEvent event, void Function() callback) { events.add(event); - if (timer != null) { - timer.cancel(); - } + timer?.cancel(); timer = Timer(_BATCH_DELAY, callback); } @@ -102,9 +100,9 @@ class _WindowsDirectoryWatcher @override void close() { - if (_watchSubscription != null) _watchSubscription.cancel(); - if (_parentWatchSubscription != null) _parentWatchSubscription.cancel(); - if (_initialListSubscription != null) _initialListSubscription.cancel(); + _watchSubscription?.cancel(); + _parentWatchSubscription?.cancel(); + _initialListSubscription?.cancel(); for (var sub in _listSubscriptions) { sub.cancel(); } @@ -401,7 +399,7 @@ class _WindowsDirectoryWatcher /// of its state. Future _listDir() { assert(!isReady); - if (_initialListSubscription != null) _initialListSubscription.cancel(); + _initialListSubscription?.cancel(); _files.clear(); var completer = Completer(); diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 7f466af3f..0b42cb9b3 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -83,7 +83,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { @override void close() { - if (_subscription != null) _subscription.cancel(); + _subscription?.cancel(); _subscription = null; _eventsController.close(); } From 9faf03618142c358c5a18e216f3399648b4c26c3 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 16 Apr 2020 11:41:51 -0700 Subject: [PATCH 0642/1215] Run tests on multiple platforms (dart-lang/watcher#86) - Only use `--fatal-warnings` for the oldest supported SDK. Use `--fatal-infos` on the dev SDK. - Run tests on all 3 OSes. --- pkgs/watcher/.travis.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index 9871d25bb..a3bc0703a 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -4,15 +4,24 @@ dart: - dev - 2.2.0 +os: +- linux +- windows +- osx + dart_task: - test -- dartanalyzer: --fatal-warnings --fatal-infos . matrix: include: - # Only validate formatting using the dev release - dart: dev dart_task: dartfmt + - dart: 2.2.0 + dart_task: + dartanalyzer: --fatal-warnings . + - dart: dev + dart_task: + dartanalyzer: --fatal-warnings --fatal-infos . # Only building master means that we don't run two builds for each pull request. branches: From 0ae79d2e7244daf13a4a3c93c79f983151a7ffa6 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 17 Apr 2020 10:01:13 -0700 Subject: [PATCH 0643/1215] Change back to Object from dynamic (dart-lang/stack_trace#66) See https://github.com/dart-lang/stack_trace/pull/64#discussion_r410279004 Enable and fix the lint `avoid_private_typedef_functions`. --- pkgs/stack_trace/CHANGELOG.md | 3 +++ pkgs/stack_trace/analysis_options.yaml | 4 ++++ pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 5 +---- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index faf6eebc7..39e7fb3b3 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,6 +1,9 @@ ## 1.9.4-dev * Added support for firefox anonymous stack traces +* Change the argument type to `Chain.capture` from `Function(dynamic, Chain)` to + `Function(Object, Chain)`. Existing functions which take `dynamic` are still + fine, but new uses can have a safer type. ## 1.9.3 diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 2762c70f2..70216af63 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -4,3 +4,7 @@ analyzer: implicit-casts: false errors: prefer_spread_collections: ignore + +linter: + rules: + - avoid_private_typedef_functions diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 48ac2d9d6..602b90c09 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -73,7 +73,7 @@ class Chain implements StackTrace { /// /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T Function() callback, - {void Function(dynamic error, Chain) onError, + {void Function(Object error, Chain) onError, bool when = true, bool errorZone = true}) { if (!errorZone && onError != null) { diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 4ac660408..f721e9405 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -10,9 +10,6 @@ import 'lazy_trace.dart'; import 'trace.dart'; import 'utils.dart'; -/// A function that handles errors in the zone wrapped by [Chain.capture]. -typedef _ChainHandler = void Function(dynamic error, Chain chain); - /// A class encapsulating the zone specification for a [Chain.capture] zone. /// /// Until they're materialized and exposed to the user, stack chains are tracked @@ -56,7 +53,7 @@ class StackZoneSpecification { /// /// If this is null, that indicates that any unhandled errors should be passed /// to the parent zone. - final _ChainHandler _onError; + final void Function(Object error, Chain) _onError; /// The most recent node of the current stack chain. _Node _currentNode; From 1fa0ba8679a340fbcc480d2fa45da50dd95091c5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 21 Apr 2020 10:46:39 -0700 Subject: [PATCH 0644/1215] Fix deprecated domain references (dart-lang/stack_trace#67) --- pkgs/stack_trace/.gitignore | 2 +- pkgs/stack_trace/README.md | 4 +- pkgs/stack_trace/lib/src/chain.dart | 2 +- pkgs/stack_trace/lib/src/frame.dart | 34 ++-- pkgs/stack_trace/lib/src/trace.dart | 8 +- pkgs/stack_trace/lib/stack_trace.dart | 17 -- pkgs/stack_trace/test/frame_test.dart | 154 ++++++++---------- pkgs/stack_trace/test/trace_test.dart | 226 +++++++++++++------------- 8 files changed, 204 insertions(+), 243 deletions(-) diff --git a/pkgs/stack_trace/.gitignore b/pkgs/stack_trace/.gitignore index 34595d725..f0230158a 100644 --- a/pkgs/stack_trace/.gitignore +++ b/pkgs/stack_trace/.gitignore @@ -1,4 +1,4 @@ -# See https://www.dartlang.org/guides/libraries/private-files +# See https://dart.dev/guides/libraries/private-files # Don’t commit the following directories created by pub. .dart_tool/ .packages diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 3f0837424..19c6daa69 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -7,7 +7,7 @@ the native [StackTrace] implementation. using `Trace.current`. Native [StackTrace]s can also be directly converted to human-readable strings using `Trace.format`. -[StackTrace]: https://api.dartlang.org/stable/dart-core/StackTrace-class.html +[StackTrace]: https://api.dart.dev/stable/dart-core/StackTrace-class.html Here's an example native stack trace from debugging this library: @@ -202,4 +202,4 @@ this: That's a lot easier to understand! -[Zone]: https://api.dartlang.org/stable/dart-async/Zone-class.html +[Zone]: https://api.dart.dev/stable/dart-async/Zone-class.html diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 602b90c09..6b2eec5a1 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -195,7 +195,7 @@ class Chain implements StackTrace { /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to /// convert JavaScript traces into Dart-style traces. /// - /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace + /// [source_map_stack_trace]: https://pub.dev/packages/source_map_stack_trace Chain get terse => foldFrames((_) => false, terse: true); /// Returns a new [Chain] based on [this] where multiple stack frames matching diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 34108f3cf..1f5533d5a 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -13,33 +13,33 @@ import 'unparsed_frame.dart'; final _vmFrame = RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // at Object.stringify (native) -// at VW.call$0 (http://pub.dartlang.org/stuff.dart.js:560:28) +// at VW.call$0 (https://example.com/stuff.dart.js:560:28) // at VW.call$0 (eval as fn -// (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28) -// at http://pub.dartlang.org/stuff.dart.js:560:28 +// (https://example.com/stuff.dart.js:560:28), efn:3:28) +// at https://example.com/stuff.dart.js:560:28 final _v8Frame = RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); -// http://pub.dartlang.org/stuff.dart.js:560:28 +// https://example.com/stuff.dart.js:560:28 final _v8UrlLocation = RegExp(r'^(.*):(\d+):(\d+)|native$'); -// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28), efn:3:28 -// eval as function (http://pub.dartlang.org/stuff.dart.js:560:28) +// eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28 +// eval as function (https://example.com/stuff.dart.js:560:28) // eval as function (eval as otherFunction -// (http://pub.dartlang.org/stuff.dart.js:560:28)) +// (https://example.com/stuff.dart.js:560:28)) final _v8EvalLocation = RegExp(r'^eval at (?:\S.*?) \((.*)\)(?:, .*?:\d+:\d+)?$'); -// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 -// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 +// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 +// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 final _firefoxEvalLocation = RegExp(r'(\S+)@(\S+) line (\d+) >.* (Function|eval):\d+:\d+'); -// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560 -// .VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560 -// .VW.call$0/name<@http://pub.dartlang.org/stuff.dart.js:560 -// .VW.call$0@http://pub.dartlang.org/stuff.dart.js:560:36 -// http://pub.dartlang.org/stuff.dart.js:560 +// .VW.call$0@https://example.com/stuff.dart.js:560 +// .VW.call$0("arg")@https://example.com/stuff.dart.js:560 +// .VW.call$0/name<@https://example.com/stuff.dart.js:560 +// .VW.call$0@https://example.com/stuff.dart.js:560:36 +// https://example.com/stuff.dart.js:560 final _firefoxSafariFrame = RegExp(r'^' r'(?:' // Member description. Not present in some Safari frames. r'([^@(/]*)' // The actual name of the member. @@ -57,7 +57,7 @@ final _firefoxSafariFrame = RegExp(r'^' // foo/bar.dart 10:11 Foo._bar // foo/bar.dart 10:11 (anonymous function).dart.fn -// http://dartlang.org/foo/bar.dart Foo._bar +// https://dart.dev/foo/bar.dart Foo._bar // data:... 10:11 Foo._bar final _friendlyFrame = RegExp(r'^(\S+)(?: (\d+)(?::(\d+))?)?\s+([^\d].*)$'); @@ -213,8 +213,8 @@ class Frame { /// Parses a Firefox 'eval' or 'function' stack frame. /// /// for example: - /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 - /// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 + /// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 + /// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 factory Frame._parseFirefoxEval(String frame) => _catchFormatException(frame, () { final match = _firefoxEvalLocation.firstMatch(frame); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index df5d455bf..96902a1a6 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -32,8 +32,8 @@ final _v8TraceLine = RegExp(r' ?at '); /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack /// /// These stack traces looks like: -/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 -/// anonymous/<@http://pub.dartlang.org/stuff.js line 693 > eval:3:40 +/// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 +/// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 final _firefoxEvalTrace = RegExp(r'@\S+ line \d+ >.* (Function|eval):\d+:\d+'); /// A RegExp to match Firefox and Safari's stack traces. @@ -43,7 +43,7 @@ final _firefoxEvalTrace = RegExp(r'@\S+ line \d+ >.* (Function|eval):\d+:\d+'); /// /// Firefox's trace frames start with the name of the function in which the /// error occurred, possibly including its parameters inside `()`. For example, -/// `.VW.call$0("arg")@http://pub.dartlang.org/stuff.dart.js:560`. +/// `.VW.call$0("arg")@https://example.com/stuff.dart.js:560`. /// /// Safari traces occasionally don't include the initial method name followed by /// "@", and they always have both the line and column number (or just a @@ -264,7 +264,7 @@ class Trace implements StackTrace { /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to /// convert JavaScript traces into Dart-style traces. /// - /// [source_map_stack_trace]: https://pub.dartlang.org/packages/source_map_stack_trace + /// [source_map_stack_trace]: https://pub.dev/packages/source_map_stack_trace /// /// For custom folding, see [foldFrames]. Trace get terse => foldFrames((_) => false, terse: true); diff --git a/pkgs/stack_trace/lib/stack_trace.dart b/pkgs/stack_trace/lib/stack_trace.dart index 8a6ba9b51..fad30ce26 100644 --- a/pkgs/stack_trace/lib/stack_trace.dart +++ b/pkgs/stack_trace/lib/stack_trace.dart @@ -2,23 +2,6 @@ // 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. -/// Stack trace generation and parsing. -/// -/// ## Installing ## -/// -/// Use [pub][] to install this package. Add the following to your `pubspec.yaml` -/// file. -/// -/// dependencies: -/// stack_trace: any -/// -/// Then run `pub install`. -/// -/// For more information, see the -/// [stack_trace package on pub.dartlang.org][pkg]. -/// -/// [pub]: http://pub.dartlang.org -/// [pkg]: http://pub.dartlang.org/packages/stack_trace export 'src/chain.dart'; export 'src/frame.dart'; export 'src/trace.dart'; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 25487c9e7..b8b675498 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -82,9 +82,8 @@ void main() { test('parses a stack frame correctly', () { var frame = Frame.parseV8(' at VW.call\$0 ' - '(http://pub.dartlang.org/stuff.dart.js:560:28)'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(https://example.com/stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); @@ -138,9 +137,8 @@ void main() { test('parses an anonymous stack frame correctly', () { var frame = - Frame.parseV8(' at http://pub.dartlang.org/stuff.dart.js:560:28'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + Frame.parseV8(' at https://example.com/stuff.dart.js:560:28'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('')); @@ -158,9 +156,8 @@ void main() { // Ignore "[as ...]", since other stack trace formats don't support a // similar construct. var frame = Frame.parseV8(' at VW.call\$0 [as call\$4] ' - '(http://pub.dartlang.org/stuff.dart.js:560:28)'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(https://example.com/stuff.dart.js:560:28)'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('VW.call\$0')); @@ -168,9 +165,8 @@ void main() { test('parses a basic eval stack frame correctly', () { var frame = Frame.parseV8(' at eval (eval at ' - '(http://pub.dartlang.org/stuff.dart.js:560:28))'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(https://example.com/stuff.dart.js:560:28))'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); @@ -178,9 +174,8 @@ void main() { test('parses an IE10 eval stack frame correctly', () { var frame = Frame.parseV8(' at eval (eval at Anonymous function ' - '(http://pub.dartlang.org/stuff.dart.js:560:28))'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(https://example.com/stuff.dart.js:560:28))'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); @@ -188,9 +183,8 @@ void main() { test('parses an eval stack frame with inner position info correctly', () { var frame = Frame.parseV8(' at eval (eval at ' - '(http://pub.dartlang.org/stuff.dart.js:560:28), :3:28)'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(https://example.com/stuff.dart.js:560:28), :3:28)'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); @@ -198,9 +192,8 @@ void main() { test('parses a nested eval stack frame correctly', () { var frame = Frame.parseV8(' at eval (eval at ' - '(eval at sub (http://pub.dartlang.org/stuff.dart.js:560:28)))'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '(eval at sub (https://example.com/stuff.dart.js:560:28)))'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, equals(28)); expect(frame.member, equals('eval')); @@ -237,22 +230,21 @@ void main() { group('.parseFirefox/.parseSafari', () { test('parses a Firefox stack trace with anonymous function', () { var trace = Trace.parse(''' -Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 -anonymous/<@http://pub.dartlang.org/stuff.js line 693 > Function:3:40 -baz@http://pub.dartlang.org/buz.js:56355:55 +Foo._bar@https://example.com/stuff.js:18056:12 +anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 +baz@https://pub.dev/buz.js:56355:55 '''); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[0].line, equals(18056)); expect(trace.frames[0].column, equals(12)); expect(trace.frames[0].member, equals('Foo._bar')); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].line, equals(693)); expect(trace.frames[1].column, isNull); expect(trace.frames[1].member, equals('')); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/buz.js'))); + expect(trace.frames[2].uri, equals(Uri.parse('https://pub.dev/buz.js'))); expect(trace.frames[2].line, equals(56355)); expect(trace.frames[2].column, equals(55)); expect(trace.frames[2].member, equals('baz')); @@ -261,12 +253,12 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a Firefox stack trace with nested evals in anonymous function', () { var trace = Trace.parse(''' - Foo._bar@http://pub.dartlang.org/stuff.js:18056:12 + Foo._bar@https://example.com/stuff.js:18056:12 anonymous@file:///C:/example.html line 7 > eval line 1 > eval:1:1 anonymous@file:///C:/example.html line 45 > Function:1:1 '''); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[0].line, equals(18056)); expect(trace.frames[0].column, equals(12)); expect(trace.frames[0].member, equals('Foo._bar')); @@ -282,9 +274,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a simple stack frame correctly', () { var frame = Frame.parseFirefox( - '.VW.call\$0@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '.VW.call\$0@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('VW.call\$0')); @@ -334,28 +325,23 @@ baz@http://pub.dartlang.org/buz.js:56355:55 }); test('parses a simple anonymous stack frame correctly', () { - var frame = - Frame.parseFirefox('@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + var frame = Frame.parseFirefox('@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('')); }); test('parses a nested anonymous stack frame correctly', () { - var frame = Frame.parseFirefox( - '.foo/<@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + var frame = + Frame.parseFirefox('.foo/<@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo.')); - frame = - Frame.parseFirefox('.foo/@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + frame = Frame.parseFirefox('.foo/@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo.')); @@ -363,17 +349,15 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a named nested anonymous stack frame correctly', () { var frame = Frame.parseFirefox( - '.foo/.name<@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '.foo/.name<@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo.')); frame = Frame.parseFirefox( - '.foo/.name@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '.foo/.name@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo.')); @@ -381,9 +365,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with parameters correctly', () { var frame = Frame.parseFirefox( - '.foo(12, "@)()/<")@http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + '.foo(12, "@)()/<")@https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo')); @@ -391,9 +374,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a nested anonymous stack frame with parameters correctly', () { var frame = Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' - 'http://pub.dartlang.org/stuff.dart.js:560'); - expect(frame.uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.dart.js'))); + 'https://example.com/stuff.dart.js:560'); + expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); expect(frame.member, equals('foo.')); @@ -403,9 +385,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'parses a deeply-nested anonymous stack frame with parameters ' 'correctly', () { var frame = Frame.parseFirefox('.convertDartClosureToJS/\$function.')); @@ -424,16 +405,16 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a simple stack frame correctly', () { var frame = - Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:11'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + Frame.parseFirefox('foo\$bar@https://dart.dev/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); }); test('parses an anonymous stack frame correctly', () { - var frame = Frame.parseFirefox('http://dartlang.org/foo/bar.dart:10:11'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + var frame = Frame.parseFirefox('https://dart.dev/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('')); @@ -441,8 +422,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line correctly', () { var frame = - Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart::11'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + Frame.parseFirefox('foo\$bar@https://dart.dev/foo/bar.dart::11'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); @@ -450,8 +431,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no column correctly', () { var frame = - Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + Frame.parseFirefox('foo\$bar@https://dart.dev/foo/bar.dart:10:'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, isNull); expect(frame.member, equals('foo\$bar')); @@ -459,8 +440,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line or column correctly', () { var frame = - Frame.parseFirefox('foo\$bar@http://dartlang.org/foo/bar.dart:10:11'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + Frame.parseFirefox('foo\$bar@https://dart.dev/foo/bar.dart:10:11'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('foo\$bar')); @@ -470,8 +451,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 group('.parseFriendly', () { test('parses a simple stack frame correctly', () { var frame = Frame.parseFriendly( - 'http://dartlang.org/foo/bar.dart 10:11 Foo..bar'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + 'https://dart.dev/foo/bar.dart 10:11 Foo..bar'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, equals(11)); expect(frame.member, equals('Foo..bar')); @@ -479,17 +460,17 @@ baz@http://pub.dartlang.org/buz.js:56355:55 test('parses a stack frame with no line or column correctly', () { var frame = - Frame.parseFriendly('http://dartlang.org/foo/bar.dart Foo..bar'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + Frame.parseFriendly('https://dart.dev/foo/bar.dart Foo..bar'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('Foo..bar')); }); test('parses a stack frame with no column correctly', () { - var frame = Frame.parseFriendly( - 'http://dartlang.org/foo/bar.dart 10 Foo..bar'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + var frame = + Frame.parseFriendly('https://dart.dev/foo/bar.dart 10 Foo..bar'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, equals(10)); expect(frame.column, isNull); expect(frame.member, equals('Foo..bar')); @@ -541,8 +522,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'parses a stack frame with spaces in the member name and no line or ' 'column correctly', () { var frame = Frame.parseFriendly( - 'http://dartlang.org/foo/bar.dart (anonymous function).dart.fn'); - expect(frame.uri, equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + 'https://dart.dev/foo/bar.dart (anonymous function).dart.fn'); + expect(frame.uri, equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(frame.line, isNull); expect(frame.column, isNull); expect(frame.member, equals('(anonymous function).dart.fn')); @@ -569,9 +550,9 @@ baz@http://pub.dartlang.org/buz.js:56355:55 equals('dart:async/future.dart')); expect( Frame.parseVM('#0 Foo ' - '(http://dartlang.org/stuff/thing.dart:0:0)') + '(https://dart.dev/stuff/thing.dart:0:0)') .library, - equals('http://dartlang.org/stuff/thing.dart')); + equals('https://dart.dev/stuff/thing.dart')); }); test('returns the relative path for file URIs', () { @@ -592,9 +573,9 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'libraries', () { expect( Frame.parseVM('#0 Foo ' - '(http://dartlang.org/thing.dart:5:10)') + '(https://dart.dev/thing.dart:5:10)') .location, - equals('http://dartlang.org/thing.dart 5:10')); + equals('https://dart.dev/thing.dart 5:10')); expect(Frame.parseVM('#0 Foo (foo/bar.dart:1:2)').location, equals('${path.join('foo', 'bar.dart')} 1:2')); }); @@ -606,7 +587,7 @@ baz@http://pub.dartlang.org/buz.js:56355:55 Frame.parseVM('#0 Foo (dart:async/future.dart:0:0)').package, isNull); expect( Frame.parseVM('#0 Foo ' - '(http://dartlang.org/stuff/thing.dart:0:0)') + '(https://dart.dev/stuff/thing.dart:0:0)') .package, isNull); }); @@ -624,9 +605,8 @@ baz@http://pub.dartlang.org/buz.js:56355:55 'returns the library and line/column numbers for non-core ' 'libraries', () { expect( - Frame.parseVM('#0 Foo (http://dartlang.org/thing.dart:5:10)') - .toString(), - equals('http://dartlang.org/thing.dart 5:10 in Foo')); + Frame.parseVM('#0 Foo (https://dart.dev/thing.dart:5:10)').toString(), + equals('https://dart.dev/thing.dart 5:10 in Foo')); }); test('converts "" to ""', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 33a077dae..561dec78f 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -19,71 +19,71 @@ void main() { var trace = Trace.parse( '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' '#1 zip..zap (dart:async/future.dart:0:2)\n' - '#2 zip..zap (http://pub.dartlang.org/thing.' + '#2 zip..zap (https://pub.dev/thing.' 'dart:1:100)'); expect(trace.frames[0].uri, equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); expect(trace.frames[1].uri, equals(Uri.parse('dart:async/future.dart'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.dart'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.dart'))); }); test('parses a V8 stack trace correctly', () { var trace = Trace.parse('Error\n' - ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at Foo._bar (https://example.com/stuff.js:42:21)\n' + ' at https://example.com/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); trace = Trace.parse('Exception: foo\n' - ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at Foo._bar (https://example.com/stuff.js:42:21)\n' + ' at https://example.com/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); trace = Trace.parse('Exception: foo\n' ' bar\n' - ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at Foo._bar (https://example.com/stuff.js:42:21)\n' + ' at https://example.com/stuff.js:0:2\n' ' at zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); trace = Trace.parse('Exception: foo\n' ' bar\n' - ' at Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - ' at http://pub.dartlang.org/stuff.js:0:2\n' + ' at Foo._bar (https://example.com/stuff.js:42:21)\n' + ' at https://example.com/stuff.js:0:2\n' ' at (anonymous function).zip.zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].member, equals('')); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); expect(trace.frames[2].member, equals('.zip.zap')); }); @@ -91,155 +91,153 @@ void main() { // header and it starts with a tab rather than spaces. test('parses a JavaScriptCore stack trace correctly', () { var trace = - Trace.parse('\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - '\tat http://pub.dartlang.org/stuff.js:0:2\n' + Trace.parse('\tat Foo._bar (https://example.com/stuff.js:42:21)\n' + '\tat https://example.com/stuff.js:0:2\n' '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); - trace = - Trace.parse('\tat Foo._bar (http://pub.dartlang.org/stuff.js:42:21)\n' - '\tat \n' - '\tat zip..zap ' - '(http://pub.dartlang.org/thing.js:1:100)'); + trace = Trace.parse('\tat Foo._bar (https://example.com/stuff.js:42:21)\n' + '\tat \n' + '\tat zip..zap ' + '(https://pub.dev/thing.js:1:100)'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[1].uri, equals(Uri.parse('https://pub.dev/thing.js'))); }); test('parses a Firefox/Safari stack trace correctly', () { - var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' + 'zip/<@https://example.com/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); - trace = Trace.parse('zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + trace = Trace.parse('zip/<@https://example.com/stuff.js:0\n' + 'Foo._bar@https://example.com/stuff.js:42\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); - trace = Trace.parse( - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'Foo._bar@http://pub.dartlang.org/stuff.js:42'); + trace = Trace.parse('zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1\n' + 'zip/<@https://example.com/stuff.js:0\n' + 'Foo._bar@https://example.com/stuff.js:42'); - expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + expect( + trace.frames[0].uri, equals(Uri.parse('https://pub.dev/thing.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); }); test('parses a Firefox/Safari stack trace containing native code correctly', () { - var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1\n' + var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' + 'zip/<@https://example.com/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1\n' '[native code]'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); expect(trace.frames.length, equals(3)); }); test('parses a Firefox/Safari stack trace without a method name correctly', () { - var trace = Trace.parse('http://pub.dartlang.org/stuff.js:42\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('https://example.com/stuff.js:42\n' + 'zip/<@https://example.com/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[0].member, equals('')); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); }); test('parses a Firefox/Safari stack trace with an empty line correctly', () { - var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42\n' + var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42\n' '\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + 'zip/<@https://example.com/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); }); test('parses a Firefox/Safari stack trace with a column number correctly', () { - var trace = Trace.parse('Foo._bar@http://pub.dartlang.org/stuff.js:42:2\n' - 'zip/<@http://pub.dartlang.org/stuff.js:0\n' - 'zip.zap(12, "@)()/<")@http://pub.dartlang.org/thing.js:1'); + var trace = Trace.parse('Foo._bar@https://example.com/stuff.js:42:2\n' + 'zip/<@https://example.com/stuff.js:0\n' + 'zip.zap(12, "@)()/<")@https://pub.dev/thing.js:1'); expect(trace.frames[0].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); expect(trace.frames[0].line, equals(42)); expect(trace.frames[0].column, equals(2)); expect(trace.frames[1].uri, - equals(Uri.parse('http://pub.dartlang.org/stuff.js'))); - expect(trace.frames[2].uri, - equals(Uri.parse('http://pub.dartlang.org/thing.js'))); + equals(Uri.parse('https://example.com/stuff.js'))); + expect( + trace.frames[2].uri, equals(Uri.parse('https://pub.dev/thing.js'))); }); test('parses a package:stack_trace stack trace correctly', () { var trace = - Trace.parse('http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/baz.dart Foo..bar'); + Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/baz.dart Foo..bar'); expect(trace.frames[0].uri, - equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://dartlang.org/foo/baz.dart'))); + equals(Uri.parse('https://dart.dev/foo/baz.dart'))); }); test('parses a package:stack_trace stack chain correctly', () { var trace = - Trace.parse('http://dartlang.org/foo/bar.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/baz.dart Foo..bar\n' + Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/baz.dart Foo..bar\n' '===== asynchronous gap ===========================\n' - 'http://dartlang.org/foo/bang.dart 10:11 Foo..bar\n' - 'http://dartlang.org/foo/quux.dart Foo..bar'); + 'https://dart.dev/foo/bang.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/quux.dart Foo..bar'); expect(trace.frames[0].uri, - equals(Uri.parse('http://dartlang.org/foo/bar.dart'))); + equals(Uri.parse('https://dart.dev/foo/bar.dart'))); expect(trace.frames[1].uri, - equals(Uri.parse('http://dartlang.org/foo/baz.dart'))); + equals(Uri.parse('https://dart.dev/foo/baz.dart'))); expect(trace.frames[2].uri, - equals(Uri.parse('http://dartlang.org/foo/bang.dart'))); + equals(Uri.parse('https://dart.dev/foo/bang.dart'))); expect(trace.frames[3].uri, - equals(Uri.parse('http://dartlang.org/foo/quux.dart'))); + equals(Uri.parse('https://dart.dev/foo/quux.dart'))); }); test('parses a real package:stack_trace stack trace correctly', () { @@ -258,13 +256,13 @@ void main() { var trace = Trace.parse(''' #0 Foo._bar (foo/bar.dart:42:21) #1 zip..zap (dart:async/future.dart:0:2) -#2 zip..zap (http://pub.dartlang.org/thing.dart:1:100) +#2 zip..zap (https://pub.dev/thing.dart:1:100) '''); expect(trace.toString(), equals(''' -${path.join('foo', 'bar.dart')} 42:21 Foo._bar -dart:async/future.dart 0:2 zip..zap -http://pub.dartlang.org/thing.dart 1:100 zip..zap +${path.join('foo', 'bar.dart')} 42:21 Foo._bar +dart:async/future.dart 0:2 zip..zap +https://pub.dev/thing.dart 1:100 zip..zap ''')); }); @@ -272,14 +270,14 @@ http://pub.dartlang.org/thing.dart 1:100 zip..zap var uri = path.toUri(path.absolute('foo')); var trace = Trace([ Frame(uri, 10, 20, 'Foo.'), - Frame(Uri.parse('http://dartlang.org/foo.dart'), null, null, 'bar'), + Frame(Uri.parse('https://dart.dev/foo.dart'), null, null, 'bar'), Frame(Uri.parse('dart:async'), 15, null, 'baz'), ]); expect( trace.vmTrace.toString(), equals('#1 Foo. ($uri:10:20)\n' - '#2 bar (http://dartlang.org/foo.dart:0:0)\n' + '#2 bar (https://dart.dev/foo.dart:0:0)\n' '#3 baz (dart:async:15:0)\n')); }); From 2131174b92a31faabcc8136ad88b41917c6912ee Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 22 Apr 2020 15:36:12 -0700 Subject: [PATCH 0645/1215] Prepare to publish (dart-lang/watcher#89) --- pkgs/watcher/CHANGELOG.md | 6 +++--- pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 74565902a..a65a6e3b2 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,4 +1,4 @@ -# 0.9.7+15-dev +# 0.9.7+15 * Fix a bug on Mac where modifying a directory with a path exactly matching a prefix of a modified file would suppress change events for that file. @@ -36,7 +36,7 @@ # 0.9.7+7 -* Updates to support Dart 2.0 core library changes (wave 2.2). +* Updates to support Dart 2.0 core library changes (wave 2.2). See [issue 31847][sdk#31847] for details. [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 @@ -44,7 +44,7 @@ # 0.9.7+6 -* Internal changes only, namely removing dep on scheduled test. +* Internal changes only, namely removing dep on scheduled test. # 0.9.7+5 diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 230b00b2c..e86192dd8 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.7+15-dev +version: 0.9.7+15 description: >- A file system watcher. It monitors changes to contents of directories and From 231a6b4a8e956d2f317229ced3715f1fb4c44bcb Mon Sep 17 00:00:00 2001 From: Sinegovsky Ivan Date: Fri, 24 Apr 2020 07:23:10 +0300 Subject: [PATCH 0646/1215] ability to parse chrome eval exceptions (dart-lang/stack_trace#56) Ability to parse chrome eval exceptions --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 9 ++++++--- pkgs/stack_trace/pubspec.yaml | 3 ++- pkgs/stack_trace/test/frame_test.dart | 2 -- pkgs/stack_trace/test/trace_test.dart | 9 +++++++++ 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 39e7fb3b3..d64052bad 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.5-dev + +* ability to parse chrome eval exceptions + ## 1.9.4-dev * Added support for firefox anonymous stack traces diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 1f5533d5a..fd7f8ebb8 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -21,7 +21,8 @@ final _v8Frame = RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // https://example.com/stuff.dart.js:560:28 -final _v8UrlLocation = RegExp(r'^(.*):(\d+):(\d+)|native$'); +// http://pub.dartlang.org/stuff.dart.js:560 +final _v8UrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?|native$'); // eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28 // eval as function (https://example.com/stuff.dart.js:560:28) @@ -179,8 +180,10 @@ class Frame { var urlMatch = _v8UrlLocation.firstMatch(location); if (urlMatch == null) return UnparsedFrame(frame); - return Frame(_uriOrPathToUri(urlMatch[1]), int.parse(urlMatch[2]), - int.parse(urlMatch[3]), member); + final uri = _uriOrPathToUri(urlMatch[1]); + final line = int.parse(urlMatch[2]); + final column = urlMatch[3] != null ? int.parse(urlMatch[3]) : null; + return Frame(uri, line, column, member); } // V8 stack frames can be in two forms. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index d16cbf979..6f0b89e45 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,6 @@ name: stack_trace -version: 1.9.4-dev +version: 1.9.5-dev + description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index b8b675498..ce7b7caff 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -220,8 +220,6 @@ void main() { (text) => Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); expectIsUnparsed( (text) => Frame.parseV8(text), ' at dart:async/future.dart'); - expectIsUnparsed( - (text) => Frame.parseV8(text), ' at dart:async/future.dart:10'); expectIsUnparsed( (text) => Frame.parseV8(text), 'dart:async/future.dart:10:15'); }); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 561dec78f..ec7b074d5 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -15,6 +15,15 @@ void main() { test('a native stack trace is parseable', () => Trace.current()); group('.parse', () { + test('.parse parses a V8 stack trace with eval statment correctly', () { + var trace = Trace.parse(r'''Error + at Object.eval (eval at Foo (main.dart.js:588), :3:47)'''); + expect(trace.frames[0].uri, Uri.parse('main.dart.js')); + expect(trace.frames[0].member, equals('Object.eval')); + expect(trace.frames[0].line, equals(588)); + expect(trace.frames[0].column, isNull); + }); + test('.parse parses a VM stack trace correctly', () { var trace = Trace.parse( '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' From 4ddf84d408247fb5198fbd480a93c6eb28011f96 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 28 Apr 2020 16:10:01 -0700 Subject: [PATCH 0647/1215] Add a reason to a flaky assert (dart-lang/watcher#88) We have seen a case of this assert failing on linux on travis. Add a reason which includes the path to hopefully get more information if we see it again. --- pkgs/watcher/test/utils.dart | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index fe86407e2..06d1a1267 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -55,12 +55,13 @@ StreamQueue _watcherEvents; /// If [path] is provided, watches a path in the sandbox with that name. Future startWatcher({String path}) async { mockGetModificationTime((path) { - path = p.normalize(p.relative(path, from: d.sandbox)); + final normalized = p.normalize(p.relative(path, from: d.sandbox)); // Make sure we got a path in the sandbox. - assert(p.isRelative(path) && !path.startsWith('..')); + assert(p.isRelative(normalized) && !normalized.startsWith('..'), + 'Path is not in the sandbox: $path not in ${d.sandbox}'); - var mtime = _mockFileModificationTimes[path]; + var mtime = _mockFileModificationTimes[normalized]; return DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); }); From 4ab721f7d6c30de630742c1a89c57d69304e3318 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 30 Apr 2020 09:09:45 -0700 Subject: [PATCH 0648/1215] Fix parsing for URIs with a : in the authority (dart-lang/stack_trace#69) Add a `$` to enforce that the `:(\d+)` is at the end of the String. The previous regex could pick up too little - we end up with `http://localhost` as the URI and the port as the line. Switch from `pub.dartlang.org` to `example.com` to avoid references to legacy URLs. --- pkgs/stack_trace/lib/src/frame.dart | 4 ++-- pkgs/stack_trace/test/frame_test.dart | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index fd7f8ebb8..3225efd26 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -21,8 +21,8 @@ final _v8Frame = RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // https://example.com/stuff.dart.js:560:28 -// http://pub.dartlang.org/stuff.dart.js:560 -final _v8UrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?|native$'); +// https://example.com/stuff.dart.js:560 +final _v8UrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?$|native$'); // eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28 // eval as function (https://example.com/stuff.dart.js:560:28) diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index ce7b7caff..1aa012d57 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -89,6 +89,16 @@ void main() { expect(frame.member, equals('VW.call\$0')); }); + test('parses a stack frame with a : in the authority', () { + var frame = Frame.parseV8(' at VW.call\$0 ' + '(http://localhost:8080/stuff.dart.js:560:28)'); + expect( + frame.uri, equals(Uri.parse('http://localhost:8080/stuff.dart.js'))); + expect(frame.line, equals(560)); + expect(frame.column, equals(28)); + expect(frame.member, equals('VW.call\$0')); + }); + test('parses a stack frame with an absolute POSIX path correctly', () { var frame = Frame.parseV8(' at VW.call\$0 ' '(/path/to/stuff.dart.js:560:28)'); From 207c71ed31ed8bdeac2309f229d17f8da9c34f05 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 30 Apr 2020 11:04:46 -0700 Subject: [PATCH 0649/1215] Prepare to publish (dart-lang/stack_trace#70) - Merge 2 recent `-dev` changelog sections into one. - Drop the `-dev` in the version. - Minor cleanup in the changelog. Use present tense and format with periods at the end of sentences. --- pkgs/stack_trace/CHANGELOG.md | 9 +++------ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index d64052bad..c9e562a04 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,10 +1,7 @@ -## 1.9.5-dev +## 1.9.4 -* ability to parse chrome eval exceptions - -## 1.9.4-dev - -* Added support for firefox anonymous stack traces +* Add support for firefox anonymous stack traces. +* Add support for chrome eval stack traces without a column. * Change the argument type to `Chain.capture` from `Function(dynamic, Chain)` to `Function(Object, Chain)`. Existing functions which take `dynamic` are still fine, but new uses can have a safer type. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 6f0b89e45..6eeb64595 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.9.5-dev +version: 1.9.4 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace From e437a224b092e78d5e6557d9ff51a4326addd2ee Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 May 2020 09:42:50 -0700 Subject: [PATCH 0650/1215] Update URLs to point to pub.dev (dart-lang/term_glyph#11) - Point links at `pub.dev` instead of `dartdocs.org`. - Remove unused `author` field from pubspec. --- pkgs/term_glyph/README.md | 2 +- pkgs/term_glyph/pubspec.yaml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md index 0d5b78c79..0d64ced35 100644 --- a/pkgs/term_glyph/README.md +++ b/pkgs/term_glyph/README.md @@ -22,7 +22,7 @@ characters instead. It currently defaults to `false`, although in the future it may default to `true` for applications running on the Dart VM on Windows. For example: -[ascii]: https://www.dartdocs.org/documentation/term_glyph/latest/term_glyph/ascii.html +[ascii]: https://pub.dev/documentation/term_glyph/latest/term_glyph/ascii.html ```dart import 'dart:io'; diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 9c650e3f1..06d09d5ac 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -2,7 +2,6 @@ name: term_glyph version: 1.1.1-dev description: Useful Unicode glyphs and ASCII substitutes. -author: Dart Team homepage: https://github.com/dart-lang/term_glyph environment: From 6aa8aeb01e8ad0bac4e5e254e80a65ebee175d48 Mon Sep 17 00:00:00 2001 From: creativecreatorormaybenot <19204050+creativecreatorormaybenot@users.noreply.github.com> Date: Wed, 27 May 2020 23:15:58 +0000 Subject: [PATCH 0651/1215] Improve docs for switchMap (dart-lang/stream_transform#109) - Expand the docs for `switchMap` and add caveats. - Crosslink between `switchMap` and `concurrentAsyncMap`. - Add test for erroring convert callback in `switchMap` --- pkgs/stream_transform/CHANGELOG.md | 2 ++ pkgs/stream_transform/lib/src/merge.dart | 11 ++++++-- pkgs/stream_transform/lib/src/switch.dart | 27 +++++++++++++++++-- pkgs/stream_transform/pubspec.yaml | 2 +- pkgs/stream_transform/test/switch_test.dart | 29 ++++++++++++++------- 5 files changed, 57 insertions(+), 14 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 5a5ea2a8c..73fc3688b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.2.1-dev +* Improve tests of `switchMap` and improve documentation with links and clarification. + ## 1.2.0 - Add support for emitting the "leading" event in `debounce`. diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index f654d35a5..afc2da4ee 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:stream_transform/src/switch.dart'; + /// Utilities to interleave events from multiple streams. extension Merge on Stream { /// Returns a stream which emits values and errors from the source stream and @@ -56,7 +58,7 @@ extension Merge on Stream { Stream mergeAll(Iterable> others) => transform(_Merge(others)); /// Like [asyncExpand] but the [convert] callback may be called for an element - /// before the Stream emitted by the previous element has closed. + /// before the [Stream] emitted by the previous element has closed. /// /// Events on the result stream will be emitted in the order they are emitted /// by the sub streams, which may not match the order of the original stream. @@ -67,7 +69,7 @@ extension Merge on Stream { /// The result stream will not close until the source stream closes and all /// sub streams have closed. /// - /// If the source stream is a broadcast stream the result will be as well, + /// If the source stream is a broadcast stream, the result will be as well, /// regardless of the types of streams created by [convert]. In this case, /// some care should be taken: /// - If [convert] returns a single subscription stream it may be listened to @@ -76,6 +78,11 @@ extension Merge on Stream { /// stream, any sub streams from previously emitted events will be ignored, /// regardless of whether they emit further events after a listener is added /// back. + /// + /// See also: + /// + /// * [switchMap], which cancels subscriptions to the previous sub + /// stream instead of concurrently emitting events from all sub streams. Stream concurrentAsyncExpand(Stream Function(T) convert) => map(convert).transform(_MergeExpanded()); } diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 5125d576b..dcd2431be 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'package:stream_transform/src/merge.dart'; + /// A utility to take events from the most recent sub stream returned by a /// callback. extension Switch on Stream { @@ -12,9 +14,30 @@ extension Switch on Stream { /// /// When the source emits a value it will be converted to a [Stream] using /// [convert] and the output will switch to emitting events from that result. + /// Like [asyncExpand] but the [Stream] emitted by a previous element + /// will be ignored as soon as the source stream emits a new event. /// - /// If the source stream is a broadcast stream, the result stream will be as - /// well, regardless of the types of the streams produced by [convert]. + /// This means that the source stream is not paused until a sub stream + /// returned from the [convert] callback is done. Instead, the subscription + /// to the sub stream is canceled as soon as the source stream emits a new event. + /// + /// Errors from [convert], the source stream, or any of the sub streams are + /// forwarded to the result stream. + /// + /// The result stream will not close until the source stream closes and + /// the current sub stream have closed. + /// + /// If the source stream is a broadcast stream, the result will be as well, + /// regardless of the types of streams created by [convert]. In this case, + /// some care should be taken: + /// + /// * If [convert] returns a single subscription stream it may be listened to + /// and never canceled. + /// + /// See also: + /// + /// * [concurrentAsyncExpand], which emits events from all sub streams + /// concurrently instead of cancelling subscriptions to previous subs streams. Stream switchMap(Stream Function(T) convert) { return map(convert).switchLatest(); } diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 8279c44fa..c566c1632 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,6 +1,6 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. -homepage: https://www.github.com/dart-lang/stream_transform +homepage: https://github.com/dart-lang/stream_transform version: 1.2.1-dev environment: diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 40030f0d2..16deb4bb3 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -145,18 +145,29 @@ void main() { expect(transformed.isBroadcast, true); }); - }); - test('handles null response from cancel', () async { - var outer = StreamController>(); - var inner = StreamController(); + test('handles null response from cancel', () async { + var outer = StreamController>(); + var inner = StreamController(); + + var subscription = + NullOnCancelStream(outer.stream).switchLatest().listen(null); - var subscription = - NullOnCancelStream(outer.stream).switchLatest().listen(null); + outer.add(NullOnCancelStream(inner.stream)); + await Future(() {}); - outer.add(NullOnCancelStream(inner.stream)); - await Future(() {}); + await subscription.cancel(); + }); - await subscription.cancel(); + test('forwards errors from the convert callback', () async { + var errors = []; + var source = Stream.fromIterable([1, 2, 3]); + source.switchMap((i) { + // ignore: only_throw_errors + throw 'Error: $i'; + }).listen((_) {}, onError: errors.add); + await Future(() {}); + expect(errors, ['Error: 1', 'Error: 2', 'Error: 3']); + }); }); } From ce1af790abbe55f3b7a5a050f6ab1091f22e6ccb Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 4 Jun 2020 17:27:16 -0700 Subject: [PATCH 0652/1215] remove redundant arg --- pkgs/pubspec_parse/test/test_utils.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 00196bb11..e51f19863 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -40,7 +40,7 @@ void _printDebugParsedYamlException(ParsedYamlException e) { if (innerError != null) { final items = [innerError]; if (innerStack != null) { - items.add(Trace.format(innerStack, terse: true)); + items.add(Trace.format(innerStack)); } final content = From e11a46d989cd89350766aa830269146b4065c42b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jun 2020 15:05:06 -0700 Subject: [PATCH 0653/1215] Readme: badgese for travis and package version (dart-lang/stream_transform#110) --- pkgs/stream_transform/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 56d114a7c..187a43b14 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,3 +1,6 @@ +[![Build Status](https://travis-ci.org/dart-lang/stream_transform.svg?branch=master)](https://travis-ci.org/dart-lang/stream_transform) +[![Pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) + Extension methods on `Stream` adding common transform operators. # Operators From c0329f1666563f54978e14cf57197688101e6a39 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 30 Jun 2020 10:48:20 -0700 Subject: [PATCH 0654/1215] Handle new style VM data URI frames (dart-lang/stack_trace#73) See https://github.com/dart-lang/test/issues/1261 Somewhere between Dart `2.1.0` and Dart `2.2.0` the output from the VM for stack frames in `data:` URIs changed. The new format wraps with `<>` and does not include the full URI. Check specifically whether the matched "uri" is instead a truncated and bracketed `data:` URI and treat it as if it were a valid empty data URI. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/frame.dart | 4 +++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/frame_test.dart | 8 +++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index c9e562a04..2f189e695 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.9.5 + +* Parse the format for `data:` URIs that the Dart VM has used since `2.2.0`. + ## 1.9.4 * Add support for firefox anonymous stack traces. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 3225efd26..7ffc05f08 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -149,7 +149,9 @@ class Frame { var member = match[1] .replaceAll(_asyncBody, '') .replaceAll('', ''); - var uri = Uri.parse(match[2]); + var uri = match[2].startsWith(':1:15)'); + expect(frame.library, equals('data:...')); + }); }); group('.location', () { From 524268d390de78f82a396747f100321f35115be5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 6 Jul 2020 15:38:03 -0700 Subject: [PATCH 0655/1215] Bump min Dart SDK to 2.7 (dart-lang/pubspec_parse#59) Works-around issue with testing Dart 2.6 in CI and changes to pkg:analyzer --- pkgs/pubspec_parse/.travis.yml | 4 ++-- pkgs/pubspec_parse/CHANGELOG.md | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml index 66bff3db8..802491f97 100644 --- a/pkgs/pubspec_parse/.travis.yml +++ b/pkgs/pubspec_parse/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: - - 2.6.0 + - 2.7.0 - dev dart_task: @@ -16,7 +16,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.6.0 + - dart: 2.7.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index df5c0e827..7e74a5575 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.1.6-dev -- Update SDK requirement to `>=2.6.0 <3.0.0`. +- Update SDK requirement to `>=2.7.0 <3.0.0`. ## 0.1.5 diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 2940ce3f9..09d2fb9b5 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -6,7 +6,7 @@ version: 0.1.6-dev homepage: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.6.0 <3.0.0' + sdk: '>=2.7.0 <3.0.0' dependencies: checked_yaml: ^1.0.0 From 7f0ec30a03975acecb8c0ab2698733941245e2e6 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 14 Jul 2020 13:11:18 -0700 Subject: [PATCH 0656/1215] merge null safety branch into master (dart-lang/term_glyph#13) --- pkgs/term_glyph/.travis.yml | 34 +++++++++----- pkgs/term_glyph/CHANGELOG.md | 4 ++ pkgs/term_glyph/analysis_options.yaml | 3 ++ pkgs/term_glyph/pubspec.yaml | 68 +++++++++++++++++++++++++-- pkgs/term_glyph/tool/generate.dart | 3 +- 5 files changed, 95 insertions(+), 17 deletions(-) diff --git a/pkgs/term_glyph/.travis.yml b/pkgs/term_glyph/.travis.yml index 31cbd43ad..8fd288834 100644 --- a/pkgs/term_glyph/.travis.yml +++ b/pkgs/term_glyph/.travis.yml @@ -1,23 +1,33 @@ language: dart dart: - - dev - - stable +- dev -dart_task: - - test - -matrix: +jobs: include: - # Only validate formatting,analyzer using the dev release - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: dartanalyzer + - stage: analyze_and_format + name: "Analyze test/" + dart: dev + os: linux + script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + - stage: analyze_and_format + name: "Format" + dart: dev + os: linux + script: dartfmt -n --set-exit-if-changed . + - stage: test + name: "Vm Tests" + dart: dev + os: linux + script: pub run --enable-experiment=non-nullable test -p vm + +stages: + - analyze_and_format + - test # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 7b73fc851..c4926bd8b 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0-nullsafety + +* Update to null safety. All apis require non-nullable types. + ## 1.1.0 * Add a `GlyphSet` class that can be used to easily choose which set of glyphs diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index 108d1058a..64ff556c6 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1 +1,4 @@ include: package:pedantic/analysis_options.yaml +analyzer: + enable-experiment: + - non-nullable diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 06d09d5ac..ace629c54 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,14 +1,76 @@ name: term_glyph -version: 1.1.1-dev +version: 1.2.0-nullsafety description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: - sdk: '>=1.8.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dev_dependencies: csv: '>=3.0.0 <5.0.0' dart_style: '>=0.2.0 <2.0.0' - meta: '>=0.9.0 <2.0.0' test: '>=0.12.0 <2.0.0' + +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + collection: 1.15.0-nullsafety + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: 1.3.0-nullsafety + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + pool: + git: + url: git://github.com/dart-lang/pool.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stack_trace: + git: + url: git://github.com/dart-lang/stack_trace.git + ref: null_safety + stream_channel: + git: + url: git://github.com/dart-lang/stream_channel.git + ref: null_safety + string_scanner: + git: + url: git://github.com/dart-lang/string_scanner.git + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_core + test: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 6e18536f0..0a1136ecf 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -5,7 +5,6 @@ import 'dart:io'; import 'package:csv/csv.dart'; -import 'package:meta/meta.dart'; void main() { var csv = CsvCodec(eol: '\n'); @@ -83,7 +82,7 @@ void _writeGlyphSetInterface(List data) { /// /// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes /// the Unicode glyph set. -void _writeGlyphSet(List data, {@required bool ascii}) { +void _writeGlyphSet(List data, {required bool ascii}) { var file = File('lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart') .openSync(mode: FileMode.write); From d647cdbb68101b7c5892ec20fc4a544c352528b0 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 14 Jul 2020 15:46:27 -0700 Subject: [PATCH 0657/1215] Merge null_safety branch into master (dart-lang/stack_trace#77) --- pkgs/stack_trace/.travis.yml | 40 +++++----- pkgs/stack_trace/CHANGELOG.md | 4 + pkgs/stack_trace/analysis_options.yaml | 2 + pkgs/stack_trace/lib/src/chain.dart | 27 ++++--- pkgs/stack_trace/lib/src/frame.dart | 62 +++++++-------- pkgs/stack_trace/lib/src/lazy_chain.dart | 4 +- pkgs/stack_trace/lib/src/lazy_trace.dart | 4 +- .../lib/src/stack_zone_specification.dart | 42 +++++----- pkgs/stack_trace/lib/src/trace.dart | 13 +--- pkgs/stack_trace/lib/src/unparsed_frame.dart | 6 +- pkgs/stack_trace/lib/src/vm_trace.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 77 ++++++++++++++++++- pkgs/stack_trace/test/chain/chain_test.dart | 6 +- pkgs/stack_trace/test/chain/dart2js_test.dart | 14 ++-- pkgs/stack_trace/test/chain/utils.dart | 4 +- pkgs/stack_trace/test/chain/vm_test.dart | 14 ++-- pkgs/stack_trace/test/frame_test.dart | 6 +- pkgs/stack_trace/test/trace_test.dart | 10 +-- pkgs/stack_trace/test/vm_test.dart | 8 +- 19 files changed, 211 insertions(+), 134 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index f3c200daf..7d59ee777 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -1,29 +1,33 @@ language: dart dart: - - dev - - 2.0.0 + - dev -dart_task: - - test: -p vm - - test: -p chrome - - dartanalyzer - -matrix: +jobs: include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.0.0 - dart_task: - dartanalyzer: --fatal-warnings . + - stage: analyze_and_format + name: "Analyzer" + dart: dev + os: linux + script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + - stage: analyze_and_format + name: "Format" + dart: dev + os: linux + script: dartfmt -n --set-exit-if-changed . + - stage: test + name: "Vm Tests" + dart: dev + os: linux + script: pub run --enable-experiment=non-nullable test -p vm + +stages: + - analyze_and_format + - test # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 2f189e695..4729e7e7a 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.0-nullsafety + +* Opt in to null safety. + ## 1.9.5 * Parse the format for `data:` URIs that the Dart VM has used since `2.2.0`. diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 70216af63..3d96bfc85 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,5 +1,7 @@ include: package:pedantic/analysis_options.yaml analyzer: + enable-experiment: + - non-nullable strong-mode: implicit-casts: false errors: diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 6b2eec5a1..ba6fa4055 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -47,8 +47,8 @@ class Chain implements StackTrace { final List traces; /// The [StackZoneSpecification] for the current zone. - static StackZoneSpecification get _currentSpec => - Zone.current[_specKey] as StackZoneSpecification; + static StackZoneSpecification? get _currentSpec => + Zone.current[_specKey] as StackZoneSpecification?; /// If [when] is `true`, runs [callback] in a [Zone] in which the current /// stack chain is tracked and automatically associated with (most) errors. @@ -73,7 +73,7 @@ class Chain implements StackTrace { /// /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T Function() callback, - {void Function(Object error, Chain) onError, + {void Function(Object error, Chain)? onError, bool when = true, bool errorZone = true}) { if (!errorZone && onError != null) { @@ -82,15 +82,17 @@ class Chain implements StackTrace { } if (!when) { - void Function(Object, StackTrace) newOnError; + void Function(Object, StackTrace)? newOnError; if (onError != null) { - newOnError = (error, stackTrace) { + void wrappedOnError(Object error, StackTrace? stackTrace) { onError( error, stackTrace == null ? Chain.current() : Chain.forTrace(stackTrace)); - }; + } + + newOnError = wrappedOnError; } return runZoned(callback, onError: newOnError); @@ -100,10 +102,15 @@ class Chain implements StackTrace { return runZoned(() { try { return callback(); - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { // TODO(nweiz): Don't special-case this when issue 19566 is fixed. Zone.current.handleUncaughtError(error, stackTrace); - return null; + + // If the expected return type of capture() is not nullable, this will + // throw a cast exception. But the only other alternative is to throw + // some other exception. Casting null to T at least lets existing uses + // where T is a nullable type continue to work. + return null as T; } }, zoneSpecification: spec.toSpec(), @@ -138,7 +145,7 @@ class Chain implements StackTrace { /// If this is called outside of a [capture] zone, it just returns a /// single-trace chain. factory Chain.current([int level = 0]) { - if (_currentSpec != null) return _currentSpec.currentChain(level + 1); + if (_currentSpec != null) return _currentSpec!.currentChain(level + 1); var chain = Chain.forTrace(StackTrace.current); return LazyChain(() { @@ -160,7 +167,7 @@ class Chain implements StackTrace { /// If [trace] is already a [Chain], it will be returned as-is. factory Chain.forTrace(StackTrace trace) { if (trace is Chain) return trace; - if (_currentSpec != null) return _currentSpec.chainFor(trace); + if (_currentSpec != null) return _currentSpec!.chainFor(trace); if (trace is Trace) return Chain([trace]); return LazyChain(() => Chain.parse(trace.toString())); } diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 7ffc05f08..c5b20e1f3 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -79,18 +79,18 @@ class Frame { /// /// This can be null, indicating that the line number is unknown or /// unimportant. - final int line; + final int? line; /// The column number of the code location. /// /// This can be null, indicating that the column number is unknown or /// unimportant. - final int column; + final int? column; /// The name of the member in which the code location occurs. /// /// Anonymous closures are represented as `` in this member string. - final String member; + final String? member; /// Whether this stack frame comes from the Dart core libraries. bool get isCore => uri.scheme == 'dart'; @@ -107,7 +107,7 @@ class Frame { /// Returns the name of the package this stack frame comes from, or `null` if /// this stack frame doesn't come from a `package:` URL. - String get package { + String? get package { if (uri.scheme != 'package') return null; return uri.path.split('/').first; } @@ -146,14 +146,14 @@ class Frame { // Get the pieces out of the regexp match. Function, URI and line should // always be found. The column is optional. - var member = match[1] + var member = match[1]! .replaceAll(_asyncBody, '') .replaceAll('', ''); - var uri = match[2].startsWith(' 1 ? int.parse(lineAndColumn[1]) : null; var column = @@ -171,7 +171,7 @@ class Frame { Frame parseLocation(String location, String member) { var evalMatch = _v8EvalLocation.firstMatch(location); while (evalMatch != null) { - location = evalMatch[1]; + location = evalMatch[1]!; evalMatch = _v8EvalLocation.firstMatch(location); } @@ -182,9 +182,10 @@ class Frame { var urlMatch = _v8UrlLocation.firstMatch(location); if (urlMatch == null) return UnparsedFrame(frame); - final uri = _uriOrPathToUri(urlMatch[1]); - final line = int.parse(urlMatch[2]); - final column = urlMatch[3] != null ? int.parse(urlMatch[3]) : null; + final uri = _uriOrPathToUri(urlMatch[1]!); + final line = int.parse(urlMatch[2]!); + final columnMatch = urlMatch[3]; + final column = columnMatch != null ? int.parse(columnMatch) : null; return Frame(uri, line, column, member); } @@ -194,15 +195,15 @@ class Frame { // lists anonymous functions within eval as "", while IE10 // lists them as "Anonymous function". return parseLocation( - match[2], - match[1] + match[2]!, + match[1]! .replaceAll('', '') .replaceAll('Anonymous function', '') .replaceAll('(anonymous function)', '')); } else { // The second form looks like " at LOCATION", and is used for // anonymous functions. - return parseLocation(match[3], ''); + return parseLocation(match[3]!, ''); } }); @@ -224,9 +225,9 @@ class Frame { _catchFormatException(frame, () { final match = _firefoxEvalLocation.firstMatch(frame); if (match == null) return UnparsedFrame(frame); - var member = match[1].replaceAll('/<', ''); - final uri = _uriOrPathToUri(match[2]); - final line = int.parse(match[3]); + var member = match[1]!.replaceAll('/<', ''); + final uri = _uriOrPathToUri(match[2]!); + final line = int.parse(match[3]!); if (member.isEmpty || member == 'anonymous') { member = ''; } @@ -238,18 +239,17 @@ class Frame { var match = _firefoxSafariFrame.firstMatch(frame); if (match == null) return UnparsedFrame(frame); - if (match[3].contains(' line ')) { + if (match[3]!.contains(' line ')) { return Frame._parseFirefoxEval(frame); } // Normally this is a URI, but in a jsshell trace it can be a path. - var uri = _uriOrPathToUri(match[3]); + var uri = _uriOrPathToUri(match[3]!); - String member; - if (match[1] != null) { - member = match[1]; + var member = match[1]; + if (member != null) { member += - List.filled('/'.allMatches(match[2]).length, '.').join(); + List.filled('/'.allMatches(match[2]!).length, '.').join(); if (member == '') member = ''; // Some Firefox members have initial dots. We remove them for @@ -259,9 +259,9 @@ class Frame { member = ''; } - var line = match[4] == '' ? null : int.parse(match[4]); + var line = match[4] == '' ? null : int.parse(match[4]!); var column = - match[5] == null || match[5] == '' ? null : int.parse(match[5]); + match[5] == null || match[5] == '' ? null : int.parse(match[5]!); return Frame(uri, line, column, member); }); @@ -288,15 +288,15 @@ class Frame { // them. var uri = match[1] == 'data:...' ? Uri.dataFromString('') - : Uri.parse(match[1]); - // If there's no scheme, this is a relative URI. We should interpret it - // as relative to the current working directory. + : Uri.parse(match[1]!); + // If there's no scheme, this is a relative URI. We should interpret it as + // relative to the current working directory. if (uri.scheme == '') { uri = path.toUri(path.absolute(path.fromUri(uri))); } - var line = match[2] == null ? null : int.parse(match[2]); - var column = match[3] == null ? null : int.parse(match[3]); + var line = match[2] == null ? null : int.parse(match[2]!); + var column = match[3] == null ? null : int.parse(match[3]!); return Frame(uri, line, column, match[4]); }); diff --git a/pkgs/stack_trace/lib/src/lazy_chain.dart b/pkgs/stack_trace/lib/src/lazy_chain.dart index 12dbacea2..e2f64a768 100644 --- a/pkgs/stack_trace/lib/src/lazy_chain.dart +++ b/pkgs/stack_trace/lib/src/lazy_chain.dart @@ -15,12 +15,10 @@ typedef ChainThunk = Chain Function(); /// necessary. class LazyChain implements Chain { final ChainThunk _thunk; - Chain _inner; + late final Chain _chain = _thunk(); LazyChain(this._thunk); - Chain get _chain => _inner ??= _thunk(); - @override List get traces => _chain.traces; @override diff --git a/pkgs/stack_trace/lib/src/lazy_trace.dart b/pkgs/stack_trace/lib/src/lazy_trace.dart index 0fa2af18b..3ecaa2df0 100644 --- a/pkgs/stack_trace/lib/src/lazy_trace.dart +++ b/pkgs/stack_trace/lib/src/lazy_trace.dart @@ -13,12 +13,10 @@ typedef TraceThunk = Trace Function(); /// necessary. class LazyTrace implements Trace { final TraceThunk _thunk; - Trace _inner; + late final Trace _trace = _thunk(); LazyTrace(this._thunk); - Trace get _trace => _inner ??= _thunk(); - @override List get frames => _trace.frames; @override diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index f721e9405..13cdf2763 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -53,10 +53,10 @@ class StackZoneSpecification { /// /// If this is null, that indicates that any unhandled errors should be passed /// to the parent zone. - final void Function(Object error, Chain) _onError; + final void Function(Object error, Chain)? _onError; /// The most recent node of the current stack chain. - _Node _currentNode; + _Node? _currentNode; /// Whether this is an error zone. final bool _errorZone; @@ -86,7 +86,7 @@ class StackZoneSpecification { /// The first stack trace in the returned chain will always be [trace] /// (converted to a [Trace] if necessary). If there is no chain associated /// with [trace], this just returns a single-trace chain containing [trace]. - Chain chainFor(StackTrace trace) { + Chain chainFor(StackTrace? trace) { if (trace is Chain) return trace; trace ??= StackTrace.current; @@ -96,11 +96,11 @@ class StackZoneSpecification { // [Chain.capture] and we should fall back to the VM's stack chaining. We // can't use [Chain.from] here because it'll just call [chainFor] again. if (trace is Trace) return Chain([trace]); - return LazyChain(() => Chain.parse(trace.toString())); + return LazyChain(() => Chain.parse(trace!.toString())); } else { if (trace is! Trace) { - var original = trace; - trace = LazyTrace(() => Trace.parse(_trimVMChain(original))); + StackTrace? original = trace; + trace = LazyTrace(() => Trace.parse(_trimVMChain(original!))); } return _Node(trace, previous).toChain(); @@ -111,7 +111,7 @@ class StackZoneSpecification { /// [f] is run. ZoneCallback _registerCallback( Zone self, ZoneDelegate parent, Zone zone, R Function() f) { - if (f == null || _disabled) return parent.registerCallback(zone, f); + if (_disabled) return parent.registerCallback(zone, f); var node = _createNode(1); return parent.registerCallback(zone, () => _run(f, node)); } @@ -120,7 +120,7 @@ class StackZoneSpecification { /// [f] is run. ZoneUnaryCallback _registerUnaryCallback( Zone self, ZoneDelegate parent, Zone zone, R Function(T) f) { - if (f == null || _disabled) return parent.registerUnaryCallback(zone, f); + if (_disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback(zone, (arg) { return _run(() => f(arg), node); @@ -131,7 +131,7 @@ class StackZoneSpecification { /// [f] is run. ZoneBinaryCallback _registerBinaryCallback( Zone self, ZoneDelegate parent, Zone zone, R Function(T1, T2) f) { - if (f == null || _disabled) return parent.registerBinaryCallback(zone, f); + if (_disabled) return parent.registerBinaryCallback(zone, f); var node = _createNode(1); return parent.registerBinaryCallback(zone, (arg1, arg2) { @@ -141,8 +141,8 @@ class StackZoneSpecification { /// Looks up the chain associated with [stackTrace] and passes it either to /// [_onError] or [parent]'s error handler. - void _handleUncaughtError( - Zone self, ZoneDelegate parent, Zone zone, error, StackTrace stackTrace) { + void _handleUncaughtError(Zone self, ZoneDelegate parent, Zone zone, + Object error, StackTrace stackTrace) { if (_disabled) { parent.handleUncaughtError(zone, error, stackTrace); return; @@ -157,8 +157,10 @@ class StackZoneSpecification { // TODO(nweiz): Currently this copies a lot of logic from [runZoned]. Just // allow [runBinary] to throw instead once issue 18134 is fixed. try { - self.parent.runBinary(_onError, error, stackChain); - } catch (newError, newStackTrace) { + // TODO(rnystrom): Is the null-assertion correct here? It is nullable in + // Zone. Should we check for that here? + self.parent!.runBinary(_onError!, error, stackChain); + } on Object catch (newError, newStackTrace) { if (identical(newError, error)) { parent.handleUncaughtError(zone, error, stackChain); } else { @@ -169,8 +171,8 @@ class StackZoneSpecification { /// Attaches the current stack chain to [stackTrace], replacing it if /// necessary. - AsyncError _errorCallback(Zone self, ZoneDelegate parent, Zone zone, - Object error, StackTrace stackTrace) { + AsyncError? _errorCallback(Zone self, ZoneDelegate parent, Zone zone, + Object error, StackTrace? stackTrace) { if (_disabled) return parent.errorCallback(zone, error, stackTrace); // Go up two levels to get through [_CustomZone.errorCallback]. @@ -217,15 +219,15 @@ class StackZoneSpecification { /// Like [new Trace.current], but if the current stack trace has VM chaining /// enabled, this only returns the innermost sub-trace. - Trace _currentTrace([int level]) { - level ??= 0; + Trace _currentTrace([int? level]) { var stackTrace = StackTrace.current; return LazyTrace(() { var text = _trimVMChain(stackTrace); var trace = Trace.parse(text); // JS includes a frame for the call to StackTrace.current, but the VM // doesn't, so we skip an extra frame in a JS context. - return Trace(trace.frames.skip(level + (inJS ? 2 : 1)), original: text); + return Trace(trace.frames.skip((level ?? 0) + (inJS ? 2 : 1)), + original: text); }); } @@ -244,14 +246,14 @@ class _Node { final Trace trace; /// The previous node in the chain. - final _Node previous; + final _Node? previous; _Node(StackTrace trace, [this.previous]) : trace = Trace.from(trace); /// Converts this to a [Chain]. Chain toChain() { var nodes = []; - var node = this; + _Node? node = this; while (node != null) { nodes.add(node.trace); node = node.previous; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 96902a1a6..dc7fd5d2e 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -107,13 +107,6 @@ class Trace implements StackTrace { /// If [trace] is a native [StackTrace], its data will be parsed out; if it's /// a [Trace], it will be returned as-is. factory Trace.from(StackTrace trace) { - // Normally explicitly validating null arguments is bad Dart style, but here - // the natural failure will only occur when the LazyTrace is materialized, - // and we want to provide an error that's more local to the actual problem. - if (trace == null) { - throw ArgumentError('Cannot create a Trace from null.'); - } - if (trace is Trace) return trace; if (trace is Chain) return trace.toTrace(); return LazyTrace(() => Trace.parse(trace.toString())); @@ -240,9 +233,9 @@ class Trace implements StackTrace { original: trace); /// Returns a new [Trace] comprised of [frames]. - Trace(Iterable frames, {String original}) + Trace(Iterable frames, {String? original}) : frames = List.unmodifiable(frames), - original = StackTrace.fromString(original); + original = StackTrace.fromString(original ?? ''); /// Returns a VM-style [StackTrace] object. /// @@ -296,7 +289,7 @@ class Trace implements StackTrace { // just get rid of them. // TODO(nweiz): Get rid of this logic some time after issue 22009 is // fixed. - if (!frame.member.contains('')) return false; + if (!frame.member!.contains('')) return false; return frame.line == null; }; } diff --git a/pkgs/stack_trace/lib/src/unparsed_frame.dart b/pkgs/stack_trace/lib/src/unparsed_frame.dart index 31d017996..27e97f6e0 100644 --- a/pkgs/stack_trace/lib/src/unparsed_frame.dart +++ b/pkgs/stack_trace/lib/src/unparsed_frame.dart @@ -11,15 +11,15 @@ class UnparsedFrame implements Frame { @override final Uri uri = Uri(path: 'unparsed'); @override - final int line = null; + final int? line = null; @override - final int column = null; + final int? column = null; @override final bool isCore = false; @override final String library = 'unparsed'; @override - final String package = null; + final String? package = null; @override final String location = 'unparsed'; diff --git a/pkgs/stack_trace/lib/src/vm_trace.dart b/pkgs/stack_trace/lib/src/vm_trace.dart index 3ba73b9fb..005b7afa3 100644 --- a/pkgs/stack_trace/lib/src/vm_trace.dart +++ b/pkgs/stack_trace/lib/src/vm_trace.dart @@ -20,7 +20,7 @@ class VMTrace implements StackTrace { var i = 1; return frames.map((frame) { var number = '#${i++}'.padRight(8); - var member = frame.member + var member = frame.member! .replaceAllMapped(RegExp(r'[^.]+\.'), (match) => '${match[1]}.<${match[1]}_async_body>') .replaceAll('', ''); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 147f7cc76..94a80543e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,15 +1,84 @@ name: stack_trace -version: 1.9.5 - +version: 1.10.0-nullsafety description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dependencies: - path: ^1.2.0 + path: '>=1.8.0-nullsafety <1.8.0' dev_dependencies: pedantic: ^1.0.0 test: '>=0.12.17 <2.0.0' + +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + collection: + git: + url: git://github.com/dart-lang/collection.git + ref: null_safety + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: + git: + url: git://github.com/dart-lang/sdk.git + ref: null_safety-pkgs + path: pkg/meta + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + pool: + git: + url: git://github.com/dart-lang/pool.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stream_channel: + git: + url: git://github.com/dart-lang/stream_channel.git + ref: null_safety + string_scanner: + git: + url: git://github.com/dart-lang/string_scanner.git + ref: null_safety + term_glyph: + git: + url: git://github.com/dart-lang/term_glyph.git + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_core + test: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index b6ad33e03..1e466ac05 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -44,7 +44,7 @@ void main() { return Future.error('oh no'); }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); - expect(chain, TypeMatcher()); + expect(chain, isA()); })); }); @@ -54,7 +54,7 @@ void main() { future.then(expectAsync1((_) {}, count: 0)); }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); - expect(chain, TypeMatcher()); + expect(chain, isA()); })); }); @@ -79,7 +79,7 @@ void main() { return Future.error('oh no'); }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); - expect(chain, TypeMatcher()); + expect(chain, isA()); }), when: false); }); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index 827c45940..c0ec913c8 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -90,7 +90,7 @@ void main() { expect(chain.traces, hasLength(2)); completer.complete(); } - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -151,10 +151,10 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, TypeMatcher()); + expect(chain, isA()); expect(chain.traces, hasLength(2)); completer.complete(); - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -171,10 +171,10 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, TypeMatcher()); + expect(chain, isA()); expect(chain.traces, hasLength(2)); completer.complete(); - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -305,7 +305,7 @@ void main() { test( 'called for an unregistered stack trace returns a chain wrapping that ' 'trace', () { - StackTrace trace; + late StackTrace trace; var chain = Chain.capture(() { try { throw 'error'; @@ -324,7 +324,7 @@ void main() { test( 'forTrace() outside of capture() returns a chain wrapping the given ' 'trace', () { - StackTrace trace; + late StackTrace trace; var chain = Chain.capture(() { try { throw 'error'; diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 0711108cb..af8e361f4 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -46,7 +46,7 @@ void inSyncFuture(void Function() callback) { /// Returns a Future that completes to an error using a completer. /// /// If [trace] is passed, it's used as the stack trace for the error. -Future completerErrorFuture([StackTrace trace]) { +Future completerErrorFuture([StackTrace? trace]) { var completer = Completer(); completer.completeError('error', trace); return completer.future; @@ -55,7 +55,7 @@ Future completerErrorFuture([StackTrace trace]) { /// Returns a Stream that emits an error using a controller. /// /// If [trace] is passed, it's used as the stack trace for the error. -Stream controllerErrorStream([StackTrace trace]) { +Stream controllerErrorStream([StackTrace? trace]) { var controller = StreamController(); controller.addError('error', trace); return controller.stream; diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 842f0a078..273276eeb 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -19,7 +19,7 @@ import 'utils.dart'; void main() { group('capture() with onError catches exceptions', () { test('thrown synchronously', () async { - StackTrace vmTrace; + late StackTrace vmTrace; var chain = await captureFuture(() { try { throw 'error'; @@ -156,7 +156,7 @@ void main() { contains(frameMember(startsWith('inPeriodicTimer')))); completer.complete(); } - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -246,11 +246,11 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, TypeMatcher()); + expect(chain, isA()); expect(chain.traces[1].frames, contains(frameMember(startsWith('inMicrotask')))); completer.complete(); - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -267,11 +267,11 @@ void main() { }, onError: (error, chain) { try { expect(error, equals('error')); - expect(chain, TypeMatcher()); + expect(chain, isA()); expect(chain.traces[1].frames, contains(frameMember(startsWith('inMicrotask')))); completer.complete(); - } catch (error, stackTrace) { + } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); } }); @@ -481,7 +481,7 @@ void main() { 'chain', () { // Disable the test package's chain-tracking. return Chain.disable(() async { - StackTrace trace; + late StackTrace trace; await Chain.capture(() async { try { throw 'error'; diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 087b5b6db..87880395e 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -40,7 +40,7 @@ void main() { }); test('converts "" to ""', () { - String parsedMember(String member) => + String? parsedMember(String member) => Frame.parseVM('#0 $member (foo:0:0)').member; expect(parsedMember('Foo.'), equals('Foo.')); @@ -210,7 +210,7 @@ void main() { }); test('converts "" to ""', () { - String parsedMember(String member) => + String? parsedMember(String member) => Frame.parseV8(' at $member (foo:0:0)').member; expect(parsedMember('Foo.'), equals('Foo.')); @@ -646,6 +646,6 @@ baz@https://pub.dev/buz.js:56355:55 void expectIsUnparsed(Frame Function(String) constructor, String text) { var frame = constructor(text); - expect(frame, TypeMatcher()); + expect(frame, isA()); expect(frame.toString(), equals(text)); } diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index ec7b074d5..a10c69d81 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -6,7 +6,7 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -Trace getCurrentTrace([int level]) => Trace.current(level); +Trace getCurrentTrace([int level = 0]) => Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); @@ -366,7 +366,7 @@ dart:core bottom '''); var folded = - trace.foldFrames((frame) => frame.member.startsWith('foo')); + trace.foldFrames((frame) => frame.member!.startsWith('foo')); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo foo.dart 1:100 fooBottom @@ -401,7 +401,7 @@ dart:async-patch/future.dart 9:11 fooBottom '''); var folded = trace.foldFrames( - (frame) => frame.member.startsWith('foo'), + (frame) => frame.member!.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo @@ -422,7 +422,7 @@ bar.dart 10:20 alsoNotFoo '''); var folded = trace.foldFrames( - (frame) => frame.member.startsWith('foo'), + (frame) => frame.member!.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' foo.dart 42:21 notFoo @@ -441,7 +441,7 @@ bar.dart 20:20 againNotFoo '''); var folded = trace.foldFrames( - (frame) => frame.member.startsWith('foo'), + (frame) => frame.member!.startsWith('foo'), terse: true); expect(folded.toString(), equals(''' package:foo fooTop diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index 4ad3de2cd..c9f819a9b 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -18,14 +18,14 @@ String getStackTraceString() => StackTrace.current.toString(); // The name of this (trivial) function is verified as part of the test StackTrace getStackTraceObject() => StackTrace.current; -Frame getCaller([int level]) { +Frame getCaller([int? level]) { if (level == null) return Frame.caller(); return Frame.caller(level); } Frame nestedGetCaller(int level) => getCaller(level); -Trace getCurrentTrace([int level]) => Trace.current(level); +Trace getCurrentTrace([int level = 0]) => Trace.current(level); Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); @@ -49,14 +49,14 @@ void main() { test('.from handles a stack overflow trace correctly', () { void overflow() => overflow(); - var trace; + late Trace? trace; try { overflow(); } catch (_, stackTrace) { trace = Trace.from(stackTrace); } - expect(trace.frames.first.member, equals('main...overflow')); + expect(trace!.frames.first.member, equals('main...overflow')); }); group('.current()', () { From 7bd4cda7a955554fd7a4c0b646d4e400b3987a3f Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 15 Jul 2020 18:58:16 -0700 Subject: [PATCH 0658/1215] Merge the null_safety branch into master (dart-lang/string_scanner#22) --- pkgs/string_scanner/.travis.yml | 6 +- pkgs/string_scanner/CHANGELOG.md | 4 + pkgs/string_scanner/analysis_options.yaml | 3 + pkgs/string_scanner/example/example.dart | 4 +- .../lib/src/eager_span_scanner.dart | 12 +-- pkgs/string_scanner/lib/src/exception.dart | 2 +- pkgs/string_scanner/lib/src/line_scanner.dart | 8 +- .../lib/src/relative_span_scanner.dart | 13 ++- pkgs/string_scanner/lib/src/span_scanner.dart | 17 ++-- .../lib/src/string_scanner.dart | 31 ++++--- pkgs/string_scanner/lib/src/utils.dart | 3 +- pkgs/string_scanner/pubspec.yaml | 85 +++++++++++++++++-- pkgs/string_scanner/test/error_test.dart | 2 +- .../test/line_scanner_test.dart | 2 +- .../test/span_scanner_test.dart | 12 +-- .../test/string_scanner_test.dart | 26 +++--- pkgs/string_scanner/test/utils.dart | 2 +- 17 files changed, 153 insertions(+), 79 deletions(-) diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml index 48e46ca18..dd4f4372d 100644 --- a/pkgs/string_scanner/.travis.yml +++ b/pkgs/string_scanner/.travis.yml @@ -2,7 +2,6 @@ language: dart dart: - dev - - 2.0.0 dart_task: - test: --platform vm,chrome @@ -15,13 +14,10 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-warnings --fatal-hints . - - dart: 2.0.0 - dart_task: - dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index fb7f74dd1..abe488c8d 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0-nullsafety + +- Migrate to null safety. + ## 1.0.5 - Added an example. diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 60abe63e6..2407da620 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -4,6 +4,9 @@ analyzer: strong-mode: implicit-casts: false + enable-experiment: + - non-nullable + linter: rules: - avoid_bool_literals_in_conditional_expressions diff --git a/pkgs/string_scanner/example/example.dart b/pkgs/string_scanner/example/example.dart index e92677f1c..fd36a73c1 100644 --- a/pkgs/string_scanner/example/example.dart +++ b/pkgs/string_scanner/example/example.dart @@ -24,11 +24,11 @@ num parseNumber(String source) { // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. - var number = num.parse(scanner.lastMatch[0]); + var number = num.parse((scanner.lastMatch![0])!); if (scanner.scan('.')) { scanner.expect(RegExp(r'\d+')); - final decimal = scanner.lastMatch[0]; + final decimal = scanner.lastMatch![0]!; number += int.parse(decimal) / math.pow(10, decimal.length); } diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 848cb72c4..415b9f32c 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -31,8 +31,7 @@ class EagerSpanScanner extends SpanScanner { @override set state(LineScannerState state) { - if (state is! _EagerSpanScannerState || - !identical((state as _EagerSpanScannerState)._scanner, this)) { + if (state is! _EagerSpanScannerState || !identical(state._scanner, this)) { throw ArgumentError('The given LineScannerState was not returned by ' 'this LineScanner.'); } @@ -69,7 +68,7 @@ class EagerSpanScanner extends SpanScanner { } } - EagerSpanScanner(String string, {sourceUrl, int position}) + EagerSpanScanner(String string, {sourceUrl, int? position}) : super(string, sourceUrl: sourceUrl, position: position); @override @@ -99,13 +98,14 @@ class EagerSpanScanner extends SpanScanner { @override bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; + final firstMatch = (lastMatch![0])!; - final newlines = _newlinesIn(lastMatch[0]); + final newlines = _newlinesIn(firstMatch); _line += newlines.length; if (newlines.isEmpty) { - _column += lastMatch[0].length; + _column += firstMatch.length; } else { - _column = lastMatch[0].length - newlines.last.end; + _column = firstMatch.length - newlines.last.end; } return true; diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 8c994b5ae..8aa7aabea 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -14,7 +14,7 @@ class StringScannerException extends SourceSpanFormatException { /// The URL of the source file being parsed. /// /// This may be `null`, indicating that the source URL is unknown. - Uri get sourceUrl => span.sourceUrl; + Uri? get sourceUrl => span?.sourceUrl; StringScannerException(String message, SourceSpan span, String source) : super(message, span, source); diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 9e7d918fa..358d4c1cb 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -73,7 +73,7 @@ class LineScanner extends StringScanner { } } - LineScanner(String string, {sourceUrl, int position}) + LineScanner(String string, {sourceUrl, int? position}) : super(string, sourceUrl: sourceUrl, position: position); @override @@ -104,12 +104,12 @@ class LineScanner extends StringScanner { bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - final newlines = _newlinesIn(lastMatch[0]); + final newlines = _newlinesIn(lastMatch![0]!); _line += newlines.length; if (newlines.isEmpty) { - _column += lastMatch[0].length; + _column += (lastMatch![0])!.length; } else { - _column = lastMatch[0].length - newlines.last.end; + _column = (lastMatch![0])!.length - newlines.last.end; } return true; diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index a7a035abb..150d5071e 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -47,8 +47,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { @override set state(LineScannerState state) { - if (state is! _SpanScannerState || - !identical((state as _SpanScannerState)._scanner, this)) { + if (state is! _SpanScannerState || !identical(state._scanner, this)) { throw ArgumentError('The given LineScannerState was not returned by ' 'this LineScanner.'); } @@ -57,8 +56,8 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { } @override - FileSpan get lastSpan => _lastSpan; - FileSpan _lastSpan; + FileSpan? get lastSpan => _lastSpan; + FileSpan? _lastSpan; @override FileLocation get location => @@ -73,7 +72,7 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { super(span.text, sourceUrl: span.sourceUrl); @override - FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + FileSpan spanFrom(LineScannerState startState, [LineScannerState? endState]) { final endPosition = endState == null ? position : endState.position; return _sourceFile.span(_startLocation.offset + startState.position, _startLocation.offset + endPosition); @@ -87,12 +86,12 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { } _lastSpan = _sourceFile.span(_startLocation.offset + position, - _startLocation.offset + lastMatch.end); + _startLocation.offset + lastMatch!.end); return true; } @override - void error(String message, {Match match, int position, int length}) { + Never error(String message, {Match? match, int? position, int? length}) { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 1a8ca2ade..806a8f8ea 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -29,8 +29,7 @@ class SpanScanner extends StringScanner implements LineScanner { @override set state(LineScannerState state) { - if (state is! _SpanScannerState || - !identical((state as _SpanScannerState)._scanner, this)) { + if (state is! _SpanScannerState || !identical(state._scanner, this)) { throw ArgumentError('The given LineScannerState was not returned by ' 'this LineScanner.'); } @@ -42,12 +41,12 @@ class SpanScanner extends StringScanner implements LineScanner { /// /// This is the span for the entire match. There's no way to get spans for /// subgroups since [Match] exposes no information about their positions. - FileSpan get lastSpan { + FileSpan? get lastSpan { if (lastMatch == null) _lastSpan = null; return _lastSpan; } - FileSpan _lastSpan; + FileSpan? _lastSpan; /// The current location of the scanner. FileLocation get location => _sourceFile.location(position); @@ -60,7 +59,7 @@ class SpanScanner extends StringScanner implements LineScanner { /// [sourceUrl] is used as [SourceLocation.sourceUrl] for the returned /// [FileSpan]s as well as for error reporting. It can be a [String], a /// [Uri], or `null`. - SpanScanner(String string, {sourceUrl, int position}) + SpanScanner(String string, {sourceUrl, int? position}) : _sourceFile = SourceFile.fromString(string, url: sourceUrl), super(string, sourceUrl: sourceUrl, position: position); @@ -75,7 +74,7 @@ class SpanScanner extends StringScanner implements LineScanner { /// itself and its `LineScannerState` are eagerly computed. To limit their /// memory footprint, returned spans and locations will still lazily compute /// their line and column numbers. - factory SpanScanner.eager(String string, {sourceUrl, int position}) = + factory SpanScanner.eager(String string, {sourceUrl, int? position}) = EagerSpanScanner; /// Creates a new [SpanScanner] that scans within [span]. @@ -88,7 +87,7 @@ class SpanScanner extends StringScanner implements LineScanner { /// Creates a [FileSpan] representing the source range between [startState] /// and the current position. - FileSpan spanFrom(LineScannerState startState, [LineScannerState endState]) { + FileSpan spanFrom(LineScannerState startState, [LineScannerState? endState]) { final endPosition = endState == null ? position : endState.position; return _sourceFile.span(startState.position, endPosition); } @@ -100,12 +99,12 @@ class SpanScanner extends StringScanner implements LineScanner { return false; } - _lastSpan = _sourceFile.span(position, lastMatch.end); + _lastSpan = _sourceFile.span(position, lastMatch!.end); return true; } @override - void error(String message, {Match match, int position, int length}) { + Never error(String message, {Match? match, int? position, int? length}) { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 55ff17d3a..f29bc3ac6 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. import 'package:charcode/charcode.dart'; -import 'package:meta/meta.dart'; import 'package:source_span/source_span.dart'; import 'exception.dart'; @@ -15,7 +14,7 @@ class StringScanner { /// /// This is used for error reporting. It may be `null`, indicating that the /// source URL is unknown or unavailable. - final Uri sourceUrl; + final Uri? sourceUrl; /// The string being scanned through. final String string; @@ -36,15 +35,15 @@ class StringScanner { /// The data about the previous match made by the scanner. /// /// If the last match failed, this will be `null`. - Match get lastMatch { + Match? get lastMatch { // Lazily unset [_lastMatch] so that we avoid extra assignments in // character-by-character methods that are used in core loops. if (_position != _lastMatchPosition) _lastMatch = null; return _lastMatch; } - Match _lastMatch; - int _lastMatchPosition; + Match? _lastMatch; + int? _lastMatchPosition; /// The portion of the string that hasn't yet been scanned. String get rest => string.substring(position); @@ -57,9 +56,10 @@ class StringScanner { /// [position] defaults to 0, the beginning of the string. [sourceUrl] is the /// URL of the source of the string being scanned, if available. It can be /// a [String], a [Uri], or `null`. - StringScanner(this.string, {sourceUrl, int position}) - : sourceUrl = - sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl as Uri { + StringScanner(this.string, {sourceUrl, int? position}) + : sourceUrl = sourceUrl == null + ? null + : sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl as Uri { if (position != null) this.position = position; } @@ -79,7 +79,7 @@ class StringScanner { /// /// This returns `null` if [offset] points outside the string. It doesn't /// affect [lastMatch]. - int peekChar([int offset]) { + int? peekChar([int? offset]) { offset ??= 0; final index = position + offset; if (index < 0 || index >= string.length) return null; @@ -102,7 +102,7 @@ class StringScanner { /// describing the position of the failure. [name] is used in this error as /// the expected name of the character being matched; if it's `null`, the /// character itself is used instead. - void expectChar(int character, {String name}) { + void expectChar(int character, {String? name}) { if (scanChar(character)) return; if (name == null) { @@ -125,7 +125,7 @@ class StringScanner { bool scan(Pattern pattern) { final success = matches(pattern); if (success) { - _position = _lastMatch.end; + _position = _lastMatch!.end; _lastMatchPosition = _position; } return success; @@ -138,7 +138,7 @@ class StringScanner { /// position of the failure. [name] is used in this error as the expected name /// of the pattern being matched; if it's `null`, the pattern itself is used /// instead. - void expect(Pattern pattern, {String name}) { + void expect(Pattern pattern, {String? name}) { if (scan(pattern)) return; if (name == null) { @@ -175,7 +175,7 @@ class StringScanner { /// /// Unlike [String.substring], [end] defaults to [position] rather than the /// end of the string. - String substring(int start, [int end]) { + String substring(int start, [int? end]) { end ??= position; return string.substring(start, end); } @@ -193,8 +193,7 @@ class StringScanner { /// position; if only [position] is passed, [length] defaults to 0. /// /// It's an error to pass [match] at the same time as [position] or [length]. - @alwaysThrows - void error(String message, {Match match, int position, int length}) { + Never error(String message, {Match? match, int? position, int? length}) { validateErrorArgs(string, match, position, length); if (match == null && position == null && length == null) match = lastMatch; @@ -209,7 +208,7 @@ class StringScanner { // TODO(nweiz): Make this handle long lines more gracefully. /// Throws a [FormatException] describing that [name] is expected at the /// current position in the string. - void _fail(String name) { + Never _fail(String name) { error('expected $name.', position: position, length: 0); } } diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index 7fe3d5241..52dfb6360 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -5,7 +5,8 @@ import 'string_scanner.dart'; /// Validates the arguments passed to [StringScanner.error]. -void validateErrorArgs(String string, Match match, int position, int length) { +void validateErrorArgs( + String string, Match? match, int? position, int? length) { if (match != null && (position != null || length != null)) { throw ArgumentError("Can't pass both match and position/length."); } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index d5cefceda..7a9826d6c 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,17 +1,90 @@ name: string_scanner -version: 1.0.5 +version: 1.1.0-nullsafety description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dependencies: - charcode: ^1.1.0 - meta: ^1.1.0 - source_span: ^1.4.0 + charcode: '>=1.2.0-nullsafety <1.2.0' + source_span: '>=1.8.0-nullsafety <1.8.0' dev_dependencies: - test: ^1.0.0 + test: '>=1.16.0-nullsafety <1.16.0' +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + collection: 1.15.0-nullsafety + js: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/js + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: 1.3.0-nullsafety + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + pool: + git: + url: git://github.com/dart-lang/pool.git + ref: null_safety + source_maps: + git: + url: git://github.com/dart-lang/source_maps.git + ref: null_safety + source_map_stack_trace: + git: + url: git://github.com/dart-lang/source_map_stack_trace.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stack_trace: + git: + url: git://github.com/dart-lang/stack_trace.git + ref: null_safety + stream_channel: + git: + url: git://github.com/dart-lang/stream_channel.git + ref: null_safety + term_glyph: + git: + url: git://github.com/dart-lang/term_glyph.git + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_core + test: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test diff --git a/pkgs/string_scanner/test/error_test.dart b/pkgs/string_scanner/test/error_test.dart index 617304070..1f98c3243 100644 --- a/pkgs/string_scanner/test/error_test.dart +++ b/pkgs/string_scanner/test/error_test.dart @@ -106,7 +106,7 @@ void main() { }); group('argument errors', () { - StringScanner scanner; + late StringScanner scanner; setUp(() { scanner = StringScanner('foo bar baz'); scanner.scan('foo'); diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index aafc74a07..0bbd499ab 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -7,7 +7,7 @@ import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; void main() { - LineScanner scanner; + late LineScanner scanner; setUp(() { scanner = LineScanner('foo\nbar\r\nbaz'); }); diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 2034d0a8d..828745fe1 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -11,19 +11,19 @@ import 'utils.dart'; void main() { testForImplementation( 'lazy', - ([String string]) => + ([String? string]) => SpanScanner(string ?? 'foo\nbar\nbaz', sourceUrl: 'source')); testForImplementation( 'eager', - ([String string]) => + ([String? string]) => SpanScanner.eager(string ?? 'foo\nbar\nbaz', sourceUrl: 'source')); group('within', () { const text = 'first\nbefore: foo\nbar\nbaz :after\nlast'; final startOffset = text.indexOf('foo'); - SpanScanner scanner; + late SpanScanner scanner; setUp(() { final file = SourceFile.fromString(text, url: 'source'); scanner = @@ -51,7 +51,7 @@ void main() { scanner.scan('fo'); scanner.scan('o\nba'); - final span = scanner.lastSpan; + final span = scanner.lastSpan!; expect(span.start.offset, equals(startOffset + 2)); expect(span.start.line, equals(1)); expect(span.start.column, equals(10)); @@ -108,14 +108,14 @@ void main() { void testForImplementation( String name, SpanScanner Function([String string]) create) { group('for a $name scanner', () { - SpanScanner scanner; + late SpanScanner scanner; setUp(() => scanner = create()); test('tracks the span for the last match', () { scanner.scan('fo'); scanner.scan('o\nba'); - final span = scanner.lastSpan; + final span = scanner.lastSpan!; expect(span.start.offset, equals(2)); expect(span.start.line, equals(0)); expect(span.start.column, equals(2)); diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 9dee9d123..0327499c7 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -8,7 +8,7 @@ import 'package:test/test.dart'; void main() { group('with an empty string', () { - StringScanner scanner; + late StringScanner scanner; setUp(() { scanner = StringScanner(''); }); @@ -90,7 +90,7 @@ void main() { }); group('at the beginning of a string', () { - StringScanner scanner; + late StringScanner scanner; setUp(() { scanner = StringScanner('foo bar'); }); @@ -156,7 +156,7 @@ void main() { test('a matching scan returns true and changes the state', () { expect(scanner.scan(RegExp('f(..)')), isTrue); - expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.lastMatch![1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); }); @@ -173,7 +173,7 @@ void main() { test('a matching expect changes the state', () { scanner.expect(RegExp('f(..)')); - expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.lastMatch![1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); }); @@ -192,7 +192,7 @@ void main() { test('a matching matches returns true and only changes lastMatch', () { expect(scanner.matches(RegExp('f(..)')), isTrue); - expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.lastMatch![1], equals('oo')); expect(scanner.position, equals(0)); expect(scanner.rest, equals('foo bar')); }); @@ -223,7 +223,7 @@ void main() { expect(scanner.rest, equals('oo bar')); expect(scanner.scan(RegExp('oo.')), isTrue); - expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.lastMatch![0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); }); @@ -242,19 +242,19 @@ void main() { test('scan accepts any Pattern', () { expect(scanner.scan('foo'), isTrue); - expect(scanner.lastMatch[0], equals('foo')); + expect(scanner.lastMatch![0], equals('foo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); }); test('scans multiple times', () { expect(scanner.scan(RegExp('f(..)')), isTrue); - expect(scanner.lastMatch[1], equals('oo')); + expect(scanner.lastMatch![1], equals('oo')); expect(scanner.position, equals(3)); expect(scanner.rest, equals(' bar')); expect(scanner.scan(RegExp(' b(..)')), isTrue); - expect(scanner.lastMatch[1], equals('ar')); + expect(scanner.lastMatch![1], equals('ar')); expect(scanner.position, equals(7)); expect(scanner.rest, equals('')); expect(scanner.isDone, isTrue); @@ -263,7 +263,7 @@ void main() { }); group('after a scan', () { - StringScanner scanner; + late StringScanner scanner; setUp(() { scanner = StringScanner('foo bar'); expect(scanner.scan('foo'), isTrue); @@ -289,7 +289,7 @@ void main() { }); group('at the end of a string', () { - StringScanner scanner; + late StringScanner scanner; setUp(() { scanner = StringScanner('foo bar'); expect(scanner.scan('foo bar'), isTrue); @@ -368,7 +368,7 @@ void main() { expect(scanner.rest, equals('oo bar')); expect(scanner.scan(RegExp('oo.')), isTrue); - expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.lastMatch![0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); }); @@ -400,7 +400,7 @@ void main() { expect(scanner.rest, equals('oo bar')); expect(scanner.scan(RegExp('oo.')), isTrue); - expect(scanner.lastMatch[0], equals('oo ')); + expect(scanner.lastMatch![0], equals('oo ')); expect(scanner.position, equals(4)); expect(scanner.rest, equals('bar')); }); diff --git a/pkgs/string_scanner/test/utils.dart b/pkgs/string_scanner/test/utils.dart index 676b69555..ca03c064f 100644 --- a/pkgs/string_scanner/test/utils.dart +++ b/pkgs/string_scanner/test/utils.dart @@ -9,4 +9,4 @@ import 'package:test/test.dart'; /// [StringScannerException] with the given [text]. Matcher throwsStringScannerException(String text) => throwsA(const TypeMatcher() - .having((e) => e.span.text, 'span.text', text)); + .having((e) => e.span!.text, 'span.text', text)); From 1f61afe1f1885427a14a4fc40225382c1844e6a5 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Wed, 15 Jul 2020 18:58:38 -0700 Subject: [PATCH 0659/1215] Merge the null_safety branch into master (dart-lang/stream_channel#60) --- pkgs/stream_channel/.travis.yml | 17 +--- pkgs/stream_channel/CHANGELOG.md | 4 +- pkgs/stream_channel/analysis_options.yaml | 2 + .../lib/src/close_guarantee_channel.dart | 17 ++-- pkgs/stream_channel/lib/src/disconnector.dart | 12 +-- .../lib/src/guarantee_channel.dart | 23 +++--- .../lib/src/isolate_channel.dart | 2 +- .../lib/src/json_document_transformer.dart | 6 +- .../stream_channel/lib/src/multi_channel.dart | 28 +++---- .../lib/src/stream_channel_completer.dart | 4 +- .../lib/src/stream_channel_controller.dart | 4 +- pkgs/stream_channel/pubspec.yaml | 81 ++++++++++++++++++- .../test/disconnector_test.dart | 8 +- .../test/isolate_channel_test.dart | 8 +- .../test/json_document_transformer_test.dart | 6 +- .../test/multi_channel_test.dart | 22 ++--- .../test/stream_channel_completer_test.dart | 8 +- .../test/stream_channel_controller_test.dart | 4 +- .../test/stream_channel_test.dart | 6 +- .../test/with_close_guarantee_test.dart | 4 +- .../test/with_guarantees_test.dart | 8 +- 21 files changed, 171 insertions(+), 103 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index d6a545496..b4907d5d1 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,27 +1,16 @@ language: dart dart: -- 2.2.0 - dev dart_task: - test: --platform vm,chrome - -matrix: - include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.2.0 - dart_task: - dartanalyzer: --fatal-warnings . +- dartfmt +- dartanalyzer: --fatal-infos --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 842129238..2c4a13ce6 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,6 @@ -## 2.1.0-dev +## 2.1.0-nullsafety -* Require Dart `2.2.0` or later. +* Migrate to null safety. ## 2.0.0 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index b36c8749b..8a712df8f 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,6 +8,8 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error + enable-experiment: + - non-nullable linter: rules: diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 60916d002..25f502235 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -16,14 +16,14 @@ import '../stream_channel.dart'; class CloseGuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _stream; - _CloseGuaranteeStream _stream; + late final _CloseGuaranteeStream _stream; @override StreamSink get sink => _sink; - _CloseGuaranteeSink _sink; + late final _CloseGuaranteeSink _sink; /// The subscription to the inner stream. - StreamSubscription _subscription; + StreamSubscription? _subscription; /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; @@ -48,8 +48,8 @@ class _CloseGuaranteeStream extends Stream { _CloseGuaranteeStream(this._inner, this._channel); @override - StreamSubscription listen(void Function(T) onData, - {Function onError, void Function() onDone, bool cancelOnError}) { + StreamSubscription listen(void Function(T)? onData, + {Function? onError, void Function()? onDone, bool? cancelOnError}) { // If the channel is already disconnected, we shouldn't dispatch anything // but a done event. if (_channel._disconnected) { @@ -80,10 +80,11 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { Future close() { var done = super.close(); _channel._disconnected = true; - if (_channel._subscription != null) { + var subscription = _channel._subscription; + if (subscription != null) { // Don't dispatch anything but a done event. - _channel._subscription.onData(null); - _channel._subscription.onError(null); + subscription.onData(null); + subscription.onError(null); } return done; } diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index e8835374f..a424146b8 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -74,11 +74,11 @@ class _DisconnectorSink implements StreamSink { /// The subscription to the stream passed to [addStream], if a stream is /// currently being added. - StreamSubscription _addStreamSubscription; + StreamSubscription? _addStreamSubscription; /// The completer for the future returned by [addStream], if a stream is /// currently being added. - Completer _addStreamCompleter; + Completer? _addStreamCompleter; /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; @@ -97,7 +97,7 @@ class _DisconnectorSink implements StreamSink { } @override - void addError(error, [StackTrace stackTrace]) { + void addError(error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); @@ -117,8 +117,8 @@ class _DisconnectorSink implements StreamSink { _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, - onError: _inner.addError, onDone: _addStreamCompleter.complete); - return _addStreamCompleter.future.then((_) { + onError: _inner.addError, onDone: _addStreamCompleter!.complete); + return _addStreamCompleter!.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; }); @@ -143,7 +143,7 @@ class _DisconnectorSink implements StreamSink { var future = _inner.close(); if (_inAddStream) { - _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter!.complete(_addStreamSubscription!.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; } diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index cfee99ee5..4780b046f 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -17,17 +17,17 @@ class GuaranteeChannel extends StreamChannelMixin { @override StreamSink get sink => _sink; - _GuaranteeSink _sink; + late final _GuaranteeSink _sink; /// The controller for [stream]. /// /// This intermediate controller allows us to continue listening for a done /// event even after the user has canceled their subscription, and to send our /// own done event when the sink is closed. - StreamController _streamController; + late final StreamController _streamController; /// The subscription to the inner stream. - StreamSubscription _subscription; + StreamSubscription? _subscription; /// Whether the sink has closed, causing the underlying channel to disconnect. bool _disconnected = false; @@ -64,7 +64,8 @@ class GuaranteeChannel extends StreamChannelMixin { /// should stop emitting events. void _onSinkDisconnected() { _disconnected = true; - if (_subscription != null) _subscription.cancel(); + var subscription = _subscription; + if (subscription != null) subscription.cancel(); _streamController.close(); } } @@ -95,11 +96,11 @@ class _GuaranteeSink implements StreamSink { /// The subscription to the stream passed to [addStream], if a stream is /// currently being added. - StreamSubscription _addStreamSubscription; + StreamSubscription? _addStreamSubscription; /// The completer for the future returned by [addStream], if a stream is /// currently being added. - Completer _addStreamCompleter; + Completer? _addStreamCompleter; /// Whether we're currently adding a stream with [addStream]. bool get _inAddStream => _addStreamSubscription != null; @@ -125,7 +126,7 @@ class _GuaranteeSink implements StreamSink { } @override - void addError(error, [StackTrace stackTrace]) { + void addError(error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); @@ -139,7 +140,7 @@ class _GuaranteeSink implements StreamSink { /// /// This is called from [addStream], so it shouldn't fail if a stream is being /// added. - void _addError(error, [StackTrace stackTrace]) { + void _addError(Object error, [StackTrace? stackTrace]) { if (_allowErrors) { _inner.addError(error, stackTrace); return; @@ -166,8 +167,8 @@ class _GuaranteeSink implements StreamSink { _addStreamCompleter = Completer.sync(); _addStreamSubscription = stream.listen(_inner.add, - onError: _addError, onDone: _addStreamCompleter.complete); - return _addStreamCompleter.future.then((_) { + onError: _addError, onDone: _addStreamCompleter!.complete); + return _addStreamCompleter!.future.then((_) { _addStreamCompleter = null; _addStreamSubscription = null; }); @@ -199,7 +200,7 @@ class _GuaranteeSink implements StreamSink { if (!_doneCompleter.isCompleted) _doneCompleter.complete(); if (!_inAddStream) return; - _addStreamCompleter.complete(_addStreamSubscription.cancel()); + _addStreamCompleter!.complete(_addStreamSubscription!.cancel()); _addStreamCompleter = null; _addStreamSubscription = null; } diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 8c1b56842..55c98143f 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -51,7 +51,7 @@ class IsolateChannel extends StreamChannelMixin { // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. - StreamSubscription subscription; + late StreamSubscription subscription; subscription = receivePort.listen((message) { if (message is SendPort) { var controller = diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 8bffc8ab9..237193b86 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -18,14 +18,14 @@ import 'stream_channel_transformer.dart'; /// If the transformed channel emits invalid JSON, this emits a /// [FormatException]. If an unencodable object is added to the sink, it /// synchronously throws a [JsonUnsupportedObjectError]. -final StreamChannelTransformer jsonDocument = +final StreamChannelTransformer jsonDocument = const _JsonDocument(); -class _JsonDocument implements StreamChannelTransformer { +class _JsonDocument implements StreamChannelTransformer { const _JsonDocument(); @override - StreamChannel bind(StreamChannel channel) { + StreamChannel bind(StreamChannel channel) { var stream = channel.stream.map(jsonDecode); var sink = StreamSinkTransformer.fromHandlers( handleData: (data, sink) { diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 79f247e08..e1e25ea04 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -73,7 +73,7 @@ abstract class MultiChannel implements StreamChannel { /// /// Throws an [ArgumentError] if a virtual channel already exists for [id]. /// Throws a [StateError] if the underlying channel is closed. - VirtualChannel virtualChannel([int id]); + VirtualChannel virtualChannel([int? id]); } /// The implementation of [MultiChannel]. @@ -85,10 +85,10 @@ class _MultiChannel extends StreamChannelMixin /// The inner channel over which all communication is conducted. /// /// This will be `null` if the underlying communication channel is closed. - StreamChannel _inner; + StreamChannel? _inner; /// The subscription to [_inner].stream. - StreamSubscription _innerStreamSubscription; + StreamSubscription? _innerStreamSubscription; @override Stream get stream => _mainController.foreign.stream; @@ -132,15 +132,15 @@ class _MultiChannel extends StreamChannelMixin /// it's coming from a channel that was originally created locally. var _nextId = 1; - _MultiChannel(this._inner) { + _MultiChannel(StreamChannel inner) : _inner = inner { // The default connection is a special case which has id 0 on both ends. // This allows it to begin connected without having to send over an id. _controllers[0] = _mainController; _mainController.local.stream.listen( - (message) => _inner.sink.add([0, message]), + (message) => _inner!.sink.add([0, message]), onDone: () => _closeChannel(0, 0)); - _innerStreamSubscription = _inner.stream.cast().listen((message) { + _innerStreamSubscription = _inner!.stream.cast().listen((message) { var id = message[0] as int; // If the channel was closed before an incoming message was processed, @@ -170,7 +170,7 @@ class _MultiChannel extends StreamChannelMixin } @override - VirtualChannel virtualChannel([int id]) { + VirtualChannel virtualChannel([int? id]) { int inputId; int outputId; if (id != null) { @@ -194,11 +194,11 @@ class _MultiChannel extends StreamChannelMixin return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); } - StreamChannelController controller; + late StreamChannelController controller; if (_pendingIds.remove(inputId)) { // If we've already received messages for this channel, use the controller // where those messages are buffered. - controller = _controllers[inputId]; + controller = _controllers[inputId]!; } else if (_controllers.containsKey(inputId) || _closedIds.contains(inputId)) { throw ArgumentError('A virtual channel with id $id already exists.'); @@ -208,7 +208,7 @@ class _MultiChannel extends StreamChannelMixin } controller.local.stream.listen( - (message) => _inner.sink.add([outputId, message]), + (message) => _inner!.sink.add([outputId, message]), onDone: () => _closeChannel(inputId, outputId)); return VirtualChannel._( this, outputId, controller.foreign.stream, controller.foreign.sink); @@ -218,21 +218,21 @@ class _MultiChannel extends StreamChannelMixin /// outgoing messages have [outputId]. void _closeChannel(int inputId, int outputId) { _closedIds.add(inputId); - var controller = _controllers.remove(inputId); + var controller = _controllers.remove(inputId)!; controller.local.sink.close(); if (_inner == null) return; // A message without data indicates that the virtual channel has been // closed. - _inner.sink.add([outputId]); + _inner!.sink.add([outputId]); if (_controllers.isEmpty) _closeInnerChannel(); } /// Closes the underlying communication channel. void _closeInnerChannel() { - _inner.sink.close(); - _innerStreamSubscription.cancel(); + _inner!.sink.close(); + _innerStreamSubscription!.cancel(); _inner = null; // Convert this to a list because the close is dispatched synchronously, and diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index a14ffde44..f6fef25dc 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -22,7 +22,7 @@ class StreamChannelCompleter { /// The channel for this completer. StreamChannel get channel => _channel; - StreamChannel _channel; + late final StreamChannel _channel; /// Whether [setChannel] has been called. bool _set = false; @@ -66,7 +66,7 @@ class StreamChannelCompleter { /// /// Either [setChannel] or [setError] may be called at most once. Trying to /// call either of them again will fail. - void setError(error, [StackTrace stackTrace]) { + void setError(Object error, [StackTrace? stackTrace]) { if (_set) throw StateError('The channel has already been set.'); _set = true; diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 136886df7..5c788667d 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -33,14 +33,14 @@ class StreamChannelController { /// This channel should be used directly by the creator of this /// [StreamChannelController] to send and receive events. StreamChannel get local => _local; - StreamChannel _local; + late final StreamChannel _local; /// The foreign channel. /// /// This channel should be returned to external users so they can communicate /// with [local]. StreamChannel get foreign => _foreign; - StreamChannel _foreign; + late final StreamChannel _foreign; /// Creates a [StreamChannelController]. /// diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 61e78c0f3..e4208b953 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-dev +version: 2.1.0-nullsafety description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,11 +8,86 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.9.0-18.0 <2.9.0' dependencies: - async: '>=1.11.0 <3.0.0' + async: '>=2.5.0-nullsafety <2.5.0' dev_dependencies: pedantic: ^1.8.0 test: ^1.2.0 + +dependency_overrides: + async: + git: + url: git://github.com/dart-lang/async.git + ref: null_safety + boolean_selector: + git: + url: git://github.com/dart-lang/boolean_selector.git + ref: null_safety + charcode: + git: + url: git://github.com/dart-lang/charcode.git + ref: null_safety + collection: 1.15.0-nullsafety + js: + git: + url: git://github.com/dart-lang/sdk.git + path: pkg/js + matcher: + git: + url: git://github.com/dart-lang/matcher.git + ref: null_safety + meta: 1.3.0-nullsafety + path: + git: + url: git://github.com/dart-lang/path.git + ref: null_safety + pedantic: + git: + url: git://github.com/dart-lang/pedantic.git + ref: null_safety + pool: + git: + url: git://github.com/dart-lang/pool.git + ref: null_safety + source_maps: + git: + url: git://github.com/dart-lang/source_maps.git + ref: null_safety + source_map_stack_trace: + git: + url: git://github.com/dart-lang/source_map_stack_trace.git + ref: null_safety + source_span: + git: + url: git://github.com/dart-lang/source_span.git + ref: null_safety + stack_trace: + git: + url: git://github.com/dart-lang/stack_trace.git + ref: null_safety + string_scanner: + git: + url: git://github.com/dart-lang/string_scanner.git + ref: null_safety + term_glyph: + git: + url: git://github.com/dart-lang/term_glyph.git + ref: null_safety + test: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test + ref: null_safety + test_api: + git: + url: git://github.com/dart-lang/test.git + ref: null_safety + path: pkgs/test_api + test_core: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test_core + ref: null_safety diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index ec0c64bc0..4f16012bf 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -10,10 +10,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - Disconnector disconnector; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late Disconnector disconnector; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index ec26fb647..a1ec37eaf 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -13,9 +13,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - ReceivePort receivePort; - SendPort sendPort; - StreamChannel channel; + late ReceivePort receivePort; + late SendPort sendPort; + late StreamChannel channel; setUp(() { receivePort = ReceivePort(); var receivePortForSend = ReceivePort(); @@ -128,7 +128,7 @@ void main() { }); group('connect constructors', () { - ReceivePort connectPort; + late ReceivePort connectPort; setUp(() { connectPort = ReceivePort(); }); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 3ccce4ead..48d8f7291 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -9,9 +9,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 0fa1df9ea..00bcabe3b 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -7,9 +7,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamChannelController controller; - MultiChannel channel1; - MultiChannel channel2; + late StreamChannelController controller; + late MultiChannel channel1; + late MultiChannel channel2; setUp(() { controller = StreamChannelController(); channel1 = MultiChannel(controller.local); @@ -85,8 +85,8 @@ void main() { }); group('a locally-created virtual channel', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -185,8 +185,8 @@ void main() { }); group('a remotely-created virtual channel', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -297,8 +297,8 @@ void main() { }); group('when the underlying stream', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); @@ -406,8 +406,8 @@ void main() { }); group('for a virtual channel:', () { - VirtualChannel virtual1; - VirtualChannel virtual2; + late VirtualChannel virtual1; + late VirtualChannel virtual2; setUp(() { virtual1 = channel1.virtualChannel(); virtual2 = channel2.virtualChannel(virtual1.id); diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 234f956ef..a87492500 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -9,10 +9,10 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamChannelCompleter completer; - StreamController streamController; - StreamController sinkController; - StreamChannel innerChannel; + late StreamChannelCompleter completer; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel innerChannel; setUp(() { completer = StreamChannelCompleter(); streamController = StreamController(); diff --git a/pkgs/stream_channel/test/stream_channel_controller_test.dart b/pkgs/stream_channel/test/stream_channel_controller_test.dart index 9b7a851d0..3d661e302 100644 --- a/pkgs/stream_channel/test/stream_channel_controller_test.dart +++ b/pkgs/stream_channel/test/stream_channel_controller_test.dart @@ -7,7 +7,7 @@ import 'package:test/test.dart'; void main() { group('asynchronously', () { - StreamChannelController controller; + late StreamChannelController controller; setUp(() { controller = StreamChannelController(); }); @@ -44,7 +44,7 @@ void main() { }); group('synchronously', () { - StreamChannelController controller; + late StreamChannelController controller; setUp(() { controller = StreamChannelController(sync: true); }); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 9bd5a86f8..e101d206d 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -11,9 +11,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index 24aef0338..decc2b448 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -17,8 +17,8 @@ final _delaySinkTransformer = StreamSinkTransformer.fromStreamTransformer(_delayTransformer); void main() { - StreamChannelController controller; - StreamChannel channel; + late StreamChannelController controller; + late StreamChannel channel; setUp(() { controller = StreamChannelController(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index fa49689af..a19dc58c2 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -9,9 +9,9 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - StreamController streamController; - StreamController sinkController; - StreamChannel channel; + late StreamController streamController; + late StreamController sinkController; + late StreamChannel channel; setUp(() { streamController = StreamController(); sinkController = StreamController(); @@ -152,7 +152,7 @@ void main() { channel.sink.addError('oh no'); expect(channel.sink.done, throwsA('oh no')); sinkController.stream - .listen(null, onError: expectAsync1((_) {}, count: 0)); + .listen(null, onError: expectAsync1((dynamic _) {}, count: 0)); }); test('adding an error causes the stream to emit a done event', () { From 1026372c5f204556234fe367524110bb10f8d7ef Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:32 -0700 Subject: [PATCH 0660/1215] update for the 2.10 dev sdk (dart-lang/stack_trace#78) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/stack_trace/.travis.yml | 10 +++--- pkgs/stack_trace/pubspec.yaml | 65 ++++++++++++++--------------------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 7d59ee777..6058d0ee1 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -1,23 +1,23 @@ language: dart dart: - - dev + - preview/raw/2.10.0-0.2-dev jobs: include: - stage: analyze_and_format name: "Analyzer" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p vm @@ -27,7 +27,7 @@ stages: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 94a80543e..2718262be 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -4,7 +4,8 @@ description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dependencies: path: '>=1.8.0-nullsafety <1.8.0' @@ -15,70 +16,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: - git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety + git: git://github.com/dart-lang/charcode.git collection: + git: git://github.com/dart-lang/collection.git + js: git: - url: git://github.com/dart-lang/collection.git - ref: null_safety + url: git://github.com/dart-lang/sdk.git + path: pkg/js + ref: 2-10-pkgs matcher: - git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety + git: git://github.com/dart-lang/matcher.git meta: git: url: git://github.com/dart-lang/sdk.git - ref: null_safety-pkgs path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git pool: - git: - url: git://github.com/dart-lang/pool.git - ref: null_safety + git: git://github.com/dart-lang/pool.git + source_maps: + git: git://github.com/dart-lang/source_maps.git + source_map_stack_trace: + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stream_channel: - git: - url: git://github.com/dart-lang/stream_channel.git - ref: null_safety + git: git://github.com/dart-lang/stream_channel.git string_scanner: - git: - url: git://github.com/dart-lang/string_scanner.git - ref: null_safety + git: git://github.com/dart-lang/string_scanner.git term_glyph: - git: - url: git://github.com/dart-lang/term_glyph.git - ref: null_safety + git: git://github.com/dart-lang/term_glyph.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_core test: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From e61fb5e430f83db5101a749239d2b4eb214ab8b9 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:41 -0700 Subject: [PATCH 0661/1215] update for the 2.10 dev sdk (dart-lang/stream_channel#61) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/stream_channel/.travis.yml | 4 +- pkgs/stream_channel/pubspec.yaml | 76 ++++++++++++-------------------- 2 files changed, 30 insertions(+), 50 deletions(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index b4907d5d1..176814674 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- dev +- preview/raw/2.10.0-0.2-dev dart_task: - test: --platform vm,chrome @@ -10,7 +10,7 @@ dart_task: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index e4208b953..0dc7c9939 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -8,7 +8,8 @@ author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' @@ -19,75 +20,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: - git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety - collection: 1.15.0-nullsafety + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git js: git: url: git://github.com/dart-lang/sdk.git path: pkg/js + ref: 2-10-pkgs matcher: + git: git://github.com/dart-lang/matcher.git + meta: git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety - meta: 1.3.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git pool: - git: - url: git://github.com/dart-lang/pool.git - ref: null_safety + git: git://github.com/dart-lang/pool.git source_maps: - git: - url: git://github.com/dart-lang/source_maps.git - ref: null_safety + git: git://github.com/dart-lang/source_maps.git source_map_stack_trace: - git: - url: git://github.com/dart-lang/source_map_stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stack_trace: - git: - url: git://github.com/dart-lang/stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/stack_trace.git string_scanner: - git: - url: git://github.com/dart-lang/string_scanner.git - ref: null_safety + git: git://github.com/dart-lang/string_scanner.git term_glyph: - git: - url: git://github.com/dart-lang/term_glyph.git - ref: null_safety - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - ref: null_safety + git: git://github.com/dart-lang/term_glyph.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git path: pkgs/test_core - ref: null_safety + test: + git: + url: git://github.com/dart-lang/test.git + path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From 9a6ecc8fc1bf03a37249a6c7ffcae138d27e36fa Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:49 -0700 Subject: [PATCH 0662/1215] update for the 2.10 dev sdk (dart-lang/string_scanner#23) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/string_scanner/.travis.yml | 10 ++--- pkgs/string_scanner/pubspec.yaml | 68 +++++++++++--------------------- 2 files changed, 29 insertions(+), 49 deletions(-) diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml index dd4f4372d..16a9cd3d1 100644 --- a/pkgs/string_scanner/.travis.yml +++ b/pkgs/string_scanner/.travis.yml @@ -1,23 +1,23 @@ language: dart dart: - - dev + - preview/raw/2.10.0-0.2-dev dart_task: - test: --platform vm,chrome matrix: include: - # Only validate formatting using the dev release - - dart: dev + # Only validate formatting using the preview/raw/2.10.0-0.2-dev release + - dart: preview/raw/2.10.0-0.2-dev dart_task: dartfmt - - dart: dev + - dart: preview/raw/2.10.0-0.2-dev dart_task: dartanalyzer: --fatal-warnings --fatal-hints . # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 7a9826d6c..1c34a645c 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -5,7 +5,8 @@ description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dependencies: charcode: '>=1.2.0-nullsafety <1.2.0' @@ -16,75 +17,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: - git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety - collection: 1.15.0-nullsafety + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git js: git: url: git://github.com/dart-lang/sdk.git path: pkg/js + ref: 2-10-pkgs matcher: + git: git://github.com/dart-lang/matcher.git + meta: git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety - meta: 1.3.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git pool: - git: - url: git://github.com/dart-lang/pool.git - ref: null_safety + git: git://github.com/dart-lang/pool.git source_maps: - git: - url: git://github.com/dart-lang/source_maps.git - ref: null_safety + git: git://github.com/dart-lang/source_maps.git source_map_stack_trace: - git: - url: git://github.com/dart-lang/source_map_stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stack_trace: - git: - url: git://github.com/dart-lang/stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/stack_trace.git stream_channel: - git: - url: git://github.com/dart-lang/stream_channel.git - ref: null_safety + git: git://github.com/dart-lang/stream_channel.git term_glyph: - git: - url: git://github.com/dart-lang/term_glyph.git - ref: null_safety + git: git://github.com/dart-lang/term_glyph.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_core test: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From 4d29fd49eb4bdb10aee2810f232dff1fd7ffd96a Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 21 Jul 2020 19:41:56 -0700 Subject: [PATCH 0663/1215] update for the 2.10 dev sdk (dart-lang/term_glyph#14) This is in preparation for the actual 2.10 dev sdk release. --- pkgs/term_glyph/.travis.yml | 10 +++--- pkgs/term_glyph/pubspec.yaml | 66 ++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 42 deletions(-) diff --git a/pkgs/term_glyph/.travis.yml b/pkgs/term_glyph/.travis.yml index 8fd288834..2d5616518 100644 --- a/pkgs/term_glyph/.travis.yml +++ b/pkgs/term_glyph/.travis.yml @@ -1,23 +1,23 @@ language: dart dart: -- dev +- preview/raw/2.10.0-0.2-dev jobs: include: - stage: analyze_and_format name: "Analyze test/" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: dev + dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p vm @@ -27,7 +27,7 @@ stages: # Only building master means that we don't run two builds for each pull request. branches: - only: [master, null_safety] + only: [master] cache: directories: diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index ace629c54..f69546ddb 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -5,7 +5,8 @@ description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: - sdk: '>=2.9.0-18.0 <2.9.0' + # This must remain a tight constraint until nnbd is stable + sdk: '>=2.10.0-0 <2.10.0' dev_dependencies: csv: '>=3.0.0 <5.0.0' @@ -14,63 +15,54 @@ dev_dependencies: dependency_overrides: async: - git: - url: git://github.com/dart-lang/async.git - ref: null_safety + git: git://github.com/dart-lang/async.git boolean_selector: - git: - url: git://github.com/dart-lang/boolean_selector.git - ref: null_safety + git: git://github.com/dart-lang/boolean_selector.git charcode: + git: git://github.com/dart-lang/charcode.git + collection: + git: git://github.com/dart-lang/collection.git + js: git: - url: git://github.com/dart-lang/charcode.git - ref: null_safety - collection: 1.15.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/js + ref: 2-10-pkgs matcher: + git: git://github.com/dart-lang/matcher.git + meta: git: - url: git://github.com/dart-lang/matcher.git - ref: null_safety - meta: 1.3.0-nullsafety + url: git://github.com/dart-lang/sdk.git + path: pkg/meta + ref: 2-10-pkgs path: - git: - url: git://github.com/dart-lang/path.git - ref: null_safety + git: git://github.com/dart-lang/path.git pedantic: - git: - url: git://github.com/dart-lang/pedantic.git - ref: null_safety + git: git://github.com/dart-lang/pedantic.git pool: - git: - url: git://github.com/dart-lang/pool.git - ref: null_safety + git: git://github.com/dart-lang/pool.git + source_maps: + git: git://github.com/dart-lang/source_maps.git + source_map_stack_trace: + git: git://github.com/dart-lang/source_map_stack_trace.git source_span: - git: - url: git://github.com/dart-lang/source_span.git - ref: null_safety + git: git://github.com/dart-lang/source_span.git stack_trace: - git: - url: git://github.com/dart-lang/stack_trace.git - ref: null_safety + git: git://github.com/dart-lang/stack_trace.git stream_channel: - git: - url: git://github.com/dart-lang/stream_channel.git - ref: null_safety + git: git://github.com/dart-lang/stream_channel.git string_scanner: - git: - url: git://github.com/dart-lang/string_scanner.git - ref: null_safety + git: git://github.com/dart-lang/string_scanner.git test_api: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_api test_core: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test_core test: git: url: git://github.com/dart-lang/test.git - ref: null_safety path: pkgs/test + typed_data: + git: git://github.com/dart-lang/typed_data.git From 83c6c48430414ec2fa110e71eeed0bc7d0d20d49 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 13:47:48 -0700 Subject: [PATCH 0664/1215] Delete .test_config No longer used --- pkgs/stream_channel/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stream_channel/.test_config diff --git a/pkgs/stream_channel/.test_config b/pkgs/stream_channel/.test_config deleted file mode 100644 index 352d2feee..000000000 --- a/pkgs/stream_channel/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} From 91f74c8e6211392c6fb896b72ba520e261016381 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 13:49:12 -0700 Subject: [PATCH 0665/1215] Delete .test_config No longer needed --- pkgs/string_scanner/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/string_scanner/.test_config diff --git a/pkgs/string_scanner/.test_config b/pkgs/string_scanner/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/string_scanner/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file From 729a4c6f74a4b5efcd42a5cdd12182c678486db6 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 14:13:08 -0700 Subject: [PATCH 0666/1215] Update Travis-CI to use dev channel (dart-lang/stream_channel#62) --- pkgs/stream_channel/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml index 176814674..be2f29d02 100644 --- a/pkgs/stream_channel/.travis.yml +++ b/pkgs/stream_channel/.travis.yml @@ -1,7 +1,7 @@ language: dart dart: -- preview/raw/2.10.0-0.2-dev +- dev dart_task: - test: --platform vm,chrome From bd748d6e5396b5632a60152ed9df7636c86dbf8e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 16:50:30 -0700 Subject: [PATCH 0667/1215] Update Travis-CI config to use dev channel (dart-lang/string_scanner#24) --- pkgs/string_scanner/.travis.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml index 16a9cd3d1..481e06250 100644 --- a/pkgs/string_scanner/.travis.yml +++ b/pkgs/string_scanner/.travis.yml @@ -1,19 +1,12 @@ language: dart dart: - - preview/raw/2.10.0-0.2-dev + - dev dart_task: - test: --platform vm,chrome - -matrix: - include: - # Only validate formatting using the preview/raw/2.10.0-0.2-dev release - - dart: preview/raw/2.10.0-0.2-dev - dart_task: dartfmt - - dart: preview/raw/2.10.0-0.2-dev - dart_task: - dartanalyzer: --fatal-warnings --fatal-hints . + - dartfmt + - dartanalyzer: --fatal-warnings --fatal-hints . # Only building master means that we don't run two builds for each pull request. branches: From fc61ff28f25bc50a437c943e13f0dba48620f777 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 16:50:38 -0700 Subject: [PATCH 0668/1215] Update Travis-CI to test on dev branch (dart-lang/term_glyph#15) --- pkgs/term_glyph/.travis.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pkgs/term_glyph/.travis.yml b/pkgs/term_glyph/.travis.yml index 2d5616518..0b9689924 100644 --- a/pkgs/term_glyph/.travis.yml +++ b/pkgs/term_glyph/.travis.yml @@ -1,25 +1,22 @@ language: dart dart: -- preview/raw/2.10.0-0.2-dev +- dev jobs: include: - stage: analyze_and_format - name: "Analyze test/" - dart: preview/raw/2.10.0-0.2-dev + name: "Analyze" os: linux - script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + script: dartanalyzer --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: preview/raw/2.10.0-0.2-dev os: linux - script: pub run --enable-experiment=non-nullable test -p vm + script: pub run test -p vm stages: - analyze_and_format From e54f3e000e917e14b9b09ec67ccdefca6e2d1036 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 20:19:15 -0700 Subject: [PATCH 0669/1215] Delete .test_config No longer used --- pkgs/stack_trace/.test_config | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 pkgs/stack_trace/.test_config diff --git a/pkgs/stack_trace/.test_config b/pkgs/stack_trace/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/stack_trace/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file From a5d8558f9e4e12c12bb5b8188c75b175af9d4763 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Jul 2020 20:29:27 -0700 Subject: [PATCH 0670/1215] Enable dev branch on Travis-CI (dart-lang/stack_trace#80) --- pkgs/stack_trace/.travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 6058d0ee1..441b12e67 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -1,23 +1,20 @@ language: dart dart: - - preview/raw/2.10.0-0.2-dev + - dev jobs: include: - stage: analyze_and_format name: "Analyzer" - dart: preview/raw/2.10.0-0.2-dev os: linux script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . - stage: analyze_and_format name: "Format" - dart: preview/raw/2.10.0-0.2-dev os: linux script: dartfmt -n --set-exit-if-changed . - stage: test name: "Vm Tests" - dart: preview/raw/2.10.0-0.2-dev os: linux script: pub run --enable-experiment=non-nullable test -p vm From dfc6fd73f92f7fdd4ae327b1f31860c89db16baf Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 30 Jul 2020 10:00:20 -0700 Subject: [PATCH 0671/1215] Remove the author section from pubspec (dart-lang/stream_channel#63) Resolves a warning from the pub tool that this field is no longer used. --- pkgs/stream_channel/CHANGELOG.md | 2 ++ pkgs/stream_channel/pubspec.yaml | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2c4a13ce6..98c1e6c29 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,5 @@ +## 2.1.0-nullsafety.1-dev + ## 2.1.0-nullsafety * Migrate to null safety. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0dc7c9939..5895aee59 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,9 @@ name: stream_channel -version: 2.1.0-nullsafety +version: 2.1.0-nullsafety.1-dev description: >- An abstraction for two-way communication channels based on the Dart Stream class. -author: Dart Team homepage: https://github.com/dart-lang/stream_channel environment: From 56a2cad6db1b76032068ce0db80badbef6ef3b79 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 31 Jul 2020 16:32:55 -0700 Subject: [PATCH 0672/1215] Bump min SDK to workaround broken analyzer (dart-lang/stream_transform#112) There is a broken version of `package:analyzer` that causes issues on travis for the `2.6.0` SDK. There is relatively little need to maintain support for an SDK that old, so bump the minimum rather than pin analyzer and be unable to pick up newer versions. https://github.com/dart-lang/sdk/issues/42888 Fix formatting in changelog. --- pkgs/stream_transform/.travis.yml | 4 ++-- pkgs/stream_transform/CHANGELOG.md | 3 ++- pkgs/stream_transform/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 596c0c618..24eb0d797 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,7 +3,7 @@ branches: only: [master] dart: - dev - - 2.6.0 + - 2.7.0 cache: directories: - $HOME/.pub-cache @@ -18,6 +18,6 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-warnings --fatal-infos . - - dart: 2.6.0 + - dart: 2.7.0 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 73fc3688b..268bf3538 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.2.1-dev -* Improve tests of `switchMap` and improve documentation with links and clarification. +- Improve tests of `switchMap` and improve documentation with links and + clarification. ## 1.2.0 diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index c566c1632..5da90b121 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/dart-lang/stream_transform version: 1.2.1-dev environment: - sdk: ">=2.6.0 <3.0.0" + sdk: ">=2.7.0 <3.0.0" dev_dependencies: async: ^2.0.0 From 7e0545dab0fd80dca726b240f7b2c762faee5b6d Mon Sep 17 00:00:00 2001 From: Michael R Fairhurst Date: Thu, 20 Aug 2020 11:28:05 -0700 Subject: [PATCH 0673/1215] Remove unused async import. (dart-lang/stream_transform#113) Since this version does not support dart 2.0, the async import is unnecessary. --- pkgs/stream_transform/lib/src/tap.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 1942b129a..2696e025b 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -1,8 +1,6 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. -import 'dart:async'; - import 'from_handlers.dart'; /// A utility to chain extra behavior on a stream. From d880864ffcfee47e9f0611af5efdfeeab01dcab4 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 4 Sep 2020 09:03:32 -0700 Subject: [PATCH 0674/1215] fix formatting for latest dev SDK --- pkgs/string_scanner/lib/src/string_scanner.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index f29bc3ac6..564774c3a 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -59,7 +59,9 @@ class StringScanner { StringScanner(this.string, {sourceUrl, int? position}) : sourceUrl = sourceUrl == null ? null - : sourceUrl is String ? Uri.parse(sourceUrl) : sourceUrl as Uri { + : sourceUrl is String + ? Uri.parse(sourceUrl) + : sourceUrl as Uri { if (position != null) this.position = position; } From b7b07fa26a253447f27e587ab143df1f898e4e43 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:13:16 -0700 Subject: [PATCH 0675/1215] Prepare for the 2.11 dev SDKs (dart-lang/stack_trace#81) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 4729e7e7a..ce7935dd6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.0-nullsafety.1 + +* Allow 2.10 stable and 2.11.0 dev SDK versions. + ## 1.10.0-nullsafety * Opt in to null safety. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 2718262be..7384c7960 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,11 @@ name: stack_trace -version: 1.10.0-nullsafety +version: 1.10.0-nullsafety.1 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dependencies: path: '>=1.8.0-nullsafety <1.8.0' From bb724781b640a759fbd7384b978310d1c66e00d2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:17:03 -0700 Subject: [PATCH 0676/1215] Prepare for the 2.11 dev SDKs (dart-lang/stream_channel#64) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/stream_channel/CHANGELOG.md | 4 +++- pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 98c1e6c29..83da2abec 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,4 +1,6 @@ -## 2.1.0-nullsafety.1-dev +## 2.1.0-nullsafety.1 + +* Allow 2.10 stable and 2.11.0 dev SDK versions. ## 2.1.0-nullsafety diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5895aee59..b8f0f97f8 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.1-dev +version: 2.1.0-nullsafety.1 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,7 +8,7 @@ homepage: https://github.com/dart-lang/stream_channel environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' From 5b24ebd45b4909b2ad03af2c0f95673dd896601e Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:19:17 -0700 Subject: [PATCH 0677/1215] Prepare for the 2.11 dev SDKs (dart-lang/string_scanner#25) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index abe488c8d..316655105 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0-nullsafety.1 + +- Allow 2.10 stable and 2.11.0 dev SDK versions. + ## 1.1.0-nullsafety - Migrate to null safety. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 1c34a645c..566f482a6 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 1.1.0-nullsafety +version: 1.1.0-nullsafety.1 description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dependencies: charcode: '>=1.2.0-nullsafety <1.2.0' From dfbcc2984d6a61a73619545e697c57983888895d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 22 Sep 2020 09:20:54 -0700 Subject: [PATCH 0678/1215] Prepare for the 2.11 dev SDKs (dart-lang/term_glyph#16) Bump the upper bound to allow 2.10 stable and 2.11.0 dev SDK versions. --- pkgs/term_glyph/CHANGELOG.md | 4 ++++ pkgs/term_glyph/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index c4926bd8b..f5c7ed2e3 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0-nullsafety.1 + +* Allow 2.10 stable and 2.11.0 dev SDK versions. + ## 1.2.0-nullsafety * Update to null safety. All apis require non-nullable types. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index f69546ddb..5027d8e86 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,12 +1,12 @@ name: term_glyph -version: 1.2.0-nullsafety +version: 1.2.0-nullsafety.1 description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.10.0' + sdk: '>=2.10.0-0 <2.11.0' dev_dependencies: csv: '>=3.0.0 <5.0.0' From 61480192638ae9550e2cb19bda3d6e69140a2b77 Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Wed, 23 Sep 2020 15:42:22 +0200 Subject: [PATCH 0679/1215] Implement the ability to register custom watcher implementations This allows registering a special-purpose factory that returns its own `Watcher` implementation that will take precedence over the default ones. The main motivation for this is handling of file systems that need custom code to watch for changes. --- .../lib/src/custom_watcher_factory.dart | 46 +++++++ pkgs/watcher/lib/src/directory_watcher.dart | 11 +- pkgs/watcher/lib/src/file_watcher.dart | 8 ++ pkgs/watcher/lib/watcher.dart | 9 +- .../test/custom_watcher_factory_test.dart | 130 ++++++++++++++++++ 5 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 pkgs/watcher/lib/src/custom_watcher_factory.dart create mode 100644 pkgs/watcher/test/custom_watcher_factory_test.dart diff --git a/pkgs/watcher/lib/src/custom_watcher_factory.dart b/pkgs/watcher/lib/src/custom_watcher_factory.dart new file mode 100644 index 000000000..ffac06bba --- /dev/null +++ b/pkgs/watcher/lib/src/custom_watcher_factory.dart @@ -0,0 +1,46 @@ +import '../watcher.dart'; + +/// Defines a way to create a custom watcher instead of the default ones. +/// +/// This will be used when a [DirectoryWatcher] or [FileWatcher] would be +/// created and will take precedence over the default ones. +abstract class CustomWatcherFactory { + /// Uniquely identify this watcher. + String get id; + + /// Tries to create a [DirectoryWatcher] for the provided path. + /// + /// Should return `null` if the path is not supported by this factory. + DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay}); + + /// Tries to create a [FileWatcher] for the provided path. + /// + /// Should return `null` if the path is not supported by this factory. + FileWatcher createFileWatcher(String path, {Duration pollingDelay}); +} + +/// Registers a custom watcher. +/// +/// It's only allowed to register a watcher once per [id]. The [supportsPath] +/// will be called to determine if the [createWatcher] should be used instead of +/// the built-in watchers. +/// +/// Note that we will try [CustomWatcherFactory] one by one in the order they +/// were registered. +void registerCustomWatcherFactory(CustomWatcherFactory customFactory) { + if (_customWatcherFactories.containsKey(customFactory.id)) { + throw ArgumentError('A custom watcher with id `${customFactory.id}` ' + 'has already been registered'); + } + _customWatcherFactories[customFactory.id] = customFactory; +} + +/// Unregisters a custom watcher and returns it (returns `null` if it was never +/// registered). +CustomWatcherFactory unregisterCustomWatcherFactory(String id) => + _customWatcherFactories.remove(id); + +Iterable get customWatcherFactories => + _customWatcherFactories.values; + +final _customWatcherFactories = {}; diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index e0ef3fcc0..858d02009 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -5,10 +5,11 @@ import 'dart:io'; import '../watcher.dart'; +import 'custom_watcher_factory.dart'; import 'directory_watcher/linux.dart'; import 'directory_watcher/mac_os.dart'; -import 'directory_watcher/windows.dart'; import 'directory_watcher/polling.dart'; +import 'directory_watcher/windows.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something /// in the directory has changed. @@ -29,6 +30,14 @@ abstract class DirectoryWatcher implements Watcher { /// watchers. factory DirectoryWatcher(String directory, {Duration pollingDelay}) { if (FileSystemEntity.isWatchSupported) { + for (var custom in customWatcherFactories) { + var watcher = custom.createDirectoryWatcher(directory, + pollingDelay: pollingDelay); + if (watcher != null) { + return watcher; + } + } + if (Platform.isLinux) return LinuxDirectoryWatcher(directory); if (Platform.isMacOS) return MacOSDirectoryWatcher(directory); if (Platform.isWindows) return WindowsDirectoryWatcher(directory); diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index c4abddd6c..0b7afc787 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -5,6 +5,7 @@ import 'dart:io'; import '../watcher.dart'; +import 'custom_watcher_factory.dart'; import 'file_watcher/native.dart'; import 'file_watcher/polling.dart'; @@ -29,6 +30,13 @@ abstract class FileWatcher implements Watcher { /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. factory FileWatcher(String file, {Duration pollingDelay}) { + for (var custom in customWatcherFactories) { + var watcher = custom.createFileWatcher(file, pollingDelay: pollingDelay); + if (watcher != null) { + return watcher; + } + } + // [File.watch] doesn't work on Windows, but // [FileSystemEntity.isWatchSupported] is still true because directory // watching does work. diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 107ac8fae..f5c7d3ec8 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -5,15 +5,20 @@ import 'dart:async'; import 'dart:io'; -import 'src/watch_event.dart'; import 'src/directory_watcher.dart'; import 'src/file_watcher.dart'; +import 'src/watch_event.dart'; -export 'src/watch_event.dart'; +export 'src/custom_watcher_factory.dart' + show + CustomWatcherFactory, + registerCustomWatcherFactory, + unregisterCustomWatcherFactory; export 'src/directory_watcher.dart'; export 'src/directory_watcher/polling.dart'; export 'src/file_watcher.dart'; export 'src/file_watcher/polling.dart'; +export 'src/watch_event.dart'; abstract class Watcher { /// The path to the file or directory whose contents are being monitored. diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart new file mode 100644 index 000000000..488b60796 --- /dev/null +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -0,0 +1,130 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:test/test.dart'; +import 'package:watcher/watcher.dart'; + +void main() { + _MemFs memFs; + + setUp(() { + memFs = _MemFs(); + registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)); + }); + + tearDown(() async { + unregisterCustomWatcherFactory('MemFs'); + }); + + test('notifes for files', () async { + var watcher = FileWatcher('file.txt'); + + var completer = Completer(); + watcher.events.listen((event) => completer.complete(event)); + await watcher.ready; + memFs.add('file.txt'); + var event = await completer.future; + + expect(event.type, ChangeType.ADD); + expect(event.path, 'file.txt'); + }); + + test('notifes for directories', () async { + var watcher = DirectoryWatcher('dir'); + + var completer = Completer(); + watcher.events.listen((event) => completer.complete(event)); + await watcher.ready; + memFs.add('dir'); + var event = await completer.future; + + expect(event.type, ChangeType.ADD); + expect(event.path, 'dir'); + }); + + test('unregister works', () async { + var memFactory = _MemFsWatcherFactory(memFs); + unregisterCustomWatcherFactory(memFactory.id); + + var completer = Completer(); + var watcher = FileWatcher('file.txt'); + watcher.events.listen((e) {}, onError: (e) => completer.complete(e)); + await watcher.ready; + memFs.add('file.txt'); + var result = await completer.future; + + expect(result, isA()); + }); + + test('registering twice throws', () async { + expect(() => registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)), + throwsA(isA())); + }); +} + +class _MemFs { + final _streams = >>{}; + + StreamController watchStream(String path) { + var controller = StreamController(); + _streams.putIfAbsent(path, () => {}).add(controller); + return controller; + } + + void add(String path) { + var controllers = _streams[path]; + if (controllers != null) { + for (var controller in controllers) { + controller.add(WatchEvent(ChangeType.ADD, path)); + } + } + } + + void remove(String path) { + var controllers = _streams[path]; + if (controllers != null) { + for (var controller in controllers) { + controller.add(WatchEvent(ChangeType.REMOVE, path)); + } + } + } +} + +class _MemFsWatcher implements FileWatcher, DirectoryWatcher, Watcher { + final String _path; + final StreamController _controller; + + _MemFsWatcher(this._path, this._controller); + + @override + String get path => _path; + + @override + String get directory => throw UnsupportedError('directory is not supported'); + + @override + Stream get events => _controller.stream; + + @override + bool get isReady => true; + + @override + Future get ready async {} +} + +class _MemFsWatcherFactory implements CustomWatcherFactory { + final _MemFs _memFs; + _MemFsWatcherFactory(this._memFs); + + @override + String get id => 'MemFs'; + + @override + DirectoryWatcher createDirectoryWatcher(String path, + {Duration pollingDelay}) => + _MemFsWatcher(path, _memFs.watchStream(path)); + + @override + FileWatcher createFileWatcher(String path, {Duration pollingDelay}) => + _MemFsWatcher(path, _memFs.watchStream(path)); +} From 66a9b5cfe615a04a28d25067e64d6fa0dd6e9f5c Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Thu, 24 Sep 2020 12:33:53 +0200 Subject: [PATCH 0680/1215] Fix the test that was timing out --- pkgs/watcher/test/custom_watcher_factory_test.dart | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 488b60796..784769c2a 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -46,14 +46,16 @@ void main() { var memFactory = _MemFsWatcherFactory(memFs); unregisterCustomWatcherFactory(memFactory.id); - var completer = Completer(); + var events = []; var watcher = FileWatcher('file.txt'); - watcher.events.listen((e) {}, onError: (e) => completer.complete(e)); + watcher.events.listen((e) => events.add(e)); await watcher.ready; - memFs.add('file.txt'); - var result = await completer.future; + memFs.add('a.txt'); + memFs.add('b.txt'); + memFs.add('c.txt'); + await Future.delayed(Duration(seconds: 1)); - expect(result, isA()); + expect(events, isEmpty); }); test('registering twice throws', () async { From b0d81fbf553b08dc61e029d54d2eeda1e924e3ed Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Thu, 24 Sep 2020 14:54:44 +0200 Subject: [PATCH 0681/1215] Throw when more than one custom factory is applicable --- .../lib/src/custom_watcher_factory.dart | 57 +++++++++++++++---- pkgs/watcher/lib/src/directory_watcher.dart | 11 +--- pkgs/watcher/lib/src/file_watcher.dart | 9 +-- .../test/custom_watcher_factory_test.dart | 27 +++++---- 4 files changed, 70 insertions(+), 34 deletions(-) diff --git a/pkgs/watcher/lib/src/custom_watcher_factory.dart b/pkgs/watcher/lib/src/custom_watcher_factory.dart index ffac06bba..b7f81fa96 100644 --- a/pkgs/watcher/lib/src/custom_watcher_factory.dart +++ b/pkgs/watcher/lib/src/custom_watcher_factory.dart @@ -10,23 +10,20 @@ abstract class CustomWatcherFactory { /// Tries to create a [DirectoryWatcher] for the provided path. /// - /// Should return `null` if the path is not supported by this factory. + /// Returns `null` if the path is not supported by this factory. DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay}); /// Tries to create a [FileWatcher] for the provided path. /// - /// Should return `null` if the path is not supported by this factory. + /// Returns `null` if the path is not supported by this factory. FileWatcher createFileWatcher(String path, {Duration pollingDelay}); } /// Registers a custom watcher. /// -/// It's only allowed to register a watcher once per [id]. The [supportsPath] -/// will be called to determine if the [createWatcher] should be used instead of -/// the built-in watchers. -/// -/// Note that we will try [CustomWatcherFactory] one by one in the order they -/// were registered. +/// It's only allowed to register a watcher factory once per [id] and at most +/// one factory should apply to any given file (creating a [Watcher] will fail +/// otherwise). void registerCustomWatcherFactory(CustomWatcherFactory customFactory) { if (_customWatcherFactories.containsKey(customFactory.id)) { throw ArgumentError('A custom watcher with id `${customFactory.id}` ' @@ -35,8 +32,48 @@ void registerCustomWatcherFactory(CustomWatcherFactory customFactory) { _customWatcherFactories[customFactory.id] = customFactory; } -/// Unregisters a custom watcher and returns it (returns `null` if it was never -/// registered). +/// Tries to create a custom [DirectoryWatcher] and returns it. +/// +/// Returns `null` if no custom watcher was applicable and throws a [StateError] +/// if more than one was. +DirectoryWatcher createCustomDirectoryWatcher(String path, + {Duration pollingDelay}) { + DirectoryWatcher customWatcher; + String customFactoryId; + for (var watcherFactory in customWatcherFactories) { + if (customWatcher != null) { + throw StateError('Two `CustomWatcherFactory`s applicable: ' + '`$customFactoryId` and `${watcherFactory.id}` for `$path`'); + } + customWatcher = + watcherFactory.createDirectoryWatcher(path, pollingDelay: pollingDelay); + customFactoryId = watcherFactory.id; + } + return customWatcher; +} + +/// Tries to create a custom [FileWatcher] and returns it. +/// +/// Returns `null` if no custom watcher was applicable and throws a [StateError] +/// if more than one was. +FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) { + FileWatcher customWatcher; + String customFactoryId; + for (var watcherFactory in customWatcherFactories) { + if (customWatcher != null) { + throw StateError('Two `CustomWatcherFactory`s applicable: ' + '`$customFactoryId` and `${watcherFactory.id}` for `$path`'); + } + customWatcher = + watcherFactory.createFileWatcher(path, pollingDelay: pollingDelay); + customFactoryId = watcherFactory.id; + } + return customWatcher; +} + +/// Unregisters a custom watcher and returns it. +/// +/// Returns `null` if the id was never registered. CustomWatcherFactory unregisterCustomWatcherFactory(String id) => _customWatcherFactories.remove(id); diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 858d02009..3fe500455 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -30,14 +30,9 @@ abstract class DirectoryWatcher implements Watcher { /// watchers. factory DirectoryWatcher(String directory, {Duration pollingDelay}) { if (FileSystemEntity.isWatchSupported) { - for (var custom in customWatcherFactories) { - var watcher = custom.createDirectoryWatcher(directory, - pollingDelay: pollingDelay); - if (watcher != null) { - return watcher; - } - } - + var customWatcher = + createCustomDirectoryWatcher(directory, pollingDelay: pollingDelay); + if (customWatcher != null) return customWatcher; if (Platform.isLinux) return LinuxDirectoryWatcher(directory); if (Platform.isMacOS) return MacOSDirectoryWatcher(directory); if (Platform.isWindows) return WindowsDirectoryWatcher(directory); diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index 0b7afc787..c41e5e678 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -30,12 +30,9 @@ abstract class FileWatcher implements Watcher { /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. factory FileWatcher(String file, {Duration pollingDelay}) { - for (var custom in customWatcherFactories) { - var watcher = custom.createFileWatcher(file, pollingDelay: pollingDelay); - if (watcher != null) { - return watcher; - } - } + var customWatcher = + createCustomFileWatcher(file, pollingDelay: pollingDelay); + if (customWatcher != null) return customWatcher; // [File.watch] doesn't work on Windows, but // [FileSystemEntity.isWatchSupported] is still true because directory diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 784769c2a..6d9ed406f 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -1,19 +1,19 @@ import 'dart:async'; -import 'dart:io'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; void main() { _MemFs memFs; + final defaultFactoryId = 'MemFs'; setUp(() { memFs = _MemFs(); - registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)); + registerCustomWatcherFactory(_MemFsWatcherFactory(defaultFactoryId, memFs)); }); tearDown(() async { - unregisterCustomWatcherFactory('MemFs'); + unregisterCustomWatcherFactory(defaultFactoryId); }); test('notifes for files', () async { @@ -43,8 +43,7 @@ void main() { }); test('unregister works', () async { - var memFactory = _MemFsWatcherFactory(memFs); - unregisterCustomWatcherFactory(memFactory.id); + unregisterCustomWatcherFactory(defaultFactoryId); var events = []; var watcher = FileWatcher('file.txt'); @@ -59,9 +58,19 @@ void main() { }); test('registering twice throws', () async { - expect(() => registerCustomWatcherFactory(_MemFsWatcherFactory(memFs)), + expect( + () => registerCustomWatcherFactory( + _MemFsWatcherFactory(defaultFactoryId, memFs)), throwsA(isA())); }); + + test('finding two applicable factories throws', () async { + // Note that _MemFsWatcherFactory always returns a watcher, so having two + // will always produce a conflict. + registerCustomWatcherFactory(_MemFsWatcherFactory('Different id', memFs)); + expect(() => FileWatcher('file.txt'), throwsA(isA())); + expect(() => DirectoryWatcher('dir'), throwsA(isA())); + }); } class _MemFs { @@ -115,11 +124,9 @@ class _MemFsWatcher implements FileWatcher, DirectoryWatcher, Watcher { } class _MemFsWatcherFactory implements CustomWatcherFactory { + final String id; final _MemFs _memFs; - _MemFsWatcherFactory(this._memFs); - - @override - String get id => 'MemFs'; + _MemFsWatcherFactory(this.id, this._memFs); @override DirectoryWatcher createDirectoryWatcher(String path, From dd23dc4d09cd666ecc4e99854899ae0288b09e7e Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Thu, 24 Sep 2020 16:01:46 +0200 Subject: [PATCH 0682/1215] Another attempt to make the test work cross platform --- .../test/custom_watcher_factory_test.dart | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 6d9ed406f..964a49d7b 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -3,6 +3,8 @@ import 'dart:async'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; +import 'utils.dart'; + void main() { _MemFs memFs; final defaultFactoryId = 'MemFs'; @@ -45,16 +47,18 @@ void main() { test('unregister works', () async { unregisterCustomWatcherFactory(defaultFactoryId); - var events = []; - var watcher = FileWatcher('file.txt'); - watcher.events.listen((e) => events.add(e)); - await watcher.ready; - memFs.add('a.txt'); - memFs.add('b.txt'); - memFs.add('c.txt'); - await Future.delayed(Duration(seconds: 1)); + watcherFactory = (path) => FileWatcher(path); + try { + // This uses standard files, so it wouldn't trigger an event in + // _MemFsWatcher. + writeFile('file.txt'); + await startWatcher(path: 'file.txt'); + deleteFile('file.txt'); + } finally { + watcherFactory = null; + } - expect(events, isEmpty); + await expectRemoveEvent('file.txt'); }); test('registering twice throws', () async { From 11c4fcd54ceea4566375da16081f63e52d6b85f9 Mon Sep 17 00:00:00 2001 From: Paul Berry Date: Thu, 24 Sep 2020 10:27:59 -0700 Subject: [PATCH 0683/1215] Avoid converting stacktrace to nullable and then null checking it. (dart-lang/stack_trace#82) The Dart implementation will soon be changed so that a declaration such as `T? x = y`, where `y` has a non-nullable type, automatically promotes `x` to a non-nullable type. This will in turn cause a warning if a non-nullable value is assigned to a nullable variable and then null checked. We're currently doing that in one place, and there's no need to, so remove the unnecessary type conversion and null check. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/lib/src/stack_zone_specification.dart | 4 ++-- pkgs/stack_trace/pubspec.yaml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ce7935dd6..da560f085 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.0-nullsafety.2 + +* Forward fix for a change in SDK type promotion behavior. + ## 1.10.0-nullsafety.1 * Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 13cdf2763..e13e5d481 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -99,8 +99,8 @@ class StackZoneSpecification { return LazyChain(() => Chain.parse(trace!.toString())); } else { if (trace is! Trace) { - StackTrace? original = trace; - trace = LazyTrace(() => Trace.parse(_trimVMChain(original!))); + var original = trace; + trace = LazyTrace(() => Trace.parse(_trimVMChain(original))); } return _Node(trace, previous).toChain(); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 7384c7960..1a19c9fd9 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.0-nullsafety.1 +version: 1.10.0-nullsafety.2 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace From 9f639cd813f7f76b72032111bbee755259cd36bf Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Fri, 25 Sep 2020 08:24:35 +0200 Subject: [PATCH 0684/1215] Minor fixes for earlier Dart versions and lint --- pkgs/watcher/test/custom_watcher_factory_test.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 964a49d7b..6c9ffd873 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -82,7 +82,9 @@ class _MemFs { StreamController watchStream(String path) { var controller = StreamController(); - _streams.putIfAbsent(path, () => {}).add(controller); + _streams + .putIfAbsent(path, () => >{}) + .add(controller); return controller; } @@ -128,6 +130,7 @@ class _MemFsWatcher implements FileWatcher, DirectoryWatcher, Watcher { } class _MemFsWatcherFactory implements CustomWatcherFactory { + @override final String id; final _MemFs _memFs; _MemFsWatcherFactory(this.id, this._memFs); From eea63b3370c042b65e6795e67307bb5d7cc836f4 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Thu, 1 Oct 2020 09:43:46 -0700 Subject: [PATCH 0685/1215] Remove pinned deps (dart-lang/stack_trace#83) * update versions for next release * remove pinned deps and depend on real versions --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/pubspec.yaml | 62 +++-------------------------------- 2 files changed, 6 insertions(+), 58 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index da560f085..c95d40599 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.10.0-nullsafety.3-dev + ## 1.10.0-nullsafety.2 * Forward fix for a change in SDK type promotion behavior. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 1a19c9fd9..b5806b14e 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.0-nullsafety.2 +version: 1.10.0-nullsafety.3-dev description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace @@ -8,62 +8,8 @@ environment: sdk: '>=2.10.0-0 <2.11.0' dependencies: - path: '>=1.8.0-nullsafety <1.8.0' + path: ^1.8.0-nullsafety dev_dependencies: - pedantic: ^1.0.0 - test: '>=0.12.17 <2.0.0' - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stream_channel: - git: git://github.com/dart-lang/stream_channel.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety From 6e78dd3085e2a28149a557d444acc7a9d97097e2 Mon Sep 17 00:00:00 2001 From: John McDole Date: Thu, 1 Oct 2020 14:48:53 -0700 Subject: [PATCH 0686/1215] Put examples in code blocks for better dart doc (dart-lang/stream_transform#115) --- pkgs/stream_transform/lib/src/merge.dart | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index afc2da4ee..c68695ca7 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -16,11 +16,11 @@ extension Merge on Stream { /// /// For example: /// - /// final result = source.merge(other); + /// final result = source.merge(other); /// - /// source: 1--2-----3--| - /// other: ------4-------5--| - /// result: 1--2--4--3----5--| + /// source: 1--2-----3--| + /// other: ------4-------5--| + /// result: 1--2--4--3----5--| /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of [other]'s type. If a single subscription stream is @@ -40,12 +40,12 @@ extension Merge on Stream { /// /// For example: /// - /// final result = first.mergeAll([second, third]); + /// final result = first.mergeAll([second, third]); /// - /// first: 1--2--------3--| - /// second: ---------4-------5--| - /// third: ------6---------------7--| - /// result: 1--2--6--4--3----5----7--| + /// first: 1--2--------3--| + /// second: ---------4-------5--| + /// third: ------6---------------7--| + /// result: 1--2--6--4--3----5----7--| /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless the types of streams in [others]. If a single From 11afd06ca693853675f6d6482752e769fc5e968f Mon Sep 17 00:00:00 2001 From: Clement Skau Date: Thu, 8 Oct 2020 18:41:05 +0200 Subject: [PATCH 0687/1215] Fix async gap handling. (dart-lang/stack_trace#84) Fix an issue where an async gap at the end of a stack trace would not get parsed correctly due to the trailing newline being `trim()`'d. Add tests to cover this case. --- pkgs/stack_trace/CHANGELOG.md | 3 ++ pkgs/stack_trace/lib/src/trace.dart | 6 +++- pkgs/stack_trace/lib/src/utils.dart | 2 +- pkgs/stack_trace/test/trace_test.dart | 41 +++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index c95d40599..a73814528 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,5 +1,8 @@ ## 1.10.0-nullsafety.3-dev +* Fix bug parsing asynchronous suspension gap markers at the end of stack + traces. + ## 1.10.0-nullsafety.2 * Forward fix for a change in SDK type promotion behavior. diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index dc7fd5d2e..7e30b9504 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -146,7 +146,11 @@ class Trace implements StackTrace { static List _parseVM(String trace) { // Ignore [vmChainGap]. This matches the behavior of // `Chain.parse().toTrace()`. - var lines = trace.trim().replaceAll(vmChainGap, '').split('\n'); + var lines = trace + .trim() + .replaceAll(vmChainGap, '') + .split('\n') + .where((line) => line.isNotEmpty); var frames = lines .take(lines.length - 1) .map((line) => Frame.parseVM(line)) diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 838a093b5..0dd1755af 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -8,7 +8,7 @@ const chainGap = '===== asynchronous gap ===========================\n'; /// The line used in the string representation of VM stack chains to represent /// the gap between traces. -const vmChainGap = '\n'; +final vmChainGap = RegExp(r'^\n?$', multiLine: true); // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index a10c69d81..ea48e039c 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -249,6 +249,25 @@ void main() { equals(Uri.parse('https://dart.dev/foo/quux.dart'))); }); + test('parses a package:stack_trace stack chain with end gap correctly', () { + var trace = + Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/baz.dart Foo..bar\n' + 'https://dart.dev/foo/bang.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/quux.dart Foo..bar' + '===== asynchronous gap ===========================\n'); + + expect(trace.frames.length, 4); + expect(trace.frames[0].uri, + equals(Uri.parse('https://dart.dev/foo/bar.dart'))); + expect(trace.frames[1].uri, + equals(Uri.parse('https://dart.dev/foo/baz.dart'))); + expect(trace.frames[2].uri, + equals(Uri.parse('https://dart.dev/foo/bang.dart'))); + expect(trace.frames[3].uri, + equals(Uri.parse('https://dart.dev/foo/quux.dart'))); + }); + test('parses a real package:stack_trace stack trace correctly', () { var traceString = Trace.current().toString(); expect(Trace.parse(traceString).toString(), equals(traceString)); @@ -259,6 +278,28 @@ void main() { expect(trace.frames, isEmpty); expect(trace.toString(), equals('')); }); + + test('parses trace with async gap correctly', () { + var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' + '\n' + '#1 twist (dart:the/future.dart:0:2)\n' + '#2 main (dart:my/file.dart:4:6)\n'); + + expect(trace.frames.length, 3); + expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); + expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); + expect(trace.frames[2].uri, equals(Uri.parse('dart:my/file.dart'))); + }); + + test('parses trace with async gap at end correctly', () { + var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' + '#1 twist (dart:the/future.dart:0:2)\n' + '\n'); + + expect(trace.frames.length, 2); + expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); + expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); + }); }); test('.toString() nicely formats the stack trace', () { From 9329e8edcda570c858a8e95e06f455ac7ef917c1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 12 Oct 2020 09:49:43 -0700 Subject: [PATCH 0688/1215] Expose a smaller surface area for custom watchers (dart-lang/watcher#92) - Remove the function to unregister a custom watcher, we can add it later when we have a specific use case for it. - Remove the class `CustomFactoryWatcher` and take callbacks instead. - Bump the version and add the changelog that was missed. - Add missing copyright notice. --- pkgs/watcher/CHANGELOG.md | 4 + .../lib/src/custom_watcher_factory.dart | 74 ++++++++++--------- pkgs/watcher/lib/watcher.dart | 6 +- .../test/custom_watcher_factory_test.dart | 47 ++++-------- 4 files changed, 57 insertions(+), 74 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index a65a6e3b2..a98ae202a 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 0.9.8 + +* Add the ability to create custom Watcher types for specific file paths. + # 0.9.7+15 * Fix a bug on Mac where modifying a directory with a path exactly matching a diff --git a/pkgs/watcher/lib/src/custom_watcher_factory.dart b/pkgs/watcher/lib/src/custom_watcher_factory.dart index b7f81fa96..3dc1beafc 100644 --- a/pkgs/watcher/lib/src/custom_watcher_factory.dart +++ b/pkgs/watcher/lib/src/custom_watcher_factory.dart @@ -1,35 +1,48 @@ -import '../watcher.dart'; +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// 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. -/// Defines a way to create a custom watcher instead of the default ones. -/// -/// This will be used when a [DirectoryWatcher] or [FileWatcher] would be -/// created and will take precedence over the default ones. -abstract class CustomWatcherFactory { - /// Uniquely identify this watcher. - String get id; +import '../watcher.dart'; - /// Tries to create a [DirectoryWatcher] for the provided path. - /// - /// Returns `null` if the path is not supported by this factory. - DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay}); +/// A factory to produce custom watchers for specific file paths. +class _CustomWatcherFactory { + final String id; + final DirectoryWatcher Function(String path, {Duration pollingDelay}) + createDirectoryWatcher; + final FileWatcher Function(String path, {Duration pollingDelay}) + createFileWatcher; - /// Tries to create a [FileWatcher] for the provided path. - /// - /// Returns `null` if the path is not supported by this factory. - FileWatcher createFileWatcher(String path, {Duration pollingDelay}); + _CustomWatcherFactory( + this.id, this.createDirectoryWatcher, this.createFileWatcher); } /// Registers a custom watcher. /// -/// It's only allowed to register a watcher factory once per [id] and at most -/// one factory should apply to any given file (creating a [Watcher] will fail -/// otherwise). -void registerCustomWatcherFactory(CustomWatcherFactory customFactory) { - if (_customWatcherFactories.containsKey(customFactory.id)) { - throw ArgumentError('A custom watcher with id `${customFactory.id}` ' +/// Each custom watcher must have a unique [id] and the same watcher may not be +/// registered more than once. +/// [createDirectoryWatcher] and [createFileWatcher] should return watchers for +/// the file paths they are able to handle. If the custom watcher is not able to +/// handle the path it should reuturn null. +/// The paths handled by each custom watch may not overlap, at most one custom +/// matcher may return a non-null watcher for a given path. +/// +/// When a file or directory watcher is created the path is checked against each +/// registered custom watcher, and if exactly one custom watcher is available it +/// will be used instead of the default. +void registerCustomWatcher( + String id, + DirectoryWatcher Function(String path, {Duration pollingDelay}) + createDirectoryWatcher, + FileWatcher Function(String path, {Duration pollingDelay}) createFileWatcher, +) { + if (_customWatcherFactories.containsKey(id)) { + throw ArgumentError('A custom watcher with id `$id` ' 'has already been registered'); } - _customWatcherFactories[customFactory.id] = customFactory; + _customWatcherFactories[id] = _CustomWatcherFactory( + id, + createDirectoryWatcher ?? (_, {pollingDelay}) => null, + createFileWatcher ?? (_, {pollingDelay}) => null); } /// Tries to create a custom [DirectoryWatcher] and returns it. @@ -40,7 +53,7 @@ DirectoryWatcher createCustomDirectoryWatcher(String path, {Duration pollingDelay}) { DirectoryWatcher customWatcher; String customFactoryId; - for (var watcherFactory in customWatcherFactories) { + for (var watcherFactory in _customWatcherFactories.values) { if (customWatcher != null) { throw StateError('Two `CustomWatcherFactory`s applicable: ' '`$customFactoryId` and `${watcherFactory.id}` for `$path`'); @@ -59,7 +72,7 @@ DirectoryWatcher createCustomDirectoryWatcher(String path, FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) { FileWatcher customWatcher; String customFactoryId; - for (var watcherFactory in customWatcherFactories) { + for (var watcherFactory in _customWatcherFactories.values) { if (customWatcher != null) { throw StateError('Two `CustomWatcherFactory`s applicable: ' '`$customFactoryId` and `${watcherFactory.id}` for `$path`'); @@ -71,13 +84,4 @@ FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) { return customWatcher; } -/// Unregisters a custom watcher and returns it. -/// -/// Returns `null` if the id was never registered. -CustomWatcherFactory unregisterCustomWatcherFactory(String id) => - _customWatcherFactories.remove(id); - -Iterable get customWatcherFactories => - _customWatcherFactories.values; - -final _customWatcherFactories = {}; +final _customWatcherFactories = {}; diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index f5c7d3ec8..5ea8beb21 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -9,11 +9,7 @@ import 'src/directory_watcher.dart'; import 'src/file_watcher.dart'; import 'src/watch_event.dart'; -export 'src/custom_watcher_factory.dart' - show - CustomWatcherFactory, - registerCustomWatcherFactory, - unregisterCustomWatcherFactory; +export 'src/custom_watcher_factory.dart' show registerCustomWatcher; export 'src/directory_watcher.dart'; export 'src/directory_watcher/polling.dart'; export 'src/file_watcher.dart'; diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 6c9ffd873..8210c065b 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -3,19 +3,17 @@ import 'dart:async'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; -import 'utils.dart'; - void main() { _MemFs memFs; final defaultFactoryId = 'MemFs'; - setUp(() { + setUpAll(() { memFs = _MemFs(); - registerCustomWatcherFactory(_MemFsWatcherFactory(defaultFactoryId, memFs)); - }); - - tearDown(() async { - unregisterCustomWatcherFactory(defaultFactoryId); + var watcherFactory = _MemFsWatcherFactory(memFs); + registerCustomWatcher( + defaultFactoryId, + watcherFactory.createDirectoryWatcher, + watcherFactory.createFileWatcher); }); test('notifes for files', () async { @@ -44,34 +42,19 @@ void main() { expect(event.path, 'dir'); }); - test('unregister works', () async { - unregisterCustomWatcherFactory(defaultFactoryId); - - watcherFactory = (path) => FileWatcher(path); - try { - // This uses standard files, so it wouldn't trigger an event in - // _MemFsWatcher. - writeFile('file.txt'); - await startWatcher(path: 'file.txt'); - deleteFile('file.txt'); - } finally { - watcherFactory = null; - } - - await expectRemoveEvent('file.txt'); - }); - test('registering twice throws', () async { expect( - () => registerCustomWatcherFactory( - _MemFsWatcherFactory(defaultFactoryId, memFs)), + () => registerCustomWatcher(defaultFactoryId, + (_, {pollingDelay}) => null, (_, {pollingDelay}) => null), throwsA(isA())); }); test('finding two applicable factories throws', () async { // Note that _MemFsWatcherFactory always returns a watcher, so having two // will always produce a conflict. - registerCustomWatcherFactory(_MemFsWatcherFactory('Different id', memFs)); + var watcherFactory = _MemFsWatcherFactory(memFs); + registerCustomWatcher('Different id', watcherFactory.createDirectoryWatcher, + watcherFactory.createFileWatcher); expect(() => FileWatcher('file.txt'), throwsA(isA())); expect(() => DirectoryWatcher('dir'), throwsA(isA())); }); @@ -129,18 +112,14 @@ class _MemFsWatcher implements FileWatcher, DirectoryWatcher, Watcher { Future get ready async {} } -class _MemFsWatcherFactory implements CustomWatcherFactory { - @override - final String id; +class _MemFsWatcherFactory { final _MemFs _memFs; - _MemFsWatcherFactory(this.id, this._memFs); + _MemFsWatcherFactory(this._memFs); - @override DirectoryWatcher createDirectoryWatcher(String path, {Duration pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); - @override FileWatcher createFileWatcher(String path, {Duration pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); } From 8a4ef3c15333561df38070a2a850ab3aab9983b4 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 13 Oct 2020 12:58:54 -0700 Subject: [PATCH 0689/1215] Prepare to publish (dart-lang/stack_trace#85) Bump the min SDk to `2.11.0-0`. There were changes previously which appear to depend on changes in the SDK that were not reflected in the lower bound constraint, bump to a much more recent SDK for safety. --- pkgs/stack_trace/CHANGELOG.md | 2 +- pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index a73814528..ae692a01a 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.10.0-nullsafety.3-dev +## 1.10.0-nullsafety.3 * Fix bug parsing asynchronous suspension gap markers at the end of stack traces. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index b5806b14e..3713f7fba 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,11 @@ name: stack_trace -version: 1.10.0-nullsafety.3-dev +version: 1.10.0-nullsafety.3 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.11.0-0 <2.11.0' dependencies: path: ^1.8.0-nullsafety From e22d281b22fca47001c35dda280528e83ebc8b9f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 14 Oct 2020 11:35:23 -0700 Subject: [PATCH 0690/1215] Allow earlier SDKs (dart-lang/stack_trace#86) This was bumped because it wasn't clear which SDKs it worked with, however a comment on an earlier PR shows that it is compatible with early SDKs. --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ae692a01a..ef00a48b0 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.0-nullsafety.4 + +* Allow the `2.10.0` stable and dev SDKs. + ## 1.10.0-nullsafety.3 * Fix bug parsing asynchronous suspension gap markers at the end of stack diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 3713f7fba..4ffb4a084 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,11 @@ name: stack_trace -version: 1.10.0-nullsafety.3 +version: 1.10.0-nullsafety.4 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.11.0-0 <2.11.0' + sdk: '>=2.10.0-0.0.dev <2.11.0' dependencies: path: ^1.8.0-nullsafety From 18d7aa816c879f767b5b134a3f92d01413e3b772 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 20 Oct 2020 16:12:08 -0700 Subject: [PATCH 0691/1215] Remove unused dart:async import The only members of dart:async used here (Future and/or Stream) are exported from dart:core now. --- pkgs/stream_channel/lib/src/stream_channel_completer.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index f6fef25dc..5a824c1f3 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -2,8 +2,6 @@ // 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. -import 'dart:async'; - import 'package:async/async.dart'; import '../stream_channel.dart'; From 01d5ab2f3c31f07060b814b23f3e68b62c832456 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 20 Oct 2020 16:25:34 -0700 Subject: [PATCH 0692/1215] Remove unused dart:async import The only members of dart:async used here (Future and/or Stream) are exported from dart:core now. --- pkgs/watcher/lib/src/async_queue.dart | 1 - pkgs/watcher/lib/src/stat.dart | 1 - pkgs/watcher/lib/watcher.dart | 1 - 3 files changed, 3 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 9f8bedf54..37f13d61d 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:async'; import 'dart:collection'; typedef ItemProcessor = Future Function(T item); diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index fb157a571..08cf935c7 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:async'; import 'dart:io'; /// A function that takes a file path and returns the last modified time for diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 5ea8beb21..01336ab5a 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:async'; import 'dart:io'; import 'src/directory_watcher.dart'; From 9a870e6688825a7b1bb8411c2cfd235d06f17eed Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:09:36 -0700 Subject: [PATCH 0693/1215] allow the 2.12 prerelease sdks (dart-lang/stack_trace#87) --- pkgs/stack_trace/CHANGELOG.md | 4 ++++ pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ef00a48b0..1e196148d 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.10.0-nullsafety.5 + +* Allow prerelease versions of the 2.12 sdk. + ## 1.10.0-nullsafety.4 * Allow the `2.10.0` stable and dev SDKs. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 4ffb4a084..7dbf9a8f5 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,11 @@ name: stack_trace -version: 1.10.0-nullsafety.4 +version: 1.10.0-nullsafety.5 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0.0.dev <2.11.0' + sdk: '>=2.10.0-0.0.dev <2.12.0' dependencies: path: ^1.8.0-nullsafety From 85fcb605844bd414e433993484864c55cabfdb90 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:10:17 -0700 Subject: [PATCH 0694/1215] allow the 2.12 prerelease sdks (dart-lang/stream_channel#66) --- pkgs/stream_channel/CHANGELOG.md | 4 +++ pkgs/stream_channel/pubspec.yaml | 62 +++----------------------------- 2 files changed, 8 insertions(+), 58 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 83da2abec..95f370c38 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0-nullsafety.2 + +* Allow prerelease versions of the 2.12 sdk. + ## 2.1.0-nullsafety.1 * Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index b8f0f97f8..9259c34c4 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.1 +version: 2.1.0-nullsafety.2 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -8,65 +8,11 @@ homepage: https://github.com/dart-lang/stream_channel environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.10.0-0 <2.12.0' dependencies: async: '>=2.5.0-nullsafety <2.5.0' dev_dependencies: - pedantic: ^1.8.0 - test: ^1.2.0 - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety From cf1691818929bd9349fc89574d0a71e495495003 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:11:02 -0700 Subject: [PATCH 0695/1215] allow the 2.12 prerelease sdks (dart-lang/string_scanner#26) --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 316655105..4379f83db 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.0-nullsafety.2 + +* Allow prerelease versions of the 2.12 sdk. + ## 1.1.0-nullsafety.1 - Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 566f482a6..9684e14f1 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,12 @@ name: string_scanner -version: 1.1.0-nullsafety.1 +version: 1.1.0-nullsafety.2 description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.10.0-0 <2.12.0' dependencies: charcode: '>=1.2.0-nullsafety <1.2.0' From da66d86e7e0bdafb6cc2c03d5a9e43e1b80d9066 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 13:14:09 -0700 Subject: [PATCH 0696/1215] allow the 2.12 prerelease sdks (dart-lang/term_glyph#17) --- pkgs/term_glyph/CHANGELOG.md | 4 +++ pkgs/term_glyph/pubspec.yaml | 60 ++---------------------------------- 2 files changed, 7 insertions(+), 57 deletions(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index f5c7ed2e3..a2c1dfbfd 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0-nullsafety.2 + +* Allow prerelease versions of the 2.12 sdk. + ## 1.2.0-nullsafety.1 * Allow 2.10 stable and 2.11.0 dev SDK versions. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 5027d8e86..148db8df4 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,68 +1,14 @@ name: term_glyph -version: 1.2.0-nullsafety.1 +version: 1.2.0-nullsafety.2 description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.11.0' + sdk: '>=2.10.0-0 <2.12.0' dev_dependencies: csv: '>=3.0.0 <5.0.0' dart_style: '>=0.2.0 <2.0.0' - test: '>=0.12.0 <2.0.0' - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - stream_channel: - git: git://github.com/dart-lang/stream_channel.git - string_scanner: - git: git://github.com/dart-lang/string_scanner.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git + test: ^1.16.0-nullsafety From 1c3b95377d5fef77e90849437a74f263ec60430e Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 23 Oct 2020 14:32:23 -0700 Subject: [PATCH 0697/1215] remove dep overrides (dart-lang/string_scanner#27) --- pkgs/string_scanner/pubspec.yaml | 54 -------------------------------- 1 file changed, 54 deletions(-) diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 9684e14f1..3319875fa 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -14,57 +14,3 @@ dependencies: dev_dependencies: test: '>=1.16.0-nullsafety <1.16.0' - -dependency_overrides: - async: - git: git://github.com/dart-lang/async.git - boolean_selector: - git: git://github.com/dart-lang/boolean_selector.git - charcode: - git: git://github.com/dart-lang/charcode.git - collection: - git: git://github.com/dart-lang/collection.git - js: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/js - ref: 2-10-pkgs - matcher: - git: git://github.com/dart-lang/matcher.git - meta: - git: - url: git://github.com/dart-lang/sdk.git - path: pkg/meta - ref: 2-10-pkgs - path: - git: git://github.com/dart-lang/path.git - pedantic: - git: git://github.com/dart-lang/pedantic.git - pool: - git: git://github.com/dart-lang/pool.git - source_maps: - git: git://github.com/dart-lang/source_maps.git - source_map_stack_trace: - git: git://github.com/dart-lang/source_map_stack_trace.git - source_span: - git: git://github.com/dart-lang/source_span.git - stack_trace: - git: git://github.com/dart-lang/stack_trace.git - stream_channel: - git: git://github.com/dart-lang/stream_channel.git - term_glyph: - git: git://github.com/dart-lang/term_glyph.git - test_api: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_api - test_core: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test_core - test: - git: - url: git://github.com/dart-lang/test.git - path: pkgs/test - typed_data: - git: git://github.com/dart-lang/typed_data.git From 5a4d85a5be57ad3a31e7f47fc5252d500352f802 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 30 Oct 2020 18:44:31 -0700 Subject: [PATCH 0698/1215] add support for github actions --- .../.github/workflows/build.yaml | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 pkgs/test_reflective_loader/.github/workflows/build.yaml diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml new file mode 100644 index 000000000..4d33943d7 --- /dev/null +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -0,0 +1,29 @@ +name: Dart + +on: + pull_request: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + + container: + image: google/dart:beta + + steps: + - uses: actions/checkout@v2 + + - name: pub get + run: pub get + + - name: dart format + run: dart format --output=none --set-exit-if-changed . + + - name: dart analyze + run: dart analyze + + - name: dart test + run: dart test From dfb474bd54e6e446d9da6099d76f90491b3dff41 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 31 Oct 2020 15:16:28 -0700 Subject: [PATCH 0699/1215] remove travis support --- pkgs/test_reflective_loader/.travis.yml | 3 --- pkgs/test_reflective_loader/README.md | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 pkgs/test_reflective_loader/.travis.yml diff --git a/pkgs/test_reflective_loader/.travis.yml b/pkgs/test_reflective_loader/.travis.yml deleted file mode 100644 index 99c700e11..000000000 --- a/pkgs/test_reflective_loader/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: dart -dart: [dev, stable, 1.24.3] -script: ./tool/travis.sh diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index 66dca98c2..46558b006 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -1,6 +1,6 @@ # test_reflective_loader -[![Build Status](https://travis-ci.org/dart-lang/test_reflective_loader.svg?branch=master)](https://travis-ci.org/dart-lang/test_reflective_loader) +[![Build Status](![Dart](https://github.com/dart-lang/test_reflective_loader/workflows/Dart/badge.svg))](https://github.com/dart-lang/test_reflective_loader/actions) Support for discovering tests and test suites using reflection. From f6b04f353f0aba90a7cbb907f8ad1d3bfc6b5d56 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 31 Oct 2020 21:38:17 -0700 Subject: [PATCH 0700/1215] Update README.md --- pkgs/test_reflective_loader/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index 46558b006..b7f5e19a7 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -1,6 +1,6 @@ # test_reflective_loader -[![Build Status](![Dart](https://github.com/dart-lang/test_reflective_loader/workflows/Dart/badge.svg))](https://github.com/dart-lang/test_reflective_loader/actions) +[![Build Status](https://github.com/dart-lang/test_reflective_loader/workflows/Dart/badge.svg)](https://github.com/dart-lang/test_reflective_loader/actions) Support for discovering tests and test suites using reflection. From ad10067ec639cdfc2b9b16e1b49ed5e87ec8a96c Mon Sep 17 00:00:00 2001 From: Clement Skau Date: Mon, 2 Nov 2020 08:49:10 +0100 Subject: [PATCH 0701/1215] Fixes async gap handling in Trace.parse and Chain.parse (dart-lang/stack_trace#89) * Fixes Trace and Chain parsing of async gap at end. * Update CHANGELOG.md. * Lint: isEmpty instead of length * Bump version in pubspec.yaml --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/lib/src/chain.dart | 6 ++++-- pkgs/stack_trace/lib/src/trace.dart | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 15 +++++++++++++++ 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 1e196148d..46a371ddc 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.10.0-nullsafety.6-dev + +* Fix bug parsing asynchronous suspension gap markers at the end of stack + traces, when parsing with `Trace.parse` and `Chain.parse`. + ## 1.10.0-nullsafety.5 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index ba6fa4055..aad0c338b 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -180,8 +180,10 @@ class Chain implements StackTrace { factory Chain.parse(String chain) { if (chain.isEmpty) return Chain([]); if (chain.contains(vmChainGap)) { - return Chain( - chain.split(vmChainGap).map((trace) => Trace.parseVM(trace))); + return Chain(chain + .split(vmChainGap) + .where((line) => line.isNotEmpty) + .map((trace) => Trace.parseVM(trace))); } if (!chain.contains(chainGap)) return Chain([Trace.parse(chain)]); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 7e30b9504..42371c744 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -151,6 +151,11 @@ class Trace implements StackTrace { .replaceAll(vmChainGap, '') .split('\n') .where((line) => line.isNotEmpty); + + if (lines.isEmpty) { + return []; + } + var frames = lines .take(lines.length - 1) .map((line) => Frame.parseVM(line)) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 7dbf9a8f5..048978c1d 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.0-nullsafety.5 +version: 1.10.0-nullsafety.6-dev description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 1e466ac05..3309ae1ca 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -36,6 +36,21 @@ void main() { expect(chain.traces[1].frames, isEmpty); expect(chain.traces[2].frames, isEmpty); }); + + test('parses a chain with VM gaps', () { + final chain = + Chain.parse('#1 MyClass.run (package:my_lib.dart:134:5)\n' + '\n' + '#2 main (file:///my_app.dart:9:3)\n' + '\n'); + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames, hasLength(1)); + expect(chain.traces[0].frames[0].toString(), + equals('package:my_lib.dart 134:5 in MyClass.run')); + expect(chain.traces[1].frames, hasLength(1)); + expect(chain.traces[1].frames[0].toString(), + equals('/my_app.dart 9:3 in main')); + }); }); group('Chain.capture()', () { From f1aa7e540bded95869ff90c294d32fedbb9063d1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 2 Nov 2020 13:10:47 -0800 Subject: [PATCH 0702/1215] Enable the last pedantic lint (dart-lang/stack_trace#90) --- pkgs/stack_trace/analysis_options.yaml | 2 -- pkgs/stack_trace/lib/src/chain.dart | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 3d96bfc85..2163f52ce 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -4,8 +4,6 @@ analyzer: - non-nullable strong-mode: implicit-casts: false - errors: - prefer_spread_collections: ignore linter: rules: diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index aad0c338b..fef2c2dd4 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -153,7 +153,7 @@ class Chain implements StackTrace { // doesn't, so we skip an extra frame in a JS context. var first = Trace(chain.traces.first.frames.skip(level + (inJS ? 2 : 1)), original: chain.traces.first.original.toString()); - return Chain([first]..addAll(chain.traces.skip(1))); + return Chain([first, ...chain.traces.skip(1)]); }); } From 4da572615de4fd1ddd46cf4343ad53acbc3436fc Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 09:38:09 -0800 Subject: [PATCH 0703/1215] Migrate to runZonedGuarded (dart-lang/stack_trace#93) The `onError` argument to `runZoned` is deprecated. Switch to the supported `runZonedGuarded`. Remove argument types on the function literal since thy can now be inferred. `runZonedGuarded` has a specific function type argument, whereas `onError` was typed as `Function` which did not allow inference on argument types. Refactor handling of `!when` since the new API doesn't allow a nullable callback. Refactor some tests to use `having` matchers which previously relied on calling methods on `dynamic`. --- pkgs/stack_trace/lib/src/chain.dart | 26 ++++++------------- pkgs/stack_trace/test/chain/chain_test.dart | 4 +-- pkgs/stack_trace/test/chain/dart2js_test.dart | 16 ++++++------ pkgs/stack_trace/test/chain/vm_test.dart | 22 +++++++++------- 4 files changed, 30 insertions(+), 38 deletions(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index fef2c2dd4..b685be9dc 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -66,10 +66,10 @@ class Chain implements StackTrace { /// parent Zone's `unhandledErrorHandler` will be called with the error and /// its chain. /// - /// If [errorZone] is `true`, the zone this creates will be an error zone, - /// even if [onError] isn't passed. This means that any errors that would - /// cross the zone boundary are considered unhandled. If [errorZone] is - /// `false`, [onError] must be `null`. + /// The zone this creates will be an error zone if either [onError] is + /// not `null` and [when] is false, + /// or if both [when] and [errorZone] are `true`. + /// If [errorZone] is `false`, [onError] must be `null`. /// /// If [callback] returns a value, it will be returned by [capture] as well. static T capture(T Function() callback, @@ -82,20 +82,10 @@ class Chain implements StackTrace { } if (!when) { - void Function(Object, StackTrace)? newOnError; - if (onError != null) { - void wrappedOnError(Object error, StackTrace? stackTrace) { - onError( - error, - stackTrace == null - ? Chain.current() - : Chain.forTrace(stackTrace)); - } - - newOnError = wrappedOnError; - } - - return runZoned(callback, onError: newOnError); + if (onError == null) return runZoned(callback); + return runZonedGuarded(callback, (error, stackTrace) { + onError(error, Chain.forTrace(stackTrace)); + }) as T; } var spec = StackZoneSpecification(onError, errorZone: errorZone); diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 3309ae1ca..bb28b792c 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -64,10 +64,10 @@ void main() { }); test('with no onError blocks errors', () { - runZoned(() { + runZonedGuarded(() { var future = Chain.capture(() => Future.error('oh no'), when: false); future.then(expectAsync1((_) {}, count: 0)); - }, onError: expectAsync2((error, chain) { + }, expectAsync2((error, chain) { expect(error, equals('oh no')); expect(chain, isA()); })); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index c0ec913c8..f7086379d 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -140,7 +140,7 @@ void main() { test('and relays them to the parent zone', () { var completer = Completer(); - runZoned(() { + runZonedGuarded(() { Chain.capture(() { inMicrotask(() => throw 'error'); }, onError: (error, chain) { @@ -148,11 +148,11 @@ void main() { expect(chain.traces, hasLength(2)); throw error; }); - }, onError: (error, chain) { + }, (error, chain) { try { expect(error, equals('error')); - expect(chain, isA()); - expect(chain.traces, hasLength(2)); + expect(chain, + isA().having((c) => c.traces, 'traces', hasLength(2))); completer.complete(); } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); @@ -166,13 +166,13 @@ void main() { test('capture() without onError passes exceptions to parent zone', () { var completer = Completer(); - runZoned(() { + runZonedGuarded(() { Chain.capture(() => inMicrotask(() => throw 'error')); - }, onError: (error, chain) { + }, (error, chain) { try { expect(error, equals('error')); - expect(chain, isA()); - expect(chain.traces, hasLength(2)); + expect(chain, + isA().having((c) => c.traces, 'traces', hasLength(2))); completer.complete(); } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 273276eeb..8a66b8360 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -234,7 +234,7 @@ void main() { test('and relays them to the parent zone', () { var completer = Completer(); - runZoned(() { + runZonedGuarded(() { Chain.capture(() { inMicrotask(() => throw 'error'); }, onError: (error, chain) { @@ -243,12 +243,13 @@ void main() { contains(frameMember(startsWith('inMicrotask')))); throw error; }); - }, onError: (error, chain) { + }, (error, chain) { try { expect(error, equals('error')); - expect(chain, isA()); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inMicrotask')))); + expect( + chain, + isA().having((c) => c.traces[1].frames, 'traces[1].frames', + contains(frameMember(startsWith('inMicrotask'))))); completer.complete(); } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); @@ -262,14 +263,15 @@ void main() { test('capture() without onError passes exceptions to parent zone', () { var completer = Completer(); - runZoned(() { + runZonedGuarded(() { Chain.capture(() => inMicrotask(() => throw 'error')); - }, onError: (error, chain) { + }, (error, chain) { try { expect(error, equals('error')); - expect(chain, isA()); - expect(chain.traces[1].frames, - contains(frameMember(startsWith('inMicrotask')))); + expect( + chain, + isA().having((c) => c.traces[1].frames, 'traces[1].frames', + contains(frameMember(startsWith('inMicrotask'))))); completer.complete(); } on Object catch (error, stackTrace) { completer.completeError(error, stackTrace); From e8efb13bda913507914d61e0c689ca38465c0d2f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 14:33:09 -0800 Subject: [PATCH 0704/1215] Bump SDK constraints for pub (dart-lang/stream_channel#67) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/stream_channel/CHANGELOG.md | 5 +++++ pkgs/stream_channel/pubspec.yaml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 95f370c38..ea31ffe2c 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.1.0-nullsafety.3 + +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. + ## 2.1.0-nullsafety.2 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 9259c34c4..d11a3567f 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.2 +version: 2.1.0-nullsafety.3 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -7,8 +7,7 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dependencies: async: '>=2.5.0-nullsafety <2.5.0' From a9f33b096e206ec5ae7a26d3666ffbbb35d8a06a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 14:35:30 -0800 Subject: [PATCH 0705/1215] Bump SDK constraints for pub (dart-lang/string_scanner#28) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/string_scanner/CHANGELOG.md | 5 +++++ pkgs/string_scanner/pubspec.yaml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 4379f83db..c8c700800 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0-nullsafety.3 + +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. + ## 1.1.0-nullsafety.2 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 3319875fa..6099c54e3 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,12 +1,11 @@ name: string_scanner -version: 1.1.0-nullsafety.2 +version: 1.1.0-nullsafety.3 description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dependencies: charcode: '>=1.2.0-nullsafety <1.2.0' From e8095c708d17e0fd95a6fa6d186ec234eed06fbd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 3 Nov 2020 14:36:32 -0800 Subject: [PATCH 0706/1215] Bump SDK constraints for pub (dart-lang/term_glyph#18) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/term_glyph/CHANGELOG.md | 5 +++++ pkgs/term_glyph/pubspec.yaml | 5 ++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index a2c1dfbfd..7f8ed6036 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.2.0-nullsafety.3 + +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. + ## 1.2.0-nullsafety.2 * Allow prerelease versions of the 2.12 sdk. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 148db8df4..f4a49e813 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,12 +1,11 @@ name: term_glyph -version: 1.2.0-nullsafety.2 +version: 1.2.0-nullsafety.3 description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0 <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dev_dependencies: csv: '>=3.0.0 <5.0.0' From 56c8d6d731d8d7737033a380dcdc17e15e51ae2c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 4 Nov 2020 12:33:56 -0800 Subject: [PATCH 0707/1215] Bump SDK constraints for pub (dart-lang/stack_trace#95) Use a 2.12.0 lower bound since pub does not understand allowed experiments for earlier versions. Use a 3.0.0 upper bound to avoid a warning in pub and to give some flexibility in publishing for stable. --- pkgs/stack_trace/CHANGELOG.md | 4 +++- pkgs/stack_trace/pubspec.yaml | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 46a371ddc..3661fe081 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,7 +1,9 @@ -## 1.10.0-nullsafety.6-dev +## 1.10.0-nullsafety.6 * Fix bug parsing asynchronous suspension gap markers at the end of stack traces, when parsing with `Trace.parse` and `Chain.parse`. +* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release + guidelines. ## 1.10.0-nullsafety.5 diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 048978c1d..7c0cfff04 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,11 +1,10 @@ name: stack_trace -version: 1.10.0-nullsafety.6-dev +version: 1.10.0-nullsafety.6 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace environment: - # This must remain a tight constraint until nnbd is stable - sdk: '>=2.10.0-0.0.dev <2.12.0' + sdk: ">=2.12.0-0 <3.0.0" dependencies: path: ^1.8.0-nullsafety From d1c8af27411cae231bb1b271404877414ae590af Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 5 Nov 2020 14:15:18 -0800 Subject: [PATCH 0708/1215] Async gap fixes (dart-lang/stack_trace#96) * Fix async gap handling. (backpublish) Fix an issue where an async gap at the end of a stack trace would not get parsed correctly due to the trailing newline being `trim()`'d. Add tests to cover this case. * Fixes async gap handling in Trace.parse and Chain.parse (backpublish) Co-authored-by: Clement Skau --- pkgs/stack_trace/CHANGELOG.md | 8 ++++ pkgs/stack_trace/lib/src/chain.dart | 6 ++- pkgs/stack_trace/lib/src/trace.dart | 11 +++++- pkgs/stack_trace/lib/src/utils.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 3 +- pkgs/stack_trace/test/chain/chain_test.dart | 15 ++++++++ pkgs/stack_trace/test/trace_test.dart | 41 +++++++++++++++++++++ 7 files changed, 80 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 2f189e695..f3cbc36cf 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.9.6 (backpublish) + +* Fix bug parsing asynchronous suspension gap markers at the end of stack + traces. (Also fixed separately in 1.10.0-nullsafety.3) +* Fix bug parsing asynchronous suspension gap markers at the end of stack + traces, when parsing with `Trace.parse` and `Chain.parse`. (Also fixed + separately in 1.10.0-nullsafety.6) + ## 1.9.5 * Parse the format for `data:` URIs that the Dart VM has used since `2.2.0`. diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 6b2eec5a1..ecab35afb 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -173,8 +173,10 @@ class Chain implements StackTrace { factory Chain.parse(String chain) { if (chain.isEmpty) return Chain([]); if (chain.contains(vmChainGap)) { - return Chain( - chain.split(vmChainGap).map((trace) => Trace.parseVM(trace))); + return Chain(chain + .split(vmChainGap) + .where((line) => line.isNotEmpty) + .map((trace) => Trace.parseVM(trace))); } if (!chain.contains(chainGap)) return Chain([Trace.parse(chain)]); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 96902a1a6..d66c0dbbf 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -153,7 +153,16 @@ class Trace implements StackTrace { static List _parseVM(String trace) { // Ignore [vmChainGap]. This matches the behavior of // `Chain.parse().toTrace()`. - var lines = trace.trim().replaceAll(vmChainGap, '').split('\n'); + var lines = trace + .trim() + .replaceAll(vmChainGap, '') + .split('\n') + .where((line) => line.isNotEmpty); + + if (lines.isEmpty) { + return []; + } + var frames = lines .take(lines.length - 1) .map((line) => Frame.parseVM(line)) diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 838a093b5..0dd1755af 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -8,7 +8,7 @@ const chainGap = '===== asynchronous gap ===========================\n'; /// The line used in the string representation of VM stack chains to represent /// the gap between traces. -const vmChainGap = '\n'; +final vmChainGap = RegExp(r'^\n?$', multiLine: true); // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 147f7cc76..e72ee38f1 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,6 +1,5 @@ name: stack_trace -version: 1.9.5 - +version: 1.9.6 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index b6ad33e03..d71b2742c 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -36,6 +36,21 @@ void main() { expect(chain.traces[1].frames, isEmpty); expect(chain.traces[2].frames, isEmpty); }); + + test('parses a chain with VM gaps', () { + final chain = + Chain.parse('#1 MyClass.run (package:my_lib.dart:134:5)\n' + '\n' + '#2 main (file:///my_app.dart:9:3)\n' + '\n'); + expect(chain.traces, hasLength(2)); + expect(chain.traces[0].frames, hasLength(1)); + expect(chain.traces[0].frames[0].toString(), + equals('package:my_lib.dart 134:5 in MyClass.run')); + expect(chain.traces[1].frames, hasLength(1)); + expect(chain.traces[1].frames[0].toString(), + equals('/my_app.dart 9:3 in main')); + }); }); group('Chain.capture()', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index ec7b074d5..4df6e9ac3 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -249,6 +249,25 @@ void main() { equals(Uri.parse('https://dart.dev/foo/quux.dart'))); }); + test('parses a package:stack_trace stack chain with end gap correctly', () { + var trace = + Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/baz.dart Foo..bar\n' + 'https://dart.dev/foo/bang.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/quux.dart Foo..bar' + '===== asynchronous gap ===========================\n'); + + expect(trace.frames.length, 4); + expect(trace.frames[0].uri, + equals(Uri.parse('https://dart.dev/foo/bar.dart'))); + expect(trace.frames[1].uri, + equals(Uri.parse('https://dart.dev/foo/baz.dart'))); + expect(trace.frames[2].uri, + equals(Uri.parse('https://dart.dev/foo/bang.dart'))); + expect(trace.frames[3].uri, + equals(Uri.parse('https://dart.dev/foo/quux.dart'))); + }); + test('parses a real package:stack_trace stack trace correctly', () { var traceString = Trace.current().toString(); expect(Trace.parse(traceString).toString(), equals(traceString)); @@ -259,6 +278,28 @@ void main() { expect(trace.frames, isEmpty); expect(trace.toString(), equals('')); }); + + test('parses trace with async gap correctly', () { + var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' + '\n' + '#1 twist (dart:the/future.dart:0:2)\n' + '#2 main (dart:my/file.dart:4:6)\n'); + + expect(trace.frames.length, 3); + expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); + expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); + expect(trace.frames[2].uri, equals(Uri.parse('dart:my/file.dart'))); + }); + + test('parses trace with async gap at end correctly', () { + var trace = Trace.parse('#0 bop (file:///pull.dart:42:23)\n' + '#1 twist (dart:the/future.dart:0:2)\n' + '\n'); + + expect(trace.frames.length, 2); + expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); + expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); + }); }); test('.toString() nicely formats the stack trace', () { From aedc897a6934e9f6c4a323e18e6209e3cd648d90 Mon Sep 17 00:00:00 2001 From: Clement Skau Date: Mon, 9 Nov 2020 11:59:26 +0100 Subject: [PATCH 0709/1215] [Test] Fixes chain/vm_test on ending async gaps. (dart-lang/stack_trace#99) --- pkgs/stack_trace/CHANGELOG.md | 3 +++ pkgs/stack_trace/test/chain/vm_test.dart | 10 +++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index b9918d53b..25773bbd6 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,5 +1,8 @@ ## 1.10.0-nullsafety.7-dev +* Fix broken test, `test/chain/vm_test.dart`, which incorrectly handles + asynchronous suspension gap markers at the end of stack traces. + ## 1.10.0-nullsafety.6 * Fix bug parsing asynchronous suspension gap markers at the end of stack diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 8a66b8360..9d82b2cd9 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -492,9 +492,13 @@ void main() { } }); - var chain = Chain.forTrace(trace); - expect(chain.traces, - hasLength(vmChainGap.allMatches(trace.toString()).length + 1)); + final chain = Chain.forTrace(trace); + final traceStr = trace.toString(); + final gaps = vmChainGap.allMatches(traceStr); + // If the trace ends on a gap, there's no sub-trace following the gap. + final expectedLength = + (gaps.last.end == traceStr.length) ? gaps.length : gaps.length + 1; + expect(chain.traces, hasLength(expectedLength)); expect( chain.traces.first.frames, contains(frameMember(startsWith('main')))); }); From 755f0d3b9e47109a1a388cb23da408c1e656d111 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Mon, 9 Nov 2020 17:46:25 -0800 Subject: [PATCH 0710/1215] opt out the tool/generate.dart script (dart-lang/term_glyph#19) --- pkgs/term_glyph/pubspec.yaml | 1 + pkgs/term_glyph/tool/generate.dart | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index f4a49e813..d989ae90b 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -10,4 +10,5 @@ environment: dev_dependencies: csv: '>=3.0.0 <5.0.0' dart_style: '>=0.2.0 <2.0.0' + meta: ^1.3.0-nullsafety test: ^1.16.0-nullsafety diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 0a1136ecf..90fc2e825 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -1,10 +1,14 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. +// +// TODO: Remove once package:csv/csv.dart is migrated. +// @dart=2.9 import 'dart:io'; import 'package:csv/csv.dart'; +import 'package:meta/meta.dart'; void main() { var csv = CsvCodec(eol: '\n'); @@ -82,7 +86,7 @@ void _writeGlyphSetInterface(List data) { /// /// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes /// the Unicode glyph set. -void _writeGlyphSet(List data, {required bool ascii}) { +void _writeGlyphSet(List data, {@required bool ascii}) { var file = File('lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart') .openSync(mode: FileMode.write); From 1edd6fe89cf0e6b2dd917a4cdc95b8d078137ee7 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Nov 2020 19:59:25 -0800 Subject: [PATCH 0711/1215] Remove unused dart:async imports. As of Dart 2.1, Future/Stream have been exported from dart:core. --- pkgs/watcher/test/file_watcher/shared.dart | 2 -- pkgs/watcher/test/utils.dart | 1 - 2 files changed, 3 deletions(-) diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index c837a2136..9b72f0ed6 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -2,8 +2,6 @@ // 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. -import 'dart:async'; - import 'package:test/test.dart'; import '../utils.dart'; diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 06d1a1267..6e7686c27 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -2,7 +2,6 @@ // 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. -import 'dart:async'; import 'dart:io'; import 'package:async/async.dart'; From c15b5184d9345ea8e9e4b17073a0f252b353b0e5 Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 11 Nov 2020 07:28:59 -0800 Subject: [PATCH 0712/1215] remove experiment --- pkgs/stack_trace/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 2163f52ce..2e022f6bc 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,7 +1,5 @@ include: package:pedantic/analysis_options.yaml analyzer: - enable-experiment: - - non-nullable strong-mode: implicit-casts: false From ff1df498b650c6545a5a967e4183767454864c6f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 11 Nov 2020 09:25:25 -0800 Subject: [PATCH 0713/1215] Remove workaround for truncated last lines (dart-lang/stack_trace#100) The referenced SDK issue has been closed. https://github.com/dart-lang/sdk/issues/23614 Remove the workaround that handles the last line specially and simplify to a collection for loop. --- pkgs/stack_trace/lib/src/trace.dart | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 42371c744..e51d4b400 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -151,22 +151,7 @@ class Trace implements StackTrace { .replaceAll(vmChainGap, '') .split('\n') .where((line) => line.isNotEmpty); - - if (lines.isEmpty) { - return []; - } - - var frames = lines - .take(lines.length - 1) - .map((line) => Frame.parseVM(line)) - .toList(); - - // TODO(nweiz): Remove this when issue 23614 is fixed. - if (!lines.last.endsWith('.da')) { - frames.add(Frame.parseVM(lines.last)); - } - - return frames; + return [for (var line in lines) Frame.parseVM(line)]; } /// Parses a string representation of a Chrome/V8 stack trace. From 87fb3b0c3eb1c2c6f03dda3d73b659d05a6422a1 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 11 Nov 2020 09:33:06 -0800 Subject: [PATCH 0714/1215] remove redundant experiment --- pkgs/stream_channel/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8a712df8f..b36c8749b 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -8,8 +8,6 @@ analyzer: unused_element: error unused_local_variable: error dead_code: error - enable-experiment: - - non-nullable linter: rules: From d092aadc46f75be94791ba62fdf13cd64ddfa7c8 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 11 Nov 2020 11:13:21 -0800 Subject: [PATCH 0715/1215] remove redundant experiment (dart-lang/string_scanner#31) * remove redundant experiment * bump dev version * bump dev version --- pkgs/string_scanner/CHANGELOG.md | 2 ++ pkgs/string_scanner/analysis_options.yaml | 3 --- pkgs/string_scanner/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index c8c700800..08216dc60 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.1.0-nullsafety.4-dev + ## 1.1.0-nullsafety.3 * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 2407da620..60abe63e6 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -4,9 +4,6 @@ analyzer: strong-mode: implicit-casts: false - enable-experiment: - - non-nullable - linter: rules: - avoid_bool_literals_in_conditional_expressions diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 6099c54e3..0d29f2e05 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.1.0-nullsafety.3 +version: 1.1.0-nullsafety.4-dev description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner From c1169d2ad4915bd0bbd9889363c9b07d9880f781 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Thu, 12 Nov 2020 07:14:16 -0800 Subject: [PATCH 0716/1215] remove redundant experiment (dart-lang/term_glyph#20) --- pkgs/term_glyph/analysis_options.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index 64ff556c6..108d1058a 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1,4 +1 @@ include: package:pedantic/analysis_options.yaml -analyzer: - enable-experiment: - - non-nullable From 2c89b9dddb2d0f491c8b2136a0dd808786d73532 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 12 Nov 2020 10:50:23 -0800 Subject: [PATCH 0717/1215] Fix deprecated zone API usage (dart-lang/watcher#95) --- pkgs/watcher/.travis.yml | 4 ++-- pkgs/watcher/CHANGELOG.md | 3 ++- pkgs/watcher/lib/src/directory_watcher/windows.dart | 4 ++-- pkgs/watcher/pubspec.yaml | 6 +++--- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index a3bc0703a..2c6dc5a72 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev -- 2.2.0 +- 2.8.4 os: - linux @@ -16,7 +16,7 @@ matrix: include: - dart: dev dart_task: dartfmt - - dart: 2.2.0 + - dart: 2.8.4 dart_task: dartanalyzer: --fatal-warnings . - dart: dev diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index a98ae202a..881aa2f84 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,6 +1,7 @@ -# 0.9.8 +# 0.9.8-dev * Add the ability to create custom Watcher types for specific file paths. +* Require at least Dart 2.8.4. # 0.9.7+15 diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index f5093c5dc..ae4670d1d 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -379,11 +379,11 @@ class _WindowsDirectoryWatcher void _startWatch() { // Note: "watcher closed" exceptions do not get sent over the stream // returned by watch, and must be caught via a zone handler. - runZoned(() { + runZonedGuarded(() { var innerStream = Directory(path).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, onError: _eventsController.addError, onDone: _onDone); - }, onError: (error, StackTrace stackTrace) { + }, (error, StackTrace stackTrace) { if (error is FileSystemException && error.message.startsWith('Directory watcher closed unexpectedly')) { _watchSubscription.cancel(); diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index e86192dd8..c4cafada7 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,13 +1,13 @@ name: watcher -version: 0.9.7+15 +version: 0.9.8-dev description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. -homepage: https://github.com/dart-lang/watcher +repository: https://github.com/dart-lang/watcher environment: - sdk: '>=2.2.0 <3.0.0' + sdk: '>=2.8.4 <3.0.0' dependencies: async: ^2.0.0 From 22a6cb37c4763d0ae8853b970ed5d65b10b21f6b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 12 Nov 2020 14:06:05 -0800 Subject: [PATCH 0718/1215] Remove an inferrable argument type (dart-lang/watcher#96) The `runZonedGuarded` API has a more specific static type which allows argument types for function literals to be inferred. --- pkgs/watcher/lib/src/directory_watcher/windows.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index ae4670d1d..98e963945 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -383,7 +383,7 @@ class _WindowsDirectoryWatcher var innerStream = Directory(path).watch(recursive: true); _watchSubscription = innerStream.listen(_onEvent, onError: _eventsController.addError, onDone: _onDone); - }, (error, StackTrace stackTrace) { + }, (error, stackTrace) { if (error is FileSystemException && error.message.startsWith('Directory watcher closed unexpectedly')) { _watchSubscription.cancel(); From 048ac64a67176ce2fbefc3deb93a9bc88d550c7c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 13 Nov 2020 13:13:02 -0800 Subject: [PATCH 0719/1215] Setup weekly cron on Github workflow (dart-lang/test_reflective_loader#29) --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 4d33943d7..2ac752518 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -5,6 +5,9 @@ on: push: branches: - master + schedule: + # “At 00:00 (UTC) on Sunday.” + - cron: '0 0 * * 0' jobs: build: From d769b0e6c94945d29b83175ed06f9eaec1571cbb Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 16 Nov 2020 14:32:23 -0800 Subject: [PATCH 0720/1215] Remove dependency on package:charcode (dart-lang/string_scanner#29) Copy in the charcode constants that are used in this package to a private library. --- pkgs/string_scanner/lib/src/charcode.dart | 24 +++++++++++++++++++ .../lib/src/eager_span_scanner.dart | 3 +-- pkgs/string_scanner/lib/src/line_scanner.dart | 3 +-- .../lib/src/string_scanner.dart | 4 ++-- pkgs/string_scanner/pubspec.yaml | 1 - .../test/line_scanner_test.dart | 2 +- .../test/string_scanner_test.dart | 2 +- 7 files changed, 30 insertions(+), 9 deletions(-) create mode 100644 pkgs/string_scanner/lib/src/charcode.dart diff --git a/pkgs/string_scanner/lib/src/charcode.dart b/pkgs/string_scanner/lib/src/charcode.dart new file mode 100644 index 000000000..d15774935 --- /dev/null +++ b/pkgs/string_scanner/lib/src/charcode.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// 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. + +/// Character '\'. +const int $backslash = 0x5C; + +/// "Carriage return" control character. +const int $cr = 0x0D; + +/// Character '"'. +const int $doubleQuote = 0x22; + +/// Character 'f'. +const int $f = 0x66; + +/// "Line feed" control character. +const int $lf = 0x0A; + +/// Space character. +const int $space = 0x20; + +/// Character 'x'. +const int $x = 0x78; diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 415b9f32c..d27a818fa 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -2,8 +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. -import 'package:charcode/ascii.dart'; - +import 'charcode.dart'; import 'line_scanner.dart'; import 'span_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 358d4c1cb..af6b6e705 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -2,8 +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. -import 'package:charcode/ascii.dart'; - +import 'charcode.dart'; import 'string_scanner.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 564774c3a..5d69c7565 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -2,9 +2,9 @@ // 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. -import 'package:charcode/charcode.dart'; import 'package:source_span/source_span.dart'; +import 'charcode.dart'; import 'exception.dart'; import 'utils.dart'; @@ -110,7 +110,7 @@ class StringScanner { if (name == null) { if (character == $backslash) { name = r'"\"'; - } else if (character == $double_quote) { + } else if (character == $doubleQuote) { name = r'"\""'; } else { name = '"${String.fromCharCode(character)}"'; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 0d29f2e05..1b2c2e5c9 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -8,7 +8,6 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - charcode: '>=1.2.0-nullsafety <1.2.0' source_span: '>=1.8.0-nullsafety <1.8.0' dev_dependencies: diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 0bbd499ab..a3deff1b7 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -2,7 +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. -import 'package:charcode/charcode.dart'; +import 'package:string_scanner/src/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 0327499c7..34176b8a3 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -2,7 +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. -import 'package:charcode/charcode.dart'; +import 'package:string_scanner/src/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; From 2664a19bb5dddd2497784c3add84c4c0c6477be9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 24 Nov 2020 10:29:19 -0800 Subject: [PATCH 0721/1215] Remove error upgrades (dart-lang/stream_transform#118) These are not necessary with `--fatal-infos`. --- pkgs/stream_transform/analysis_options.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 90cc2c2fa..39d5c5e03 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -6,11 +6,6 @@ analyzer: strict-raw-types: true errors: todo: ignore - dead_code: error - override_on_non_overriding_method: error - unused_element: error - unused_import: error - unused_local_variable: error linter: rules: - annotate_overrides From 91c37d91cf0ca83a1a778eb255cf35ab1bf7afd3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 24 Nov 2020 11:14:30 -0800 Subject: [PATCH 0722/1215] Fix tests for latest pub parsing rules for environment (dart-lang/pubspec_parse#60) Since https://github.com/dart-lang/pub/commit/656803e924eae5cf6574f5200232ef69ac3b4f92 (SDK-2.12.0-28.0.dev) pub requires an SDK constraint. Update tests so this requirement no longer causes failures. Also updated test expectations for latest `pkg:json_annotation` changes --- pkgs/pubspec_parse/test/dependency_test.dart | 6 +- pkgs/pubspec_parse/test/parse_test.dart | 66 ++++++++++++-------- pkgs/pubspec_parse/test/test_utils.dart | 5 ++ 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 35ac6b67c..0afbf3645 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -214,7 +214,7 @@ line 5, column 4: These keys had `null` values, which is not allowed: [sdk] _expectThrows( {'sdk': 42}, r''' -line 5, column 11: Unsupported value for "sdk". +line 5, column 11: Unsupported value for "sdk". type 'int' is not a subtype of type 'String' in type cast ╷ 5 │ "sdk": 42 │ ┌───────────^ @@ -332,7 +332,7 @@ line 6, column 5: These keys had `null` values, which is not allowed: [url] 'git': {'url': 42} }, r''' -line 6, column 12: Unsupported value for "url". +line 6, column 12: Unsupported value for "url". type 'int' is not a subtype of type 'String' in type cast ╷ 6 │ "url": 42 │ ┌────────────^ @@ -404,7 +404,7 @@ void _expectThrows(Object content, String expectedError) { T _dependency(Object content, {bool skipTryPub = false}) { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'dependencies': {'dep': content} }, skipTryPub: skipTryPub); expect(value.name, 'sample'); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 75c3f83e8..179d0d8d1 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -14,7 +14,7 @@ import 'test_utils.dart'; void main() { test('minimal set values', () { - final value = parse({'name': 'sample'}); + final value = parse(defaultPubspec); expect(value.name, 'sample'); expect(value.version, isNull); expect(value.publishTo, isNull); @@ -23,7 +23,10 @@ void main() { // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, isEmpty); - expect(value.environment, isEmpty); + expect( + value.environment, + {'sdk': VersionConstraint.parse('>=2.7.0 <3.0.0')}, + ); expect(value.documentation, isNull); expect(value.dependencies, isEmpty); expect(value.devDependencies, isEmpty); @@ -70,17 +73,20 @@ void main() { test('environment values can be null', () { final value = parse({ 'name': 'sample', - 'environment': {'sdk': null} + 'environment': { + 'sdk': '>=2.7.0 <3.0.0', + 'bob': null, + } }); expect(value.name, 'sample'); - expect(value.environment, hasLength(1)); - expect(value.environment, containsPair('sdk', isNull)); + expect(value.environment, hasLength(2)); + expect(value.environment, containsPair('bob', isNull)); }); group('publish_to', () { for (var entry in { 42: r''' -line 3, column 16: Unsupported value for "publish_to". +line 3, column 16: Unsupported value for "publish_to". type 'int' is not a subtype of type 'String' in type cast ╷ 3 │ "publish_to": 42 │ ^^ @@ -120,7 +126,10 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https 'none': 'none' }.entries) { test('can be ${entry.key}', () { - final value = parse({'name': 'sample', 'publish_to': entry.value}); + final value = parse({ + ...defaultPubspec, + 'publish_to': entry.value, + }); expect(value.publishTo, entry.value); }); } @@ -128,7 +137,10 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https group('author, authors', () { test('one author', () { - final value = parse({'name': 'sample', 'author': 'name@example.com'}); + final value = parse({ + ...defaultPubspec, + 'author': 'name@example.com', + }); // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); @@ -136,7 +148,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('one author, via authors', () { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'authors': ['name@example.com'] }); // ignore: deprecated_member_use_from_same_package @@ -146,7 +158,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('many authors', () { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'authors': ['name@example.com', 'name2@example.com'] }); // ignore: deprecated_member_use_from_same_package @@ -156,7 +168,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('author and authors', () { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'author': 'name@example.com', 'authors': ['name2@example.com'] }); @@ -167,7 +179,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('duplicate author values', () { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'author': 'name@example.com', 'authors': ['name@example.com', 'name@example.com'] }); @@ -178,7 +190,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('flutter', () { final value = parse({ - 'name': 'sample', + ...defaultPubspec, 'flutter': {'key': 'value'}, }); expect(value.flutter, {'key': 'value'}); @@ -282,16 +294,16 @@ line 4, column 10: Unsupported value for "sdk". Could not parse version "silly". test('bad repository url', () { expectParseThrows( { - 'name': 'foo', + ...defaultPubspec, 'repository': {'x': 'y'}, }, r''' -line 3, column 16: Unsupported value for "repository". +line 6, column 16: Unsupported value for "repository". type 'YamlMap' is not a subtype of type 'String' in type cast ╷ -3 │ "repository": { +6 │ "repository": { │ ┌────────────────^ -4 │ │ "x": "y" -5 │ └ } +7 │ │ "x": "y" +8 │ └ } ╵''', skipTryPub: true, ); @@ -300,11 +312,11 @@ line 3, column 16: Unsupported value for "repository". test('bad issue_tracker url', () { expectParseThrows( { - 'name': 'foo', + 'name': 'sample', 'issue_tracker': {'x': 'y'}, }, r''' -line 3, column 19: Unsupported value for "issue_tracker". +line 3, column 19: Unsupported value for "issue_tracker". type 'YamlMap' is not a subtype of type 'String' in type cast ╷ 3 │ "issue_tracker": { │ ┌───────────────────^ @@ -359,37 +371,37 @@ line 1, column 1: "name" cannot be empty. test('bad repository url', () { final value = parse( { - 'name': 'foo', + ...defaultPubspec, 'repository': {'x': 'y'}, }, lenient: true, ); - expect(value.name, 'foo'); + expect(value.name, 'sample'); expect(value.repository, isNull); }); test('bad issue_tracker url', () { final value = parse( { - 'name': 'foo', + ...defaultPubspec, 'issue_tracker': {'x': 'y'}, }, lenient: true, ); - expect(value.name, 'foo'); + expect(value.name, 'sample'); expect(value.issueTracker, isNull); }); test('multiple bad values', () { final value = parse( { - 'name': 'foo', + ...defaultPubspec, 'repository': {'x': 'y'}, 'issue_tracker': {'x': 'y'}, }, lenient: true, ); - expect(value.name, 'foo'); + expect(value.name, 'sample'); expect(value.repository, isNull); expect(value.issueTracker, isNull); }); @@ -397,7 +409,7 @@ line 1, column 1: "name" cannot be empty. test('deep error throws with lenient', () { expect( () => parse({ - 'name': 'foo', + 'name': 'sample', 'dependencies': { 'foo': { 'git': {'url': 1} diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index e51f19863..ac5abba06 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -13,6 +13,11 @@ import 'package:test/test.dart'; import 'pub_utils.dart'; +const defaultPubspec = { + 'name': 'sample', + 'environment': {'sdk': '>=2.7.0 <3.0.0'}, +}; + String _encodeJson(Object input) => const JsonEncoder.withIndent(' ').convert(input); From 0bbb6d0a83c48ddba55c88efc25912bb017ff132 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 1 Dec 2020 14:04:30 -0800 Subject: [PATCH 0723/1215] Migrate to null safety (dart-lang/stream_transform#119) - Bump SDK constraint. - Bump to null safe dependencies. - Migrate code, examples, and tests. - Add an opt-out test for testing the behavior of transforming streams with the `subscription.cancel()` call returns null despite a statically non-nullable return. This requires an unusual pattern in the code. --- pkgs/stream_transform/.travis.yml | 4 -- pkgs/stream_transform/CHANGELOG.md | 3 +- pkgs/stream_transform/example/main.dart | 4 +- .../lib/src/aggregate_sample.dart | 30 ++++---- pkgs/stream_transform/lib/src/async_map.dart | 4 +- .../lib/src/combine_latest.dart | 48 +++++++------ .../stream_transform/lib/src/concatenate.dart | 12 ++-- .../lib/src/from_handlers.dart | 22 +++--- pkgs/stream_transform/lib/src/merge.dart | 17 +++-- pkgs/stream_transform/lib/src/rate_limit.dart | 20 +++--- pkgs/stream_transform/lib/src/scan.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 8 ++- pkgs/stream_transform/lib/src/take_until.dart | 8 +-- pkgs/stream_transform/lib/src/tap.dart | 6 +- pkgs/stream_transform/pubspec.yaml | 10 +-- .../test/async_map_buffer_test.dart | 58 +++++++-------- .../test/async_map_sample_test.dart | 67 ++++++++--------- pkgs/stream_transform/test/audit_test.dart | 14 ++-- pkgs/stream_transform/test/buffer_test.dart | 29 +++----- .../test/combine_latest_all_test.dart | 12 ---- .../test/combine_latest_test.dart | 13 ---- .../test/concurrent_async_expand_test.dart | 33 +++------ .../test/concurrent_async_map_test.dart | 20 +++--- pkgs/stream_transform/test/debounce_test.dart | 36 +++++----- .../test/followd_by_test.dart | 20 +++--- .../test/from_handlers_test.dart | 28 ++++---- pkgs/stream_transform/test/merge_test.dart | 13 ---- pkgs/stream_transform/test/opt_out_test.dart | 72 +++++++++++++++++++ pkgs/stream_transform/test/scan_test.dart | 2 +- .../test/start_with_test.dart | 12 ++-- pkgs/stream_transform/test/switch_test.dart | 33 +++------ .../test/take_until_test.dart | 16 ++--- pkgs/stream_transform/test/throttle_test.dart | 12 ++-- pkgs/stream_transform/test/utils.dart | 25 ------- 34 files changed, 339 insertions(+), 374 deletions(-) create mode 100644 pkgs/stream_transform/test/opt_out_test.dart diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml index 24eb0d797..3b2eb080e 100644 --- a/pkgs/stream_transform/.travis.yml +++ b/pkgs/stream_transform/.travis.yml @@ -3,7 +3,6 @@ branches: only: [master] dart: - dev - - 2.7.0 cache: directories: - $HOME/.pub-cache @@ -18,6 +17,3 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-warnings --fatal-infos . - - dart: 2.7.0 - dart_task: - dartanalyzer: --fatal-warnings . diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 268bf3538..68f885912 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,5 +1,6 @@ -## 1.2.1-dev +## 2.0.0-nullsafety.0-dev +- Migrate to null safety. - Improve tests of `switchMap` and improve documentation with links and clarification. diff --git a/pkgs/stream_transform/example/main.dart b/pkgs/stream_transform/example/main.dart index 4ed53d834..70b3e7f28 100644 --- a/pkgs/stream_transform/example/main.dart +++ b/pkgs/stream_transform/example/main.dart @@ -9,7 +9,7 @@ import 'package:stream_transform/stream_transform.dart'; void main() { var firstInput = document.querySelector('#first_input') as InputElement; var secondInput = document.querySelector('#second_input') as InputElement; - var output = document.querySelector('#output'); + var output = document.querySelector('#output')!; _inputValues(firstInput) .combineLatest(_inputValues(secondInput), @@ -21,6 +21,6 @@ void main() { }); } -Stream _inputValues(InputElement element) => element.onKeyUp +Stream _inputValues(InputElement element) => element.onKeyUp .debounce(const Duration(milliseconds: 100)) .map((_) => element.value); diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index 88fc4909a..3a967d4a3 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -15,7 +15,7 @@ import 'dart:async'; /// the output. class AggregateSample extends StreamTransformerBase { final Stream _trigger; - final T Function(S, T) _aggregate; + final T Function(S, T?) _aggregate; AggregateSample(this._trigger, this._aggregate); @@ -25,15 +25,15 @@ class AggregateSample extends StreamTransformerBase { ? StreamController.broadcast(sync: true) : StreamController(sync: true); - T currentResults; + T? currentResults; var waitingForTrigger = true; var isTriggerDone = false; var isValueDone = false; - StreamSubscription valueSub; - StreamSubscription triggerSub; + StreamSubscription? valueSub; + StreamSubscription? triggerSub; void emit() { - controller.add(currentResults); + controller.add(currentResults!); currentResults = null; waitingForTrigger = true; } @@ -44,7 +44,7 @@ class AggregateSample extends StreamTransformerBase { if (!waitingForTrigger) emit(); if (isTriggerDone) { - valueSub.cancel(); + valueSub!.cancel(); controller.close(); } } @@ -63,7 +63,7 @@ class AggregateSample extends StreamTransformerBase { if (currentResults != null) emit(); if (isValueDone) { - triggerSub.cancel(); + triggerSub!.cancel(); controller.close(); } } @@ -80,8 +80,9 @@ class AggregateSample extends StreamTransformerBase { assert(valueSub == null); valueSub = values.listen(onValue, onError: controller.addError, onDone: onValuesDone); - if (triggerSub != null) { - if (triggerSub.isPaused) triggerSub.resume(); + final priorTriggerSub = triggerSub; + if (priorTriggerSub != null) { + if (priorTriggerSub.isPaused) priorTriggerSub.resume(); } else { triggerSub = _trigger.listen(onTrigger, onError: controller.addError, onDone: onTriggerDone); @@ -98,17 +99,16 @@ class AggregateSample extends StreamTransformerBase { }; } controller.onCancel = () { - var toCancel = >[]; - if (!isValueDone) toCancel.add(valueSub); + var cancels = >[if (!isValueDone) valueSub!.cancel()]; valueSub = null; if (_trigger.isBroadcast || !values.isBroadcast) { - if (!isTriggerDone) toCancel.add(triggerSub); + if (!isTriggerDone) cancels.add(triggerSub!.cancel()); triggerSub = null; } else { - triggerSub.pause(); + triggerSub!.pause(); } - var cancels = - toCancel.map((s) => s.cancel()).where((f) => f != null).toList(); + // Handle opt-out nulls + cancels.removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; return Future.wait(cancels).then((_) => null); }; diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index c5b160b3d..7b406c7f9 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -117,13 +117,13 @@ T _dropPrevious(T event, _) => event; /// work. StreamTransformer _asyncMapThen( Future Function(S) convert, void Function(void) then) { - Future pendingEvent; + Future? pendingEvent; return fromHandlers(handleData: (event, sink) { pendingEvent = convert(event).then(sink.add).catchError(sink.addError).then(then); }, handleDone: (sink) { if (pendingEvent != null) { - pendingEvent.then((_) => sink.close()); + pendingEvent!.then((_) => sink.close()); } else { sink.close(); } diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 303b16a4a..6e268e370 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -92,14 +92,14 @@ class _CombineLatest extends StreamTransformerBase { ? _other.asBroadcastStream() : _other; - StreamSubscription sourceSubscription; - StreamSubscription otherSubscription; + StreamSubscription? sourceSubscription; + StreamSubscription? otherSubscription; var sourceDone = false; var otherDone = false; - S latestSource; - T latestOther; + late S latestSource; + late T latestOther; var sourceStarted = false; var otherStarted = false; @@ -114,16 +114,16 @@ class _CombineLatest extends StreamTransformerBase { return; } if (result is Future) { - sourceSubscription.pause(); - otherSubscription.pause(); + sourceSubscription!.pause(); + otherSubscription!.pause(); result .then(controller.add, onError: controller.addError) .whenComplete(() { - sourceSubscription.resume(); - otherSubscription.resume(); + sourceSubscription!.resume(); + otherSubscription!.resume(); }); } else { - controller.add(result as R); + controller.add(result); } } @@ -142,7 +142,7 @@ class _CombineLatest extends StreamTransformerBase { controller.close(); } else if (!sourceStarted) { // Nothing can ever be emitted - otherSubscription.cancel(); + otherSubscription!.cancel(); controller.close(); } }); @@ -159,24 +159,28 @@ class _CombineLatest extends StreamTransformerBase { controller.close(); } else if (!otherStarted) { // Nothing can ever be emitted - sourceSubscription.cancel(); + sourceSubscription!.cancel(); controller.close(); } }); if (!source.isBroadcast) { controller ..onPause = () { - sourceSubscription.pause(); - otherSubscription.pause(); + sourceSubscription!.pause(); + otherSubscription!.pause(); } ..onResume = () { - sourceSubscription.resume(); - otherSubscription.resume(); + sourceSubscription!.resume(); + otherSubscription!.resume(); }; } controller.onCancel = () { - var cancels = [sourceSubscription.cancel(), otherSubscription.cancel()] - .where((f) => f != null); + var cancels = [ + sourceSubscription!.cancel(), + otherSubscription!.cancel() + ] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); sourceSubscription = null; otherSubscription = null; return Future.wait(cancels).then((_) => null); @@ -208,7 +212,7 @@ class _CombineLatestAll extends StreamTransformerBase> { controller.onListen = () { final subscriptions = >[]; - final latestData = List(allStreams.length); + final latestData = List.filled(allStreams.length, null); final hasEmitted = {}; void handleData(int index, T data) { latestData[index] = data; @@ -249,10 +253,10 @@ class _CombineLatestAll extends StreamTransformerBase> { }; } controller.onCancel = () { - var cancels = subscriptions - .map((s) => s.cancel()) - .where((f) => f != null) - .toList(); + if (subscriptions.isEmpty) return null; + var cancels = [for (var s in subscriptions) s.cancel()] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; return Future.wait(cancels).then((_) => null); }; diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index 05c977fc3..402d8a0c0 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -68,12 +68,12 @@ class _FollowedBy extends StreamTransformerBase { ? _next.asBroadcastStream() : _next; - StreamSubscription subscription; + StreamSubscription? subscription; var currentStream = first; var firstDone = false; var secondDone = false; - Function currentDoneHandler; + late void Function() currentDoneHandler; void listen() { subscription = currentStream.listen(controller.add, @@ -100,18 +100,18 @@ class _FollowedBy extends StreamTransformerBase { if (!first.isBroadcast) { controller ..onPause = () { - if (!firstDone || !next.isBroadcast) return subscription.pause(); - subscription.cancel(); + if (!firstDone || !next.isBroadcast) return subscription!.pause(); + subscription!.cancel(); subscription = null; } ..onResume = () { - if (!firstDone || !next.isBroadcast) return subscription.resume(); + if (!firstDone || !next.isBroadcast) return subscription!.resume(); listen(); }; } controller.onCancel = () { if (secondDone) return null; - var toCancel = subscription; + var toCancel = subscription!; subscription = null; return toCancel.cancel(); }; diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index 3e5689fba..c7c93325f 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -7,9 +7,9 @@ import 'dart:async'; /// Like [new StreamTransformer.fromHandlers] but the handlers are called once /// per event rather than once per listener for broadcast streams. StreamTransformer fromHandlers( - {void Function(S, EventSink) handleData, - void Function(Object, StackTrace, EventSink) handleError, - void Function(EventSink) handleDone}) => + {void Function(S, EventSink)? handleData, + void Function(Object, StackTrace, EventSink)? handleError, + void Function(EventSink)? handleDone}) => _StreamTransformer( handleData: handleData, handleError: handleError, @@ -21,9 +21,9 @@ class _StreamTransformer extends StreamTransformerBase { final void Function(Object, StackTrace, EventSink) _handleError; _StreamTransformer( - {void Function(S, EventSink) handleData, - void Function(Object, StackTrace, EventSink) handleError, - void Function(EventSink) handleDone}) + {void Function(S, EventSink)? handleData, + void Function(Object, StackTrace, EventSink)? handleError, + void Function(EventSink)? handleDone}) : _handleData = handleData ?? _defaultHandleData, _handleError = handleError ?? _defaultHandleError, _handleDone = handleDone ?? _defaultHandleDone; @@ -47,12 +47,12 @@ class _StreamTransformer extends StreamTransformerBase { ? StreamController.broadcast(sync: true) : StreamController(sync: true); - StreamSubscription subscription; + StreamSubscription? subscription; controller.onListen = () { assert(subscription == null); var valuesDone = false; subscription = values.listen((value) => _handleData(value, controller), - onError: (error, StackTrace stackTrace) { + onError: (Object error, StackTrace stackTrace) { _handleError(error, stackTrace, controller); }, onDone: () { valuesDone = true; @@ -60,13 +60,13 @@ class _StreamTransformer extends StreamTransformerBase { }); if (!values.isBroadcast) { controller - ..onPause = subscription.pause - ..onResume = subscription.resume; + ..onPause = subscription!.pause + ..onResume = subscription!.resume; } controller.onCancel = () { var toCancel = subscription; subscription = null; - if (!valuesDone) return toCancel.cancel(); + if (!valuesDone) return toCancel!.cancel(); return null; }; }; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index c68695ca7..61b5e2170 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -131,10 +131,10 @@ class _Merge extends StreamTransformerBase { }; } controller.onCancel = () { - var cancels = subscriptions - .map((s) => s.cancel()) - .where((f) => f != null) - .toList(); + if (subscriptions.isEmpty) return null; + var cancels = [for (var s in subscriptions) s.cancel()] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; return Future.wait(cancels).then((_) => null); }; @@ -183,11 +183,10 @@ class _MergeExpanded extends StreamTransformerBase, T> { }; } controller.onCancel = () { - var cancels = subscriptions - .map((s) => s.cancel()) - .where((f) => f != null) - .toList(); - if (cancels.isEmpty) return null; + if (subscriptions.isEmpty) return null; + var cancels = [for (var s in subscriptions) s.cancel()] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); return Future.wait(cancels).then((_) => null); }; }; diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index e42f8f43f..23dfbc556 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -85,7 +85,7 @@ extension RateLimit on Stream { /// Events emitted by the source stream within [duration] following an emitted /// event will be discarded. Errors are always forwarded immediately. Stream throttle(Duration duration) { - Timer timer; + Timer? timer; return transform(fromHandlers(handleData: (data, sink) { if (timer == null) { @@ -125,7 +125,7 @@ extension RateLimit on Stream { /// source: a------b--c----d--| /// output: -----a------c--------d| Stream audit(Duration duration) { - Timer timer; + Timer? timer; var shouldClose = false; T recentData; @@ -161,7 +161,7 @@ extension RateLimit on Stream { transform(AggregateSample>(trigger, _collect)); } -List _collectToList(T element, List soFar) { +List _collectToList(T element, List? soFar) { soFar ??= []; soFar.add(element); return soFar; @@ -172,10 +172,10 @@ T _dropPrevious(T element, _) => element; /// Creates a StreamTransformer which aggregates values until the source stream /// does not emit for [duration], then emits the aggregated values. StreamTransformer _debounceAggregate( - Duration duration, R Function(T element, R soFar) collect, - {bool leading, bool trailing}) { - Timer timer; - R soFar; + Duration duration, R Function(T element, R? soFar) collect, + {required bool leading, required bool trailing}) { + Timer? timer; + R? soFar; var shouldClose = false; var emittedLatestAsLeading = false; return fromHandlers(handleData: (T value, EventSink sink) { @@ -183,12 +183,12 @@ StreamTransformer _debounceAggregate( soFar = collect(value, soFar); if (timer == null && leading) { emittedLatestAsLeading = true; - sink.add(soFar); + sink.add(soFar as R); } else { emittedLatestAsLeading = false; } timer = Timer(duration, () { - if (trailing && !emittedLatestAsLeading) sink.add(soFar); + if (trailing && !emittedLatestAsLeading) sink.add(soFar as R); if (shouldClose) { sink.close(); } @@ -205,4 +205,4 @@ StreamTransformer _debounceAggregate( }); } -List _collect(T event, List soFar) => (soFar ?? [])..add(event); +List _collect(T event, List? soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index 4e022f598..d14381cb1 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -21,7 +21,7 @@ extension Scan on Stream { if (result is Future) { return result.then((r) => accumulated = r); } else { - return accumulated = result as S; + return accumulated = result; } }); } diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index dcd2431be..df7f1b8f9 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -65,7 +65,7 @@ class _SwitchTransformer extends StreamTransformerBase, T> { : StreamController(sync: true); controller.onListen = () { - StreamSubscription innerSubscription; + StreamSubscription? innerSubscription; var outerStreamDone = false; final outerSubscription = outer.listen( @@ -96,8 +96,10 @@ class _SwitchTransformer extends StreamTransformerBase, T> { controller.onCancel = () { var cancels = [ if (!outerStreamDone) outerSubscription.cancel(), - if (innerSubscription != null) innerSubscription.cancel(), - ].where((f) => f != null); + if (innerSubscription != null) innerSubscription!.cancel(), + ] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; return Future.wait(cancels).then((_) => null); }; diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 43b35d17d..542050034 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -27,7 +27,7 @@ class _TakeUntil extends StreamTransformerBase { ? StreamController.broadcast(sync: true) : StreamController(sync: true); - StreamSubscription subscription; + StreamSubscription? subscription; var isDone = false; _trigger.then((_) { if (isDone) return; @@ -46,12 +46,12 @@ class _TakeUntil extends StreamTransformerBase { }); if (!values.isBroadcast) { controller - ..onPause = subscription.pause - ..onResume = subscription.resume; + ..onPause = subscription!.pause + ..onResume = subscription!.resume; } controller.onCancel = () { if (isDone) return null; - var toCancel = subscription; + var toCancel = subscription!; subscription = null; return toCancel.cancel(); }; diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 2696e025b..b7e03214a 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -22,9 +22,9 @@ extension Tap on Stream { /// /// The callbacks may not be called until the tapped stream has a listener, /// and may not be called after the listener has canceled the subscription. - Stream tap(void Function(T) onValue, - {void Function(Object, StackTrace) onError, - void Function() onDone}) => + Stream tap(void Function(T)? onValue, + {void Function(Object, StackTrace)? onError, + void Function()? onDone}) => transform(fromHandlers(handleData: (value, sink) { try { onValue?.call(value); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 5da90b121..ba4bd5177 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://github.com/dart-lang/stream_transform -version: 1.2.1-dev +version: 2.0.0-nullsafety.0-dev environment: - sdk: ">=2.7.0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dev_dependencies: - async: ^2.0.0 - pedantic: ^1.5.0 - test: ^1.0.0 + async: ^2.5.0-nullsafety + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index 9b46e1fe5..1280b51e2 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -11,16 +11,16 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; - Completer finishWork; - List workArgument; + Completer? finishWork; + List? workArgument; /// Represents the async `convert` function and asserts that is is only called /// after the previous iteration has completed. @@ -28,15 +28,15 @@ void main() { expect(finishWork, isNull, reason: 'See $values befor previous work is complete'); workArgument = values; - finishWork = Completer(); - finishWork.future.then((_) { - workArgument = null; - finishWork = null; - }).catchError((_) { - workArgument = null; - finishWork = null; - }); - return finishWork.future; + finishWork = Completer() + ..future.then((_) { + workArgument = null; + finishWork = null; + }).catchError((_) { + workArgument = null; + finishWork = null; + }); + return finishWork!.future; } for (var streamType in streamTypes) { @@ -64,7 +64,7 @@ void main() { await Future(() {}); expect(emittedValues, isEmpty); expect(workArgument, [1]); - finishWork.complete('result'); + finishWork!.complete('result'); await Future(() {}); expect(emittedValues, ['result']); }); @@ -74,7 +74,7 @@ void main() { await Future(() {}); values..add(2)..add(3); await Future(() {}); - finishWork.complete(); + finishWork!.complete(''); await Future(() {}); expect(workArgument, [2, 3]); }); @@ -90,7 +90,7 @@ void main() { test('forwards errors which occur during the work', () async { values.add(1); await Future(() {}); - finishWork.completeError('error'); + finishWork!.completeError('error'); await Future(() {}); expect(errors, ['error']); }); @@ -98,11 +98,11 @@ void main() { test('can continue handling events after an error', () async { values.add(1); await Future(() {}); - finishWork.completeError('error'); + finishWork!.completeError('error'); values.add(2); await Future(() {}); expect(workArgument, [2]); - finishWork.completeError('another'); + finishWork!.completeError('another'); await Future(() {}); expect(errors, ['error', 'another']); }); @@ -140,11 +140,11 @@ void main() { values.add(2); await values.close(); expect(isDone, false); - finishWork.complete(null); + finishWork!.complete(''); await Future(() {}); // Still a pending value expect(isDone, false); - finishWork.complete(null); + finishWork!.complete(''); await Future(() {}); expect(isDone, true); }); @@ -161,7 +161,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); await Future(() {}); - finishWork.complete('result'); + finishWork!.complete('result'); await Future(() {}); expect(emittedValues, ['result']); expect(otherValues, ['result']); @@ -175,7 +175,7 @@ void main() { await values.close(); expect(isDone, false); expect(otherDone, false); - finishWork.complete(); + finishWork!.complete(''); await Future(() {}); expect(isDone, true); expect(otherDone, true); @@ -184,7 +184,7 @@ void main() { test('can cancel and relisten', () async { values.add(1); await Future(() {}); - finishWork.complete('first'); + finishWork!.complete('first'); await Future(() {}); await subscription.cancel(); values.add(2); @@ -193,7 +193,7 @@ void main() { values.add(3); await Future(() {}); expect(workArgument, [3]); - finishWork.complete('second'); + finishWork!.complete('second'); await Future(() {}); expect(emittedValues, ['first', 'second']); }); diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 9c37cd491..06457d899 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -11,16 +11,16 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; - Completer finishWork; - int workArgument; + Completer? finishWork; + int? workArgument; /// Represents the async `convert` function and asserts that is is only called /// after the previous iteration has completed. @@ -28,15 +28,15 @@ void main() { expect(finishWork, isNull, reason: 'See $values befor previous work is complete'); workArgument = value; - finishWork = Completer(); - finishWork.future.then((_) { - workArgument = null; - finishWork = null; - }).catchError((_) { - workArgument = null; - finishWork = null; - }); - return finishWork.future; + finishWork = Completer() + ..future.then((_) { + workArgument = null; + finishWork = null; + }).catchError((_) { + workArgument = null; + finishWork = null; + }); + return finishWork!.future; } for (var streamType in streamTypes) { @@ -64,7 +64,7 @@ void main() { await Future(() {}); expect(emittedValues, isEmpty); expect(workArgument, 1); - finishWork.complete('result'); + finishWork!.complete('result'); await Future(() {}); expect(emittedValues, ['result']); }); @@ -74,7 +74,7 @@ void main() { await Future(() {}); values..add(2)..add(3); await Future(() {}); - finishWork.complete(); + finishWork!.complete(''); await Future(() {}); expect(workArgument, 3); }); @@ -90,7 +90,7 @@ void main() { test('forwards errors which occur during the work', () async { values.add(1); await Future(() {}); - finishWork.completeError('error'); + finishWork!.completeError('error'); await Future(() {}); expect(errors, ['error']); }); @@ -98,11 +98,11 @@ void main() { test('can continue handling events after an error', () async { values.add(1); await Future(() {}); - finishWork.completeError('error'); + finishWork!.completeError('error'); values.add(2); await Future(() {}); expect(workArgument, 2); - finishWork.completeError('another'); + finishWork!.completeError('another'); await Future(() {}); expect(errors, ['error', 'another']); }); @@ -140,11 +140,11 @@ void main() { values.add(2); await values.close(); expect(isDone, false); - finishWork.complete(null); + finishWork!.complete(''); await Future(() {}); // Still a pending value expect(isDone, false); - finishWork.complete(null); + finishWork!.complete(''); await Future(() {}); expect(isDone, true); }); @@ -161,7 +161,7 @@ void main() { transformed.listen(otherValues.add); values.add(1); await Future(() {}); - finishWork.complete('result'); + finishWork!.complete('result'); await Future(() {}); expect(emittedValues, ['result']); expect(otherValues, ['result']); @@ -175,7 +175,7 @@ void main() { await values.close(); expect(isDone, false); expect(otherDone, false); - finishWork.complete(); + finishWork!.complete(''); await Future(() {}); expect(isDone, true); expect(otherDone, true); @@ -184,7 +184,7 @@ void main() { test('can cancel and relisten', () async { values.add(1); await Future(() {}); - finishWork.complete('first'); + finishWork!.complete('first'); await Future(() {}); await subscription.cancel(); values.add(2); @@ -193,20 +193,11 @@ void main() { values.add(3); await Future(() {}); expect(workArgument, 3); - finishWork.complete('second'); + finishWork!.complete('second'); await Future(() {}); expect(emittedValues, ['first', 'second']); }); } }); } - test('handles null response from cancel', () async { - var controller = StreamController(); - - var subscription = NullOnCancelStream(controller.stream) - .asyncMapSample((_) async {}) - .listen(null); - - await subscription.cancel(); - }); } diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 58cb95bcb..20c7d9f89 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -12,13 +12,13 @@ import 'utils.dart'; void main() { for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; group('audit', () { setUp(() async { diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 80a793cbc..b528fa298 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -10,16 +10,16 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - StreamController trigger; - StreamController values; - List> emittedValues; - bool valuesCanceled; - bool triggerCanceled; - bool triggerPaused; - bool isDone; - List errors; - Stream> transformed; - StreamSubscription> subscription; + late StreamController trigger; + late StreamController values; + late List> emittedValues; + late bool valuesCanceled; + late bool triggerCanceled; + late bool triggerPaused; + late bool isDone; + late List errors; + late Stream> transformed; + late StreamSubscription> subscription; void setUpForStreamTypes(String triggerType, String valuesType) { valuesCanceled = false; @@ -243,13 +243,4 @@ void main() { ]); }); } - - test('handles null response from cancel', () async { - var controller = StreamController(); - var trigger = StreamController(); - var subscription = NullOnCancelStream(controller.stream) - .buffer(trigger.stream) - .listen(null); - await subscription.cancel(); - }); } diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart index d57d61852..2943449fd 100644 --- a/pkgs/stream_transform/test/combine_latest_all_test.dart +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -8,8 +8,6 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; -import 'utils.dart'; - Future tick() => Future(() {}); void main() { @@ -166,14 +164,4 @@ void main() { }); }); }); - - test('handles null response from cancel', () async { - var source = StreamController(); - var other = StreamController(); - - var subscription = NullOnCancelStream(source.stream) - .combineLatestAll([NullOnCancelStream(other.stream)]).listen(null); - - await subscription.cancel(); - }); } diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index 4ea94994d..2b35e2c21 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -9,8 +9,6 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; -import 'utils.dart'; - void main() { group('combineLatest', () { test('flows through combine callback', () async { @@ -170,17 +168,6 @@ void main() { }); }); }); - - test('handles null response from cancel', () async { - var source = StreamController(); - var other = StreamController(); - - var subscription = NullOnCancelStream(source.stream) - .combineLatest(NullOnCancelStream(other.stream), (a, b) => null) - .listen(null); - - await subscription.cancel(); - }); } class _NumberedException implements Exception { diff --git a/pkgs/stream_transform/test/concurrent_async_expand_test.dart b/pkgs/stream_transform/test/concurrent_async_expand_test.dart index 9ed02d036..d0b4ad457 100644 --- a/pkgs/stream_transform/test/concurrent_async_expand_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_expand_test.dart @@ -24,15 +24,15 @@ void main() { for (var outerType in streamTypes) { for (var innerType in streamTypes) { group('concurrentAsyncExpand $outerType to $innerType', () { - StreamController outerController; - bool outerCanceled; - List> innerControllers; - List innerCanceled; - List emittedValues; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController outerController; + late bool outerCanceled; + late List> innerControllers; + late List innerCanceled; + late List emittedValues; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; setUp(() { outerController = createController(outerType) @@ -184,19 +184,4 @@ void main() { }); } } - - test('hendles null response from cancel', () async { - var source = StreamController(); - var other = StreamController(); - - var subscription = NullOnCancelStream(source.stream) - .concurrentAsyncExpand((_) => NullOnCancelStream(other.stream)) - .listen(null); - - source.add(1); - - await Future(() {}); - - await subscription.cancel(); - }); } diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index 6da21012e..a894e7f02 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -11,16 +11,16 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - StreamController controller; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController controller; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; - List> finishWork; - List values; + late List> finishWork; + late List values; Future convert(int value) { values.add(value); @@ -127,7 +127,7 @@ void main() { await controller.close(); expect(isDone, false); expect(otherDone, false); - finishWork.first.complete(); + finishWork.first.complete(''); await Future(() {}); expect(isDone, true); expect(otherDone, true); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index de6b74020..f24bfb9d9 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -13,13 +13,13 @@ void main() { for (var streamType in streamTypes) { group('Stream type [$streamType]', () { group('debounce - trailing', () { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - StreamSubscription subscription; - Stream transformed; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late StreamSubscription subscription; + late Stream transformed; setUp(() async { valuesCanceled = false; @@ -89,10 +89,10 @@ void main() { }); group('debounce - leading', () { - StreamController values; - List emittedValues; - Stream transformed; - bool isDone; + late StreamController values; + late List emittedValues; + late Stream transformed; + late bool isDone; setUp(() async { values = createController(streamType); @@ -139,9 +139,9 @@ void main() { }); group('debounce - leading and trailing', () { - StreamController values; - List emittedValues; - Stream transformed; + late StreamController values; + late List emittedValues; + late Stream transformed; setUp(() async { values = createController(streamType); @@ -179,10 +179,10 @@ void main() { }); group('debounceBuffer', () { - StreamController values; - List> emittedValues; - List errors; - Stream> transformed; + late StreamController values; + late List> emittedValues; + late List errors; + late Stream> transformed; setUp(() async { values = createController(streamType); diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index c8864b5bc..fbe904ab4 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -13,17 +13,17 @@ void main() { for (var firstType in streamTypes) { for (var secondType in streamTypes) { group('followedBy [$firstType] with [$secondType]', () { - StreamController first; - StreamController second; + late StreamController first; + late StreamController second; - List emittedValues; - bool firstCanceled; - bool secondCanceled; - bool secondListened; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late List emittedValues; + late bool firstCanceled; + late bool secondCanceled; + late bool secondListened; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; setUp(() async { firstCanceled = false; diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 50d59c5d0..206acc8b1 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -9,13 +9,13 @@ import 'package:test/test.dart'; import 'package:stream_transform/src/from_handlers.dart'; void main() { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; void setUpForController(StreamController controller, StreamTransformer transformer) { @@ -68,10 +68,10 @@ void main() { }); group('broadcast stream with muliple listeners', () { - List emittedValues2; - List errors2; - bool isDone2; - StreamSubscription subscription2; + late List emittedValues2; + late List errors2; + late bool isDone2; + late StreamSubscription subscription2; setUp(() { setUpForController(StreamController.broadcast(), fromHandlers()); @@ -133,9 +133,9 @@ void main() { }); group('broadcast stream with multiple listeners', () { - int dataCallCount; - int doneCallCount; - int errorCallCount; + late int dataCallCount; + late int doneCallCount; + late int errorCallCount; setUp(() async { dataCallCount = 0; diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 2eef5d1a5..24cd76b16 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -8,8 +8,6 @@ import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; -import 'utils.dart'; - void main() { group('merge', () { test('includes all values', () async { @@ -140,15 +138,4 @@ void main() { expect(secondListenerValues, [1, 2, 3, 4, 5, 6]); }); }); - - test('handles null response rom cancel', () async { - var source = StreamController(); - var other = StreamController(); - - var subscription = NullOnCancelStream(source.stream) - .merge(NullOnCancelStream(other.stream)) - .listen(null); - - await subscription.cancel(); - }); } diff --git a/pkgs/stream_transform/test/opt_out_test.dart b/pkgs/stream_transform/test/opt_out_test.dart new file mode 100644 index 000000000..8ab4fc49f --- /dev/null +++ b/pkgs/stream_transform/test/opt_out_test.dart @@ -0,0 +1,72 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// 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.9 + +import 'dart:async'; + +import 'package:async/async.dart'; +import 'package:test/test.dart'; + +import 'package:stream_transform/stream_transform.dart'; + +void main() { + group('null returned from StreamSubscription.cancel', () { + void testNullCancel( + String name, Stream Function(Stream) transform) { + test(name, () async { + var subscription = transform(_NullOnCancelStream()).listen(null); + await subscription.cancel(); + }); + } + + testNullCancel('asyncMapSample', (s) => s.asyncMapSample((_) async {})); + testNullCancel('buffer', (s) => s.buffer(_nonEndingStream())); + testNullCancel( + 'combineLatestAll', (s) => s.combineLatestAll([_NullOnCancelStream()])); + testNullCancel('combineLatest', + (s) => s.combineLatest(_NullOnCancelStream(), (a, b) {})); + testNullCancel('merge', (s) => s.merge(_NullOnCancelStream())); + + test('switchLatest', () async { + var subscription = + _NullOnCancelStream(Stream>.value(_NullOnCancelStream())) + .switchLatest() + .listen(null); + await Future(() {}); + await subscription.cancel(); + }); + + test('concurrentAsyncExpand', () async { + var subscription = _NullOnCancelStream(Stream.value(null)) + .concurrentAsyncExpand((_) => _NullOnCancelStream()) + .listen(null); + await Future(() {}); + await subscription.cancel(); + }); + }); +} + +class _NullOnCancelStream extends StreamView { + _NullOnCancelStream([Stream stream]) : super(stream ?? _nonEndingStream()); + + @override + StreamSubscription listen(void Function(T) onData, + {Function onError, void Function() onDone, bool cancelOnError}) => + _NullOnCancelSubscription(super.listen(onData, + onError: onError, onDone: onDone, cancelOnError: cancelOnError)); +} + +class _NullOnCancelSubscription extends DelegatingStreamSubscription { + final StreamSubscription _subscription; + _NullOnCancelSubscription(this._subscription) : super(_subscription); + + @override + Future cancel() { + _subscription.cancel(); + return null; + } +} + +Stream _nonEndingStream() => StreamController().stream; diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 4e58680dc..e3effb315 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -22,7 +22,7 @@ void main() { test('can create a broadcast stream', () { var source = StreamController.broadcast(); - var transformed = source.stream.scan(null, null); + var transformed = source.stream.scan(null, (_, __) {}); expect(transformed.isBroadcast, true); }); diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 3a5a02550..29241beef 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -11,12 +11,12 @@ import 'package:stream_transform/stream_transform.dart'; import 'utils.dart'; void main() { - StreamController values; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late Stream transformed; + late StreamSubscription subscription; - List emittedValues; - bool isDone; + late List emittedValues; + late bool isDone; void setupForStreamType( String streamType, Stream Function(Stream) transform) { @@ -102,7 +102,7 @@ void main() { for (var startingStreamType in streamTypes) { group('startWithStream [$startingStreamType] then [$streamType]', () { - StreamController starting; + late StreamController starting; setUp(() async { starting = createController(startingStreamType); setupForStreamType( diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 16deb4bb3..b69c8b041 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -14,16 +14,16 @@ void main() { for (var outerType in streamTypes) { for (var innerType in streamTypes) { group('Outer type: [$outerType], Inner type: [$innerType]', () { - StreamController first; - StreamController second; - StreamController> outer; + late StreamController first; + late StreamController second; + late StreamController> outer; - List emittedValues; - bool firstCanceled; - bool outerCanceled; - bool isDone; - List errors; - StreamSubscription subscription; + late List emittedValues; + late bool firstCanceled; + late bool outerCanceled; + late bool isDone; + late List errors; + late StreamSubscription subscription; setUp(() async { firstCanceled = false; @@ -141,24 +141,11 @@ void main() { test('can create a broadcast stream', () async { var outer = StreamController.broadcast(); - var transformed = outer.stream.switchMap(null); + var transformed = outer.stream.switchMap((_) => const Stream.empty()); expect(transformed.isBroadcast, true); }); - test('handles null response from cancel', () async { - var outer = StreamController>(); - var inner = StreamController(); - - var subscription = - NullOnCancelStream(outer.stream).switchLatest().listen(null); - - outer.add(NullOnCancelStream(inner.stream)); - await Future(() {}); - - await subscription.cancel(); - }); - test('forwards errors from the convert callback', () async { var errors = []; var source = Stream.fromIterable([1, 2, 3]); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index c25d34288..11e906fd2 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -13,14 +13,14 @@ import 'utils.dart'; void main() { for (var streamType in streamTypes) { group('takeUntil on Stream type [$streamType]', () { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - List errors; - Stream transformed; - StreamSubscription subscription; - Completer closeTrigger; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; + late Completer closeTrigger; setUp(() { valuesCanceled = false; diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index e51ef844f..d84fdf475 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -12,12 +12,12 @@ import 'utils.dart'; void main() { for (var streamType in streamTypes) { group('Stream type [$streamType]', () { - StreamController values; - List emittedValues; - bool valuesCanceled; - bool isDone; - Stream transformed; - StreamSubscription subscription; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool isDone; + late Stream transformed; + late StreamSubscription subscription; group('throttle', () { setUp(() async { diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart index 4aa583751..b6196d687 100644 --- a/pkgs/stream_transform/test/utils.dart +++ b/pkgs/stream_transform/test/utils.dart @@ -4,8 +4,6 @@ import 'dart:async'; -import 'package:async/async.dart'; - /// Cycle the event loop to ensure timers are started, then wait for a delay /// longer than [milliseconds] to allow for the timer to fire. Future waitForTimer(int milliseconds) => @@ -25,26 +23,3 @@ StreamController createController(String streamType) { } const streamTypes = ['single subscription', 'broadcast']; - -class NullOnCancelStream extends StreamView { - final Stream _stream; - - NullOnCancelStream(this._stream) : super(_stream); - - @override - StreamSubscription listen(void Function(T) onData, - {Function onError, void Function() onDone, bool cancelOnError}) => - _NullOnCancelSubscription(_stream.listen(onData, - onError: onError, onDone: onDone, cancelOnError: cancelOnError)); -} - -class _NullOnCancelSubscription extends DelegatingStreamSubscription { - final StreamSubscription _subscription; - _NullOnCancelSubscription(this._subscription) : super(_subscription); - - @override - Future cancel() { - _subscription.cancel(); - return null; - } -} From 1520964c63adbec217cc1d0d905a7e05b3d99d21 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 2 Dec 2020 22:01:00 -0800 Subject: [PATCH 0724/1215] Migrate to nullsafety --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++ .../lib/test_reflective_loader.dart | 44 +++++++++---------- pkgs/test_reflective_loader/pubspec.yaml | 4 +- .../test/test_reflective_loader_test.dart | 2 - 4 files changed, 28 insertions(+), 26 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 616d02194..7efa79cda 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0-nullsafety.0 + +- Migrate to the null safety language feature. + ## 0.1.9 - Add `@SkippedTest` annotation and `skip_test` prefix. diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 6430c6676..04caa51fd 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -38,7 +38,7 @@ const _SoloTest soloTest = const _SoloTest(); final List<_Group> _currentGroups = <_Group>[]; int _currentSuiteLevel = 0; -String _currentSuiteName = null; +String? _currentSuiteName = null; /** * Is `true` the application is running in the checked mode. @@ -58,8 +58,8 @@ final bool _isCheckedMode = () { * create embedded suites. If the current suite is the top-level one, perform * check for "solo" groups and tests, and run all or only "solo" items. */ -void defineReflectiveSuite(void define(), {String name}) { - String groupName = _currentSuiteName; +void defineReflectiveSuite(void define(), {String? name}) { + String? groupName = _currentSuiteName; _currentSuiteLevel++; try { _currentSuiteName = _combineNames(_currentSuiteName, name); @@ -167,13 +167,13 @@ void defineReflectiveTests(Type type) { */ void _addTestsIfTopLevelSuite() { if (_currentSuiteLevel == 0) { - void runTests({bool allGroups, bool allTests}) { + void runTests({/*required*/ required bool allGroups, /*required*/ required bool allTests}) { for (_Group group in _currentGroups) { if (allGroups || group.isSolo) { for (_Test test in group.tests) { if (allTests || test.isSolo) { - test_package.test(test.name, test.function, - timeout: test.timeout, skip: test.isSkipped); + test_package.test(test.name, test.function!, + timeout: test.timeout!, skip: test.isSkipped); } } } @@ -195,7 +195,7 @@ void _addTestsIfTopLevelSuite() { * Return the combination of the [base] and [addition] names. * If any other two is `null`, then the other one is returned. */ -String _combineNames(String base, String addition) { +String? _combineNames(String? base, String? addition) { if (base == null) { return addition; } else if (addition == null) { @@ -205,7 +205,7 @@ String _combineNames(String base, String addition) { } } -Object _getAnnotationInstance(DeclarationMirror declaration, Type type) { +Object? _getAnnotationInstance(DeclarationMirror declaration, Type type) { for (InstanceMirror annotation in declaration.metadata) { if (annotation.reflectee.runtimeType == type) { return annotation.reflectee; @@ -227,9 +227,9 @@ bool _hasFailingTestAnnotation(MethodMirror method) => bool _hasSkippedTestAnnotation(MethodMirror method) => _hasAnnotationInstance(method, skippedTest); -Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { - var invocationResult = null; - InstanceMirror closure; +Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { + Object? invocationResult = null; + InstanceMirror? closure; try { closure = instanceMirror.getField(symbol); } on NoSuchMethodError {} @@ -248,7 +248,7 @@ Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { * - The test returns a future which completes with an error. * - An exception is thrown to the zone handler from a timer task. */ -Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { +Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { bool passed = false; return runZoned(() { return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { @@ -270,7 +270,7 @@ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { }); } -Future _runTest(ClassMirror classMirror, Symbol symbol) { +Future _runTest(ClassMirror classMirror, Symbol symbol) { InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); return _invokeSymbolIfExists(instanceMirror, #setUp) .then((_) => instanceMirror.invoke(symbol, []).reflectee) @@ -289,7 +289,7 @@ class FailingTest { * [issue] is a full URI describing the failure and used for tracking. * [reason] is a free form textual description. */ - const FailingTest({String issue, String reason}); + const FailingTest({String? issue, String? reason}); } /** @@ -302,7 +302,7 @@ class SkippedTest { * [issue] is a full URI describing the failure and used for tracking. * [reason] is a free form textual description. */ - const SkippedTest({String issue, String reason}); + const SkippedTest({String? issue, String? reason}); } /** @@ -331,7 +331,7 @@ class _AssertFailingTest { */ class _Group { final bool isSolo; - final String name; + final String? name; final List<_Test> tests = <_Test>[]; _Group(this.isSolo, this.name); @@ -339,14 +339,14 @@ class _Group { bool get hasSoloTest => tests.any((test) => test.isSolo); void addSkippedTest(String name) { - String fullName = _combineNames(this.name, name); + String? fullName = _combineNames(this.name, name); tests.add(new _Test.skipped(isSolo, fullName)); } void addTest(bool isSolo, String name, MethodMirror memberMirror, _TestFunction function) { - String fullName = _combineNames(this.name, name); - TestTimeout timeout = _getAnnotationInstance(memberMirror, TestTimeout); + String? fullName = _combineNames(this.name, name); + var timeout = _getAnnotationInstance(memberMirror, TestTimeout) as TestTimeout?; tests.add(new _Test(isSolo, fullName, function, timeout?._timeout)); } } @@ -371,9 +371,9 @@ class _SoloTest { */ class _Test { final bool isSolo; - final String name; - final _TestFunction function; - final test_package.Timeout timeout; + final String? name; + final _TestFunction? function; + final test_package.Timeout? timeout; final bool isSkipped; diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 8cfc3fa6f..75df05f52 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,12 +1,12 @@ name: test_reflective_loader -version: 0.1.9 +version: 0.2.0-nullsafety.0 description: Support for discovering tests and test suites using reflection. author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: - sdk: '>=1.8.0 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: test: '>=0.12.0 <2.0.0' diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index a657b0477..2c69ccebd 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -15,8 +15,6 @@ void main() { @reflectiveTest class TestReflectiveLoaderTest { - String pathname; - void test_passes() { expect(true, true); } From 9a7c70e4a6a8bcee97890cbb70cff071f51f1582 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 2 Dec 2020 22:02:00 -0800 Subject: [PATCH 0725/1215] nit --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 04caa51fd..dea1b16c7 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -167,7 +167,7 @@ void defineReflectiveTests(Type type) { */ void _addTestsIfTopLevelSuite() { if (_currentSuiteLevel == 0) { - void runTests({/*required*/ required bool allGroups, /*required*/ required bool allTests}) { + void runTests({required bool allGroups, required bool allTests}) { for (_Group group in _currentGroups) { if (allGroups || group.isSolo) { for (_Test test in group.tests) { From b5b95d879cf74070132df3f94034b02884d8e59d Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 2 Dec 2020 22:02:11 -0800 Subject: [PATCH 0726/1215] fmt --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index dea1b16c7..98b66ad84 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -227,7 +227,8 @@ bool _hasFailingTestAnnotation(MethodMirror method) => bool _hasSkippedTestAnnotation(MethodMirror method) => _hasAnnotationInstance(method, skippedTest); -Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) { +Future _invokeSymbolIfExists( + InstanceMirror instanceMirror, Symbol symbol) { Object? invocationResult = null; InstanceMirror? closure; try { @@ -346,7 +347,8 @@ class _Group { void addTest(bool isSolo, String name, MethodMirror memberMirror, _TestFunction function) { String? fullName = _combineNames(this.name, name); - var timeout = _getAnnotationInstance(memberMirror, TestTimeout) as TestTimeout?; + var timeout = + _getAnnotationInstance(memberMirror, TestTimeout) as TestTimeout?; tests.add(new _Test(isSolo, fullName, function, timeout?._timeout)); } } From 296db46cf7c5594a16d53d17461eff321030dc0b Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 3 Dec 2020 11:10:21 -0800 Subject: [PATCH 0727/1215] Feedback; much less nullable --- .../lib/test_reflective_loader.dart | 32 +++++++++---------- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 98b66ad84..71d436648 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -38,7 +38,7 @@ const _SoloTest soloTest = const _SoloTest(); final List<_Group> _currentGroups = <_Group>[]; int _currentSuiteLevel = 0; -String? _currentSuiteName = null; +String _currentSuiteName = ''; /** * Is `true` the application is running in the checked mode. @@ -58,8 +58,8 @@ final bool _isCheckedMode = () { * create embedded suites. If the current suite is the top-level one, perform * check for "solo" groups and tests, and run all or only "solo" items. */ -void defineReflectiveSuite(void define(), {String? name}) { - String? groupName = _currentSuiteName; +void defineReflectiveSuite(void define(), {String name = ''}) { + String groupName = _currentSuiteName; _currentSuiteLevel++; try { _currentSuiteName = _combineNames(_currentSuiteName, name); @@ -172,8 +172,8 @@ void _addTestsIfTopLevelSuite() { if (allGroups || group.isSolo) { for (_Test test in group.tests) { if (allTests || test.isSolo) { - test_package.test(test.name, test.function!, - timeout: test.timeout!, skip: test.isSkipped); + test_package.test(test.name, test.function, + timeout: test.timeout, skip: test.isSkipped); } } } @@ -195,10 +195,10 @@ void _addTestsIfTopLevelSuite() { * Return the combination of the [base] and [addition] names. * If any other two is `null`, then the other one is returned. */ -String? _combineNames(String? base, String? addition) { - if (base == null) { +String _combineNames(String base, String addition) { + if (base.isEmpty) { return addition; - } else if (addition == null) { + } else if (addition.isEmpty) { return base; } else { return '$base | $addition'; @@ -249,7 +249,7 @@ Future _invokeSymbolIfExists( * - The test returns a future which completes with an error. * - An exception is thrown to the zone handler from a timer task. */ -Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { +Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { bool passed = false; return runZoned(() { return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { @@ -271,7 +271,7 @@ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { }); } -Future _runTest(ClassMirror classMirror, Symbol symbol) { +Future _runTest(ClassMirror classMirror, Symbol symbol) { InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); return _invokeSymbolIfExists(instanceMirror, #setUp) .then((_) => instanceMirror.invoke(symbol, []).reflectee) @@ -332,7 +332,7 @@ class _AssertFailingTest { */ class _Group { final bool isSolo; - final String? name; + final String name; final List<_Test> tests = <_Test>[]; _Group(this.isSolo, this.name); @@ -340,13 +340,13 @@ class _Group { bool get hasSoloTest => tests.any((test) => test.isSolo); void addSkippedTest(String name) { - String? fullName = _combineNames(this.name, name); + var fullName = _combineNames(this.name, name); tests.add(new _Test.skipped(isSolo, fullName)); } void addTest(bool isSolo, String name, MethodMirror memberMirror, _TestFunction function) { - String? fullName = _combineNames(this.name, name); + var fullName = _combineNames(this.name, name); var timeout = _getAnnotationInstance(memberMirror, TestTimeout) as TestTimeout?; tests.add(new _Test(isSolo, fullName, function, timeout?._timeout)); @@ -373,8 +373,8 @@ class _SoloTest { */ class _Test { final bool isSolo; - final String? name; - final _TestFunction? function; + final String name; + final _TestFunction function; final test_package.Timeout? timeout; final bool isSkipped; @@ -384,6 +384,6 @@ class _Test { _Test.skipped(this.isSolo, this.name) : isSkipped = true, - function = null, + function = (() {}), timeout = null; } diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 75df05f52..6d081e48d 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -9,4 +9,4 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - test: '>=0.12.0 <2.0.0' + test: '>=1.16.0-nullsafety.12 <2.0.0' From 3810364bd1d1d9b7f7d1fd350162225bc8736b32 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 3 Dec 2020 15:46:41 -0800 Subject: [PATCH 0728/1215] Use runZonedGuarded --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 71d436648..cfd738db4 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -249,9 +249,9 @@ Future _invokeSymbolIfExists( * - The test returns a future which completes with an error. * - An exception is thrown to the zone handler from a timer task. */ -Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { +Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { bool passed = false; - return runZoned(() { + return runZonedGuarded(() { return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { passed = true; test_package.fail('Test passed - expected to fail.'); @@ -262,7 +262,7 @@ Future _runFailingTest(ClassMirror classMirror, Symbol symbol) { } // otherwise, an exception is not a failure for _runFailingTest }); - }, onError: (e) { + }, (e, st) { // if passed, and we call fail(), rethrow this exception if (passed) { throw e; From bcfa4c6e941e9304ef71642c2328553659b97290 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 3 Dec 2020 16:22:19 -0800 Subject: [PATCH 0729/1215] Fix test --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index cfd738db4..3528a43f3 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -252,7 +252,7 @@ Future _invokeSymbolIfExists( Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { bool passed = false; return runZonedGuarded(() { - return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { + return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { passed = true; test_package.fail('Test passed - expected to fail.'); }).catchError((e) { From ce8d0828facf05bbd638fbca71473319f85810dd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 4 Dec 2020 10:58:30 -0800 Subject: [PATCH 0730/1215] Refactor to remove StreamTransformer instantiation (dart-lang/stream_transform#120) Directly implement the behavior from `bind` which is the `Stream` to `Stream` implementation in the extension methods rather than in separate `StreamTransformer` classes. This pattern has fewer potential issues around generics since it's fully based on function calls which are type checked appropriately unlike the `StreamTransformer` interface which suffers from the incorrect covariant subtype relationships. It also may avoid some unnecessary allocations as improve stack traces. For the transforms that were changed, aim for better consistency around generic type arguments. `T` is now more consistently the source stream type, while `S` is the output stream type. --- .../lib/src/aggregate_sample.dart | 53 ++++--- pkgs/stream_transform/lib/src/async_map.dart | 49 ++++--- .../lib/src/combine_latest.dart | 136 ++++++++---------- .../stream_transform/lib/src/concatenate.dart | 99 ++++++------- .../lib/src/from_handlers.dart | 76 +++++----- pkgs/stream_transform/lib/src/merge.dart | 96 ++++++------- pkgs/stream_transform/lib/src/rate_limit.dart | 92 ++++++------ pkgs/stream_transform/lib/src/switch.dart | 15 +- pkgs/stream_transform/lib/src/take_until.dart | 21 +-- pkgs/stream_transform/lib/src/tap.dart | 8 +- pkgs/stream_transform/lib/src/where.dart | 11 +- .../test/from_handlers_test.dart | 34 ++--- 12 files changed, 301 insertions(+), 389 deletions(-) diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index 3a967d4a3..cd0a7d018 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -4,32 +4,27 @@ import 'dart:async'; -/// A StreamTransformer which aggregates values and emits when it sees a value -/// on [_trigger]. -/// -/// If there are no pending values when [_trigger] emits the first value on the -/// source Stream will immediately flow through. Otherwise, the pending values -/// and released when [_trigger] emits. -/// -/// Errors from the source stream or the trigger are immediately forwarded to -/// the output. -class AggregateSample extends StreamTransformerBase { - final Stream _trigger; - final T Function(S, T?) _aggregate; +extension AggregateSample on Stream { + /// Aggregates values and emits when it sees a value on [trigger]. + /// + /// If there are no pending values when [trigger] emits, the next value on the + /// source Stream will be passed to [aggregate] and emitted on the result + /// stream immediately. Otherwise, the pending values are released when + /// [trigger] emits. + /// + /// Errors from the source stream or the trigger are immediately forwarded to + /// the output. + Stream aggregateSample( + Stream trigger, S Function(T, S?) aggregate) { + var controller = isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); - AggregateSample(this._trigger, this._aggregate); - - @override - Stream bind(Stream values) { - var controller = values.isBroadcast - ? StreamController.broadcast(sync: true) - : StreamController(sync: true); - - T? currentResults; + S? currentResults; var waitingForTrigger = true; var isTriggerDone = false; var isValueDone = false; - StreamSubscription? valueSub; + StreamSubscription? valueSub; StreamSubscription? triggerSub; void emit() { @@ -38,8 +33,8 @@ class AggregateSample extends StreamTransformerBase { waitingForTrigger = true; } - void onValue(S value) { - currentResults = _aggregate(value, currentResults); + void onValue(T value) { + currentResults = aggregate(value, currentResults); if (!waitingForTrigger) emit(); @@ -78,16 +73,16 @@ class AggregateSample extends StreamTransformerBase { controller.onListen = () { assert(valueSub == null); - valueSub = values.listen(onValue, - onError: controller.addError, onDone: onValuesDone); + valueSub = + listen(onValue, onError: controller.addError, onDone: onValuesDone); final priorTriggerSub = triggerSub; if (priorTriggerSub != null) { if (priorTriggerSub.isPaused) priorTriggerSub.resume(); } else { - triggerSub = _trigger.listen(onTrigger, + triggerSub = trigger.listen(onTrigger, onError: controller.addError, onDone: onTriggerDone); } - if (!values.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { valueSub?.pause(); @@ -101,7 +96,7 @@ class AggregateSample extends StreamTransformerBase { controller.onCancel = () { var cancels = >[if (!isValueDone) valueSub!.cancel()]; valueSub = null; - if (_trigger.isBroadcast || !values.isBroadcast) { + if (trigger.isBroadcast || !isBroadcast) { if (!isTriggerDone) cancels.add(triggerSub!.cancel()); triggerSub = null; } else { diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index 7b406c7f9..f6022525f 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -41,8 +41,7 @@ extension AsyncMap on Stream { var workFinished = StreamController() // Let the first event through. ..add(null); - return buffer(workFinished.stream) - .transform(_asyncMapThen(convert, workFinished.add)); + return buffer(workFinished.stream)._asyncMapThen(convert, workFinished.add); } /// Like [asyncMap] but events are discarded while work is happening in @@ -68,8 +67,8 @@ extension AsyncMap on Stream { var workFinished = StreamController() // Let the first event through. ..add(null); - return transform(AggregateSample(workFinished.stream, _dropPrevious)) - .transform(_asyncMapThen(convert, workFinished.add)); + return aggregateSample(workFinished.stream, _dropPrevious) + ._asyncMapThen(convert, workFinished.add); } /// Like [asyncMap] but the [convert] callback may be called for an element @@ -92,7 +91,7 @@ extension AsyncMap on Stream { Stream concurrentAsyncMap(FutureOr Function(T) convert) { var valuesWaiting = 0; var sourceDone = false; - return transform(fromHandlers(handleData: (element, sink) { + return transformByHandlers(onData: (element, sink) { valuesWaiting++; () async { try { @@ -103,29 +102,29 @@ extension AsyncMap on Stream { valuesWaiting--; if (valuesWaiting <= 0 && sourceDone) sink.close(); }(); - }, handleDone: (sink) { + }, onDone: (sink) { sourceDone = true; if (valuesWaiting <= 0) sink.close(); - })); + }); + } + + /// Like [Stream.asyncMap] but the [convert] is only called once per event, + /// rather than once per listener, and [then] is called after completing the + /// work. + Stream _asyncMapThen( + Future Function(T) convert, void Function(void) then) { + Future? pendingEvent; + return transformByHandlers(onData: (event, sink) { + pendingEvent = + convert(event).then(sink.add).catchError(sink.addError).then(then); + }, onDone: (sink) { + if (pendingEvent != null) { + pendingEvent!.then((_) => sink.close()); + } else { + sink.close(); + } + }); } } T _dropPrevious(T event, _) => event; - -/// Like [Stream.asyncMap] but the [convert] is only called once per event, -/// rather than once per listener, and [then] is called after completing the -/// work. -StreamTransformer _asyncMapThen( - Future Function(S) convert, void Function(void) then) { - Future? pendingEvent; - return fromHandlers(handleData: (event, sink) { - pendingEvent = - convert(event).then(sink.add).catchError(sink.addError).then(then); - }, handleDone: (sink) { - if (pendingEvent != null) { - pendingEvent!.then((_) => sink.close()); - } else { - sink.close(); - } - }); -} diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 6e268e370..dcaf672b5 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -34,86 +34,36 @@ extension CombineLatest on Stream { /// well, regardless of [other]'s type. If a single subscription stream is /// combined with a broadcast stream it may never be canceled. Stream combineLatest( - Stream other, FutureOr Function(T, T2) combine) => - transform(_CombineLatest(other, combine)); + Stream other, FutureOr Function(T, T2) combine) { + final controller = isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); - /// Combine the latest value emitted from the source stream with the latest - /// values emitted from [others]. - /// - /// [combineLatestAll] subscribes to the source stream and [others] and when - /// any one of the streams emits, the result stream will emit a [List] of - /// the latest values emitted from all streams. - /// - /// No event will be emitted until all source streams emit at least once. If a - /// source stream emits multiple values before another starts emitting, all - /// but the last value will be discarded. Once all source streams have emitted - /// at least once, the result stream will emit any time any source stream - /// emits. - /// - /// The result stream will not close until all source streams have closed. When - /// a source stream closes, the result stream will continue to emit the last - /// value from the closed stream when the other source streams emit until the - /// result stream has closed. If a source stream closes without emitting any - /// value, the result stream will close as well. - /// - /// For example: - /// - /// final combined = first - /// .combineLatestAll([second, third]) - /// .map((data) => data.join()); - /// - /// first: a----b------------------c--------d---| - /// second: --1---------2-----------------| - /// third: -------&----------%---| - /// combined: -------b1&--b2&---b2%---c2%------d2%-| - /// - /// Errors thrown by any source stream will be forwarded to the result stream. - /// - /// If the source stream is a broadcast stream, the result stream will be as - /// well, regardless of the types of [others]. If a single subscription stream - /// is combined with a broadcast source stream, it may never be canceled. - Stream> combineLatestAll(Iterable> others) => - transform(_CombineLatestAll(others)); -} - -class _CombineLatest extends StreamTransformerBase { - final Stream _other; - final FutureOr Function(S, T) _combine; - - _CombineLatest(this._other, this._combine); - - @override - Stream bind(Stream source) { - final controller = source.isBroadcast - ? StreamController.broadcast(sync: true) - : StreamController(sync: true); + other = + (isBroadcast && !other.isBroadcast) ? other.asBroadcastStream() : other; - final other = (source.isBroadcast && !_other.isBroadcast) - ? _other.asBroadcastStream() - : _other; - - StreamSubscription? sourceSubscription; - StreamSubscription? otherSubscription; + StreamSubscription? sourceSubscription; + StreamSubscription? otherSubscription; var sourceDone = false; var otherDone = false; - late S latestSource; - late T latestOther; + late T latestSource; + late T2 latestOther; var sourceStarted = false; var otherStarted = false; void emitCombined() { if (!sourceStarted || !otherStarted) return; - FutureOr result; + FutureOr result; try { - result = _combine(latestSource, latestOther); + result = combine(latestSource, latestOther); } catch (e, s) { controller.addError(e, s); return; } - if (result is Future) { + if (result is Future) { sourceSubscription!.pause(); otherSubscription!.pause(); result @@ -129,7 +79,7 @@ class _CombineLatest extends StreamTransformerBase { controller.onListen = () { assert(sourceSubscription == null); - sourceSubscription = source.listen( + sourceSubscription = listen( (s) { sourceStarted = true; latestSource = s; @@ -163,7 +113,7 @@ class _CombineLatest extends StreamTransformerBase { controller.close(); } }); - if (!source.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { sourceSubscription!.pause(); @@ -188,25 +138,51 @@ class _CombineLatest extends StreamTransformerBase { }; return controller.stream; } -} - -class _CombineLatestAll extends StreamTransformerBase> { - final Iterable> _others; - _CombineLatestAll(this._others); - - @override - Stream> bind(Stream first) { - final controller = first.isBroadcast + /// Combine the latest value emitted from the source stream with the latest + /// values emitted from [others]. + /// + /// [combineLatestAll] subscribes to the source stream and [others] and when + /// any one of the streams emits, the result stream will emit a [List] of + /// the latest values emitted from all streams. + /// + /// No event will be emitted until all source streams emit at least once. If a + /// source stream emits multiple values before another starts emitting, all + /// but the last value will be discarded. Once all source streams have emitted + /// at least once, the result stream will emit any time any source stream + /// emits. + /// + /// The result stream will not close until all source streams have closed. When + /// a source stream closes, the result stream will continue to emit the last + /// value from the closed stream when the other source streams emit until the + /// result stream has closed. If a source stream closes without emitting any + /// value, the result stream will close as well. + /// + /// For example: + /// + /// final combined = first + /// .combineLatestAll([second, third]) + /// .map((data) => data.join()); + /// + /// first: a----b------------------c--------d---| + /// second: --1---------2-----------------| + /// third: -------&----------%---| + /// combined: -------b1&--b2&---b2%---c2%------d2%-| + /// + /// Errors thrown by any source stream will be forwarded to the result stream. + /// + /// If the source stream is a broadcast stream, the result stream will be as + /// well, regardless of the types of [others]. If a single subscription stream + /// is combined with a broadcast source stream, it may never be canceled. + Stream> combineLatestAll(Iterable> others) { + final controller = isBroadcast ? StreamController>.broadcast(sync: true) : StreamController>(sync: true); final allStreams = [ - first, - for (final other in _others) - !first.isBroadcast || other.isBroadcast - ? other - : other.asBroadcastStream(), + this, + for (final other in others) + !isBroadcast || other.isBroadcast ? other : other.asBroadcastStream(), ]; controller.onListen = () { @@ -239,7 +215,7 @@ class _CombineLatestAll extends StreamTransformerBase> { streamId++; } - if (!first.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { for (final subscription in subscriptions) { diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index 402d8a0c0..37a4d96f7 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -17,60 +17,20 @@ extension Concatenate on Stream { /// to and never canceled since there may be broadcast listeners added later. /// /// If a broadcast stream follows any other stream it will miss any events or - /// errors which occur before the first stream is done. If a broadcast stream - /// follows a single-subscription stream, pausing the stream while it is - /// listening to the second stream will cause events to be dropped rather than - /// buffered. - Stream followedBy(Stream next) => transform(_FollowedBy(next)); - - /// Returns a stream which emits [initial] before any values from the original - /// stream. - /// - /// If the original stream is a broadcast stream the result will be as well. - Stream startWith(T initial) => - startWithStream(Future.value(initial).asStream()); - - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. - /// - /// If the original stream is a broadcast stream the result will be as well. - /// If the original stream is a broadcast stream it will miss any events which - /// occur before the initial values are all emitted. - Stream startWithMany(Iterable initial) => - startWithStream(Stream.fromIterable(initial)); - - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. - /// - /// If the original stream is a broadcast stream the result will be as well. If - /// the original stream is a broadcast stream it will miss any events which - /// occur before [initial] closes. - Stream startWithStream(Stream initial) { - if (isBroadcast && !initial.isBroadcast) { - initial = initial.asBroadcastStream(); - } - return initial.followedBy(this); - } -} - -class _FollowedBy extends StreamTransformerBase { - final Stream _next; - - _FollowedBy(this._next); - - @override - Stream bind(Stream first) { - var controller = first.isBroadcast + /// errors which occur before the original stream is done. If a broadcast + /// stream follows a single-subscription stream, pausing the stream while it + /// is listening to the second stream will cause events to be dropped rather + /// than buffered. + Stream followedBy(Stream next) { + var controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); - var next = first.isBroadcast && !_next.isBroadcast - ? _next.asBroadcastStream() - : _next; + next = isBroadcast && !next.isBroadcast ? next.asBroadcastStream() : next; StreamSubscription? subscription; - var currentStream = first; - var firstDone = false; + var currentStream = this; + var thisDone = false; var secondDone = false; late void Function() currentDoneHandler; @@ -85,27 +45,27 @@ class _FollowedBy extends StreamTransformerBase { controller.close(); } - void onFirstDone() { - firstDone = true; + void onThisDone() { + thisDone = true; currentStream = next; currentDoneHandler = onSecondDone; listen(); } - currentDoneHandler = onFirstDone; + currentDoneHandler = onThisDone; controller.onListen = () { assert(subscription == null); listen(); - if (!first.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { - if (!firstDone || !next.isBroadcast) return subscription!.pause(); + if (!thisDone || !next.isBroadcast) return subscription!.pause(); subscription!.cancel(); subscription = null; } ..onResume = () { - if (!firstDone || !next.isBroadcast) return subscription!.resume(); + if (!thisDone || !next.isBroadcast) return subscription!.resume(); listen(); }; } @@ -118,4 +78,33 @@ class _FollowedBy extends StreamTransformerBase { }; return controller.stream; } + + /// Returns a stream which emits [initial] before any values from the original + /// stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + Stream startWith(T initial) => + startWithStream(Future.value(initial).asStream()); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. + /// If the original stream is a broadcast stream it will miss any events which + /// occur before the initial values are all emitted. + Stream startWithMany(Iterable initial) => + startWithStream(Stream.fromIterable(initial)); + + /// Returns a stream which emits all values in [initial] before any values + /// from the original stream. + /// + /// If the original stream is a broadcast stream the result will be as well. If + /// the original stream is a broadcast stream it will miss any events which + /// occur before [initial] closes. + Stream startWithStream(Stream initial) { + if (isBroadcast && !initial.isBroadcast) { + initial = initial.asBroadcastStream(); + } + return initial.followedBy(this); + } } diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index c7c93325f..f5c4b847e 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -4,46 +4,21 @@ import 'dart:async'; -/// Like [new StreamTransformer.fromHandlers] but the handlers are called once -/// per event rather than once per listener for broadcast streams. -StreamTransformer fromHandlers( - {void Function(S, EventSink)? handleData, - void Function(Object, StackTrace, EventSink)? handleError, - void Function(EventSink)? handleDone}) => - _StreamTransformer( - handleData: handleData, - handleError: handleError, - handleDone: handleDone); - -class _StreamTransformer extends StreamTransformerBase { - final void Function(S, EventSink) _handleData; - final void Function(EventSink) _handleDone; - final void Function(Object, StackTrace, EventSink) _handleError; - - _StreamTransformer( - {void Function(S, EventSink)? handleData, - void Function(Object, StackTrace, EventSink)? handleError, - void Function(EventSink)? handleDone}) - : _handleData = handleData ?? _defaultHandleData, - _handleError = handleError ?? _defaultHandleError, - _handleDone = handleDone ?? _defaultHandleDone; - - static void _defaultHandleData(S value, EventSink sink) { - sink.add(value as T); - } - - static void _defaultHandleError( - Object error, StackTrace stackTrace, EventSink sink) { - sink.addError(error, stackTrace); - } - - static void _defaultHandleDone(EventSink sink) { - sink.close(); - } - - @override - Stream bind(Stream values) { - var controller = values.isBroadcast +extension TransformByHandlers on Stream { + /// Transform a stream by callbacks. + /// + /// This is similar to `transform(StreamTransformer.fromHandler(...))` except + /// that the handlers are called once per event rather than called for the + /// same event for each listener on a broadcast stream. + Stream transformByHandlers( + {void Function(S, EventSink)? onData, + void Function(Object, StackTrace, EventSink)? onError, + void Function(EventSink)? onDone}) { + final handleData = onData ?? _defaultHandleData; + final handleError = onError ?? _defaultHandleError; + final handleDone = onDone ?? _defaultHandleDone; + + var controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); @@ -51,14 +26,14 @@ class _StreamTransformer extends StreamTransformerBase { controller.onListen = () { assert(subscription == null); var valuesDone = false; - subscription = values.listen((value) => _handleData(value, controller), + subscription = listen((value) => handleData(value, controller), onError: (Object error, StackTrace stackTrace) { - _handleError(error, stackTrace, controller); + handleError(error, stackTrace, controller); }, onDone: () { valuesDone = true; - _handleDone(controller); + handleDone(controller); }); - if (!values.isBroadcast) { + if (!isBroadcast) { controller ..onPause = subscription!.pause ..onResume = subscription!.resume; @@ -72,4 +47,17 @@ class _StreamTransformer extends StreamTransformerBase { }; return controller.stream; } + + static void _defaultHandleData(S value, EventSink sink) { + sink.add(value as T); + } + + static void _defaultHandleError( + Object error, StackTrace stackTrace, EventSink sink) { + sink.addError(error, stackTrace); + } + + static void _defaultHandleDone(EventSink sink) { + sink.close(); + } } diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 61b5e2170..55fe40951 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -30,7 +30,7 @@ extension Merge on Stream { /// If a broadcast stream is merged into a single-subscription stream any /// events emitted by [other] before the result stream has a subscriber will /// be discarded. - Stream merge(Stream other) => transform(_Merge([other])); + Stream merge(Stream other) => mergeAll([other]); /// Returns a stream which emits values and errors from the source stream and /// any stream in [others] in any order as they arrive. @@ -55,55 +55,15 @@ extension Merge on Stream { /// If a broadcast stream is merged into a single-subscription stream any /// events emitted by that stream before the result stream has a subscriber /// will be discarded. - Stream mergeAll(Iterable> others) => transform(_Merge(others)); - - /// Like [asyncExpand] but the [convert] callback may be called for an element - /// before the [Stream] emitted by the previous element has closed. - /// - /// Events on the result stream will be emitted in the order they are emitted - /// by the sub streams, which may not match the order of the original stream. - /// - /// Errors from [convert], the source stream, or any of the sub streams are - /// forwarded to the result stream. - /// - /// The result stream will not close until the source stream closes and all - /// sub streams have closed. - /// - /// If the source stream is a broadcast stream, the result will be as well, - /// regardless of the types of streams created by [convert]. In this case, - /// some care should be taken: - /// - If [convert] returns a single subscription stream it may be listened to - /// and never canceled. - /// - For any period of time where there are no listeners on the result - /// stream, any sub streams from previously emitted events will be ignored, - /// regardless of whether they emit further events after a listener is added - /// back. - /// - /// See also: - /// - /// * [switchMap], which cancels subscriptions to the previous sub - /// stream instead of concurrently emitting events from all sub streams. - Stream concurrentAsyncExpand(Stream Function(T) convert) => - map(convert).transform(_MergeExpanded()); -} - -class _Merge extends StreamTransformerBase { - final Iterable> _others; - - _Merge(this._others); - - @override - Stream bind(Stream first) { - final controller = first.isBroadcast + Stream mergeAll(Iterable> others) { + final controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); final allStreams = [ - first, - for (final other in _others) - !first.isBroadcast || other.isBroadcast - ? other - : other.asBroadcastStream(), + this, + for (final other in others) + !isBroadcast || other.isBroadcast ? other : other.asBroadcastStream(), ]; controller.onListen = () { @@ -117,7 +77,7 @@ class _Merge extends StreamTransformerBase { }); subscriptions.add(subscription); } - if (!first.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { for (final subscription in subscriptions) { @@ -141,19 +101,47 @@ class _Merge extends StreamTransformerBase { }; return controller.stream; } + + /// Like [asyncExpand] but the [convert] callback may be called for an element + /// before the [Stream] emitted by the previous element has closed. + /// + /// Events on the result stream will be emitted in the order they are emitted + /// by the sub streams, which may not match the order of the original stream. + /// + /// Errors from [convert], the source stream, or any of the sub streams are + /// forwarded to the result stream. + /// + /// The result stream will not close until the source stream closes and all + /// sub streams have closed. + /// + /// If the source stream is a broadcast stream, the result will be as well, + /// regardless of the types of streams created by [convert]. In this case, + /// some care should be taken: + /// - If [convert] returns a single subscription stream it may be listened to + /// and never canceled. + /// - For any period of time where there are no listeners on the result + /// stream, any sub streams from previously emitted events will be ignored, + /// regardless of whether they emit further events after a listener is added + /// back. + /// + /// See also: + /// + /// * [switchMap], which cancels subscriptions to the previous sub + /// stream instead of concurrently emitting events from all sub streams. + Stream concurrentAsyncExpand(Stream Function(T) convert) => + map(convert).mergeExpanded(); } -class _MergeExpanded extends StreamTransformerBase, T> { - @override - Stream bind(Stream> streams) { - final controller = streams.isBroadcast +extension _MergeExpanded on Stream> { + Stream mergeExpanded() { + final controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); controller.onListen = () { final subscriptions = >[]; - final outerSubscription = streams.listen((inner) { - if (streams.isBroadcast && !inner.isBroadcast) { + final outerSubscription = listen((inner) { + if (isBroadcast && !inner.isBroadcast) { inner = inner.asBroadcastStream(); } final subscription = @@ -169,7 +157,7 @@ class _MergeExpanded extends StreamTransformerBase, T> { if (subscriptions.isEmpty) controller.close(); }); subscriptions.add(outerSubscription); - if (!streams.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { for (final subscription in subscriptions) { diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 23dfbc556..d558f6171 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -56,8 +56,8 @@ extension RateLimit on Stream { /// To collect values emitted during the debounce period see [debounceBuffer]. Stream debounce(Duration duration, {bool leading = false, bool trailing = true}) => - transform(_debounceAggregate(duration, _dropPrevious, - leading: leading, trailing: trailing)); + _debounceAggregate(duration, _dropPrevious, + leading: leading, trailing: trailing); /// Returns a Stream which collects values until the source stream does not /// emit for [duration] then emits the collected values. @@ -76,8 +76,7 @@ extension RateLimit on Stream { /// To keep only the most recent event during the debounce perios see /// [debounce]. Stream> debounceBuffer(Duration duration) => - transform(_debounceAggregate(duration, _collectToList, - leading: false, trailing: true)); + _debounceAggregate(duration, _collect, leading: false, trailing: true); /// Returns a stream which only emits once per [duration], at the beginning of /// the period. @@ -87,14 +86,14 @@ extension RateLimit on Stream { Stream throttle(Duration duration) { Timer? timer; - return transform(fromHandlers(handleData: (data, sink) { + return transformByHandlers(onData: (data, sink) { if (timer == null) { sink.add(data); timer = Timer(duration, () { timer = null; }); } - })); + }); } /// Returns a Stream which only emits once per [duration], at the end of the @@ -129,7 +128,7 @@ extension RateLimit on Stream { var shouldClose = false; T recentData; - return transform(fromHandlers(handleData: (T data, EventSink sink) { + return transformByHandlers(onData: (data, sink) { recentData = data; timer ??= Timer(duration, () { sink.add(recentData); @@ -138,13 +137,13 @@ extension RateLimit on Stream { sink.close(); } }); - }, handleDone: (EventSink sink) { + }, onDone: (sink) { if (timer != null) { shouldClose = true; } else { sink.close(); } - })); + }); } /// Returns a Stream which collects values and emits when it sees a value on @@ -158,51 +157,44 @@ extension RateLimit on Stream { /// Errors from the source stream or the trigger are immediately forwarded to /// the output. Stream> buffer(Stream trigger) => - transform(AggregateSample>(trigger, _collect)); -} + aggregateSample>(trigger, _collect); -List _collectToList(T element, List? soFar) { - soFar ??= []; - soFar.add(element); - return soFar; -} - -T _dropPrevious(T element, _) => element; - -/// Creates a StreamTransformer which aggregates values until the source stream -/// does not emit for [duration], then emits the aggregated values. -StreamTransformer _debounceAggregate( - Duration duration, R Function(T element, R? soFar) collect, - {required bool leading, required bool trailing}) { - Timer? timer; - R? soFar; - var shouldClose = false; - var emittedLatestAsLeading = false; - return fromHandlers(handleData: (T value, EventSink sink) { - timer?.cancel(); - soFar = collect(value, soFar); - if (timer == null && leading) { - emittedLatestAsLeading = true; - sink.add(soFar as R); - } else { - emittedLatestAsLeading = false; - } - timer = Timer(duration, () { - if (trailing && !emittedLatestAsLeading) sink.add(soFar as R); - if (shouldClose) { + /// Aggregates values until the source stream does not emit for [duration], + /// then emits the aggregated values. + Stream _debounceAggregate( + Duration duration, S Function(T element, S? soFar) collect, + {required bool leading, required bool trailing}) { + Timer? timer; + S? soFar; + var shouldClose = false; + var emittedLatestAsLeading = false; + return transformByHandlers(onData: (value, sink) { + timer?.cancel(); + soFar = collect(value, soFar); + if (timer == null && leading) { + emittedLatestAsLeading = true; + sink.add(soFar as S); + } else { + emittedLatestAsLeading = false; + } + timer = Timer(duration, () { + if (trailing && !emittedLatestAsLeading) sink.add(soFar as S); + if (shouldClose) { + sink.close(); + } + soFar = null; + timer = null; + }); + }, onDone: (EventSink sink) { + if (soFar != null && trailing) { + shouldClose = true; + } else { + timer?.cancel(); sink.close(); } - soFar = null; - timer = null; }); - }, handleDone: (EventSink sink) { - if (soFar != null && trailing) { - shouldClose = true; - } else { - timer?.cancel(); - sink.close(); - } - }); + } } +T _dropPrevious(T element, _) => element; List _collect(T event, List? soFar) => (soFar ?? [])..add(event); diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index df7f1b8f9..17fbb811d 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -52,15 +52,8 @@ extension SwitchLatest on Stream> { /// /// If the source stream is a broadcast stream, the result stream will be as /// well, regardless of the types of streams emitted. - Stream switchLatest() => transform(_SwitchTransformer()); -} - -class _SwitchTransformer extends StreamTransformerBase, T> { - const _SwitchTransformer(); - - @override - Stream bind(Stream> outer) { - var controller = outer.isBroadcast + Stream switchLatest() { + var controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); @@ -68,7 +61,7 @@ class _SwitchTransformer extends StreamTransformerBase, T> { StreamSubscription? innerSubscription; var outerStreamDone = false; - final outerSubscription = outer.listen( + final outerSubscription = listen( (innerStream) { innerSubscription?.cancel(); innerSubscription = innerStream.listen(controller.add, @@ -82,7 +75,7 @@ class _SwitchTransformer extends StreamTransformerBase, T> { outerStreamDone = true; if (innerSubscription == null) controller.close(); }); - if (!outer.isBroadcast) { + if (!isBroadcast) { controller ..onPause = () { innerSubscription?.pause(); diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 542050034..32366edba 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -13,23 +13,14 @@ extension TakeUntil on Stream { /// which are emitted before the trigger, but have further asynchronous delays /// in transformations following the takeUtil, will still go through. /// Cancelling a subscription immediately stops values. - Stream takeUntil(Future trigger) => transform(_TakeUntil(trigger)); -} - -class _TakeUntil extends StreamTransformerBase { - final Future _trigger; - - _TakeUntil(this._trigger); - - @override - Stream bind(Stream values) { - var controller = values.isBroadcast + Stream takeUntil(Future trigger) { + var controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); StreamSubscription? subscription; var isDone = false; - _trigger.then((_) { + trigger.then((_) { if (isDone) return; isDone = true; subscription?.cancel(); @@ -38,13 +29,13 @@ class _TakeUntil extends StreamTransformerBase { controller.onListen = () { if (isDone) return; - subscription = values.listen(controller.add, onError: controller.addError, - onDone: () { + subscription = + listen(controller.add, onError: controller.addError, onDone: () { if (isDone) return; isDone = true; controller.close(); }); - if (!values.isBroadcast) { + if (!isBroadcast) { controller ..onPause = subscription!.pause ..onResume = subscription!.resume; diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index b7e03214a..05ab32f0d 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -25,20 +25,20 @@ extension Tap on Stream { Stream tap(void Function(T)? onValue, {void Function(Object, StackTrace)? onError, void Function()? onDone}) => - transform(fromHandlers(handleData: (value, sink) { + transformByHandlers(onData: (value, sink) { try { onValue?.call(value); } catch (_) {/*Ignore*/} sink.add(value); - }, handleError: (error, stackTrace, sink) { + }, onError: (error, stackTrace, sink) { try { onError?.call(error, stackTrace); } catch (_) {/*Ignore*/} sink.addError(error, stackTrace); - }, handleDone: (sink) { + }, onDone: (sink) { try { onDone?.call(); } catch (_) {/*Ignore*/} sink.close(); - })); + }); } diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 97ec57b30..ed3532e25 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -17,10 +17,9 @@ extension Where on Stream { /// [S] should be a subtype of the stream's generic type, otherwise nothing of /// type [S] could possibly be emitted, however there is no static or runtime /// checking that this is the case. - Stream whereType() => - transform(StreamTransformer.fromHandlers(handleData: (event, sink) { + Stream whereType() => transformByHandlers(onData: (event, sink) { if (event is S) sink.add(event); - })); + }); /// Like [where] but allows the [test] to return a [Future]. /// @@ -40,7 +39,7 @@ extension Where on Stream { Stream asyncWhere(FutureOr Function(T) test) { var valuesWaiting = 0; var sourceDone = false; - return transform(fromHandlers(handleData: (element, sink) { + return transformByHandlers(onData: (element, sink) { valuesWaiting++; () async { try { @@ -51,9 +50,9 @@ extension Where on Stream { valuesWaiting--; if (valuesWaiting <= 0 && sourceDone) sink.close(); }(); - }, handleDone: (sink) { + }, onDone: (sink) { sourceDone = true; if (valuesWaiting <= 0) sink.close(); - })); + }); } } diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 206acc8b1..7ae3368a7 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -18,7 +18,7 @@ void main() { late StreamSubscription subscription; void setUpForController(StreamController controller, - StreamTransformer transformer) { + Stream Function(Stream) transform) { valuesCanceled = false; values = controller ..onCancel = () { @@ -27,7 +27,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = values.stream.transform(transformer); + transformed = transform(values.stream); subscription = transformed.listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; @@ -37,7 +37,7 @@ void main() { group('default from_handlers', () { group('Single subscription stream', () { setUp(() { - setUpForController(StreamController(), fromHandlers()); + setUpForController(StreamController(), (s) => s.transformByHandlers()); }); test('has correct stream type', () { @@ -74,7 +74,8 @@ void main() { late StreamSubscription subscription2; setUp(() { - setUpForController(StreamController.broadcast(), fromHandlers()); + setUpForController( + StreamController.broadcast(), (s) => s.transformByHandlers()); emittedValues2 = []; errors2 = []; isDone2 = false; @@ -120,10 +121,11 @@ void main() { group('custom handlers', () { group('single subscription', () { setUp(() async { - setUpForController(StreamController(), - fromHandlers(handleData: (value, sink) { - sink.add(value + 1); - })); + setUpForController( + StreamController(), + (s) => s.transformByHandlers(onData: (value, sink) { + sink.add(value + 1); + })); }); test('uses transform from handleData', () async { values..add(1)..add(2); @@ -143,14 +145,14 @@ void main() { errorCallCount = 0; setUpForController( StreamController.broadcast(), - fromHandlers(handleData: (value, sink) { - dataCallCount++; - }, handleError: (error, stackTrace, sink) { - errorCallCount++; - sink.addError(error, stackTrace); - }, handleDone: (sink) { - doneCallCount++; - })); + (s) => s.transformByHandlers(onData: (value, sink) { + dataCallCount++; + }, onError: (error, stackTrace, sink) { + errorCallCount++; + sink.addError(error, stackTrace); + }, onDone: (sink) { + doneCallCount++; + })); transformed.listen((_) {}, onError: (_, __) {}); }); From 3b92db701694c052faf1b94de91ddaf1ecf5d9f2 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Mon, 7 Dec 2020 13:36:07 -0800 Subject: [PATCH 0731/1215] migrate from `dartanalyzer` to `dart analyze` the experiment is no longer required and warnings are fatal by default --- pkgs/stack_trace/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 441b12e67..6d6ea7c91 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -8,7 +8,7 @@ jobs: - stage: analyze_and_format name: "Analyzer" os: linux - script: dartanalyzer --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + script: dart analyze --fatal-infos . - stage: analyze_and_format name: "Format" os: linux From 6a5bbfcc76a1f72b5d88a67c4abaabfc83d0f9a3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Dec 2020 13:05:52 -0800 Subject: [PATCH 0732/1215] Allow null-safe json_annotation (dart-lang/pubspec_parse#61) prepare to release v0.1.6 --- pkgs/pubspec_parse/CHANGELOG.md | 3 ++- pkgs/pubspec_parse/pubspec.yaml | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 7e74a5575..f7a1a3ae3 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ -## 0.1.6-dev +## 0.1.6 - Update SDK requirement to `>=2.7.0 <3.0.0`. +- Allow `package:json_annotation` `v4.x`. ## 0.1.5 diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 09d2fb9b5..6e2a7e9cd 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,8 +2,8 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.6-dev -homepage: https://github.com/dart-lang/pubspec_parse +version: 0.1.6 +repository: https://github.com/dart-lang/pubspec_parse environment: sdk: '>=2.7.0 <3.0.0' @@ -11,7 +11,7 @@ environment: dependencies: checked_yaml: ^1.0.0 # Verified that no new features since 1.0.0 are used - be careful! - json_annotation: '>=1.0.0 <4.0.0' + json_annotation: '>=1.0.0 <5.0.0' pub_semver: ^1.3.2 yaml: ^2.1.12 From 2fcd77b6d0f84bc030e08de25ca537027cd64b1b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Dec 2020 13:53:18 -0800 Subject: [PATCH 0733/1215] Allow null-safe pkg:yaml (dart-lang/pubspec_parse#62) Prepare to release v0.1.7 --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index f7a1a3ae3..26b1d3139 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.7 + +- Allow `package:yaml` `v3.x`. + ## 0.1.6 - Update SDK requirement to `>=2.7.0 <3.0.0`. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 6e2a7e9cd..5cda97668 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.6 +version: 0.1.7 repository: https://github.com/dart-lang/pubspec_parse environment: @@ -13,7 +13,7 @@ dependencies: # Verified that no new features since 1.0.0 are used - be careful! json_annotation: '>=1.0.0 <5.0.0' pub_semver: ^1.3.2 - yaml: ^2.1.12 + yaml: '>=2.1.12 <4.0.0' dev_dependencies: build_runner: ^1.0.0 From 3dc7c7d792fb1a0491f17c2d93628bec0809f861 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 8 Dec 2020 17:57:35 -0800 Subject: [PATCH 0734/1215] Allow the null-safe version of json_annotation (dart-lang/timing#14) prepare to publish v0.1.1+3 --- pkgs/timing/.travis.yml | 2 +- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/pubspec.yaml | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/timing/.travis.yml b/pkgs/timing/.travis.yml index 581db8936..df4148983 100644 --- a/pkgs/timing/.travis.yml +++ b/pkgs/timing/.travis.yml @@ -5,7 +5,7 @@ dart: - dev dart_task: -- dartanalyzer: --fatal-infos --fatal-warnings . +- dartanalyzer: --fatal-infos . - test matrix: diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 8cb1627c1..c8092209a 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.1+3 + +- Allow `package:json_annotation` `'>=1.0.0 <5.0.0'`. + ## 0.1.1+2 - Support the latest version of `package:json_annotation`. diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 0b9b4e496..cbbacc836 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,15 +1,15 @@ name: timing -version: 0.1.1+3-dev +version: 0.1.1+3 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. -homepage: https://github.com/dart-lang/timing +repository: https://github.com/dart-lang/timing environment: sdk: ">=2.2.0 <3.0.0" dependencies: - json_annotation: '>=1.0.0 <4.0.0' + json_annotation: '>=1.0.0 <5.0.0' dev_dependencies: build_runner: ^1.0.0 From 8b6685f338b75b34e265a4d4aea73521b5dd1bf9 Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 9 Dec 2020 14:00:35 -0800 Subject: [PATCH 0735/1215] migrate from `dartfmt` to `dart format` --- pkgs/stack_trace/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml index 6d6ea7c91..e87b82737 100644 --- a/pkgs/stack_trace/.travis.yml +++ b/pkgs/stack_trace/.travis.yml @@ -12,7 +12,7 @@ jobs: - stage: analyze_and_format name: "Format" os: linux - script: dartfmt -n --set-exit-if-changed . + script: dart format -o none --set-exit-if-changed . - stage: test name: "Vm Tests" os: linux From db7d36a49f3132e0c60d9c25bad70aac2ac2b625 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 11 Dec 2020 18:18:44 -0800 Subject: [PATCH 0736/1215] Migrate to null safety. --- pkgs/watcher/lib/src/async_queue.dart | 3 +- .../lib/src/custom_watcher_factory.dart | 25 +++++++------- pkgs/watcher/lib/src/directory_watcher.dart | 2 +- .../lib/src/directory_watcher/linux.dart | 23 ++++++++----- .../lib/src/directory_watcher/mac_os.dart | 19 ++++++----- .../lib/src/directory_watcher/polling.dart | 16 ++++----- .../lib/src/directory_watcher/windows.dart | 32 ++++++++++-------- pkgs/watcher/lib/src/file_watcher.dart | 2 +- pkgs/watcher/lib/src/file_watcher/native.dart | 2 +- .../watcher/lib/src/file_watcher/polling.dart | 8 ++--- pkgs/watcher/lib/src/path_set.dart | 16 +++++---- pkgs/watcher/lib/src/resubscribable.dart | 6 ++-- pkgs/watcher/lib/src/stat.dart | 10 +++--- pkgs/watcher/lib/src/utils.dart | 4 +-- pkgs/watcher/lib/watcher.dart | 2 +- pkgs/watcher/pubspec.yaml | 16 ++++----- .../test/custom_watcher_factory_test.dart | 12 +++---- pkgs/watcher/test/path_set_test.dart | 2 +- pkgs/watcher/test/utils.dart | 33 ++++++++++--------- 19 files changed, 127 insertions(+), 106 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 37f13d61d..93899e7c6 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -33,7 +33,8 @@ class AsyncQueue { /// Used to avoid top-leveling asynchronous errors. final Function _errorHandler; - AsyncQueue(this._processor, {Function onError}) : _errorHandler = onError; + AsyncQueue(this._processor, {required Function onError}) + : _errorHandler = onError; /// Enqueues [item] to be processed and starts asynchronously processing it /// if a process isn't already running. diff --git a/pkgs/watcher/lib/src/custom_watcher_factory.dart b/pkgs/watcher/lib/src/custom_watcher_factory.dart index 3dc1beafc..8f4132b99 100644 --- a/pkgs/watcher/lib/src/custom_watcher_factory.dart +++ b/pkgs/watcher/lib/src/custom_watcher_factory.dart @@ -7,9 +7,9 @@ import '../watcher.dart'; /// A factory to produce custom watchers for specific file paths. class _CustomWatcherFactory { final String id; - final DirectoryWatcher Function(String path, {Duration pollingDelay}) + final DirectoryWatcher? Function(String path, {Duration? pollingDelay}) createDirectoryWatcher; - final FileWatcher Function(String path, {Duration pollingDelay}) + final FileWatcher? Function(String path, {Duration? pollingDelay}) createFileWatcher; _CustomWatcherFactory( @@ -22,7 +22,7 @@ class _CustomWatcherFactory { /// registered more than once. /// [createDirectoryWatcher] and [createFileWatcher] should return watchers for /// the file paths they are able to handle. If the custom watcher is not able to -/// handle the path it should reuturn null. +/// handle the path it should return null. /// The paths handled by each custom watch may not overlap, at most one custom /// matcher may return a non-null watcher for a given path. /// @@ -31,9 +31,10 @@ class _CustomWatcherFactory { /// will be used instead of the default. void registerCustomWatcher( String id, - DirectoryWatcher Function(String path, {Duration pollingDelay}) + DirectoryWatcher Function(String path, {Duration? pollingDelay})? createDirectoryWatcher, - FileWatcher Function(String path, {Duration pollingDelay}) createFileWatcher, + FileWatcher Function(String path, {Duration? pollingDelay})? + createFileWatcher, ) { if (_customWatcherFactories.containsKey(id)) { throw ArgumentError('A custom watcher with id `$id` ' @@ -49,10 +50,10 @@ void registerCustomWatcher( /// /// Returns `null` if no custom watcher was applicable and throws a [StateError] /// if more than one was. -DirectoryWatcher createCustomDirectoryWatcher(String path, - {Duration pollingDelay}) { - DirectoryWatcher customWatcher; - String customFactoryId; +DirectoryWatcher? createCustomDirectoryWatcher(String path, + {Duration? pollingDelay}) { + DirectoryWatcher? customWatcher; + String? customFactoryId; for (var watcherFactory in _customWatcherFactories.values) { if (customWatcher != null) { throw StateError('Two `CustomWatcherFactory`s applicable: ' @@ -69,9 +70,9 @@ DirectoryWatcher createCustomDirectoryWatcher(String path, /// /// Returns `null` if no custom watcher was applicable and throws a [StateError] /// if more than one was. -FileWatcher createCustomFileWatcher(String path, {Duration pollingDelay}) { - FileWatcher customWatcher; - String customFactoryId; +FileWatcher? createCustomFileWatcher(String path, {Duration? pollingDelay}) { + FileWatcher? customWatcher; + String? customFactoryId; for (var watcherFactory in _customWatcherFactories.values) { if (customWatcher != null) { throw StateError('Two `CustomWatcherFactory`s applicable: ' diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 3fe500455..043ebab75 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -28,7 +28,7 @@ abstract class DirectoryWatcher implements Watcher { /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. - factory DirectoryWatcher(String directory, {Duration pollingDelay}) { + factory DirectoryWatcher(String directory, {Duration? pollingDelay}) { if (FileSystemEntity.isWatchSupported) { var customWatcher = createCustomDirectoryWatcher(directory, pollingDelay: pollingDelay); diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 7348cb45f..06d3508ef 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -91,7 +91,7 @@ class _LinuxDirectoryWatcher } else { _files.add(entity.path); } - }, onError: (error, StackTrace stackTrace) { + }, onError: (Object error, StackTrace stackTrace) { _eventsController.addError(error, stackTrace); close(); }, onDone: () { @@ -155,13 +155,16 @@ class _LinuxDirectoryWatcher files.remove(event.path); dirs.remove(event.path); - changed.add(event.destination); + var destination = event.destination; + if (destination == null) continue; + + changed.add(destination); if (event.isDirectory) { - files.remove(event.destination); - dirs.add(event.destination); + files.remove(destination); + dirs.add(destination); } else { - files.add(event.destination); - dirs.remove(event.destination); + files.add(destination); + dirs.remove(destination); } } else if (event is FileSystemDeleteEvent) { files.remove(event.path); @@ -221,7 +224,7 @@ class _LinuxDirectoryWatcher _files.add(entity.path); _emit(ChangeType.ADD, entity.path); } - }, onError: (error, StackTrace stackTrace) { + }, onError: (Object error, StackTrace stackTrace) { // Ignore an exception caused by the dir not existing. It's fine if it // was added and then quickly removed. if (error is FileSystemException) return; @@ -258,8 +261,10 @@ class _LinuxDirectoryWatcher /// Like [Stream.listen], but automatically adds the subscription to /// [_subscriptions] so that it can be canceled when [close] is called. void _listen(Stream stream, void Function(T) onData, - {Function onError, void Function() onDone, bool cancelOnError}) { - StreamSubscription subscription; + {Function? onError, + void Function()? onDone, + bool cancelOnError = false}) { + late StreamSubscription subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); onDone?.call(); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 4408ff1eb..e44b7f54e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -64,11 +64,11 @@ class _MacOSDirectoryWatcher /// /// This is separate from [_listSubscriptions] because this stream /// occasionally needs to be resubscribed in order to work around issue 14849. - StreamSubscription> _watchSubscription; + StreamSubscription>? _watchSubscription; /// The subscription to the [Directory.list] call for the initial listing of /// the directory to determine its initial state. - StreamSubscription _initialListSubscription; + StreamSubscription? _initialListSubscription; /// The subscriptions to [Directory.list] calls for listing the contents of a /// subdirectory that was moved into the watched directory. @@ -76,7 +76,7 @@ class _MacOSDirectoryWatcher /// The timer for tracking how long we wait for an initial batch of bogus /// events (see issue 14373). - Timer _bogusEventTimer; + late Timer _bogusEventTimer; _MacOSDirectoryWatcher(String path) : path = path, @@ -144,14 +144,14 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; - StreamSubscription subscription; + late StreamSubscription subscription; subscription = Directory(path).list(recursive: true).listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (e, StackTrace stackTrace) { + }, onError: (Object e, StackTrace stackTrace) { _emitError(e, stackTrace); }, onDone: () { _listSubscriptions.remove(subscription); @@ -192,7 +192,10 @@ class _MacOSDirectoryWatcher var directories = unionAll(batch.map((event) { if (!event.isDirectory) return {}; if (event is FileSystemMoveEvent) { - return {event.path, event.destination}; + var destination = event.destination; + if (destination != null) { + return {event.path, destination}; + } } return {event.path}; })); @@ -224,7 +227,7 @@ class _MacOSDirectoryWatcher /// If [batch] does contain contradictory events, this returns `null` to /// indicate that the state of the path on the filesystem should be checked to /// determine what occurred. - FileSystemEvent _canonicalEvent(Set batch) { + FileSystemEvent? _canonicalEvent(Set batch) { // An empty batch indicates that we've learned earlier that the batch is // contradictory (e.g. because of a move). if (batch.isEmpty) return null; @@ -394,7 +397,7 @@ class _MacOSDirectoryWatcher } /// Emit an error, then close the watcher. - void _emitError(error, StackTrace stackTrace) { + void _emitError(Object error, StackTrace stackTrace) { _eventsController.addError(error, stackTrace); close(); } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 902e8b861..968c9c62f 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -24,7 +24,7 @@ class PollingDirectoryWatcher extends ResubscribableWatcher /// will pause between successive polls of the directory contents. Making this /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. - PollingDirectoryWatcher(String directory, {Duration pollingDelay}) + PollingDirectoryWatcher(String directory, {Duration? pollingDelay}) : super(directory, () { return _PollingDirectoryWatcher( directory, pollingDelay ?? Duration(seconds: 1)); @@ -56,12 +56,12 @@ class _PollingDirectoryWatcher /// The previous modification times of the files in the directory. /// /// Used to tell which files have been modified. - final _lastModifieds = {}; + final _lastModifieds = {}; /// The subscription used while [directory] is being listed. /// /// Will be `null` if a list is not currently happening. - StreamSubscription _listSubscription; + StreamSubscription? _listSubscription; /// The queue of files waiting to be processed to see if they have been /// modified. @@ -70,7 +70,7 @@ class _PollingDirectoryWatcher /// queue exists to let each of those proceed at their own rate. The lister /// will enqueue files as quickly as it can. Meanwhile, files are dequeued /// and processed sequentially. - AsyncQueue _filesToProcess; + late AsyncQueue _filesToProcess; /// The set of files that have been seen in the current directory listing. /// @@ -79,8 +79,8 @@ class _PollingDirectoryWatcher final _polledFiles = {}; _PollingDirectoryWatcher(this.path, this._pollingDelay) { - _filesToProcess = - AsyncQueue(_processFile, onError: (e, StackTrace stackTrace) { + _filesToProcess = AsyncQueue(_processFile, + onError: (Object e, StackTrace stackTrace) { if (!_events.isClosed) _events.addError(e, stackTrace); }); @@ -120,7 +120,7 @@ class _PollingDirectoryWatcher if (entity is! File) return; _filesToProcess.add(entity.path); - }, onError: (error, StackTrace stackTrace) { + }, onError: (Object error, StackTrace stackTrace) { if (!isDirectoryNotFoundException(error)) { // It's some unknown error. Pipe it over to the event stream so the // user can see it. @@ -136,7 +136,7 @@ class _PollingDirectoryWatcher /// Processes [file] to determine if it has been modified since the last /// time it was scanned. - Future _processFile(String file) async { + Future _processFile(String? file) async { // `null` is the sentinel which means the directory listing is complete. if (file == null) { await _completePoll(); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 98e963945..764037377 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -28,7 +28,7 @@ class WindowsDirectoryWatcher extends ResubscribableWatcher class _EventBatcher { static const Duration _BATCH_DELAY = Duration(milliseconds: 100); final List events = []; - Timer timer; + Timer? timer; void addEvent(FileSystemEvent event, void Function() callback) { events.add(event); @@ -37,7 +37,7 @@ class _EventBatcher { } void cancelTimer() { - timer.cancel(); + timer?.cancel(); } } @@ -71,16 +71,16 @@ class _WindowsDirectoryWatcher final PathSet _files; /// The subscription to the stream returned by [Directory.watch]. - StreamSubscription _watchSubscription; + StreamSubscription? _watchSubscription; /// The subscription to the stream returned by [Directory.watch] of the /// parent directory to [directory]. This is needed to detect changes to /// [directory], as they are not included on Windows. - StreamSubscription _parentWatchSubscription; + StreamSubscription? _parentWatchSubscription; /// The subscription to the [Directory.list] call for the initial listing of /// the directory to determine its initial state. - StreamSubscription _initialListSubscription; + StreamSubscription? _initialListSubscription; /// The subscriptions to the [Directory.list] calls for listing the contents /// of subdirectories that were moved into the watched directory. @@ -148,7 +148,7 @@ class _WindowsDirectoryWatcher // Ignore errors, simply close the stream. The user listens on // [directory], and while it can fail to listen on the parent, we may // still be able to listen on the path requested. - _parentWatchSubscription.cancel(); + _parentWatchSubscription?.cancel(); _parentWatchSubscription = null; }); } @@ -184,7 +184,7 @@ class _WindowsDirectoryWatcher if (_files.containsDir(path)) continue; var stream = Directory(path).list(recursive: true); - StreamSubscription subscription; + late StreamSubscription subscription; subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; @@ -193,7 +193,7 @@ class _WindowsDirectoryWatcher _files.add(entity.path); }, onDone: () { _listSubscriptions.remove(subscription); - }, onError: (e, StackTrace stackTrace) { + }, onError: (Object e, StackTrace stackTrace) { _listSubscriptions.remove(subscription); _emitError(e, stackTrace); }, cancelOnError: true); @@ -229,7 +229,10 @@ class _WindowsDirectoryWatcher var directories = unionAll(batch.map((event) { if (!event.isDirectory) return {}; if (event is FileSystemMoveEvent) { - return {event.path, event.destination}; + var destination = event.destination; + if (destination != null) { + return {event.path, destination}; + } } return {event.path}; })); @@ -244,7 +247,10 @@ class _WindowsDirectoryWatcher for (var event in batch) { if (event is FileSystemMoveEvent) { - addEvent(event.destination, event); + var destination = event.destination; + if (destination != null) { + addEvent(destination, event); + } } addEvent(event.path, event); } @@ -262,7 +268,7 @@ class _WindowsDirectoryWatcher /// If [batch] does contain contradictory events, this returns `null` to /// indicate that the state of the path on the filesystem should be checked to /// determine what occurred. - FileSystemEvent _canonicalEvent(Set batch) { + FileSystemEvent? _canonicalEvent(Set batch) { // An empty batch indicates that we've learned earlier that the batch is // contradictory (e.g. because of a move). if (batch.isEmpty) return null; @@ -386,7 +392,7 @@ class _WindowsDirectoryWatcher }, (error, stackTrace) { if (error is FileSystemException && error.message.startsWith('Directory watcher closed unexpectedly')) { - _watchSubscription.cancel(); + _watchSubscription?.cancel(); _eventsController.addError(error, stackTrace); _startWatch(); } else { @@ -421,7 +427,7 @@ class _WindowsDirectoryWatcher } /// Emit an error, then close the watcher. - void _emitError(error, StackTrace stackTrace) { + void _emitError(Object error, StackTrace stackTrace) { _eventsController.addError(error, stackTrace); close(); } diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index c41e5e678..9b8ecc4a5 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -29,7 +29,7 @@ abstract class FileWatcher implements Watcher { /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. - factory FileWatcher(String file, {Duration pollingDelay}) { + factory FileWatcher(String file, {Duration? pollingDelay}) { var customWatcher = createCustomFileWatcher(file, pollingDelay: pollingDelay); if (customWatcher != null) return customWatcher; diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 0b42cb9b3..f7d92d49e 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -33,7 +33,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { Future get ready => _readyCompleter.future; final _readyCompleter = Completer(); - StreamSubscription _subscription; + StreamSubscription? _subscription; _NativeFileWatcher(this.path) { _listen(); diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 11c0c6d9f..b208a4b0b 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -14,7 +14,7 @@ import '../watch_event.dart'; /// Periodically polls a file for changes. class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { - PollingFileWatcher(String path, {Duration pollingDelay}) + PollingFileWatcher(String path, {Duration? pollingDelay}) : super(path, () { return _PollingFileWatcher( path, pollingDelay ?? Duration(seconds: 1)); @@ -37,13 +37,13 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { final _readyCompleter = Completer(); /// The timer that controls polling. - Timer _timer; + late Timer _timer; /// The previous modification time of the file. /// /// Used to tell when the file was modified. This is `null` before the file's /// mtime has first been checked. - DateTime _lastModified; + DateTime? _lastModified; _PollingFileWatcher(this.path, Duration pollingDelay) { _timer = Timer.periodic(pollingDelay, (_) => _poll()); @@ -64,7 +64,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { return; } - DateTime modified; + DateTime? modified; try { modified = await modificationTime(path); } on FileSystemException catch (error, stackTrace) { diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 41a0a390b..090090eeb 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -119,8 +119,9 @@ class PathSet { var entry = _entries; for (var part in p.split(path)) { - entry = entry.contents[part]; - if (entry == null) return false; + var child = entry.contents[part]; + if (child == null) return false; + entry = child; } return entry.isExplicit; @@ -132,8 +133,9 @@ class PathSet { var entry = _entries; for (var part in p.split(path)) { - entry = entry.contents[part]; - if (entry == null) return false; + var child = entry.contents[part]; + if (child == null) return false; + entry = child; } return entry.contents.isNotEmpty; @@ -144,9 +146,9 @@ class PathSet { var result = []; void recurse(_Entry dir, String path) { - for (var name in dir.contents.keys) { - var entry = dir.contents[name]; - var entryPath = p.join(path, name); + for (var mapEntry in dir.contents.entries) { + var entry = mapEntry.value; + var entryPath = p.join(path, mapEntry.key); if (entry.isExplicit) result.add(entryPath); recurse(entry, entryPath); } diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 071909607..1c4bb25d8 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -29,7 +29,7 @@ abstract class ResubscribableWatcher implements Watcher { @override Stream get events => _eventsController.stream; - StreamController _eventsController; + late StreamController _eventsController; @override bool get isReady => _readyCompleter.isCompleted; @@ -41,8 +41,8 @@ abstract class ResubscribableWatcher implements Watcher { /// Creates a new [ResubscribableWatcher] wrapping the watchers /// emitted by [_factory]. ResubscribableWatcher(this.path, this._factory) { - ManuallyClosedWatcher watcher; - StreamSubscription subscription; + late ManuallyClosedWatcher watcher; + late StreamSubscription subscription; _eventsController = StreamController.broadcast( onListen: () async { diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 08cf935c7..06e3febf4 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -8,7 +8,7 @@ import 'dart:io'; /// the file at that path. typedef MockTimeCallback = DateTime Function(String path); -MockTimeCallback _mockTimeCallback; +MockTimeCallback? _mockTimeCallback; /// Overrides the default behavior for accessing a file's modification time /// with [callback]. @@ -21,9 +21,11 @@ void mockGetModificationTime(MockTimeCallback callback) { } /// Gets the modification time for the file at [path]. -Future modificationTime(String path) async { - if (_mockTimeCallback != null) { - return _mockTimeCallback(path); +/// Completes with `null` if the file does not exist. +Future modificationTime(String path) async { + var mockTimeCallback = _mockTimeCallback; + if (mockTimeCallback != null) { + return mockTimeCallback(path); } final stat = await FileStat.stat(path); diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 24b8184c2..66c59d3e5 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -8,12 +8,12 @@ import 'dart:collection'; /// Returns `true` if [error] is a [FileSystemException] for a missing /// directory. -bool isDirectoryNotFoundException(error) { +bool isDirectoryNotFoundException(Object error) { if (error is! FileSystemException) return false; // See dartbug.com/12461 and tests/standalone/io/directory_error_test.dart. var notFoundCode = Platform.operatingSystem == 'windows' ? 3 : 2; - return error.osError.errorCode == notFoundCode; + return error.osError?.errorCode == notFoundCode; } /// Returns the union of all elements in each set in [sets]. diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 01336ab5a..22e0d6e04 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -57,7 +57,7 @@ abstract class Watcher { /// shorter will give more immediate feedback at the expense of doing more IO /// and higher CPU usage. Defaults to one second. Ignored for non-polling /// watchers. - factory Watcher(String path, {Duration pollingDelay}) { + factory Watcher(String path, {Duration? pollingDelay}) { if (File(path).existsSync()) { return FileWatcher(path, pollingDelay: pollingDelay); } else { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index c4cafada7..8567e9bc6 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.9.8-dev +version: 0.10.0-nullsafety.0 description: >- A file system watcher. It monitors changes to contents of directories and @@ -7,14 +7,14 @@ description: >- repository: https://github.com/dart-lang/watcher environment: - sdk: '>=2.8.4 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: - async: ^2.0.0 - path: ^1.0.0 - pedantic: ^1.1.0 + async: ^2.5.0-nullsafety.3 + path: ^1.8.0-nullsafety.3 + pedantic: ^1.10.0-nullsafety.3 dev_dependencies: - benchmark_harness: ^1.0.4 - test: ^1.0.0 - test_descriptor: ^1.0.0 + benchmark_harness: ^2.0.0-nullsafety.0 + test: ^1.16.0-nullsafety.13 + test_descriptor: ^2.0.0-nullsafety diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 8210c065b..89f8e3cd0 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -4,7 +4,7 @@ import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; void main() { - _MemFs memFs; + late _MemFs memFs; final defaultFactoryId = 'MemFs'; setUpAll(() { @@ -16,7 +16,7 @@ void main() { watcherFactory.createFileWatcher); }); - test('notifes for files', () async { + test('notifies for files', () async { var watcher = FileWatcher('file.txt'); var completer = Completer(); @@ -29,7 +29,7 @@ void main() { expect(event.path, 'file.txt'); }); - test('notifes for directories', () async { + test('notifies for directories', () async { var watcher = DirectoryWatcher('dir'); var completer = Completer(); @@ -45,7 +45,7 @@ void main() { test('registering twice throws', () async { expect( () => registerCustomWatcher(defaultFactoryId, - (_, {pollingDelay}) => null, (_, {pollingDelay}) => null), + (_, {pollingDelay}) => throw 0, (_, {pollingDelay}) => throw 0), throwsA(isA())); }); @@ -117,9 +117,9 @@ class _MemFsWatcherFactory { _MemFsWatcherFactory(this._memFs); DirectoryWatcher createDirectoryWatcher(String path, - {Duration pollingDelay}) => + {Duration? pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); - FileWatcher createFileWatcher(String path, {Duration pollingDelay}) => + FileWatcher createFileWatcher(String path, {Duration? pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); } diff --git a/pkgs/watcher/test/path_set_test.dart b/pkgs/watcher/test/path_set_test.dart index 25cf96943..61ab2cd64 100644 --- a/pkgs/watcher/test/path_set_test.dart +++ b/pkgs/watcher/test/path_set_test.dart @@ -15,7 +15,7 @@ Matcher containsDir(String path) => predicate( 'set contains directory "$path"'); void main() { - PathSet paths; + late PathSet paths; setUp(() => paths = PathSet('root')); group('adding a path', () { diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 6e7686c27..9b4fd2874 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -30,12 +30,12 @@ set watcherFactory(WatcherFactory factory) { /// increment the mod time for that file instantly. final _mockFileModificationTimes = {}; -WatcherFactory _watcherFactory; +late WatcherFactory _watcherFactory; /// Creates a new [Watcher] that watches a temporary file or directory. /// /// If [path] is provided, watches a subdirectory in the sandbox with that name. -Watcher createWatcher({String path}) { +Watcher createWatcher({String? path}) { if (path == null) { path = d.sandbox; } else { @@ -46,13 +46,13 @@ Watcher createWatcher({String path}) { } /// The stream of events from the watcher started with [startWatcher]. -StreamQueue _watcherEvents; +late StreamQueue _watcherEvents; /// Creates a new [Watcher] that watches a temporary file or directory and /// starts monitoring it for events. /// /// If [path] is provided, watches a path in the sandbox with that name. -Future startWatcher({String path}) async { +Future startWatcher({String? path}) async { mockGetModificationTime((path) { final normalized = p.normalize(p.relative(path, from: d.sandbox)); @@ -86,7 +86,7 @@ void startClosingEventStream() async { /// A list of [StreamMatcher]s that have been collected using /// [_collectStreamMatcher]. -List _collectedStreamMatchers; +List? _collectedStreamMatchers; /// Collects all stream matchers that are registered within [block] into a /// single stream matcher. @@ -94,10 +94,10 @@ List _collectedStreamMatchers; /// The returned matcher will match each of the collected matchers in order. StreamMatcher _collectStreamMatcher(void Function() block) { var oldStreamMatchers = _collectedStreamMatchers; - _collectedStreamMatchers = []; + var collectedStreamMatchers = _collectedStreamMatchers = []; try { block(); - return emitsInOrder(_collectedStreamMatchers); + return emitsInOrder(collectedStreamMatchers); } finally { _collectedStreamMatchers = oldStreamMatchers; } @@ -108,9 +108,10 @@ StreamMatcher _collectStreamMatcher(void Function() block) { /// /// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value. Future _expectOrCollect(streamMatcher) { - if (_collectedStreamMatchers != null) { - _collectedStreamMatchers.add(emits(streamMatcher)); - return null; + var collectedStreamMatchers = _collectedStreamMatchers; + if (collectedStreamMatchers != null) { + collectedStreamMatchers.add(emits(streamMatcher)); + return Future.sync(() {}); } else { return expectLater(_watcherEvents, emits(streamMatcher)); } @@ -202,7 +203,7 @@ Future allowRemoveEvent(String path) => /// /// If [contents] is omitted, creates an empty file. If [updateModified] is /// `false`, the mock file modification time is not changed. -void writeFile(String path, {String contents, bool updateModified}) { +void writeFile(String path, {String? contents, bool? updateModified}) { contents ??= ''; updateModified ??= true; @@ -219,8 +220,8 @@ void writeFile(String path, {String contents, bool updateModified}) { if (updateModified) { path = p.normalize(path); - _mockFileModificationTimes.putIfAbsent(path, () => 0); - _mockFileModificationTimes[path]++; + _mockFileModificationTimes.update(path, (value) => value + 1, + ifAbsent: () => 1); } } @@ -236,8 +237,8 @@ void renameFile(String from, String to) { // Make sure we always use the same separator on Windows. to = p.normalize(to); - _mockFileModificationTimes.putIfAbsent(to, () => 0); - _mockFileModificationTimes[to]++; + _mockFileModificationTimes.update(to, (value) => value + 1, + ifAbsent: () => 1); } /// Schedules creating a directory in the sandbox at [path]. @@ -261,7 +262,7 @@ void deleteDir(String path) { /// Returns a set of all values returns by [callback]. /// /// [limit] defaults to 3. -Set withPermutations(S Function(int, int, int) callback, {int limit}) { +Set withPermutations(S Function(int, int, int) callback, {int? limit}) { limit ??= 3; var results = {}; for (var i = 0; i < limit; i++) { From c30964f273a67f80c5a1dea992ea436ee0be3f48 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 14 Dec 2020 10:08:49 -0800 Subject: [PATCH 0737/1215] Add dependency override for analyzer. --- pkgs/watcher/pubspec.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 8567e9bc6..0309be578 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -18,3 +18,6 @@ dev_dependencies: benchmark_harness: ^2.0.0-nullsafety.0 test: ^1.16.0-nullsafety.13 test_descriptor: ^2.0.0-nullsafety + +dependency_overrides: + analyzer: ^0.41.1 From 42d3623342f063bb40caa1ed069673a0dde33303 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Mon, 14 Dec 2020 11:56:09 -0800 Subject: [PATCH 0738/1215] Stop testing on SDK 2.8.4 --- pkgs/watcher/.travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml index 2c6dc5a72..ca68b1759 100644 --- a/pkgs/watcher/.travis.yml +++ b/pkgs/watcher/.travis.yml @@ -2,7 +2,6 @@ language: dart dart: - dev -- 2.8.4 os: - linux @@ -16,9 +15,6 @@ matrix: include: - dart: dev dart_task: dartfmt - - dart: 2.8.4 - dart_task: - dartanalyzer: --fatal-warnings . - dart: dev dart_task: dartanalyzer: --fatal-warnings --fatal-infos . From cb570df39f7fe35219671a3709d71d2283184f3d Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 15 Dec 2020 15:15:18 -0800 Subject: [PATCH 0739/1215] Fixes for review comments. --- pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 14 ++++++++------ .../watcher/lib/src/directory_watcher/polling.dart | 2 +- .../watcher/lib/src/directory_watcher/windows.dart | 11 ++++++----- pkgs/watcher/lib/src/file_watcher/polling.dart | 2 +- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index e44b7f54e..7dc6e7cfa 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -144,18 +144,20 @@ class _MacOSDirectoryWatcher if (_files.containsDir(path)) continue; - late StreamSubscription subscription; - subscription = Directory(path).list(recursive: true).listen((entity) { + var stream = Directory(path).list(recursive: true); + var subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onError: (Object e, StackTrace stackTrace) { - _emitError(e, stackTrace); - }, onDone: () { - _listSubscriptions.remove(subscription); }, cancelOnError: true); + subscription.onDone(() { + _listSubscriptions.remove(subscription); + }); + subscription.onError((Object e, StackTrace stackTrace) { + _emitError(e, stackTrace); + }); _listSubscriptions.add(subscription); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 968c9c62f..6baa49dc7 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -70,7 +70,7 @@ class _PollingDirectoryWatcher /// queue exists to let each of those proceed at their own rate. The lister /// will enqueue files as quickly as it can. Meanwhile, files are dequeued /// and processed sequentially. - late AsyncQueue _filesToProcess; + late final AsyncQueue _filesToProcess; /// The set of files that have been seen in the current directory listing. /// diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 764037377..a8200eed9 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -184,19 +184,20 @@ class _WindowsDirectoryWatcher if (_files.containsDir(path)) continue; var stream = Directory(path).list(recursive: true); - late StreamSubscription subscription; - subscription = stream.listen((entity) { + var subscription = stream.listen((entity) { if (entity is Directory) return; if (_files.contains(path)) return; _emitEvent(ChangeType.ADD, entity.path); _files.add(entity.path); - }, onDone: () { + }, cancelOnError: true); + subscription.onDone(() { _listSubscriptions.remove(subscription); - }, onError: (Object e, StackTrace stackTrace) { + }); + subscription.onError((Object e, StackTrace stackTrace) { _listSubscriptions.remove(subscription); _emitError(e, stackTrace); - }, cancelOnError: true); + }); _listSubscriptions.add(subscription); } else if (event is FileSystemModifyEvent) { if (!event.isDirectory) { diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index b208a4b0b..9b9ac5be3 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -37,7 +37,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { final _readyCompleter = Completer(); /// The timer that controls polling. - late Timer _timer; + late final Timer _timer; /// The previous modification time of the file. /// From 23206c06faaba67d768bacaff756063a32fb24db Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Tue, 15 Dec 2020 15:17:21 -0800 Subject: [PATCH 0740/1215] Move '_filesToProcess' initializer. --- pkgs/watcher/lib/src/directory_watcher/polling.dart | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 6baa49dc7..95fb683a8 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -70,7 +70,10 @@ class _PollingDirectoryWatcher /// queue exists to let each of those proceed at their own rate. The lister /// will enqueue files as quickly as it can. Meanwhile, files are dequeued /// and processed sequentially. - late final AsyncQueue _filesToProcess; + late final AsyncQueue _filesToProcess = AsyncQueue( + _processFile, onError: (Object e, StackTrace stackTrace) { + if (!_events.isClosed) _events.addError(e, stackTrace); + }); /// The set of files that have been seen in the current directory listing. /// @@ -79,11 +82,6 @@ class _PollingDirectoryWatcher final _polledFiles = {}; _PollingDirectoryWatcher(this.path, this._pollingDelay) { - _filesToProcess = AsyncQueue(_processFile, - onError: (Object e, StackTrace stackTrace) { - if (!_events.isClosed) _events.addError(e, stackTrace); - }); - _poll(); } From f5c13384698895da15cab0b021a4d623a4ef1ad7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 16 Dec 2020 09:07:26 -0800 Subject: [PATCH 0741/1215] Add a better static Function type (dart-lang/watcher#100) Improves inference so it is no longer necessary to add types on the function literal at the usage point. --- pkgs/watcher/lib/src/async_queue.dart | 5 +++-- pkgs/watcher/lib/src/directory_watcher/polling.dart | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index 93899e7c6..eca28ad57 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -31,9 +31,10 @@ class AsyncQueue { /// The handler for errors thrown during processing. /// /// Used to avoid top-leveling asynchronous errors. - final Function _errorHandler; + final void Function(Object, StackTrace) _errorHandler; - AsyncQueue(this._processor, {required Function onError}) + AsyncQueue(this._processor, + {required void Function(Object, StackTrace) onError}) : _errorHandler = onError; /// Enqueues [item] to be processed and starts asynchronously processing it diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 95fb683a8..2a43937b8 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -70,9 +70,9 @@ class _PollingDirectoryWatcher /// queue exists to let each of those proceed at their own rate. The lister /// will enqueue files as quickly as it can. Meanwhile, files are dequeued /// and processed sequentially. - late final AsyncQueue _filesToProcess = AsyncQueue( - _processFile, onError: (Object e, StackTrace stackTrace) { - if (!_events.isClosed) _events.addError(e, stackTrace); + late final AsyncQueue _filesToProcess = + AsyncQueue(_processFile, onError: (error, stackTrace) { + if (!_events.isClosed) _events.addError(error, stackTrace); }); /// The set of files that have been seen in the current directory listing. From f7024e9090a8db77d9ded5ce3c966fce10e553c2 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 17 Dec 2020 14:13:03 -0800 Subject: [PATCH 0742/1215] Remove unused test utils (dart-lang/watcher#101) --- pkgs/watcher/test/utils.dart | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 9b4fd2874..aa23d50a5 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -175,14 +175,6 @@ Future expectModifyEvent(String path) => Future expectRemoveEvent(String path) => _expectOrCollect(isWatchEvent(ChangeType.REMOVE, path)); -/// Consumes an add event for [path] if one is emitted at this point in the -/// schedule, but doesn't throw an error if it isn't. -/// -/// If this is used at the end of a test, [startClosingEventStream] should be -/// called before it. -Future allowAddEvent(String path) => - _expectOrCollect(mayEmit(isWatchEvent(ChangeType.ADD, path))); - /// Consumes a modification event for [path] if one is emitted at this point in /// the schedule, but doesn't throw an error if it isn't. /// @@ -191,14 +183,6 @@ Future allowAddEvent(String path) => Future allowModifyEvent(String path) => _expectOrCollect(mayEmit(isWatchEvent(ChangeType.MODIFY, path))); -/// Consumes a removal event for [path] if one is emitted at this point in the -/// schedule, but doesn't throw an error if it isn't. -/// -/// If this is used at the end of a test, [startClosingEventStream] should be -/// called before it. -Future allowRemoveEvent(String path) => - _expectOrCollect(mayEmit(isWatchEvent(ChangeType.REMOVE, path))); - /// Schedules writing a file in the sandbox at [path] with [contents]. /// /// If [contents] is omitted, creates an empty file. If [updateModified] is From e83d89bbab68bc4637bccbaae4feb9935ad7bd75 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 17 Dec 2020 14:13:44 -0800 Subject: [PATCH 0743/1215] Rewrite a StreamTransformer as an extension (dart-lang/watcher#102) --- .../lib/src/directory_watcher/linux.dart | 3 +-- .../lib/src/directory_watcher/mac_os.dart | 4 +--- pkgs/watcher/lib/src/file_watcher/native.dart | 2 +- pkgs/watcher/lib/src/utils.dart | 21 +++++++++---------- 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 06d3508ef..1bf5efd33 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -81,8 +81,7 @@ class _LinuxDirectoryWatcher }))); // Batch the inotify changes together so that we can dedup events. - var innerStream = _nativeEvents.stream - .transform(BatchedStreamTransformer()); + var innerStream = _nativeEvents.stream.batchEvents(); _listen(innerStream, _onBatch, onError: _eventsController.addError); _listen(Directory(path).list(recursive: true), (FileSystemEntity entity) { diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 7dc6e7cfa..4ad94d44e 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -359,9 +359,7 @@ class _MacOSDirectoryWatcher /// Start or restart the underlying [Directory.watch] stream. void _startWatch() { // Batch the FSEvent changes together so that we can dedup events. - var innerStream = Directory(path) - .watch(recursive: true) - .transform(BatchedStreamTransformer()); + var innerStream = Directory(path).watch(recursive: true).batchEvents(); _watchSubscription = innerStream.listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); } diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index f7d92d49e..48f12e672 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -47,7 +47,7 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { // Batch the events together so that we can dedup them. _subscription = File(path) .watch() - .transform(BatchedStreamTransformer()) + .batchEvents() .listen(_onBatch, onError: _eventsController.addError, onDone: _onDone); } diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index 66c59d3e5..ecf4e105c 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -20,16 +20,15 @@ bool isDirectoryNotFoundException(Object error) { Set unionAll(Iterable> sets) => sets.fold({}, (union, set) => union.union(set)); -/// A stream transformer that batches all events that are sent at the same time. -/// -/// When multiple events are synchronously added to a stream controller, the -/// [StreamController] implementation uses [scheduleMicrotask] to schedule the -/// asynchronous firing of each event. In order to recreate the synchronous -/// batches, this collates all the events that are received in "nearby" -/// microtasks. -class BatchedStreamTransformer extends StreamTransformerBase> { - @override - Stream> bind(Stream input) { +extension BatchEvents on Stream { + /// Batches all events that are sent at the same time. + /// + /// When multiple events are synchronously added to a stream controller, the + /// [StreamController] implementation uses [scheduleMicrotask] to schedule the + /// asynchronous firing of each event. In order to recreate the synchronous + /// batches, this collates all the events that are received in "nearby" + /// microtasks. + Stream> batchEvents() { var batch = Queue(); return StreamTransformer>.fromHandlers( handleData: (event, sink) { @@ -48,6 +47,6 @@ class BatchedStreamTransformer extends StreamTransformerBase> { batch.clear(); } sink.close(); - }).bind(input); + }).bind(this); } } From f2dcd319ec1efca9d01abd5500436e2cb63e4c53 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Tue, 29 Dec 2020 22:31:22 -0800 Subject: [PATCH 0744/1215] Remove unnecessary import --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 237193b86..3feda43fd 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,7 +7,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. From cd14204d7d52083b3217ce29a23e0d73d3eee1e4 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 30 Dec 2020 09:47:39 -0800 Subject: [PATCH 0745/1215] Remove unnecessary imports (dart-lang/watcher#104) --- pkgs/watcher/lib/src/directory_watcher.dart | 1 - pkgs/watcher/lib/src/file_watcher.dart | 1 - pkgs/watcher/lib/src/resubscribable.dart | 1 - 3 files changed, 3 deletions(-) diff --git a/pkgs/watcher/lib/src/directory_watcher.dart b/pkgs/watcher/lib/src/directory_watcher.dart index 043ebab75..158b86b05 100644 --- a/pkgs/watcher/lib/src/directory_watcher.dart +++ b/pkgs/watcher/lib/src/directory_watcher.dart @@ -8,7 +8,6 @@ import '../watcher.dart'; import 'custom_watcher_factory.dart'; import 'directory_watcher/linux.dart'; import 'directory_watcher/mac_os.dart'; -import 'directory_watcher/polling.dart'; import 'directory_watcher/windows.dart'; /// Watches the contents of a directory and emits [WatchEvent]s when something diff --git a/pkgs/watcher/lib/src/file_watcher.dart b/pkgs/watcher/lib/src/file_watcher.dart index 9b8ecc4a5..143aa3172 100644 --- a/pkgs/watcher/lib/src/file_watcher.dart +++ b/pkgs/watcher/lib/src/file_watcher.dart @@ -7,7 +7,6 @@ import 'dart:io'; import '../watcher.dart'; import 'custom_watcher_factory.dart'; import 'file_watcher/native.dart'; -import 'file_watcher/polling.dart'; /// Watches a file and emits [WatchEvent]s when the file has changed. /// diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 1c4bb25d8..91f509079 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -5,7 +5,6 @@ import 'dart:async'; import '../watcher.dart'; -import 'watch_event.dart'; /// A wrapper for [ManuallyClosedWatcher] that encapsulates support for closing /// the watcher when it has no subscribers and re-opening it when it's From 5e3fce1a80bff62be48c3ae4370c19523580a8a9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 6 Jan 2021 08:38:48 -0800 Subject: [PATCH 0746/1215] Update changelog version following migration (dart-lang/watcher#106) Bump to version 1.0.0 and make changelog and pubspec agree. Add changelog entry for the null safety migration. --- pkgs/watcher/CHANGELOG.md | 4 ++-- pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 881aa2f84..832f0e7b9 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,7 +1,7 @@ -# 0.9.8-dev +# 1.0.0-nullsafety.0 +* Migrate to null safety. * Add the ability to create custom Watcher types for specific file paths. -* Require at least Dart 2.8.4. # 0.9.7+15 diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 0309be578..d09361af3 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 0.10.0-nullsafety.0 +version: 1.0.0-nullsafety.0 description: >- A file system watcher. It monitors changes to contents of directories and From 07b47f3c8cc565b22d343baeba3366acdababb84 Mon Sep 17 00:00:00 2001 From: Michal Terepeta Date: Thu, 7 Jan 2021 20:06:14 +0100 Subject: [PATCH 0747/1215] Fix registerCustomWatcher to allow nulls (dart-lang/watcher#107) The idea behind the closures passed to `registerCustomWatcher` is that they should return `null` if the particular implementation does not support the provided path (in which case we should fallback to other implementations). Modified a test to check this. --- .../lib/src/custom_watcher_factory.dart | 4 +-- .../test/custom_watcher_factory_test.dart | 30 ++++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pkgs/watcher/lib/src/custom_watcher_factory.dart b/pkgs/watcher/lib/src/custom_watcher_factory.dart index 8f4132b99..fc4e3fb90 100644 --- a/pkgs/watcher/lib/src/custom_watcher_factory.dart +++ b/pkgs/watcher/lib/src/custom_watcher_factory.dart @@ -31,9 +31,9 @@ class _CustomWatcherFactory { /// will be used instead of the default. void registerCustomWatcher( String id, - DirectoryWatcher Function(String path, {Duration? pollingDelay})? + DirectoryWatcher? Function(String path, {Duration? pollingDelay})? createDirectoryWatcher, - FileWatcher Function(String path, {Duration? pollingDelay})? + FileWatcher? Function(String path, {Duration? pollingDelay})? createFileWatcher, ) { if (_customWatcherFactories.containsKey(id)) { diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 89f8e3cd0..331d24382 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -5,15 +5,21 @@ import 'package:watcher/watcher.dart'; void main() { late _MemFs memFs; - final defaultFactoryId = 'MemFs'; + final memFsFactoryId = 'MemFs'; + final noOpFactoryId = 'NoOp'; setUpAll(() { memFs = _MemFs(); - var watcherFactory = _MemFsWatcherFactory(memFs); + var memFsWatcherFactory = _MemFsWatcherFactory(memFs); + var noOpWatcherFactory = _NoOpWatcherFactory(); registerCustomWatcher( - defaultFactoryId, - watcherFactory.createDirectoryWatcher, - watcherFactory.createFileWatcher); + noOpFactoryId, + noOpWatcherFactory.createDirectoryWatcher, + noOpWatcherFactory.createFileWatcher); + registerCustomWatcher( + memFsFactoryId, + memFsWatcherFactory.createDirectoryWatcher, + memFsWatcherFactory.createFileWatcher); }); test('notifies for files', () async { @@ -44,7 +50,7 @@ void main() { test('registering twice throws', () async { expect( - () => registerCustomWatcher(defaultFactoryId, + () => registerCustomWatcher(memFsFactoryId, (_, {pollingDelay}) => throw 0, (_, {pollingDelay}) => throw 0), throwsA(isA())); }); @@ -116,10 +122,18 @@ class _MemFsWatcherFactory { final _MemFs _memFs; _MemFsWatcherFactory(this._memFs); - DirectoryWatcher createDirectoryWatcher(String path, + DirectoryWatcher? createDirectoryWatcher(String path, {Duration? pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); - FileWatcher createFileWatcher(String path, {Duration? pollingDelay}) => + FileWatcher? createFileWatcher(String path, {Duration? pollingDelay}) => _MemFsWatcher(path, _memFs.watchStream(path)); } + +class _NoOpWatcherFactory { + DirectoryWatcher? createDirectoryWatcher(String path, + {Duration? pollingDelay}) => + null; + + FileWatcher? createFileWatcher(String path, {Duration? pollingDelay}) => null; +} From 8bb79ade621cf97d4d3a6d46ba69ee160f4cf7df Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 11 Jan 2021 16:36:06 -0800 Subject: [PATCH 0748/1215] Add trailing argument to throttle (dart-lang/stream_transform#123) Closes dart-lang/stream_transform#122 The existing rate limit utilities don't cover the case of wanting to update a UI with some changing data with a limited frequency. In this case the goal is to get the "latest" event with minimal lag time, while maintaining at least a given duration in between events. Add a `trailing` argument to `throttle` for an operator which will emit immediately when possible (unlike `audit`), and does not get starved by a long series of frequent events (unlike `debounce`). Expand the doc with the same timeline diagrams as used for other operators. Split the implementation into two methods to avoid extra conditional checks and unused variables for the common case of `trailing: false`. Add tests for the behavior of emitting the trailing event, suppressing intermediate events, and keeping the stream open until the final trailing even is emitted. --- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/lib/src/rate_limit.dart | 82 ++++++++++++++++++- pkgs/stream_transform/test/throttle_test.dart | 62 +++++++++++++- 3 files changed, 139 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 68f885912..2bae49782 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -3,6 +3,7 @@ - Migrate to null safety. - Improve tests of `switchMap` and improve documentation with links and clarification. +- Add `trailing` argument to `throttle`. ## 1.2.0 diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index d558f6171..6a02703fe 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -73,7 +73,7 @@ extension RateLimit on Stream { /// debounce period before closing. If there are no pending debounced events /// when the source stream closes the returned stream will close immediately. /// - /// To keep only the most recent event during the debounce perios see + /// To keep only the most recent event during the debounce period see /// [debounce]. Stream> debounceBuffer(Duration duration) => _debounceAggregate(duration, _collect, leading: false, trailing: true); @@ -81,9 +81,46 @@ extension RateLimit on Stream { /// Returns a stream which only emits once per [duration], at the beginning of /// the period. /// - /// Events emitted by the source stream within [duration] following an emitted - /// event will be discarded. Errors are always forwarded immediately. - Stream throttle(Duration duration) { + /// No events will ever be emitted within [duration] of another event on the + /// result stream. + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors are forwarded immediately. + /// + /// If [trailing] is `false`, source events emitted during the [duration] + /// period following a result event are discarded. The result stream will not + /// emit an event until the source stream emits an event following the + /// throttled period. If the source stream is consistently emitting events + /// with less than [duration] between events, the time between events on the + /// result stream may still be more than [duration]. The result stream will + /// close immediately when the source stream closes. + /// + /// If [trailing] is `true`, the latest source event emitted during the + /// [duration] period following an result event is held and emitted following + /// the period. If the source stream is consistently emitting events with less + /// than [duration] between events, the time between events on the result + /// stream will be [duration]. If the source stream closes the result stream + /// will wait to emit a pending event before closing. + /// + /// For example: + /// + /// source.throtte(Duration(seconds: 6)); + /// + /// source: 1-2-3---4-5-6---7-8-| + /// result: 1-------4-------7---| + /// + /// source.throttle(Duration(seconds: 6), trailing: true); + /// + /// source: 1-2-3---4-5----6--| + /// result: 1-----3-----5-----6| + /// + /// source.throttle(Duration(seconds: 6), trailing: true); + /// + /// source: 1-2-----------3| + /// result: 1-----2-------3| + Stream throttle(Duration duration, {bool trailing = false}) => + trailing ? _throttleTrailing(duration) : _throttle(duration); + + Stream _throttle(Duration duration) { Timer? timer; return transformByHandlers(onData: (data, sink) { @@ -96,6 +133,43 @@ extension RateLimit on Stream { }); } + Stream _throttleTrailing(Duration duration) { + Timer? timer; + T? pending; + var hasPending = false; + var isDone = false; + + return transformByHandlers(onData: (data, sink) { + void onTimer() { + if (hasPending) { + sink.add(pending as T); + if (isDone) { + sink.close(); + } else { + timer = Timer(duration, onTimer); + hasPending = false; + pending = null; + } + } else { + timer = null; + } + } + + if (timer == null) { + sink.add(data); + timer = Timer(duration, onTimer); + } else { + hasPending = true; + pending = data; + } + }, onDone: (sink) { + isDone = true; + if (hasPending) return; // Will be closed by timer. + timer?.cancel(); + timer = null; + }); + } + /// Returns a Stream which only emits once per [duration], at the end of the /// period. /// diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index d84fdf475..27d9b11bf 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -19,7 +19,7 @@ void main() { late Stream transformed; late StreamSubscription subscription; - group('throttle', () { + group('throttle - trailing: false', () { setUp(() async { valuesCanceled = false; values = createController(streamType) @@ -64,7 +64,7 @@ void main() { if (streamType == 'broadcast') { test('multiple listeners all get values', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values.add(1); await Future(() {}); @@ -73,6 +73,64 @@ void main() { }); } }); + + group('throttle - trailing: true', () { + setUp(() async { + valuesCanceled = false; + values = createController(streamType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + isDone = false; + transformed = values.stream + .throttle(const Duration(milliseconds: 5), trailing: true); + subscription = transformed.listen(emittedValues.add, onDone: () { + isDone = true; + }); + }); + + test('emits both first and last in a period', () async { + values..add(1)..add(2); + await values.close(); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + }); + + test('swallows values that are not the latest in a period', () async { + values..add(1)..add(2)..add(3); + await values.close(); + await waitForTimer(5); + expect(emittedValues, [1, 3]); + }); + + test('waits to output the last value even if the stream closes', + () async { + values..add(1)..add(2); + await values.close(); + await Future(() {}); + expect(isDone, false); + expect(emittedValues, [1], + reason: 'Should not be emitted until after duration'); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + expect(isDone, true); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () async { + var otherValues = []; + transformed.listen(otherValues.add); + values..add(1)..add(2); + await Future(() {}); + expect(emittedValues, [1]); + expect(otherValues, [1]); + await waitForTimer(5); + expect(emittedValues, [1, 2]); + expect(otherValues, [1, 2]); + }); + } + }); }); } } From 7cd0d9e43c8e6a7172751e9dc6f1a52b971844b9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 11 Jan 2021 16:53:11 -0800 Subject: [PATCH 0749/1215] Allow null values in asyncMapSample and buffer (dart-lang/stream_transform#124) Closes dart-lang/stream_transform#121 - Add a boolean to track whether we have a value since we can't use `null` as a sentinel value for a potentially nullable generic type. - Replace `!` with `as S` to allow for nullable `S`. --- .../lib/src/aggregate_sample.dart | 9 ++++++--- pkgs/stream_transform/lib/src/rate_limit.dart | 20 ++++++++++++------- .../test/async_map_sample_test.dart | 5 +++++ pkgs/stream_transform/test/debounce_test.dart | 5 +++++ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index cd0a7d018..0eea768ff 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -21,6 +21,7 @@ extension AggregateSample on Stream { : StreamController(sync: true); S? currentResults; + var hasCurrentResults = false; var waitingForTrigger = true; var isTriggerDone = false; var isValueDone = false; @@ -28,13 +29,15 @@ extension AggregateSample on Stream { StreamSubscription? triggerSub; void emit() { - controller.add(currentResults!); + controller.add(currentResults as S); currentResults = null; + hasCurrentResults = false; waitingForTrigger = true; } void onValue(T value) { currentResults = aggregate(value, currentResults); + hasCurrentResults = true; if (!waitingForTrigger) emit(); @@ -46,7 +49,7 @@ extension AggregateSample on Stream { void onValuesDone() { isValueDone = true; - if (currentResults == null) { + if (!hasCurrentResults) { triggerSub?.cancel(); controller.close(); } @@ -55,7 +58,7 @@ extension AggregateSample on Stream { void onTrigger(_) { waitingForTrigger = false; - if (currentResults != null) emit(); + if (hasCurrentResults) emit(); if (isValueDone) { triggerSub!.cancel(); diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 6a02703fe..ebb55a225 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -240,27 +240,33 @@ extension RateLimit on Stream { {required bool leading, required bool trailing}) { Timer? timer; S? soFar; + var hasPending = false; var shouldClose = false; var emittedLatestAsLeading = false; + return transformByHandlers(onData: (value, sink) { + void emit() { + sink.add(soFar as S); + soFar = null; + hasPending = false; + } + timer?.cancel(); soFar = collect(value, soFar); + hasPending = true; if (timer == null && leading) { emittedLatestAsLeading = true; - sink.add(soFar as S); + emit(); } else { emittedLatestAsLeading = false; } timer = Timer(duration, () { - if (trailing && !emittedLatestAsLeading) sink.add(soFar as S); - if (shouldClose) { - sink.close(); - } - soFar = null; + if (trailing && !emittedLatestAsLeading) emit(); + if (shouldClose) sink.close(); timer = null; }); }, onDone: (EventSink sink) { - if (soFar != null && trailing) { + if (hasPending && trailing) { shouldClose = true; } else { timer?.cancel(); diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 06457d899..0d2d8464c 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -200,4 +200,9 @@ void main() { } }); } + + test('allows nulls', () async { + var stream = Stream.value(null); + await stream.asyncMapSample(expectAsync1((_) async {})).drain(); + }); } diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index f24bfb9d9..9031db51a 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -231,4 +231,9 @@ void main() { }); }); } + test('allows nulls', () async { + final values = Stream.fromIterable([null]); + final transformed = values.debounce(const Duration(milliseconds: 1)); + expect(await transformed.toList(), [null]); + }); } From 69f0c13fcf72572030f4e7257a6a7f699e9843b7 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 11 Jan 2021 17:51:11 -0800 Subject: [PATCH 0750/1215] Close sink on trailing throttle without pending (dart-lang/stream_transform#125) --- pkgs/stream_transform/lib/src/rate_limit.dart | 1 + pkgs/stream_transform/test/throttle_test.dart | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index ebb55a225..b29f4f561 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -165,6 +165,7 @@ extension RateLimit on Stream { }, onDone: (sink) { isDone = true; if (hasPending) return; // Will be closed by timer. + sink.close(); timer?.cancel(); timer = null; }); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 27d9b11bf..bbd0cfbad 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -117,6 +117,13 @@ void main() { expect(isDone, true); }); + test('closes immediately if there is no pending value', () async { + values.add(1); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); + if (streamType == 'broadcast') { test('multiple listeners all get values', () async { var otherValues = []; From dce07a6531e619631246c2dba3b22550990f9aef Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 13 Jan 2021 13:21:15 -0800 Subject: [PATCH 0751/1215] Prepare to publish (dart-lang/stream_transform#126) --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 2bae49782..7b68aa597 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.0-nullsafety.0-dev +## 2.0.0-nullsafety.0 - Migrate to null safety. - Improve tests of `switchMap` and improve documentation with links and diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index ba4bd5177..4e5b37977 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. homepage: https://github.com/dart-lang/stream_transform -version: 2.0.0-nullsafety.0-dev +version: 2.0.0-nullsafety.0 environment: sdk: ">=2.12.0-0 <3.0.0" From c1b71a3cdce70cd3384bf7029e6b7e7165fa7058 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Thu, 14 Jan 2021 16:45:06 +0100 Subject: [PATCH 0752/1215] Migrate to GitHub Actions (dart-lang/timing#15) * Migrate to GitHub Actions * Delete .travis.yml * Replace Travis badge * Use legacy commands to support old SDKs --- .../timing/.github/workflows/test-package.yml | 68 +++++++++++++++++++ pkgs/timing/.travis.yml | 23 ------- pkgs/timing/README.md | 4 +- 3 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 pkgs/timing/.github/workflows/test-package.yml delete mode 100644 pkgs/timing/.travis.yml diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml new file mode 100644 index 000000000..b04d6e25a --- /dev/null +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -0,0 +1,68 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + version: [latest] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev, 2.2.0 + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + version: [latest] + include: + - os: ubuntu-latest + sdk: stable + version: 2.2.0 + steps: + - uses: actions/checkout@v2 + - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + with: + release-channel: ${{ matrix.sdk }} + version: ${{ matrix.version }} + - id: install + name: Install dependencies + run: pub get + - name: Run VM tests + run: pub run test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/timing/.travis.yml b/pkgs/timing/.travis.yml deleted file mode 100644 index df4148983..000000000 --- a/pkgs/timing/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -language: dart - -dart: - - 2.2.0 - - dev - -dart_task: -- dartanalyzer: --fatal-infos . -- test - -matrix: - include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - -branches: - only: - - master - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md index 400bc4b86..d34648d4b 100644 --- a/pkgs/timing/README.md +++ b/pkgs/timing/README.md @@ -1,4 +1,4 @@ -# [![Build Status](https://travis-ci.org/dart-lang/timing.svg?branch=master)](https://travis-ci.org/dart-lang/timing) +# [![Build Status](https://github.com/dart-lang/timing/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/timing/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) Timing is a simple package for tracking performance of both async and sync actions @@ -19,4 +19,4 @@ Use the following command to re-generate `lib/src/timing.g.dart` file: ```bash pub run build_runner build -``` \ No newline at end of file +``` From 05d803db4d71d131e0e80ad825dcbd654082aead Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Thu, 14 Jan 2021 17:36:55 +0100 Subject: [PATCH 0753/1215] Migrate to GitHub Actions (dart-lang/watcher#108) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 60 +++++++++++++++++++ pkgs/watcher/.travis.yml | 28 --------- 2 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 pkgs/watcher/.github/workflows/test-package.yml delete mode 100644 pkgs/watcher/.travis.yml diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml new file mode 100644 index 000000000..e5e47ea27 --- /dev/null +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -0,0 +1,60 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, macos-latest, windows-latest + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.1 + with: + channel: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/watcher/.travis.yml b/pkgs/watcher/.travis.yml deleted file mode 100644 index ca68b1759..000000000 --- a/pkgs/watcher/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: dart - -dart: -- dev - -os: -- linux -- windows -- osx - -dart_task: -- test - -matrix: - include: - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-warnings --fatal-infos . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 100498c048aae66e21c2a298771ac31d5cb58190 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 16:35:56 +0100 Subject: [PATCH 0754/1215] Migrate to GitHub Actions (dart-lang/term_glyph#21) * Migrate to GitHub Actions --- .../.github/workflows/test-package.yml | 61 +++++++++++++++++++ pkgs/term_glyph/.travis.yml | 31 ---------- 2 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 pkgs/term_glyph/.github/workflows/test-package.yml delete mode 100644 pkgs/term_glyph/.travis.yml diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml new file mode 100644 index 000000000..21a3c50b6 --- /dev/null +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -0,0 +1,61 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/term_glyph/.travis.yml b/pkgs/term_glyph/.travis.yml deleted file mode 100644 index 0b9689924..000000000 --- a/pkgs/term_glyph/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: dart - -dart: -- dev - -jobs: - include: - - stage: analyze_and_format - name: "Analyze" - os: linux - script: dartanalyzer --fatal-warnings --fatal-infos . - - stage: analyze_and_format - name: "Format" - os: linux - script: dartfmt -n --set-exit-if-changed . - - stage: test - name: "Vm Tests" - os: linux - script: pub run test -p vm - -stages: - - analyze_and_format - - test - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 85a211c9fc11741d70310c39c7142cde5d18db5e Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 16:38:42 +0100 Subject: [PATCH 0755/1215] Migrate to GitHub Actions (dart-lang/stream_channel#70) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 64 +++++++++++++++++++ pkgs/stream_channel/.travis.yml | 17 ----- 2 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 pkgs/stream_channel/.github/workflows/test-package.yml delete mode 100644 pkgs/stream_channel/.travis.yml diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml new file mode 100644 index 000000000..0a2a87433 --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/stream_channel/.travis.yml b/pkgs/stream_channel/.travis.yml deleted file mode 100644 index be2f29d02..000000000 --- a/pkgs/stream_channel/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: dart - -dart: -- dev - -dart_task: -- test: --platform vm,chrome -- dartfmt -- dartanalyzer: --fatal-infos --fatal-warnings . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 347ce027f113cb6d6b4bde62850de4e2cccb1011 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 16:43:13 +0100 Subject: [PATCH 0756/1215] Migrate to GitHub Actions (dart-lang/stack_trace#103) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 61 +++++++++++++++++++ pkgs/stack_trace/.travis.yml | 31 ---------- 2 files changed, 61 insertions(+), 31 deletions(-) create mode 100644 pkgs/stack_trace/.github/workflows/test-package.yml delete mode 100644 pkgs/stack_trace/.travis.yml diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml new file mode 100644 index 000000000..21a3c50b6 --- /dev/null +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -0,0 +1,61 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/stack_trace/.travis.yml b/pkgs/stack_trace/.travis.yml deleted file mode 100644 index e87b82737..000000000 --- a/pkgs/stack_trace/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: dart - -dart: - - dev - -jobs: - include: - - stage: analyze_and_format - name: "Analyzer" - os: linux - script: dart analyze --fatal-infos . - - stage: analyze_and_format - name: "Format" - os: linux - script: dart format -o none --set-exit-if-changed . - - stage: test - name: "Vm Tests" - os: linux - script: pub run --enable-experiment=non-nullable test -p vm - -stages: - - analyze_and_format - - test - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 85f4f74336993146894b0f8482fb40107cf4de59 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 18:26:21 +0100 Subject: [PATCH 0757/1215] Migrate to GitHub Actions (dart-lang/string_scanner#32) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 64 +++++++++++++++++++ pkgs/string_scanner/.travis.yml | 17 ----- 2 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 pkgs/string_scanner/.github/workflows/test-package.yml delete mode 100644 pkgs/string_scanner/.travis.yml diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml new file mode 100644 index 000000000..0a2a87433 --- /dev/null +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/string_scanner/.travis.yml b/pkgs/string_scanner/.travis.yml deleted file mode 100644 index 481e06250..000000000 --- a/pkgs/string_scanner/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -language: dart - -dart: - - dev - -dart_task: - - test: --platform vm,chrome - - dartfmt - - dartanalyzer: --fatal-warnings --fatal-hints . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From cc74a72670d5223abb310947bec29516cfc0972f Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Wed, 20 Jan 2021 18:28:03 +0100 Subject: [PATCH 0758/1215] Migrate to GitHub Actions (dart-lang/stream_transform#127) * Delete .travis.yml --- .../.github/workflows/test-package.yml | 64 +++++++++++++++++++ pkgs/stream_transform/.travis.yml | 19 ------ 2 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 pkgs/stream_transform/.github/workflows/test-package.yml delete mode 100644 pkgs/stream_transform/.travis.yml diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml new file mode 100644 index 000000000..b781a90c8 --- /dev/null +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -0,0 +1,64 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm --test-randomize-ordering-seed=random + if: always() && steps.install.outcome == 'success' + - name: Run Chrome tests + run: dart test --platform chrome --test-randomize-ordering-seed=random + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/stream_transform/.travis.yml b/pkgs/stream_transform/.travis.yml deleted file mode 100644 index 3b2eb080e..000000000 --- a/pkgs/stream_transform/.travis.yml +++ /dev/null @@ -1,19 +0,0 @@ -language: dart -branches: - only: [master] -dart: - - dev -cache: - directories: - - $HOME/.pub-cache -dart_task: - - test --test-randomize-ordering-seed=random - - test -p chrome --test-randomize-ordering-seed=random - -matrix: - include: - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-warnings --fatal-infos . From 190f93add7d7c8e9eaa74b7db983937a32b245b8 Mon Sep 17 00:00:00 2001 From: Alexander Thomas Date: Thu, 28 Jan 2021 16:23:09 +0100 Subject: [PATCH 0759/1215] Migrate to GitHub Actions (dart-lang/pubspec_parse#63) --- .../.github/workflows/test-package.yml | 85 +++++++++++++++++++ pkgs/pubspec_parse/.travis.yml | 29 ------- pkgs/pubspec_parse/README.md | 2 +- 3 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 pkgs/pubspec_parse/.github/workflows/test-package.yml delete mode 100644 pkgs/pubspec_parse/.travis.yml diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml new file mode 100644 index 000000000..fa37a1f87 --- /dev/null +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -0,0 +1,85 @@ +name: Dart CI + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: dart pub get + - name: Run VM tests + run: dart test --platform vm --run-skipped + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release: 2.7.0 + test-legacy-sdk: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [2.7.0] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: pub get + - name: Run VM tests + run: pub run test --platform vm --run-skipped + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/pubspec_parse/.travis.yml b/pkgs/pubspec_parse/.travis.yml deleted file mode 100644 index 802491f97..000000000 --- a/pkgs/pubspec_parse/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -language: dart - -dart: - - 2.7.0 - - dev - -dart_task: - - test: -x presubmit-only - - test: --run-skipped -t presubmit-only - -matrix: - include: - # Only validate formatting using the dev release - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-infos --fatal-warnings . - - dart: 2.7.0 - dart_task: - dartanalyzer: --fatal-warnings . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index 7287d5f4e..ed00eed97 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/dart-lang/pubspec_parse.svg?branch=master)](https://travis-ci.org/dart-lang/pubspec_parse) +[![Build Status](https://github.com/dart-lang/pubspec_parse/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/pubspec_parse/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/pubspec_parse) Supports parsing `pubspec.yaml` files with robust error reporting and support From 4bbbff29df9d12317b1c42eb089e60571b7c3742 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 29 Jan 2021 14:47:54 -0800 Subject: [PATCH 0760/1215] Revert "Remove dependency on package:charcode (dart-lang/string_scanner#29)" (dart-lang/string_scanner#33) This reverts commit d769b0e6c94945d29b83175ed06f9eaec1571cbb. Since this has not been published or rolled through to the SDK or Flutter we will hold it back to reduce risk. --- pkgs/string_scanner/lib/src/charcode.dart | 24 ------------------- .../lib/src/eager_span_scanner.dart | 3 ++- pkgs/string_scanner/lib/src/line_scanner.dart | 3 ++- .../lib/src/string_scanner.dart | 4 ++-- pkgs/string_scanner/pubspec.yaml | 1 + .../test/line_scanner_test.dart | 2 +- .../test/string_scanner_test.dart | 2 +- 7 files changed, 9 insertions(+), 30 deletions(-) delete mode 100644 pkgs/string_scanner/lib/src/charcode.dart diff --git a/pkgs/string_scanner/lib/src/charcode.dart b/pkgs/string_scanner/lib/src/charcode.dart deleted file mode 100644 index d15774935..000000000 --- a/pkgs/string_scanner/lib/src/charcode.dart +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// 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. - -/// Character '\'. -const int $backslash = 0x5C; - -/// "Carriage return" control character. -const int $cr = 0x0D; - -/// Character '"'. -const int $doubleQuote = 0x22; - -/// Character 'f'. -const int $f = 0x66; - -/// "Line feed" control character. -const int $lf = 0x0A; - -/// Space character. -const int $space = 0x20; - -/// Character 'x'. -const int $x = 0x78; diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index d27a818fa..415b9f32c 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -2,7 +2,8 @@ // 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. -import 'charcode.dart'; +import 'package:charcode/ascii.dart'; + import 'line_scanner.dart'; import 'span_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index af6b6e705..358d4c1cb 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -2,7 +2,8 @@ // 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. -import 'charcode.dart'; +import 'package:charcode/ascii.dart'; + import 'string_scanner.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 5d69c7565..564774c3a 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -2,9 +2,9 @@ // 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. +import 'package:charcode/charcode.dart'; import 'package:source_span/source_span.dart'; -import 'charcode.dart'; import 'exception.dart'; import 'utils.dart'; @@ -110,7 +110,7 @@ class StringScanner { if (name == null) { if (character == $backslash) { name = r'"\"'; - } else if (character == $doubleQuote) { + } else if (character == $double_quote) { name = r'"\""'; } else { name = '"${String.fromCharCode(character)}"'; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 1b2c2e5c9..0d29f2e05 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -8,6 +8,7 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: + charcode: '>=1.2.0-nullsafety <1.2.0' source_span: '>=1.8.0-nullsafety <1.8.0' dev_dependencies: diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index a3deff1b7..0bbd499ab 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -2,7 +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. -import 'package:string_scanner/src/charcode.dart'; +import 'package:charcode/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 34176b8a3..0327499c7 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -2,7 +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. -import 'package:string_scanner/src/charcode.dart'; +import 'package:charcode/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; From 8fff9b57e1dc76c9503d15f322da041f651e68a0 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 2 Feb 2021 11:20:18 -0800 Subject: [PATCH 0761/1215] Revert "Remove unnecessary import" (dart-lang/stream_channel#71) This reverts commit f2dcd319ec1efca9d01abd5500436e2cb63e4c53. Since this has not been published or rolled through to the SDK or Flutter we will hold it back to reduce risk. --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 3feda43fd..237193b86 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,6 +7,7 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; +import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. From 07dc3e55903525f6f84b0d338902ac8c69197ffc Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Tue, 2 Feb 2021 11:23:03 -0800 Subject: [PATCH 0762/1215] Revert "Remove workaround for truncated last lines (dart-lang/stack_trace#100)" (dart-lang/stack_trace#104) This reverts commit ff1df498b650c6545a5a967e4183767454864c6f. --- pkgs/stack_trace/lib/src/trace.dart | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index e51d4b400..42371c744 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -151,7 +151,22 @@ class Trace implements StackTrace { .replaceAll(vmChainGap, '') .split('\n') .where((line) => line.isNotEmpty); - return [for (var line in lines) Frame.parseVM(line)]; + + if (lines.isEmpty) { + return []; + } + + var frames = lines + .take(lines.length - 1) + .map((line) => Frame.parseVM(line)) + .toList(); + + // TODO(nweiz): Remove this when issue 23614 is fixed. + if (!lines.last.endsWith('.da')) { + frames.add(Frame.parseVM(lines.last)); + } + + return frames; } /// Parses a string representation of a Chrome/V8 stack trace. From f114ba87d21f5259bd413edb4dffa4f8728cae7b Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 13:31:22 -0800 Subject: [PATCH 0763/1215] Prepare to publish for stable null safety (dart-lang/stream_channel#72) --- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index ea31ffe2c..2bb6c1f26 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +* Stable release for null safety. + ## 2.1.0-nullsafety.3 * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index d11a3567f..e7f6c7a7c 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0-nullsafety.3 +version: 2.1.0 description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -10,7 +10,7 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - async: '>=2.5.0-nullsafety <2.5.0' + async: ^2.5.0 dev_dependencies: pedantic: ^1.10.0-nullsafety From 4a559ca4dc4ed06310fa5e1812d6ab30c6769875 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 15:18:29 -0800 Subject: [PATCH 0764/1215] Prepare to publish for stable null safety (dart-lang/stack_trace#105) --- pkgs/stack_trace/CHANGELOG.md | 3 ++- pkgs/stack_trace/pubspec.yaml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 25773bbd6..ec80e2aae 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,5 +1,6 @@ -## 1.10.0-nullsafety.7-dev +## 1.10.0 +* Stable release for null safety. * Fix broken test, `test/chain/vm_test.dart`, which incorrectly handles asynchronous suspension gap markers at the end of stack traces. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index be5bced32..721fc9613 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.0-nullsafety.7-dev +version: 1.10.0 description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace @@ -7,7 +7,7 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - path: ^1.8.0-nullsafety + path: ^1.8.0 dev_dependencies: pedantic: ^1.10.0-nullsafety From 370a95dbbaaa08e6af9892dd7c673c87e0da63c9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 15:20:17 -0800 Subject: [PATCH 0765/1215] Prepare to publish for stable null safety (dart-lang/term_glyph#22) --- pkgs/term_glyph/CHANGELOG.md | 4 ++++ pkgs/term_glyph/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 7f8ed6036..15cbaf5cb 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.0 + +* Stable release for null safety. + ## 1.2.0-nullsafety.3 * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index d989ae90b..18177a356 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.2.0-nullsafety.3 +version: 1.2.0 description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph From e05804976dcfe0de678609b6f47cfa172a52d3be Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 2 Feb 2021 15:49:51 -0800 Subject: [PATCH 0766/1215] Prepare for stable release of null safety (dart-lang/string_scanner#34) --- pkgs/string_scanner/CHANGELOG.md | 4 +++- pkgs/string_scanner/pubspec.yaml | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 08216dc60..4465d5191 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.1.0-nullsafety.4-dev +## 1.1.0 + +* Stable release for null safety. ## 1.1.0-nullsafety.3 diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 0d29f2e05..5ecd164e3 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.1.0-nullsafety.4-dev +version: 1.1.0 description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner @@ -8,8 +8,8 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - charcode: '>=1.2.0-nullsafety <1.2.0' - source_span: '>=1.8.0-nullsafety <1.8.0' + charcode: ^1.2.0 + source_span: ^1.8.0 dev_dependencies: - test: '>=1.16.0-nullsafety <1.16.0' + test: ^1.16.0-nullsafety From 57097299c2e45e96b572a6ca4e9780e50a730050 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 4 Feb 2021 16:17:00 -0800 Subject: [PATCH 0767/1215] Revert "Revert "Remove dependency on package:charcode (dart-lang/string_scanner#29)" (dart-lang/string_scanner#33)" (dart-lang/string_scanner#36) This reverts commit 4bbbff29df9d12317b1c42eb089e60571b7c3742. --- pkgs/string_scanner/CHANGELOG.md | 2 ++ pkgs/string_scanner/lib/src/charcode.dart | 24 +++++++++++++++++++ .../lib/src/eager_span_scanner.dart | 3 +-- pkgs/string_scanner/lib/src/line_scanner.dart | 3 +-- .../lib/src/string_scanner.dart | 4 ++-- pkgs/string_scanner/pubspec.yaml | 3 +-- .../test/line_scanner_test.dart | 2 +- .../test/string_scanner_test.dart | 2 +- 8 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 pkgs/string_scanner/lib/src/charcode.dart diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 4465d5191..2a76ec94d 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.1.1-dev + ## 1.1.0 * Stable release for null safety. diff --git a/pkgs/string_scanner/lib/src/charcode.dart b/pkgs/string_scanner/lib/src/charcode.dart new file mode 100644 index 000000000..d15774935 --- /dev/null +++ b/pkgs/string_scanner/lib/src/charcode.dart @@ -0,0 +1,24 @@ +// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file +// 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. + +/// Character '\'. +const int $backslash = 0x5C; + +/// "Carriage return" control character. +const int $cr = 0x0D; + +/// Character '"'. +const int $doubleQuote = 0x22; + +/// Character 'f'. +const int $f = 0x66; + +/// "Line feed" control character. +const int $lf = 0x0A; + +/// Space character. +const int $space = 0x20; + +/// Character 'x'. +const int $x = 0x78; diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 415b9f32c..d27a818fa 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -2,8 +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. -import 'package:charcode/ascii.dart'; - +import 'charcode.dart'; import 'line_scanner.dart'; import 'span_scanner.dart'; diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 358d4c1cb..af6b6e705 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -2,8 +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. -import 'package:charcode/ascii.dart'; - +import 'charcode.dart'; import 'string_scanner.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 564774c3a..5d69c7565 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -2,9 +2,9 @@ // 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. -import 'package:charcode/charcode.dart'; import 'package:source_span/source_span.dart'; +import 'charcode.dart'; import 'exception.dart'; import 'utils.dart'; @@ -110,7 +110,7 @@ class StringScanner { if (name == null) { if (character == $backslash) { name = r'"\"'; - } else if (character == $double_quote) { + } else if (character == $doubleQuote) { name = r'"\""'; } else { name = '"${String.fromCharCode(character)}"'; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 5ecd164e3..9eee52bfd 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.1.0 +version: 1.1.1-dev description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner @@ -8,7 +8,6 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - charcode: ^1.2.0 source_span: ^1.8.0 dev_dependencies: diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index 0bbd499ab..a3deff1b7 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -2,7 +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. -import 'package:charcode/charcode.dart'; +import 'package:string_scanner/src/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 0327499c7..34176b8a3 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -2,7 +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. -import 'package:charcode/charcode.dart'; +import 'package:string_scanner/src/charcode.dart'; import 'package:string_scanner/string_scanner.dart'; import 'package:test/test.dart'; From 8fd6d28a8d907004470ab9e377d6320ccadfa27d Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Fri, 5 Feb 2021 13:46:34 -0800 Subject: [PATCH 0768/1215] null safety stable release (dart-lang/watcher#109) --- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/pubspec.yaml | 14 ++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 832f0e7b9..6b7785cc1 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.0 + +* Stable null safety release. + # 1.0.0-nullsafety.0 * Migrate to null safety. diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index d09361af3..bbb07a311 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.0.0-nullsafety.0 +version: 1.0.0 description: >- A file system watcher. It monitors changes to contents of directories and @@ -10,14 +10,12 @@ environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - async: ^2.5.0-nullsafety.3 - path: ^1.8.0-nullsafety.3 - pedantic: ^1.10.0-nullsafety.3 + async: ^2.5.0 + path: ^1.8.0 + pedantic: ^1.10.0 dev_dependencies: - benchmark_harness: ^2.0.0-nullsafety.0 - test: ^1.16.0-nullsafety.13 + benchmark_harness: ^2.0.0 + test: ^1.16.0 test_descriptor: ^2.0.0-nullsafety -dependency_overrides: - analyzer: ^0.41.1 From 417cb8ac9d3903060b4a82ab909899d04639983b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Feb 2021 12:39:04 -0800 Subject: [PATCH 0769/1215] Publish stable version of stream_transform (dart-lang/stream_transform#128) --- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/pubspec.yaml | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 7b68aa597..5a59f6f94 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.0-nullsafety.0 +## 2.0.0 - Migrate to null safety. - Improve tests of `switchMap` and improve documentation with links and diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 4e5b37977..98086c539 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. -homepage: https://github.com/dart-lang/stream_transform -version: 2.0.0-nullsafety.0 +repository: https://github.com/dart-lang/stream_transform +version: 2.0.0 environment: sdk: ">=2.12.0-0 <3.0.0" dev_dependencies: - async: ^2.5.0-nullsafety - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + async: ^2.5.0 + pedantic: ^1.10.0 + test: ^1.16.0 From 0b72f1c2d2b2d490fdeb29410dd63e49f47e1034 Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Mon, 8 Feb 2021 13:42:55 -0800 Subject: [PATCH 0770/1215] stable null safety release (dart-lang/test_reflective_loader#31) * stable null safety release * Remove author. --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ pkgs/test_reflective_loader/pubspec.yaml | 3 +-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 7efa79cda..bb0f5ab88 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0 + +- Stable null safety release. + ## 0.2.0-nullsafety.0 - Migrate to the null safety language feature. diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 6d081e48d..fcdf6b745 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,8 +1,7 @@ name: test_reflective_loader -version: 0.2.0-nullsafety.0 +version: 0.2.0 description: Support for discovering tests and test suites using reflection. -author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: From 1a84a1ea7d6aaac817bf6534feb46b6c10ee689e Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Mon, 8 Feb 2021 13:49:51 -0800 Subject: [PATCH 0771/1215] Revert "stable null safety release (dart-lang/test_reflective_loader#31)" (dart-lang/test_reflective_loader#32) This reverts commit 0b72f1c2d2b2d490fdeb29410dd63e49f47e1034. --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ---- pkgs/test_reflective_loader/pubspec.yaml | 3 ++- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index bb0f5ab88..7efa79cda 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,7 +1,3 @@ -## 0.2.0 - -- Stable null safety release. - ## 0.2.0-nullsafety.0 - Migrate to the null safety language feature. diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index fcdf6b745..6d081e48d 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,7 +1,8 @@ name: test_reflective_loader -version: 0.2.0 +version: 0.2.0-nullsafety.0 description: Support for discovering tests and test suites using reflection. +author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: From b3c03dbf27a89f389782e2fd6dab7d2dd813df54 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Feb 2021 13:57:09 -0800 Subject: [PATCH 0772/1215] allow latest pkg:pub_semver (dart-lang/pubspec_parse#64) --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 26b1d3139..a07e48885 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.8 + +- Allow the latest `package:pub_semver`. + ## 0.1.7 - Allow `package:yaml` `v3.x`. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 5cda97668..dee30ecde 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.7 +version: 0.1.8 repository: https://github.com/dart-lang/pubspec_parse environment: @@ -12,7 +12,7 @@ dependencies: checked_yaml: ^1.0.0 # Verified that no new features since 1.0.0 are used - be careful! json_annotation: '>=1.0.0 <5.0.0' - pub_semver: ^1.3.2 + pub_semver: '>=1.3.2 <3.0.0' yaml: '>=2.1.12 <4.0.0' dev_dependencies: From 7c4cefac88b168ce5af03cc0c716323a23c3ff30 Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Mon, 8 Feb 2021 16:43:13 -0800 Subject: [PATCH 0773/1215] stable null safety release (dart-lang/test_reflective_loader#33) --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ pkgs/test_reflective_loader/pubspec.yaml | 5 ++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 7efa79cda..bb0f5ab88 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0 + +- Stable null safety release. + ## 0.2.0-nullsafety.0 - Migrate to the null safety language feature. diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 6d081e48d..1a727331e 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,12 +1,11 @@ name: test_reflective_loader -version: 0.2.0-nullsafety.0 +version: 0.2.0 description: Support for discovering tests and test suites using reflection. -author: Dart Team homepage: https://github.com/dart-lang/test_reflective_loader environment: sdk: '>=2.12.0-0 <3.0.0' dependencies: - test: '>=1.16.0-nullsafety.12 <2.0.0' + test: '>=1.16.0 <2.0.0' From b8f2892926fecbaa7185b899b0b936b2755c55be Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 2 Mar 2021 09:27:49 -0800 Subject: [PATCH 0774/1215] migrate to stable, null-safety (dart-lang/pubspec_parse#65) Co-authored-by: Jacob MacDonald --- .../.github/workflows/test-package.yml | 28 +----- pkgs/pubspec_parse/CHANGELOG.md | 6 ++ pkgs/pubspec_parse/build.yaml | 2 + pkgs/pubspec_parse/lib/src/dependency.dart | 53 ++++++----- pkgs/pubspec_parse/lib/src/dependency.g.dart | 24 ++--- pkgs/pubspec_parse/lib/src/pubspec.dart | 94 ++++++++++--------- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 29 +++--- pkgs/pubspec_parse/pubspec.yaml | 27 ++++-- pkgs/pubspec_parse/test/dependency_test.dart | 44 +++++---- .../pubspec_parse/test/ensure_build_test.dart | 2 + pkgs/pubspec_parse/test/parse_test.dart | 48 +++++++--- pkgs/pubspec_parse/test/test_utils.dart | 20 ++-- 12 files changed, 199 insertions(+), 178 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index fa37a1f87..d63264526 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -45,9 +45,9 @@ jobs: strategy: fail-fast: false matrix: - # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + # change beta to 2.12.0 when released! + sdk: [beta, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v0.3 @@ -59,27 +59,3 @@ jobs: - name: Run VM tests run: dart test --platform vm --run-skipped if: always() && steps.install.outcome == 'success' - - # Run tests on a matrix consisting of two dimensions: - # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release: 2.7.0 - test-legacy-sdk: - needs: analyze - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - # Add macos-latest and/or windows-latest if relevant for this package. - os: [ubuntu-latest] - sdk: [2.7.0] - steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 - with: - sdk: ${{ matrix.sdk }} - - id: install - name: Install dependencies - run: pub get - - name: Run VM tests - run: pub run test --platform vm --run-skipped - if: always() && steps.install.outcome == 'success' diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index a07e48885..97c410f74 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.0.0 + +- Migrate to null-safety. +- Pubspec: `author` and `authors` are both now deprecated. + See https://dart.dev/tools/pub/pubspec#authorauthors + ## 0.1.8 - Allow the latest `package:pub_semver`. diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index aa3ea69ec..3e642b8f1 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -18,4 +18,6 @@ targets: source_gen|combining_builder: options: ignore_for_file: + - deprecated_member_use_from_same_package + - lines_longer_than_80_chars - prefer_expression_function_bodies diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 2d4eda696..e4996c58e 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -2,16 +2,17 @@ // 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. +import 'package:collection/collection.dart'; import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; part 'dependency.g.dart'; -Map parseDeps(Map source) => +Map parseDeps(Map? source) => source?.map((k, v) { final key = k as String; - Dependency value; + Dependency? value; try { value = _fromJson(v); } on CheckedFromJsonException catch (e) { @@ -19,7 +20,7 @@ Map parseDeps(Map source) => // This is likely a "synthetic" map created from a String value // Use `source` to throw this exception with an actual YamlMap and // extract the associated error information. - throw CheckedFromJsonException(source, key, e.className, e.message); + throw CheckedFromJsonException(source, key, e.className!, e.message); } rethrow; } @@ -35,7 +36,7 @@ Map parseDeps(Map source) => const _sourceKeys = ['sdk', 'git', 'path', 'hosted']; /// Returns `null` if the data could not be parsed. -Dependency _fromJson(dynamic data) { +Dependency? _fromJson(Object? data) { if (data is String || data == null) { return _$HostedDependencyFromJson({'version': data}); } @@ -47,8 +48,8 @@ Dependency _fromJson(dynamic data) { if (data.isEmpty || (matchedKeys.isEmpty && data.containsKey('version'))) { return _$HostedDependencyFromJson(data); } else { - final firstUnrecognizedKey = matchedKeys - .firstWhere((k) => !_sourceKeys.contains(k), orElse: () => null); + final firstUnrecognizedKey = + matchedKeys.firstWhereOrNull((k) => !_sourceKeys.contains(k)); return $checkedNew('Dependency', data, () { if (firstUnrecognizedKey != null) { @@ -92,12 +93,13 @@ abstract class Dependency { @JsonSerializable() class SdkDependency extends Dependency { - @JsonKey(nullable: false, disallowNullValue: true, required: true) final String sdk; @JsonKey(fromJson: _constraintFromString) final VersionConstraint version; - SdkDependency(this.sdk, {this.version}) : super._(); + SdkDependency(this.sdk, {VersionConstraint? version}) + : version = version ?? VersionConstraint.any, + super._(); @override String get _info => sdk; @@ -105,14 +107,14 @@ class SdkDependency extends Dependency { @JsonSerializable() class GitDependency extends Dependency { - @JsonKey(fromJson: parseGitUri, required: true, disallowNullValue: true) + @JsonKey(fromJson: parseGitUri) final Uri url; - final String ref; - final String path; + final String? ref; + final String? path; - GitDependency(this.url, this.ref, this.path) : super._(); + GitDependency(this.url, {this.ref, this.path}) : super._(); - factory GitDependency.fromData(Object data) { + factory GitDependency.fromData(Object? data) { if (data is String) { data = {'url': data}; } @@ -128,12 +130,14 @@ class GitDependency extends Dependency { String get _info => 'url@$url'; } -Uri parseGitUri(String value) => - value == null ? null : _tryParseScpUri(value) ?? Uri.parse(value); +Uri? parseGitUriOrNull(String? value) => + value == null ? null : parseGitUri(value); + +Uri parseGitUri(String value) => _tryParseScpUri(value) ?? Uri.parse(value); /// Supports URIs like `[user@]host.xz:path/to/repo.git/` /// See https://git-scm.com/docs/git-clone#_git_urls_a_id_urls_a -Uri _tryParseScpUri(String value) { +Uri? _tryParseScpUri(String value) { final colonIndex = value.indexOf(':'); if (colonIndex < 0) { @@ -167,7 +171,7 @@ class PathDependency extends Dependency { PathDependency(this.path) : super._(); - factory PathDependency.fromData(Object data) { + factory PathDependency.fromData(Object? data) { if (data is String) { return PathDependency(data); } @@ -184,9 +188,9 @@ class HostedDependency extends Dependency { final VersionConstraint version; @JsonKey(disallowNullValue: true) - final HostedDetails hosted; + final HostedDetails? hosted; - HostedDependency({VersionConstraint version, this.hosted}) + HostedDependency({VersionConstraint? version, this.hosted}) : version = version ?? VersionConstraint.any, super._(); @@ -196,15 +200,14 @@ class HostedDependency extends Dependency { @JsonSerializable(disallowUnrecognizedKeys: true) class HostedDetails { - @JsonKey(required: true, disallowNullValue: true) final String name; - @JsonKey(fromJson: parseGitUri, disallowNullValue: true) - final Uri url; + @JsonKey(fromJson: parseGitUriOrNull, disallowNullValue: true) + final Uri? url; HostedDetails(this.name, this.url); - factory HostedDetails.fromJson(Object data) { + factory HostedDetails.fromJson(Object? data) { if (data is String) { data = {'name': data}; } @@ -217,5 +220,5 @@ class HostedDetails { } } -VersionConstraint _constraintFromString(String input) => - input == null ? null : VersionConstraint.parse(input); +VersionConstraint _constraintFromString(String? input) => + input == null ? VersionConstraint.any : VersionConstraint.parse(input); diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 37352b37f..95b177993 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, prefer_expression_function_bodies part of 'dependency.dart'; @@ -10,12 +10,10 @@ part of 'dependency.dart'; SdkDependency _$SdkDependencyFromJson(Map json) { return $checkedNew('SdkDependency', json, () { - $checkKeys(json, - requiredKeys: const ['sdk'], disallowNullValues: const ['sdk']); final val = SdkDependency( $checkedConvert(json, 'sdk', (v) => v as String), version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String)), + json, 'version', (v) => _constraintFromString(v as String?)), ); return val; }); @@ -23,12 +21,10 @@ SdkDependency _$SdkDependencyFromJson(Map json) { GitDependency _$GitDependencyFromJson(Map json) { return $checkedNew('GitDependency', json, () { - $checkKeys(json, - requiredKeys: const ['url'], disallowNullValues: const ['url']); final val = GitDependency( $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), - $checkedConvert(json, 'ref', (v) => v as String), - $checkedConvert(json, 'path', (v) => v as String), + ref: $checkedConvert(json, 'ref', (v) => v as String?), + path: $checkedConvert(json, 'path', (v) => v as String?), ); return val; }); @@ -41,9 +37,9 @@ HostedDependency _$HostedDependencyFromJson(Map json) { disallowNullValues: const ['hosted']); final val = HostedDependency( version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String)), - hosted: $checkedConvert( - json, 'hosted', (v) => v == null ? null : HostedDetails.fromJson(v)), + json, 'version', (v) => _constraintFromString(v as String?)), + hosted: $checkedConvert(json, 'hosted', + (v) => v == null ? null : HostedDetails.fromJson(v as Object)), ); return val; }); @@ -52,12 +48,10 @@ HostedDependency _$HostedDependencyFromJson(Map json) { HostedDetails _$HostedDetailsFromJson(Map json) { return $checkedNew('HostedDetails', json, () { $checkKeys(json, - allowedKeys: const ['name', 'url'], - requiredKeys: const ['name'], - disallowNullValues: const ['name', 'url']); + allowedKeys: const ['name', 'url'], disallowNullValues: const ['url']); final val = HostedDetails( $checkedConvert(json, 'name', (v) => v as String), - $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), + $checkedConvert(json, 'url', (v) => parseGitUriOrNull(v as String?)), ); return val; }); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index e3dbac14f..b851486ec 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -17,53 +17,57 @@ class Pubspec { final String name; @JsonKey(fromJson: _versionFromString) - final Version version; + final Version? version; - final String description; + final String? description; /// This should be a URL pointing to the website for the package. - final String homepage; + final String? homepage; /// Specifies where to publish this package. /// /// Accepted values: `null`, `'none'` or an `http` or `https` URL. /// /// [More information](https://dart.dev/tools/pub/pubspec#publish_to). - final String publishTo; + final String? publishTo; /// Optional field to specify the source code repository of the package. /// Useful when a package has both a home page and a repository. - final Uri repository; + final Uri? repository; /// Optional field to a web page where developers can report new issues or /// view existing ones. - final Uri issueTracker; + final Uri? issueTracker; /// If there is exactly 1 value in [authors], returns it. /// /// If there are 0 or more than 1, returns `null`. @Deprecated( - 'Here for completeness, but not recommended. Use `authors` instead.') - String get author { + 'See https://dart.dev/tools/pub/pubspec#authorauthors', + ) + String? get author { if (authors.length == 1) { return authors.single; } return null; } + @Deprecated( + 'See https://dart.dev/tools/pub/pubspec#authorauthors', + ) final List authors; - final String documentation; + final String? documentation; @JsonKey(fromJson: _environmentMap) - final Map environment; + final Map? environment; - @JsonKey(fromJson: parseDeps, nullable: false) + @JsonKey(fromJson: parseDeps) final Map dependencies; - @JsonKey(fromJson: parseDeps, nullable: false) + @JsonKey(fromJson: parseDeps) final Map devDependencies; - @JsonKey(fromJson: parseDeps, nullable: false) + @JsonKey(fromJson: parseDeps) final Map dependencyOverrides; /// Optional configuration specific to [Flutter](https://flutter.io/) @@ -72,7 +76,7 @@ class Pubspec { /// May include /// [assets](https://flutter.io/docs/development/ui/assets-and-images) /// and other settings. - final Map flutter; + final Map? flutter; /// If [author] and [authors] are both provided, their values are combined /// with duplicates eliminated. @@ -80,30 +84,38 @@ class Pubspec { this.name, { this.version, this.publishTo, - String author, - List authors, - Map environment, + @Deprecated( + 'See https://dart.dev/tools/pub/pubspec#authorauthors', + ) + String? author, + @Deprecated( + 'See https://dart.dev/tools/pub/pubspec#authorauthors', + ) + List? authors, + Map? environment, this.homepage, this.repository, this.issueTracker, this.documentation, this.description, - Map dependencies, - Map devDependencies, - Map dependencyOverrides, + Map? dependencies, + Map? devDependencies, + Map? dependencyOverrides, this.flutter, - }) : authors = _normalizeAuthors(author, authors), + }) : + // ignore: deprecated_member_use_from_same_package + authors = _normalizeAuthors(author, authors), environment = environment ?? const {}, dependencies = dependencies ?? const {}, devDependencies = devDependencies ?? const {}, dependencyOverrides = dependencyOverrides ?? const {} { - if (name == null || name.isEmpty) { + if (name.isEmpty) { throw ArgumentError.value(name, 'name', '"name" cannot be empty.'); } if (publishTo != null && publishTo != 'none') { try { - final targetUri = Uri.parse(publishTo); + final targetUri = Uri.parse(publishTo!); if (!(targetUri.isScheme('http') || targetUri.isScheme('https'))) { throw const FormatException('Must be an http or https URL.'); } @@ -114,8 +126,6 @@ class Pubspec { } factory Pubspec.fromJson(Map json, {bool lenient = false}) { - lenient ??= false; - if (lenient) { while (json.isNotEmpty) { // Attempting to remove top-level properties that cause parsing errors. @@ -138,30 +148,26 @@ class Pubspec { /// /// When [lenient] is set, top-level property-parsing or type cast errors are /// ignored and `null` values are returned. - factory Pubspec.parse(String yaml, {sourceUrl, bool lenient = false}) { - lenient ??= false; - - return checkedYamlDecode( - yaml, (map) => Pubspec.fromJson(map, lenient: lenient), - sourceUrl: sourceUrl); - } - - static List _normalizeAuthors(String author, List authors) { - final value = {}; - if (author != null) { - value.add(author); - } - if (authors != null) { - value.addAll(authors); - } + factory Pubspec.parse(String yaml, {Uri? sourceUrl, bool lenient = false}) => + checkedYamlDecode( + yaml, + (map) => Pubspec.fromJson(map!, lenient: lenient), + sourceUrl: sourceUrl, + ); + + static List _normalizeAuthors(String? author, List? authors) { + final value = { + if (author != null) author, + ...?authors, + }; return value.toList(); } } -Version _versionFromString(String input) => +Version? _versionFromString(String? input) => input == null ? null : Version.parse(input); -Map _environmentMap(Map source) => +Map? _environmentMap(Map? source) => source?.map((k, value) { final key = k as String; if (key == 'dart') { @@ -176,7 +182,7 @@ Map _environmentMap(Map source) => ); } - VersionConstraint constraint; + VersionConstraint? constraint; if (value == null) { constraint = null; } else if (value is String) { diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index c29a221d3..72ed2a264 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: prefer_expression_function_bodies +// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, prefer_expression_function_bodies part of 'pubspec.dart'; @@ -13,30 +13,31 @@ Pubspec _$PubspecFromJson(Map json) { final val = Pubspec( $checkedConvert(json, 'name', (v) => v as String), version: $checkedConvert( - json, 'version', (v) => _versionFromString(v as String)), - publishTo: $checkedConvert(json, 'publish_to', (v) => v as String), - author: $checkedConvert(json, 'author', (v) => v as String), + json, 'version', (v) => _versionFromString(v as String?)), + publishTo: $checkedConvert(json, 'publish_to', (v) => v as String?), + author: $checkedConvert(json, 'author', (v) => v as String?), authors: $checkedConvert(json, 'authors', - (v) => (v as List)?.map((e) => e as String)?.toList()), + (v) => (v as List?)?.map((e) => e as String).toList()), environment: $checkedConvert( - json, 'environment', (v) => _environmentMap(v as Map)), - homepage: $checkedConvert(json, 'homepage', (v) => v as String), + json, 'environment', (v) => _environmentMap(v as Map?)), + homepage: $checkedConvert(json, 'homepage', (v) => v as String?), repository: $checkedConvert( json, 'repository', (v) => v == null ? null : Uri.parse(v as String)), issueTracker: $checkedConvert(json, 'issue_tracker', (v) => v == null ? null : Uri.parse(v as String)), - documentation: $checkedConvert(json, 'documentation', (v) => v as String), - description: $checkedConvert(json, 'description', (v) => v as String), + documentation: + $checkedConvert(json, 'documentation', (v) => v as String?), + description: $checkedConvert(json, 'description', (v) => v as String?), dependencies: - $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map)), - devDependencies: - $checkedConvert(json, 'dev_dependencies', (v) => parseDeps(v as Map)), + $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map?)), + devDependencies: $checkedConvert( + json, 'dev_dependencies', (v) => parseDeps(v as Map?)), dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => parseDeps(v as Map)), + json, 'dependency_overrides', (v) => parseDeps(v as Map?)), flutter: $checkedConvert( json, 'flutter', - (v) => (v as Map)?.map( + (v) => (v as Map?)?.map( (k, e) => MapEntry(k as String, e), )), ); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index dee30ecde..4179feadf 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,28 +2,35 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 0.1.8 +version: 1.0.0 repository: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.7.0 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' dependencies: - checked_yaml: ^1.0.0 - # Verified that no new features since 1.0.0 are used - be careful! - json_annotation: '>=1.0.0 <5.0.0' - pub_semver: '>=1.3.2 <3.0.0' - yaml: '>=2.1.12 <4.0.0' + checked_yaml: ^2.0.1 + collection: ^1.15.0 + json_annotation: ^4.0.0 + pub_semver: ^2.0.0 + yaml: ^3.0.0 dev_dependencies: build_runner: ^1.0.0 build_verify: ^1.0.0 - json_serializable: ^3.0.0 + json_serializable: ^4.0.2 path: ^1.5.1 pedantic: ^1.4.0 # Needed because we are configuring `combining_builder` source_gen: ^0.9.5 stack_trace: ^1.9.2 test: ^1.0.0 - test_descriptor: ^1.0.3 - test_process: ^1.0.2 + test_descriptor: ^2.0.0 + test_process: ^2.0.0 + +dependency_overrides: + # Need to update dependencies on these packages + build_config: 0.4.6 + build_runner: any + checked_yaml: ^2.0.1 + json_annotation: 4.0.0 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 0afbf3645..c6f2dc50b 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -112,8 +112,8 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} }); expect(dep.version.toString(), '^1.0.0'); - expect(dep.hosted.name, 'hosted_name'); - expect(dep.hosted.url.toString(), 'hosted_url'); + expect(dep.hosted!.name, 'hosted_name'); + expect(dep.hosted!.url.toString(), 'hosted_url'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); @@ -149,16 +149,16 @@ line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git final dep = _dependency( {'version': '^1.0.0', 'hosted': 'hosted_name'}); expect(dep.version.toString(), '^1.0.0'); - expect(dep.hosted.name, 'hosted_name'); - expect(dep.hosted.url, isNull); + expect(dep.hosted!.name, 'hosted_name'); + expect(dep.hosted!.url, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); test('map w/ hosted as String', () { final dep = _dependency({'hosted': 'hosted_name'}); expect(dep.version, VersionConstraint.any); - expect(dep.hosted.name, 'hosted_name'); - expect(dep.hosted.url, isNull); + expect(dep.hosted!.name, 'hosted_name'); + expect(dep.hosted!.url, isNull); expect(dep.toString(), 'HostedDependency: any'); }); @@ -186,7 +186,7 @@ void _sdkDependency() { test('without version', () { final dep = _dependency({'sdk': 'flutter'}); expect(dep.sdk, 'flutter'); - expect(dep.version, isNull); + expect(dep.version, VersionConstraint.any); expect(dep.toString(), 'SdkDependency: flutter'); }); @@ -202,10 +202,12 @@ void _sdkDependency() { _expectThrows( {'sdk': null}, r''' -line 5, column 4: These keys had `null` values, which is not allowed: [sdk] +line 5, column 11: Unsupported value for "sdk". type 'Null' is not a subtype of type 'String' in type cast ╷ -5 │ "sdk": null - │ ^^^^^ +5 │ "sdk": null + │ ┌───────────^ +6 │ │ } + │ └──^ ╵''', ); }); @@ -304,12 +306,15 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. }); test('git - empty map', () { - _expectThrows({'git': {}}, r''' -line 5, column 11: Required keys are missing: url. + _expectThrows( + {'git': {}}, + r''' +line 5, column 11: Missing key "url". type 'Null' is not a subtype of type 'String' in type cast ╷ 5 │ "git": {} │ ^^ - ╵'''); + ╵''', + ); }); test('git - null url', () { @@ -318,10 +323,12 @@ line 5, column 11: Required keys are missing: url. 'git': {'url': null} }, r''' -line 6, column 5: These keys had `null` values, which is not allowed: [url] +line 6, column 12: Unsupported value for "url". type 'Null' is not a subtype of type 'String' in type cast ╷ -6 │ "url": null - │ ^^^^^ +6 │ "url": null + │ ┌────────────^ +7 │ │ } + │ └───^ ╵''', ); }); @@ -402,7 +409,10 @@ void _expectThrows(Object content, String expectedError) { }, expectedError); } -T _dependency(Object content, {bool skipTryPub = false}) { +T _dependency( + Object? content, { + bool skipTryPub = false, +}) { final value = parse({ ...defaultPubspec, 'dependencies': {'dep': content} diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index d64fa4f66..a75d1bd32 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -2,6 +2,8 @@ // 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.9 + @TestOn('vm') @Tags(['presubmit-only']) import 'package:build_verify/build_verify.dart'; diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 179d0d8d1..52df370d0 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -2,9 +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. -// TODO(kevmoo) Remove when github.com/dart-lang/sdk/commit/dac5a56422 lands -// in a shipped SDK. -// ignore_for_file: deprecated_member_use +// ignore_for_file: deprecated_member_use_from_same_package library parse_test; import 'package:pub_semver/pub_semver.dart'; @@ -20,7 +18,6 @@ void main() { expect(value.publishTo, isNull); expect(value.description, isNull); expect(value.homepage, isNull); - // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, isEmpty); expect( @@ -56,7 +53,6 @@ void main() { expect(value.publishTo, 'none'); expect(value.description, 'description'); expect(value.homepage, 'homepage'); - // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); expect(value.environment, hasLength(1)); @@ -86,7 +82,7 @@ void main() { group('publish_to', () { for (var entry in { 42: r''' -line 3, column 16: Unsupported value for "publish_to". type 'int' is not a subtype of type 'String' in type cast +line 3, column 16: Unsupported value for "publish_to". type 'int' is not a subtype of type 'String?' in type cast ╷ 3 │ "publish_to": 42 │ ^^ @@ -141,7 +137,6 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https ...defaultPubspec, 'author': 'name@example.com', }); - // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); @@ -151,7 +146,6 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https ...defaultPubspec, 'authors': ['name@example.com'] }); - // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); @@ -161,7 +155,6 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https ...defaultPubspec, 'authors': ['name@example.com', 'name2@example.com'] }); - // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); }); @@ -172,7 +165,6 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https 'author': 'name@example.com', 'authors': ['name2@example.com'] }); - // ignore: deprecated_member_use_from_same_package expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); }); @@ -183,7 +175,6 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https 'author': 'name@example.com', 'authors': ['name@example.com', 'name@example.com'] }); - // ignore: deprecated_member_use_from_same_package expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); }); @@ -230,12 +221,39 @@ line 1, column 1: Not a map }); test('missing name', () { - expectParseThrows({}, r''' -line 1, column 1: "name" cannot be empty. + expectParseThrows( + {}, + r''' +line 1, column 1: Missing key "name". type 'Null' is not a subtype of type 'String' in type cast ╷ 1 │ {} │ ^^ - ╵'''); + ╵''', + ); + }); + + test('null name value', () { + expectParseThrows( + {'name': null}, + r''' +line 2, column 10: Unsupported value for "name". type 'Null' is not a subtype of type 'String' in type cast + ╷ +2 │ "name": null + │ ^^^^ + ╵''', + ); + }); + + test('empty name value', () { + expectParseThrows( + {'name': ''}, + r''' +line 2, column 10: Unsupported value for "name". "name" cannot be empty. + ╷ +2 │ "name": "" + │ ^^ + ╵''', + ); }); test('"dart" is an invalid environment key', () { @@ -359,7 +377,7 @@ line 1, column 1: Not a map expectParseThrows( {}, r''' -line 1, column 1: "name" cannot be empty. +line 1, column 1: Missing key "name". type 'Null' is not a subtype of type 'String' in type cast ╷ 1 │ {} │ ^^ diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index ac5abba06..b66adba87 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -18,7 +18,7 @@ const defaultPubspec = { 'environment': {'sdk': '>=2.7.0 <3.0.0'}, }; -String _encodeJson(Object input) => +String _encodeJson(Object? input) => const JsonEncoder.withIndent(' ').convert(input); Matcher _throwsParsedYamlException(String prettyValue) => @@ -31,10 +31,10 @@ Matcher _throwsParsedYamlException(String prettyValue) => void _printDebugParsedYamlException(ParsedYamlException e) { var innerError = e.innerError; - StackTrace innerStack; + StackTrace? innerStack; if (innerError is CheckedFromJsonException) { - final cfje = innerError as CheckedFromJsonException; + final cfje = innerError; if (cfje.innerError != null) { innerError = cfje.innerError; @@ -56,18 +56,14 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } Pubspec parse( - Object content, { + Object? content, { bool quietOnError = false, bool skipTryPub = false, bool lenient = false, }) { - quietOnError ??= false; - skipTryPub ??= false; - lenient ??= false; - final encoded = _encodeJson(content); - ProcResult pubResult; + ProcResult? pubResult; if (!skipTryPub) { pubResult = waitFor(tryPub(encoded)); expect(pubResult, isNotNull); @@ -78,7 +74,7 @@ Pubspec parse( if (pubResult != null) { addTearDown(() { - expect(pubResult.cleanParse, isTrue, + expect(pubResult!.cleanParse, isTrue, reason: 'On success, parsing from the pub client should also succeed.'); }); @@ -87,7 +83,7 @@ Pubspec parse( } catch (e) { if (pubResult != null) { addTearDown(() { - expect(pubResult.cleanParse, isFalse, + expect(pubResult!.cleanParse, isFalse, reason: 'On failure, parsing from the pub client should also fail.'); }); @@ -102,7 +98,7 @@ Pubspec parse( } void expectParseThrows( - Object content, + Object? content, String expectedError, { bool skipTryPub = false, bool lenient = false, From bba1fe8e09c526e9c19b8b9d2ffdb477a8e116a3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 10 Mar 2021 11:04:24 -0800 Subject: [PATCH 0775/1215] Enable null-safety, prep to release v1 (dart-lang/timing#16) --- .../timing/.github/workflows/test-package.yml | 22 ++++++----------- pkgs/timing/CHANGELOG.md | 5 ++++ pkgs/timing/analysis_options.yaml | 3 +++ pkgs/timing/lib/src/clock.dart | 2 +- pkgs/timing/lib/src/timing.dart | 24 +++++++++---------- pkgs/timing/lib/src/timing.g.dart | 2 +- pkgs/timing/pubspec.yaml | 13 ++++++---- pkgs/timing/test/timing_test.dart | 10 ++++---- 8 files changed, 43 insertions(+), 38 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index b04d6e25a..173d3f49f 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -20,13 +20,12 @@ jobs: strategy: fail-fast: false matrix: - sdk: [dev] - version: [latest] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get @@ -48,21 +47,14 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] - version: [latest] - include: - - os: ubuntu-latest - sdk: stable - version: 2.2.0 + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: cedx/setup-dart@v2 # TODO(dart-lang/setup-dart#3): use the official setup-dart action + - uses: dart-lang/setup-dart@v1.0 with: - release-channel: ${{ matrix.sdk }} - version: ${{ matrix.version }} + sdk: ${{ matrix.sdk }} - id: install - name: Install dependencies run: pub get - name: Run VM tests - run: pub run test --platform vm + run: dart test --platform vm if: always() && steps.install.outcome == 'success' diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index c8092209a..0ceb3d793 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.0.0 + +- Enable null safety. +- Require Dart `2.12`. + ## 0.1.1+3 - Allow `package:json_annotation` `'>=1.0.0 <5.0.0'`. diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index 210b18f99..9f7e9212b 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -1,13 +1,16 @@ include: package:pedantic/analysis_options.yaml + analyzer: strong-mode: implicit-casts: false + linter: rules: - always_declare_return_types - annotate_overrides - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members + - avoid_dynamic_calls - avoid_empty_else - avoid_function_literals_in_foreach_calls - avoid_init_to_null diff --git a/pkgs/timing/lib/src/clock.dart b/pkgs/timing/lib/src/clock.dart index 2fdfc7c6b..6a9d29509 100644 --- a/pkgs/timing/lib/src/clock.dart +++ b/pkgs/timing/lib/src/clock.dart @@ -13,7 +13,7 @@ const _zoneKey = #timing_Clock; /// Returns the current [DateTime]. /// /// May be overridden for tests using [scopeClock]. -DateTime now() => (Zone.current[_zoneKey] as _Clock ?? _defaultClock)(); +DateTime now() => (Zone.current[_zoneKey] as _Clock? ?? _defaultClock)(); /// Runs [f], with [clock] scoped whenever [now] is called. T scopeClock(DateTime Function() clock, T Function() f) => diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index 17e2fb11d..013f2f741 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -12,7 +12,7 @@ part 'timing.g.dart'; /// The timings of an operation, including its [startTime], [stopTime], and /// [duration]. -@JsonSerializable(nullable: false) +@JsonSerializable() class TimeSlice { /// The total duration of this operation, equivalent to taking the difference /// between [stopTime] and [startTime]. @@ -35,7 +35,7 @@ class TimeSlice { /// The timings of an async operation, consist of several sync [slices] and /// includes total [startTime], [stopTime], and [duration]. -@JsonSerializable(nullable: false) +@JsonSerializable() class TimeSliceGroup implements TimeSlice { final List slices; @@ -96,13 +96,13 @@ abstract class TimeTracker implements TimeSlice { class SyncTimeTracker implements TimeTracker { /// When this operation started, call [_start] to set this. @override - DateTime get startTime => _startTime; - DateTime _startTime; + DateTime get startTime => _startTime!; + DateTime? _startTime; /// When this operation stopped, call [_stop] to set this. @override - DateTime get stopTime => _stopTime; - DateTime _stopTime; + DateTime get stopTime => _stopTime!; + DateTime? _stopTime; /// Start tracking this operation, must only be called once, before [_stop]. void _start() { @@ -128,7 +128,7 @@ class SyncTimeTracker implements TimeTracker { throw StateError('Can be only called while tracking'); } final _now = now(); - final prevSlice = TimeSlice(_startTime, _now); + final prevSlice = TimeSlice(_startTime!, _now); _startTime = _now; return prevSlice; } @@ -147,16 +147,16 @@ class SyncTimeTracker implements TimeTracker { } @override - bool get isStarted => startTime != null; + bool get isStarted => _startTime != null; @override - bool get isTracking => startTime != null && stopTime == null; + bool get isTracking => _startTime != null && _stopTime == null; @override - bool get isFinished => startTime != null && stopTime != null; + bool get isFinished => _startTime != null && _stopTime != null; @override - Duration get duration => stopTime?.difference(startTime); + Duration get duration => _stopTime!.difference(_startTime!); /// Converts to JSON representation /// @@ -324,7 +324,7 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { } } - bool _tracking; + bool? _tracking; @override bool get isStarted => _tracking != null; diff --git a/pkgs/timing/lib/src/timing.g.dart b/pkgs/timing/lib/src/timing.g.dart index 91293b2f8..64b64eff1 100644 --- a/pkgs/timing/lib/src/timing.g.dart +++ b/pkgs/timing/lib/src/timing.g.dart @@ -20,7 +20,7 @@ Map _$TimeSliceToJson(TimeSlice instance) => { TimeSliceGroup _$TimeSliceGroupFromJson(Map json) { return TimeSliceGroup( - (json['slices'] as List) + (json['slices'] as List) .map((e) => TimeSlice.fromJson(e as Map)) .toList(), ); diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index cbbacc836..08e24421c 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,18 +1,23 @@ name: timing -version: 0.1.1+3 +version: 1.0.0 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. repository: https://github.com/dart-lang/timing environment: - sdk: ">=2.2.0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: - json_annotation: '>=1.0.0 <5.0.0' + json_annotation: ^4.0.0 dev_dependencies: build_runner: ^1.0.0 - json_serializable: ^3.1.0 + json_serializable: ^4.0.0 pedantic: ^1.1.0 test: ^1.0.0 + +dependency_overrides: + # Remove these when they are updated to support the latest pkg:timing + build_runner: ^1.0.0 + build_runner_core: ^6.0.0 diff --git a/pkgs/timing/test/timing_test.dart b/pkgs/timing/test/timing_test.dart index 56f5f98de..610cfceb3 100644 --- a/pkgs/timing/test/timing_test.dart +++ b/pkgs/timing/test/timing_test.dart @@ -13,12 +13,12 @@ import 'package:timing/src/timing.dart'; void _noop() {} void main() { - DateTime time; + late DateTime time; final startTime = DateTime(2017); DateTime fakeClock() => time; - TimeTracker tracker; - TimeTracker nestedTracker; + late TimeTracker tracker; + late TimeTracker nestedTracker; T scopedTrack(T Function() f) => scopeClock(fakeClock, () => tracker.track(f)); @@ -222,8 +222,8 @@ void main() { }); group('AsyncTimeTracker', () { - AsyncTimeTracker asyncTracker; - AsyncTimeTracker nestedAsyncTracker; + late AsyncTimeTracker asyncTracker; + late AsyncTimeTracker nestedAsyncTracker; setUp(() { tracker = asyncTracker = AsyncTimeTracker(); nestedTracker = nestedAsyncTracker = AsyncTimeTracker(); From ecb8daf34b3db050b66e999db9c8057a63749cb6 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 15 Mar 2021 15:54:09 -0700 Subject: [PATCH 0776/1215] Drop dependency_overrides, bump CI script and SDK constraint (dart-lang/pubspec_parse#66) --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 7 +++---- pkgs/pubspec_parse/CHANGELOG.md | 2 ++ pkgs/pubspec_parse/pubspec.yaml | 11 ++--------- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index d63264526..df7aeb463 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,11 +46,10 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - # change beta to 2.12.0 when released! - sdk: [beta, dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 97c410f74..0c72a39d0 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.0.1-dev + ## 1.0.0 - Migrate to null-safety. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 4179feadf..bd9f678a8 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,11 +2,11 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.0.0 +version: 1.0.1-dev repository: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: checked_yaml: ^2.0.1 @@ -27,10 +27,3 @@ dev_dependencies: test: ^1.0.0 test_descriptor: ^2.0.0 test_process: ^2.0.0 - -dependency_overrides: - # Need to update dependencies on these packages - build_config: 0.4.6 - build_runner: any - checked_yaml: ^2.0.1 - json_annotation: 4.0.0 From f75f35190461adf932bd26fa48098bd148e96039 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 16 Mar 2021 10:17:31 -0700 Subject: [PATCH 0777/1215] latest build verify (dart-lang/pubspec_parse#67) --- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/ensure_build_test.dart | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index bd9f678a8..bd0342df3 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: dev_dependencies: build_runner: ^1.0.0 - build_verify: ^1.0.0 + build_verify: ^2.0.0 json_serializable: ^4.0.2 path: ^1.5.1 pedantic: ^1.4.0 diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index a75d1bd32..d64fa4f66 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -2,8 +2,6 @@ // 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.9 - @TestOn('vm') @Tags(['presubmit-only']) import 'package:build_verify/build_verify.dart'; From b151328b9395ea934e79b6e900228e75ea4799bb Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 19 Mar 2021 12:15:10 -0700 Subject: [PATCH 0778/1215] A bunch of general cleanup (dart-lang/term_glyph#23) Set the SDK constraint to stable Bump dependencies to stable versions drop unneeded deps Move last bit of code to null safety Update CI Enable and fix standard lints --- .../.github/workflows/test-package.yml | 6 +- pkgs/term_glyph/CHANGELOG.md | 2 + pkgs/term_glyph/analysis_options.yaml | 77 +++++++++++ .../lib/src/generated/ascii_glyph_set.dart | 2 +- .../lib/src/generated/glyph_set.dart | 4 +- .../lib/src/generated/top_level.dart | 120 +++++++++--------- .../lib/src/generated/unicode_glyph_set.dart | 2 +- pkgs/term_glyph/lib/term_glyph.dart | 6 +- pkgs/term_glyph/pubspec.yaml | 11 +- pkgs/term_glyph/tool/generate.dart | 36 +++--- 10 files changed, 170 insertions(+), 96 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 21a3c50b6..e47bf6600 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 15cbaf5cb..f2cd28f40 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.1-dev + ## 1.2.0 * Stable release for null safety. diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index 108d1058a..acbc3d01c 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1 +1,78 @@ include: package:pedantic/analysis_options.yaml + +analyzer: + strong-mode: + implicit-casts: false + +linter: + rules: + - avoid_bool_literals_in_conditional_expressions + - avoid_catching_errors + - avoid_classes_with_only_static_members + - avoid_function_literals_in_foreach_calls + - avoid_private_typedef_functions + - avoid_redundant_argument_values + - avoid_renaming_method_parameters + - avoid_returning_null + - avoid_returning_null_for_future + - avoid_returning_null_for_void + - avoid_returning_this + - avoid_single_cascade_in_expression_statements + - avoid_unused_constructor_parameters + - avoid_void_async + - await_only_futures + - camel_case_types + - cancel_subscriptions + #- cascade_invocations + - comment_references + - constant_identifier_names + - control_flow_in_finally + - directives_ordering + - empty_statements + - file_names + - hash_and_equals + - implementation_imports + - invariant_booleans + - iterable_contains_unrelated_type + - join_return_with_assignment + #- lines_longer_than_80_chars + - list_remove_unrelated_type + - literal_only_boolean_expressions + - missing_whitespace_between_adjacent_strings + - no_adjacent_strings_in_list + - no_runtimeType_toString + - non_constant_identifier_names + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_asserts_in_initializer_lists + - prefer_const_constructors + - prefer_const_declarations + - prefer_expression_function_bodies + - prefer_final_locals + - prefer_function_declarations_over_variables + - prefer_initializing_formals + - prefer_inlined_adds + - prefer_interpolation_to_compose_strings + - prefer_is_not_operator + - prefer_null_aware_operators + - prefer_relative_imports + - prefer_typing_uninitialized_variables + - prefer_void_to_null + - provide_deprecation_message + - sort_pub_dependencies + - test_types_in_equals + - throw_in_finally + - unnecessary_await_in_return + - unnecessary_brace_in_string_interps + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_null_aware_assignments + - unnecessary_overrides + - unnecessary_parenthesis + - unnecessary_statements + - unnecessary_string_interpolations + - use_string_buffers + - void_checks diff --git a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart index e0c3a4994..7c97d7f29 100644 --- a/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/ascii_glyph_set.dart @@ -10,7 +10,7 @@ import 'glyph_set.dart'; class AsciiGlyphSet implements GlyphSet { const AsciiGlyphSet(); - /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// Returns [glyph] if `this` supports Unicode glyphs and [alternative] /// otherwise. @override String glyphOrAscii(String glyph, String alternative) => alternative; diff --git a/pkgs/term_glyph/lib/src/generated/glyph_set.dart b/pkgs/term_glyph/lib/src/generated/glyph_set.dart index 941da4f00..10713b275 100644 --- a/pkgs/term_glyph/lib/src/generated/glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/glyph_set.dart @@ -7,7 +7,7 @@ /// A class that provides access to every configurable glyph. /// /// This is provided as a class so that individual chunks of code can choose -/// between [ascii] and [unicode] glyphs. For example: +/// between `ascii` and `unicode` glyphs. For example: /// /// ```dart /// import 'package:term_glyph/term_glyph.dart' as glyph; @@ -28,7 +28,7 @@ /// } /// ``` abstract class GlyphSet { - /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// Returns [glyph] if `this` supports Unicode glyphs and [alternative] /// otherwise. String glyphOrAscii(String glyph, String alternative); diff --git a/pkgs/term_glyph/lib/src/generated/top_level.dart b/pkgs/term_glyph/lib/src/generated/top_level.dart index 9475953ce..c430b33b9 100644 --- a/pkgs/term_glyph/lib/src/generated/top_level.dart +++ b/pkgs/term_glyph/lib/src/generated/top_level.dart @@ -8,7 +8,7 @@ import '../../term_glyph.dart' as glyph; /// A bullet point. /// -/// If [ascii] is `false`, this is "•". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "•". If it's `true`, this is /// "*" instead. String get bullet => glyph.glyphs.bullet; @@ -17,7 +17,7 @@ String get bullet => glyph.glyphs.bullet; /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// -/// If [ascii] is `false`, this is "←". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "←". If it's `true`, this is /// "<" instead. String get leftArrow => glyph.glyphs.leftArrow; @@ -26,355 +26,355 @@ String get leftArrow => glyph.glyphs.leftArrow; /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some /// terminal fonts, and should generally be surrounding by spaces. /// -/// If [ascii] is `false`, this is "→". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "→". If it's `true`, this is /// ">" instead. String get rightArrow => glyph.glyphs.rightArrow; /// An upwards-pointing arrow. /// -/// If [ascii] is `false`, this is "↑". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "↑". If it's `true`, this is /// "^" instead. String get upArrow => glyph.glyphs.upArrow; /// A downwards-pointing arrow. /// -/// If [ascii] is `false`, this is "↓". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "↓". If it's `true`, this is /// "v" instead. String get downArrow => glyph.glyphs.downArrow; /// A two-character left-pointing arrow. /// -/// If [ascii] is `false`, this is "◀━". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "◀━". If it's `true`, this is /// "<=" instead. String get longLeftArrow => glyph.glyphs.longLeftArrow; /// A two-character right-pointing arrow. /// -/// If [ascii] is `false`, this is "━▶". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "━▶". If it's `true`, this is /// "=>" instead. String get longRightArrow => glyph.glyphs.longRightArrow; /// A horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "─". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "─". If it's `true`, this is /// "-" instead. String get horizontalLine => glyph.glyphs.horizontalLine; /// A vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "│". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "│". If it's `true`, this is /// "|" instead. String get verticalLine => glyph.glyphs.verticalLine; /// The upper left-hand corner of a box. /// -/// If [ascii] is `false`, this is "┌". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┌". If it's `true`, this is /// "," instead. String get topLeftCorner => glyph.glyphs.topLeftCorner; /// The upper right-hand corner of a box. /// -/// If [ascii] is `false`, this is "┐". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┐". If it's `true`, this is /// "," instead. String get topRightCorner => glyph.glyphs.topRightCorner; /// The lower left-hand corner of a box. /// -/// If [ascii] is `false`, this is "└". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "└". If it's `true`, this is /// "'" instead. String get bottomLeftCorner => glyph.glyphs.bottomLeftCorner; /// The lower right-hand corner of a box. /// -/// If [ascii] is `false`, this is "┘". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┘". If it's `true`, this is /// "'" instead. String get bottomRightCorner => glyph.glyphs.bottomRightCorner; /// An intersection of vertical and horizontal box lines. /// -/// If [ascii] is `false`, this is "┼". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┼". If it's `true`, this is /// "+" instead. String get cross => glyph.glyphs.cross; /// A horizontal box line with a vertical line going up from the middle. /// -/// If [ascii] is `false`, this is "┴". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┴". If it's `true`, this is /// "+" instead. String get teeUp => glyph.glyphs.teeUp; /// A horizontal box line with a vertical line going down from the middle. /// -/// If [ascii] is `false`, this is "┬". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┬". If it's `true`, this is /// "+" instead. String get teeDown => glyph.glyphs.teeDown; /// A vertical box line with a horizontal line going left from the middle. /// -/// If [ascii] is `false`, this is "┤". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┤". If it's `true`, this is /// "+" instead. String get teeLeft => glyph.glyphs.teeLeft; /// A vertical box line with a horizontal line going right from the middle. /// -/// If [ascii] is `false`, this is "├". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "├". If it's `true`, this is /// "+" instead. String get teeRight => glyph.glyphs.teeRight; /// The top half of a vertical box line. /// -/// If [ascii] is `false`, this is "╵". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╵". If it's `true`, this is /// "'" instead. String get upEnd => glyph.glyphs.upEnd; /// The bottom half of a vertical box line. /// -/// If [ascii] is `false`, this is "╷". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╷". If it's `true`, this is /// "," instead. String get downEnd => glyph.glyphs.downEnd; /// The left half of a horizontal box line. /// -/// If [ascii] is `false`, this is "╴". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╴". If it's `true`, this is /// "-" instead. String get leftEnd => glyph.glyphs.leftEnd; /// The right half of a horizontal box line. /// -/// If [ascii] is `false`, this is "╶". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╶". If it's `true`, this is /// "-" instead. String get rightEnd => glyph.glyphs.rightEnd; /// A bold horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "━". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "━". If it's `true`, this is /// "=" instead. String get horizontalLineBold => glyph.glyphs.horizontalLineBold; /// A bold vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┃". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┃". If it's `true`, this is /// "|" instead. String get verticalLineBold => glyph.glyphs.verticalLineBold; /// The bold upper left-hand corner of a box. /// -/// If [ascii] is `false`, this is "┏". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┏". If it's `true`, this is /// "," instead. String get topLeftCornerBold => glyph.glyphs.topLeftCornerBold; /// The bold upper right-hand corner of a box. /// -/// If [ascii] is `false`, this is "┓". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┓". If it's `true`, this is /// "," instead. String get topRightCornerBold => glyph.glyphs.topRightCornerBold; /// The bold lower left-hand corner of a box. /// -/// If [ascii] is `false`, this is "┗". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┗". If it's `true`, this is /// "'" instead. String get bottomLeftCornerBold => glyph.glyphs.bottomLeftCornerBold; /// The bold lower right-hand corner of a box. /// -/// If [ascii] is `false`, this is "┛". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┛". If it's `true`, this is /// "'" instead. String get bottomRightCornerBold => glyph.glyphs.bottomRightCornerBold; /// An intersection of bold vertical and horizontal box lines. /// -/// If [ascii] is `false`, this is "╋". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╋". If it's `true`, this is /// "+" instead. String get crossBold => glyph.glyphs.crossBold; /// A bold horizontal box line with a vertical line going up from the middle. /// -/// If [ascii] is `false`, this is "┻". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┻". If it's `true`, this is /// "+" instead. String get teeUpBold => glyph.glyphs.teeUpBold; /// A bold horizontal box line with a vertical line going down from the middle. /// -/// If [ascii] is `false`, this is "┳". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┳". If it's `true`, this is /// "+" instead. String get teeDownBold => glyph.glyphs.teeDownBold; /// A bold vertical box line with a horizontal line going left from the middle. /// -/// If [ascii] is `false`, this is "┫". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┫". If it's `true`, this is /// "+" instead. String get teeLeftBold => glyph.glyphs.teeLeftBold; /// A bold vertical box line with a horizontal line going right from the middle. /// -/// If [ascii] is `false`, this is "┣". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┣". If it's `true`, this is /// "+" instead. String get teeRightBold => glyph.glyphs.teeRightBold; /// The top half of a bold vertical box line. /// -/// If [ascii] is `false`, this is "╹". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╹". If it's `true`, this is /// "'" instead. String get upEndBold => glyph.glyphs.upEndBold; /// The bottom half of a bold vertical box line. /// -/// If [ascii] is `false`, this is "╻". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╻". If it's `true`, this is /// "," instead. String get downEndBold => glyph.glyphs.downEndBold; /// The left half of a bold horizontal box line. /// -/// If [ascii] is `false`, this is "╸". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╸". If it's `true`, this is /// "-" instead. String get leftEndBold => glyph.glyphs.leftEndBold; /// The right half of a bold horizontal box line. /// -/// If [ascii] is `false`, this is "╺". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╺". If it's `true`, this is /// "-" instead. String get rightEndBold => glyph.glyphs.rightEndBold; /// A double horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "═". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "═". If it's `true`, this is /// "=" instead. String get horizontalLineDouble => glyph.glyphs.horizontalLineDouble; /// A double vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "║". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "║". If it's `true`, this is /// "|" instead. String get verticalLineDouble => glyph.glyphs.verticalLineDouble; /// The double upper left-hand corner of a box. /// -/// If [ascii] is `false`, this is "╔". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╔". If it's `true`, this is /// "," instead. String get topLeftCornerDouble => glyph.glyphs.topLeftCornerDouble; /// The double upper right-hand corner of a box. /// -/// If [ascii] is `false`, this is "╗". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╗". If it's `true`, this is /// "," instead. String get topRightCornerDouble => glyph.glyphs.topRightCornerDouble; /// The double lower left-hand corner of a box. /// -/// If [ascii] is `false`, this is "╚". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╚". If it's `true`, this is /// """ instead. String get bottomLeftCornerDouble => glyph.glyphs.bottomLeftCornerDouble; /// The double lower right-hand corner of a box. /// -/// If [ascii] is `false`, this is "╝". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╝". If it's `true`, this is /// """ instead. String get bottomRightCornerDouble => glyph.glyphs.bottomRightCornerDouble; /// An intersection of double vertical and horizontal box lines. /// -/// If [ascii] is `false`, this is "╬". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╬". If it's `true`, this is /// "+" instead. String get crossDouble => glyph.glyphs.crossDouble; /// A double horizontal box line with a vertical line going up from the middle. /// -/// If [ascii] is `false`, this is "╩". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╩". If it's `true`, this is /// "+" instead. String get teeUpDouble => glyph.glyphs.teeUpDouble; /// A double horizontal box line with a vertical line going down from the middle. /// -/// If [ascii] is `false`, this is "╦". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╦". If it's `true`, this is /// "+" instead. String get teeDownDouble => glyph.glyphs.teeDownDouble; /// A double vertical box line with a horizontal line going left from the middle. /// -/// If [ascii] is `false`, this is "╣". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╣". If it's `true`, this is /// "+" instead. String get teeLeftDouble => glyph.glyphs.teeLeftDouble; /// A double vertical box line with a horizontal line going right from the middle. /// -/// If [ascii] is `false`, this is "╠". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╠". If it's `true`, this is /// "+" instead. String get teeRightDouble => glyph.glyphs.teeRightDouble; /// A dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "╌". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╌". If it's `true`, this is /// "-" instead. String get horizontalLineDoubleDash => glyph.glyphs.horizontalLineDoubleDash; /// A bold dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "╍". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╍". If it's `true`, this is /// "-" instead. String get horizontalLineDoubleDashBold => glyph.glyphs.horizontalLineDoubleDashBold; /// A dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "╎". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╎". If it's `true`, this is /// "|" instead. String get verticalLineDoubleDash => glyph.glyphs.verticalLineDoubleDash; /// A bold dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "╏". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "╏". If it's `true`, this is /// "|" instead. String get verticalLineDoubleDashBold => glyph.glyphs.verticalLineDoubleDashBold; /// A dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┄". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┄". If it's `true`, this is /// "-" instead. String get horizontalLineTripleDash => glyph.glyphs.horizontalLineTripleDash; /// A bold dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┅". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┅". If it's `true`, this is /// "-" instead. String get horizontalLineTripleDashBold => glyph.glyphs.horizontalLineTripleDashBold; /// A dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┆". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┆". If it's `true`, this is /// "|" instead. String get verticalLineTripleDash => glyph.glyphs.verticalLineTripleDash; /// A bold dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┇". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┇". If it's `true`, this is /// "|" instead. String get verticalLineTripleDashBold => glyph.glyphs.verticalLineTripleDashBold; /// A dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┈". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┈". If it's `true`, this is /// "-" instead. String get horizontalLineQuadrupleDash => glyph.glyphs.horizontalLineQuadrupleDash; /// A bold dashed horizontal line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┉". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┉". If it's `true`, this is /// "-" instead. String get horizontalLineQuadrupleDashBold => glyph.glyphs.horizontalLineQuadrupleDashBold; /// A dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┊". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┊". If it's `true`, this is /// "|" instead. String get verticalLineQuadrupleDash => glyph.glyphs.verticalLineQuadrupleDash; /// A bold dashed vertical line that can be used to draw a box. /// -/// If [ascii] is `false`, this is "┋". If it's `true`, this is +/// If [glyph.ascii] is `false`, this is "┋". If it's `true`, this is /// "|" instead. String get verticalLineQuadrupleDashBold => glyph.glyphs.verticalLineQuadrupleDashBold; diff --git a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart index 1737b391b..1ddd165d7 100644 --- a/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/unicode_glyph_set.dart @@ -10,7 +10,7 @@ import 'glyph_set.dart'; class UnicodeGlyphSet implements GlyphSet { const UnicodeGlyphSet(); - /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// Returns [glyph] if `this` supports Unicode glyphs and [alternative] /// otherwise. @override String glyphOrAscii(String glyph, String alternative) => glyph; diff --git a/pkgs/term_glyph/lib/term_glyph.dart b/pkgs/term_glyph/lib/term_glyph.dart index b7361be6d..9f2b42293 100644 --- a/pkgs/term_glyph/lib/term_glyph.dart +++ b/pkgs/term_glyph/lib/term_glyph.dart @@ -2,13 +2,13 @@ // 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. -export 'src/generated/glyph_set.dart'; -export 'src/generated/top_level.dart'; - import 'src/generated/ascii_glyph_set.dart'; import 'src/generated/glyph_set.dart'; import 'src/generated/unicode_glyph_set.dart'; +export 'src/generated/glyph_set.dart'; +export 'src/generated/top_level.dart'; + /// A [GlyphSet] that always returns ASCII glyphs. const GlyphSet asciiGlyphs = AsciiGlyphSet(); diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 18177a356..428f76665 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,14 +1,13 @@ name: term_glyph -version: 1.2.0 +version: 1.2.1-dev description: Useful Unicode glyphs and ASCII substitutes. homepage: https://github.com/dart-lang/term_glyph environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dev_dependencies: - csv: '>=3.0.0 <5.0.0' - dart_style: '>=0.2.0 <2.0.0' - meta: ^1.3.0-nullsafety - test: ^1.16.0-nullsafety + csv: ^5.0.0 + dart_style: ^2.0.0 + test: ^1.16.0 diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 90fc2e825..007913b3a 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -1,18 +1,14 @@ // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file // 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. -// -// TODO: Remove once package:csv/csv.dart is migrated. -// @dart=2.9 import 'dart:io'; import 'package:csv/csv.dart'; -import 'package:meta/meta.dart'; void main() { - var csv = CsvCodec(eol: '\n'); - var data = csv.decoder.convert(File('data.csv').readAsStringSync()); + final csv = CsvCodec(eol: '\n'); + final data = csv.decoder.convert(File('data.csv').readAsStringSync()); // Remove comments and empty lines. data.removeWhere((row) => row.length < 3); @@ -24,7 +20,7 @@ void main() { _writeGlyphSet(data, ascii: true); _writeTopLevel(data); - var result = Process.runSync( + final result = Process.runSync( 'pub', ['run', 'dart_style:format', '-w', 'lib/src/generated']); print(result.stderr); exit(result.exitCode); @@ -32,7 +28,7 @@ void main() { /// Writes `lib/src/generated/glyph_set.dart`. void _writeGlyphSetInterface(List data) { - var file = + final file = File('lib/src/generated/glyph_set.dart').openSync(mode: FileMode.write); file.writeStringSync(r''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file @@ -44,7 +40,7 @@ void _writeGlyphSetInterface(List data) { /// A class that provides access to every configurable glyph. /// /// This is provided as a class so that individual chunks of code can choose - /// between [ascii] and [unicode] glyphs. For example: + /// between `ascii` and `unicode` glyphs. For example: /// /// ```dart /// import 'package:term_glyph/term_glyph.dart' as glyph; @@ -65,13 +61,13 @@ void _writeGlyphSetInterface(List data) { /// } /// ``` abstract class GlyphSet { - /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// Returns [glyph] if `this` supports Unicode glyphs and [alternative] /// otherwise. String glyphOrAscii(String glyph, String alternative); '''); for (var glyph in data) { - for (var line in glyph[3].split('\n')) { + for (var line in (glyph[3] as String).split('\n')) { file.writeStringSync('/// $line\n'); } @@ -86,12 +82,12 @@ void _writeGlyphSetInterface(List data) { /// /// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes /// the Unicode glyph set. -void _writeGlyphSet(List data, {@required bool ascii}) { - var file = +void _writeGlyphSet(List data, {required bool ascii}) { + final file = File('lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart') .openSync(mode: FileMode.write); - var className = '${ascii ? "Ascii" : "Unicode"}GlyphSet'; + final className = '${ascii ? "Ascii" : "Unicode"}GlyphSet'; file.writeStringSync(''' // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -104,18 +100,18 @@ void _writeGlyphSet(List data, {@required bool ascii}) { /// A [GlyphSet] that includes only ${ascii ? "ASCII" : "Unicode"} glyphs. class $className implements GlyphSet { const $className(); - /// Returns [glyph] if [this] supports Unicode glyphs and [alternative] + /// Returns [glyph] if `this` supports Unicode glyphs and [alternative] /// otherwise. @override String glyphOrAscii(String glyph, String alternative) => ${ascii ? "alternative" : "glyph"}; '''); - var index = ascii ? 2 : 1; + final index = ascii ? 2 : 1; for (var glyph in data) { file.writeStringSync(''' @override - String get ${glyph[0]} => ${_quote(glyph[index])}; + String get ${glyph[0]} => ${_quote(glyph[index] as String)}; '''); } @@ -125,7 +121,7 @@ void _writeGlyphSet(List data, {@required bool ascii}) { /// Writes `lib/src/generated/top_level.dart`. void _writeTopLevel(List data) { - var file = + final file = File('lib/src/generated/top_level.dart').openSync(mode: FileMode.write); file.writeStringSync(''' @@ -139,13 +135,13 @@ void _writeTopLevel(List data) { '''); for (var glyph in data) { - for (var line in glyph[3].split('\n')) { + for (var line in (glyph[3] as String).split('\n')) { file.writeStringSync('/// $line\n'); } file.writeStringSync(''' /// - /// If [ascii] is `false`, this is "${glyph[1]}". If it's `true`, this is + /// If [glyph.ascii] is `false`, this is "${glyph[1]}". If it's `true`, this is /// "${glyph[2]}" instead. String get ${glyph[0]} => glyph.glyphs.${glyph[0]}; '''); From 10f56b75a173789b81b47dd1048f58de568ff164 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Tue, 30 Mar 2021 17:11:46 -0700 Subject: [PATCH 0779/1215] Update LICENSE Changes to comply with open source review --- pkgs/stack_trace/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/LICENSE b/pkgs/stack_trace/LICENSE index 5c60afea3..162572a44 100644 --- a/pkgs/stack_trace/LICENSE +++ b/pkgs/stack_trace/LICENSE @@ -1,4 +1,5 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2014, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 4c0925597075481d10db9c80bef9966872781df4 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 30 Mar 2021 20:35:31 -0700 Subject: [PATCH 0780/1215] Latest setup, test on oldest supported SDK (dart-lang/watcher#110) --- pkgs/watcher/.github/workflows/test-package.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index e5e47ea27..36c2478d8 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,9 +23,9 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get @@ -46,12 +46,12 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.1 + - uses: dart-lang/setup-dart@v1.0 with: - channel: ${{ matrix.sdk }} + sdk: ${{ matrix.sdk }} - id: install name: Install dependencies run: dart pub get From 2cb754777407c53b3a608f0c87df6645d7f77592 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:12:05 -0700 Subject: [PATCH 0781/1215] Update LICENSE Changes to comply to internal review --- pkgs/stream_channel/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/LICENSE b/pkgs/stream_channel/LICENSE index de31e1a0a..dbd2843a0 100644 --- a/pkgs/stream_channel/LICENSE +++ b/pkgs/stream_channel/LICENSE @@ -1,4 +1,5 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From cc20f55a56e9c089ca3905963ecb068676df6765 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Wed, 31 Mar 2021 15:21:34 -0700 Subject: [PATCH 0782/1215] Update LICENSE (dart-lang/term_glyph#24) Changes to comply to internal review --- pkgs/term_glyph/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/LICENSE b/pkgs/term_glyph/LICENSE index 389ce9856..03af64abe 100644 --- a/pkgs/term_glyph/LICENSE +++ b/pkgs/term_glyph/LICENSE @@ -1,4 +1,5 @@ -Copyright 2017, the Dart project authors. All rights reserved. +Copyright 2017, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From cbcb9dec78d5d4b9002792f26dbc5905d7faf87e Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Thu, 1 Apr 2021 16:58:46 -0700 Subject: [PATCH 0783/1215] Update LICENSE (dart-lang/string_scanner#37) Changes to comply with internal review --- pkgs/string_scanner/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/LICENSE b/pkgs/string_scanner/LICENSE index 5c60afea3..000cd7bec 100644 --- a/pkgs/string_scanner/LICENSE +++ b/pkgs/string_scanner/LICENSE @@ -1,4 +1,5 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2014, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 8c0f82dccfa23b4f44f1dd1e8550e8a5d714dbf4 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Fri, 2 Apr 2021 15:53:43 -0700 Subject: [PATCH 0784/1215] Update LICENSE Changes to comply with internal review --- pkgs/watcher/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/LICENSE b/pkgs/watcher/LICENSE index 5c60afea3..000cd7bec 100644 --- a/pkgs/watcher/LICENSE +++ b/pkgs/watcher/LICENSE @@ -1,4 +1,5 @@ -Copyright 2014, the Dart project authors. All rights reserved. +Copyright 2014, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From a9a289f7cf6a5561ef626c7f777801fbaee4b6e2 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Fri, 2 Apr 2021 16:46:52 -0700 Subject: [PATCH 0785/1215] Update LICENSE Changes to comply with internal review --- pkgs/test_reflective_loader/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/LICENSE b/pkgs/test_reflective_loader/LICENSE index de31e1a0a..633672ab3 100644 --- a/pkgs/test_reflective_loader/LICENSE +++ b/pkgs/test_reflective_loader/LICENSE @@ -1,4 +1,5 @@ -Copyright 2015, the Dart project authors. All rights reserved. +Copyright 2015, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From d1886def5cbc059bdcd58b7baae24d7746c57d32 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Fri, 2 Apr 2021 17:09:02 -0700 Subject: [PATCH 0786/1215] Update LICENSE (dart-lang/pubspec_parse#68) Changes to comply with internal review --- pkgs/pubspec_parse/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/LICENSE b/pkgs/pubspec_parse/LICENSE index c4dc9ba3c..9972f6e70 100644 --- a/pkgs/pubspec_parse/LICENSE +++ b/pkgs/pubspec_parse/LICENSE @@ -1,4 +1,5 @@ -Copyright 2018, the Dart project authors. All rights reserved. +Copyright 2018, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 3a7b15b6132a1dbccb492c0003f22da864083af9 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Sat, 3 Apr 2021 14:31:10 -0700 Subject: [PATCH 0787/1215] Update LICENSE (dart-lang/stream_transform#130) Changes to comply with internal review --- pkgs/stream_transform/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/LICENSE b/pkgs/stream_transform/LICENSE index 389ce9856..03af64abe 100644 --- a/pkgs/stream_transform/LICENSE +++ b/pkgs/stream_transform/LICENSE @@ -1,4 +1,5 @@ -Copyright 2017, the Dart project authors. All rights reserved. +Copyright 2017, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From ccee073306758058f73adf605bc9edbb713eae9d Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Mon, 5 Apr 2021 14:10:57 -0700 Subject: [PATCH 0788/1215] Update LICENSE Changes to comply with internal review --- pkgs/timing/LICENSE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/LICENSE b/pkgs/timing/LICENSE index c4dc9ba3c..9972f6e70 100644 --- a/pkgs/timing/LICENSE +++ b/pkgs/timing/LICENSE @@ -1,4 +1,5 @@ -Copyright 2018, the Dart project authors. All rights reserved. +Copyright 2018, the Dart project authors. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -9,7 +10,7 @@ met: copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Google Inc. nor the names of its + * Neither the name of Google LLC nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. From 32489a75ac8140d6f90365d59b989e1921684a27 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Apr 2021 07:33:03 -0700 Subject: [PATCH 0789/1215] latest deps (dart-lang/pubspec_parse#69) --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index bd0342df3..469e0046f 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -22,7 +22,7 @@ dev_dependencies: path: ^1.5.1 pedantic: ^1.4.0 # Needed because we are configuring `combining_builder` - source_gen: ^0.9.5 + source_gen: ^1.0.0 stack_trace: ^1.9.2 test: ^1.0.0 test_descriptor: ^2.0.0 From d71db5ef0efc170888f7bbb2fc26c9395927bf8d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 25 Apr 2021 17:04:10 -0700 Subject: [PATCH 0790/1215] fix lints --- pkgs/term_glyph/test/symbol_test.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/term_glyph/test/symbol_test.dart b/pkgs/term_glyph/test/symbol_test.dart index 22993a737..b3b4d0937 100644 --- a/pkgs/term_glyph/test/symbol_test.dart +++ b/pkgs/term_glyph/test/symbol_test.dart @@ -2,9 +2,8 @@ // 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. -import 'package:test/test.dart'; - import 'package:term_glyph/term_glyph.dart' as glyph; +import 'package:test/test.dart'; void main() { group('with ascii = false', () { From d486804e89f54ab099a787a56752d1f3bccb9577 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 26 Apr 2021 08:34:23 -0700 Subject: [PATCH 0791/1215] Fix newly enforced lint (dart-lang/stream_transform#131) --- pkgs/stream_transform/test/async_map_buffer_test.dart | 3 +-- pkgs/stream_transform/test/async_map_sample_test.dart | 3 +-- pkgs/stream_transform/test/async_where_test.dart | 3 +-- pkgs/stream_transform/test/audit_test.dart | 2 +- pkgs/stream_transform/test/buffer_test.dart | 3 +-- pkgs/stream_transform/test/combine_latest_all_test.dart | 3 +-- pkgs/stream_transform/test/combine_latest_test.dart | 3 +-- pkgs/stream_transform/test/concurrent_async_map_test.dart | 3 +-- pkgs/stream_transform/test/debounce_test.dart | 2 +- pkgs/stream_transform/test/followd_by_test.dart | 3 +-- pkgs/stream_transform/test/from_handlers_test.dart | 3 +-- pkgs/stream_transform/test/merge_test.dart | 3 +-- pkgs/stream_transform/test/opt_out_test.dart | 3 +-- pkgs/stream_transform/test/scan_test.dart | 3 +-- pkgs/stream_transform/test/start_with_test.dart | 3 +-- pkgs/stream_transform/test/switch_test.dart | 3 +-- pkgs/stream_transform/test/take_until_test.dart | 3 +-- pkgs/stream_transform/test/tap_test.dart | 3 +-- pkgs/stream_transform/test/throttle_test.dart | 2 +- pkgs/stream_transform/test/where_type_test.dart | 3 +-- 20 files changed, 20 insertions(+), 37 deletions(-) diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index 1280b51e2..f527a0ec4 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 0d2d8464c..c32b7a79c 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index a90210caa..43f0239be 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { test('forwards only events that pass the predicate', () async { diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 20c7d9f89..e06c9629c 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -4,8 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index b528fa298..68f38479e 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/combine_latest_all_test.dart b/pkgs/stream_transform/test/combine_latest_all_test.dart index 2943449fd..f4b719c7a 100644 --- a/pkgs/stream_transform/test/combine_latest_all_test.dart +++ b/pkgs/stream_transform/test/combine_latest_all_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; Future tick() => Future(() {}); diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index 2b35e2c21..8c4b66feb 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -5,9 +5,8 @@ import 'dart:async'; import 'package:pedantic/pedantic.dart'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { group('combineLatest', () { diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index a894e7f02..c47ff8702 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index 9031db51a..38ee436ac 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -4,8 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index fbe904ab4..69b0a9933 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -3,9 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 7ae3368a7..f2f3546d3 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/src/from_handlers.dart'; +import 'package:test/test.dart'; void main() { late StreamController values; diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 24cd76b16..7217945fc 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { group('merge', () { diff --git a/pkgs/stream_transform/test/opt_out_test.dart b/pkgs/stream_transform/test/opt_out_test.dart index 8ab4fc49f..6bd654b23 100644 --- a/pkgs/stream_transform/test/opt_out_test.dart +++ b/pkgs/stream_transform/test/opt_out_test.dart @@ -7,9 +7,8 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { group('null returned from StreamSubscription.cancel', () { diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index e3effb315..aaa099ce7 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -5,9 +5,8 @@ import 'dart:async'; import 'package:pedantic/pedantic.dart'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { group('Scan', () { diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 29241beef..71758b592 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index b69c8b041..8cae7c420 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 11e906fd2..7cd30f83f 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index 79d47b4c1..a42bdc622 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { test('calls function for values', () async { diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index bbd0cfbad..52c79b59b 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -4,8 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; import 'utils.dart'; diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart index 2ea478222..03e259ab1 100644 --- a/pkgs/stream_transform/test/where_type_test.dart +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -4,9 +4,8 @@ import 'dart:async'; -import 'package:test/test.dart'; - import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; void main() { test('forwards only events that match the type', () async { From 91048ca82672239a46dfbba4a8c9a06565c1dc7f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 21 May 2021 16:27:13 -0700 Subject: [PATCH 0792/1215] bump build_runner dep dependency (dart-lang/pubspec_parse#70) --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 469e0046f..c5577b04d 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -16,7 +16,7 @@ dependencies: yaml: ^3.0.0 dev_dependencies: - build_runner: ^1.0.0 + build_runner: ^2.0.3 build_verify: ^2.0.0 json_serializable: ^4.0.2 path: ^1.5.1 From 242cca39e056cbb009a7f28bdca1d8457f811b4a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 May 2021 10:44:22 -0700 Subject: [PATCH 0793/1215] Remove unneeded imports (dart-lang/stream_channel#74) All cleanup null-safety bits from pubspec --- pkgs/stream_channel/lib/src/json_document_transformer.dart | 1 - pkgs/stream_channel/pubspec.yaml | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/lib/src/json_document_transformer.dart b/pkgs/stream_channel/lib/src/json_document_transformer.dart index 237193b86..3feda43fd 100644 --- a/pkgs/stream_channel/lib/src/json_document_transformer.dart +++ b/pkgs/stream_channel/lib/src/json_document_transformer.dart @@ -7,7 +7,6 @@ import 'dart:convert'; import 'package:async/async.dart'; import '../stream_channel.dart'; -import 'stream_channel_transformer.dart'; /// A [StreamChannelTransformer] that transforms JSON documents—strings that /// contain individual objects encoded as JSON—into decoded Dart objects. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index e7f6c7a7c..d4a717361 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -7,11 +7,11 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: '>=2.12.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + pedantic: ^1.10.0 + test: ^1.16.0 From df6fa5b00d9049372c4a0fe23ce076eb320a8f6c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 25 May 2021 19:24:31 -0700 Subject: [PATCH 0794/1215] Fix test for wrapping in error zone (dart-lang/stack_trace#109) When this test was written it had a bug - it should not pass `when: false` because that argument makes the method ignore the `errorZone` argument entirely. Omitting the argument allows the default `errorZone: true` behavior. The bug in the test was masked by the fact that `package:test` had previously run tests wrapped in a chain capturing zone by default. Remove the `when` argument to correct the test. Add an `onError` argument to the `.then` call to make the test stronger and assert that the resulting future does not complete at all - either with a value or an error. Also add the same check that the future does not complete on another test for error blocking. --- pkgs/stack_trace/CHANGELOG.md | 2 ++ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index ec80e2aae..779532810 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.10.1-dev + ## 1.10.0 * Stable release for null safety. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 721fc9613..bd4065c15 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.0 +version: 1.10.1-dev description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index bb28b792c..0931951f6 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -60,13 +60,15 @@ void main() { }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); expect(chain, isA()); - })); + })).then(expectAsync1((_) {}, count: 0), + onError: expectAsync2((_, __) {}, count: 0)); }); test('with no onError blocks errors', () { runZonedGuarded(() { - var future = Chain.capture(() => Future.error('oh no'), when: false); - future.then(expectAsync1((_) {}, count: 0)); + Chain.capture(() => Future.error('oh no')).then( + expectAsync1((_) {}, count: 0), + onError: expectAsync2((_, __) {}, count: 0)); }, expectAsync2((error, chain) { expect(error, equals('oh no')); expect(chain, isA()); From 4750598666c624a61694a1e97fe137bc119927aa Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 25 May 2021 19:28:00 -0700 Subject: [PATCH 0795/1215] Update CI (dart-lang/stack_trace#108) Co-authored-by: Nate Bosch --- pkgs/stack_trace/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 21a3c50b6..e47bf6600 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1.0 with: sdk: ${{ matrix.sdk }} - id: install From ce86c26e703c3f69e41c289b8fea22eddda7d68f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 5 Jun 2021 12:55:50 -0700 Subject: [PATCH 0796/1215] add dependabot --- pkgs/string_scanner/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/string_scanner/.github/dependabot.yml diff --git a/pkgs/string_scanner/.github/dependabot.yml b/pkgs/string_scanner/.github/dependabot.yml new file mode 100644 index 000000000..430a85e7d --- /dev/null +++ b/pkgs/string_scanner/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 74bcd128c5a00d4b220894198387e97e718f4e8c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:02:14 -0700 Subject: [PATCH 0797/1215] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/string_scanner#38) * Bump dart-lang/setup-dart from 0.3 to 1 Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * Update test-package.yml Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kevin Moore --- pkgs/string_scanner/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 0a2a87433..bd93fbed8 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From da7d979f2c3dc1d7262c5d10d0e3960bc0fbd6c5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 5 Jun 2021 12:55:29 -0700 Subject: [PATCH 0798/1215] add dependabot --- pkgs/stream_channel/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/stream_channel/.github/dependabot.yml diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml new file mode 100644 index 000000000..430a85e7d --- /dev/null +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 9ec8e84d51b9b8e893bb7a220f90a5da7a74c817 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 5 Jun 2021 13:31:06 -0700 Subject: [PATCH 0799/1215] Add dependabot --- pkgs/stream_transform/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/stream_transform/.github/dependabot.yml diff --git a/pkgs/stream_transform/.github/dependabot.yml b/pkgs/stream_transform/.github/dependabot.yml new file mode 100644 index 000000000..430a85e7d --- /dev/null +++ b/pkgs/stream_transform/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 2c5c7e9b563e3013b30d63fc6ff257f551dd8b97 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:41:09 -0700 Subject: [PATCH 0800/1215] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/stream_channel#75) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kevin Moore --- pkgs/stream_channel/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 0a2a87433..bd93fbed8 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From ef2074e675e1c8c89f1a4eeef5bf3988585d2202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:42:48 -0700 Subject: [PATCH 0801/1215] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/stream_transform#133) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kevin Moore --- pkgs/stream_transform/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index b781a90c8..84369c1f8 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From 3f712859c53dff4faf70edde6d54a0a6575941d9 Mon Sep 17 00:00:00 2001 From: Nikita Mishkov Date: Tue, 15 Jun 2021 01:08:50 +0300 Subject: [PATCH 0802/1215] changed "< 0" to ".isNegative" (dart-lang/string_scanner#39) --- pkgs/string_scanner/lib/src/string_scanner.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index 5d69c7565..d254b044b 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -22,7 +22,7 @@ class StringScanner { /// The current position of the scanner in the string, in characters. int get position => _position; set position(int position) { - if (position < 0 || position > string.length) { + if (position.isNegative || position > string.length) { throw ArgumentError('Invalid position $position'); } From fbeb8df59ff12d3232d7910d75a2dec23f69e44e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Jul 2021 15:03:36 -0700 Subject: [PATCH 0803/1215] Dart format with latest SDK (dart-lang/stream_transform#134) --- .../test/async_map_buffer_test.dart | 4 ++- .../test/async_map_sample_test.dart | 4 ++- .../test/async_where_test.dart | 10 ++++-- pkgs/stream_transform/test/audit_test.dart | 8 +++-- pkgs/stream_transform/test/buffer_test.dart | 28 +++++++++++---- .../test/combine_latest_test.dart | 4 ++- .../test/concurrent_async_expand_test.dart | 16 ++++++--- .../test/concurrent_async_map_test.dart | 5 ++- pkgs/stream_transform/test/debounce_test.dart | 35 ++++++++++++++----- .../test/followd_by_test.dart | 8 +++-- .../test/from_handlers_test.dart | 12 +++++-- pkgs/stream_transform/test/scan_test.dart | 4 ++- .../test/start_with_test.dart | 24 +++++++++---- pkgs/stream_transform/test/switch_test.dart | 8 +++-- .../test/take_until_test.dart | 8 +++-- pkgs/stream_transform/test/throttle_test.dart | 21 ++++++++--- .../test/where_type_test.dart | 14 ++++++-- 17 files changed, 161 insertions(+), 52 deletions(-) diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index f527a0ec4..b43c617cf 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -71,7 +71,9 @@ void main() { test('buffers values while work is ongoing', () async { values.add(1); await Future(() {}); - values..add(2)..add(3); + values + ..add(2) + ..add(3); await Future(() {}); finishWork!.complete(''); await Future(() {}); diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index c32b7a79c..6cab7d085 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -71,7 +71,9 @@ void main() { test('buffers values while work is ongoing', () async { values.add(1); await Future(() {}); - values..add(2)..add(3); + values + ..add(2) + ..add(3); await Future(() {}); finishWork!.complete(''); await Future(() {}); diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 43f0239be..3a13a389f 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -39,8 +39,14 @@ void main() { var filtered = values.stream.asyncWhere((e) async => e > 2); var firstValues = []; var secondValues = []; - filtered..listen(firstValues.add)..listen(secondValues.add); - values..add(1)..add(2)..add(3)..add(4); + filtered + ..listen(firstValues.add) + ..listen(secondValues.add); + values + ..add(1) + ..add(2) + ..add(3) + ..add(4); await Future(() {}); expect(firstValues, [3, 4]); expect(secondValues, [3, 4]); diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index e06c9629c..cc8f08a9e 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -43,7 +43,9 @@ void main() { }); test('swallows values that come faster than duration', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [2]); @@ -90,7 +92,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 68f38479e..fc17f4ba3 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -77,9 +77,13 @@ void main() { }); test('two triggers in a row - emit then emit next value', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); - trigger..add(null)..add(null); + trigger + ..add(null) + ..add(null); await Future(() {}); values.add(3); await Future(() {}); @@ -92,7 +96,9 @@ void main() { test('pre-emptive trigger then trigger after values', () async { trigger.add(null); await Future(() {}); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); trigger.add(null); await Future(() {}); @@ -103,9 +109,13 @@ void main() { }); test('multiple pre-emptive triggers, only emits first value', () async { - trigger..add(null)..add(null); + trigger + ..add(null) + ..add(null); await Future(() {}); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [ [1] @@ -113,10 +123,14 @@ void main() { }); test('groups values between trigger', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); trigger.add(null); - values..add(3)..add(4); + values + ..add(3) + ..add(4); await Future(() {}); trigger.add(null); await Future(() {}); diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index 8c4b66feb..a463bce2b 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -50,7 +50,9 @@ void main() { .combineLatest(other.stream, times) .forEach(results.add)); - source..add('a')..add('b'); + source + ..add('a') + ..add('b'); await Future(() {}); expect(results, isEmpty); diff --git a/pkgs/stream_transform/test/concurrent_async_expand_test.dart b/pkgs/stream_transform/test/concurrent_async_expand_test.dart index d0b4ad457..379416567 100644 --- a/pkgs/stream_transform/test/concurrent_async_expand_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_expand_test.dart @@ -61,7 +61,9 @@ void main() { }); test('interleaves events from sub streams', () async { - outerController..add(1)..add(2); + outerController + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, isEmpty); expect(innerControllers, hasLength(2)); @@ -79,7 +81,9 @@ void main() { }); test('forwards errors from inner streams', () async { - outerController..add(1)..add(2); + outerController + ..add(1) + ..add(2); await Future(() {}); innerControllers[0].addError('Error 1'); innerControllers[1].addError('Error 2'); @@ -108,7 +112,9 @@ void main() { // A single subscription inner stream in a broadcast outer stream is // not canceled. test('cancels inner subscriptions if output canceled', () async { - outerController..add(1)..add(2); + outerController + ..add(1) + ..add(2); await Future(() {}); await subscription.cancel(); expect(innerCanceled, [true, true]); @@ -164,7 +170,9 @@ void main() { }); test('can cancel and relisten', () async { - outerController..add(1)..add(2); + outerController + ..add(1) + ..add(2); await Future(() {}); innerControllers[0].add('First'); innerControllers[1].add('Second'); diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index c47ff8702..3c46a9657 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -59,7 +59,10 @@ void main() { }); test('allows calls to convert before the last one finished', () async { - controller..add(1)..add(2)..add(3); + controller + ..add(1) + ..add(2) + ..add(3); await Future(() {}); expect(values, [1, 2, 3]); }); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index 38ee436ac..f9c97ebe4 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -43,7 +43,9 @@ void main() { }); test('swallows values that come faster than duration', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [2]); @@ -80,7 +82,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await waitForTimer(5); expect(emittedValues, [2]); expect(otherValues, [2]); @@ -106,7 +110,9 @@ void main() { }); test('swallows values that come faster than duration', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); expect(emittedValues, [1]); }); @@ -123,7 +129,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await waitForTimer(5); expect(emittedValues, [1]); expect(otherValues, [1]); @@ -152,7 +160,10 @@ void main() { }); test('swallows values that come faster than duration', () async { - values..add(1)..add(2)..add(3); + values + ..add(1) + ..add(2) + ..add(3); await values.close(); await waitForTimer(5); expect(emittedValues, [1, 3]); @@ -170,7 +181,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await waitForTimer(5); expect(emittedValues, [1, 2]); expect(otherValues, [1, 2]); @@ -190,11 +203,13 @@ void main() { errors = []; transformed = values.stream .debounceBuffer(const Duration(milliseconds: 5)) - ..listen(emittedValues.add, onError: errors.add); + ..listen(emittedValues.add, onError: errors.add); }); test('Emits all values as a list', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [ @@ -218,7 +233,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await waitForTimer(5); expect(emittedValues, [ [1, 2] diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 69b0a9933..436d61380 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -50,10 +50,14 @@ void main() { }); test('adds all values from both streams', () async { - first..add(1)..add(2); + first + ..add(1) + ..add(2); await first.close(); await Future(() {}); - second..add(3)..add(4); + second + ..add(3) + ..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index f2f3546d3..4e9134f1d 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -44,7 +44,9 @@ void main() { }); test('forwards values', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [1, 2]); }); @@ -89,7 +91,9 @@ void main() { }); test('forwards values', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [1, 2]); expect(emittedValues2, [1, 2]); @@ -127,7 +131,9 @@ void main() { })); }); test('uses transform from handleData', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [2, 3]); }); diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index aaa099ce7..49bb8b8c7 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -78,7 +78,9 @@ void main() { unawaited(source.stream.scan(0, combine).forEach(results.add)); - source..add(1)..add(2); + source + ..add(1) + ..add(2); await Future(() {}); expect(calledWith, [1]); expect(results, isEmpty); diff --git a/pkgs/stream_transform/test/start_with_test.dart b/pkgs/stream_transform/test/start_with_test.dart index 71758b592..35f03308e 100644 --- a/pkgs/stream_transform/test/start_with_test.dart +++ b/pkgs/stream_transform/test/start_with_test.dart @@ -32,7 +32,9 @@ void main() { setUp(() => setupForStreamType(streamType, (s) => s.startWith(1))); test('outputs all values', () async { - values..add(2)..add(3); + values + ..add(2) + ..add(3); await Future(() {}); expect(emittedValues, [1, 2, 3]); }); @@ -70,7 +72,9 @@ void main() { }); test('outputs all values', () async { - values..add(3)..add(4); + values + ..add(3) + ..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -109,9 +113,13 @@ void main() { }); test('outputs all values', () async { - starting..add(1)..add(2); + starting + ..add(1) + ..add(2); await starting.close(); - values..add(3)..add(4); + values + ..add(3) + ..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); @@ -132,13 +140,17 @@ void main() { subscription = transformed.listen(emittedValues.add); starting.add(2); await starting.close(); - values..add(3)..add(4); + values + ..add(3) + ..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); }); test('can cancel and relisten during values', () async { - starting..add(1)..add(2); + starting + ..add(1) + ..add(2); await starting.close(); values.add(3); await Future(() {}); diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 8cae7c420..e35cb0ace 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -49,12 +49,16 @@ void main() { test('forwards events', () async { outer.add(first.stream); await Future(() {}); - first..add(1)..add(2); + first + ..add(1) + ..add(2); await Future(() {}); outer.add(second.stream); await Future(() {}); - second..add(3)..add(4); + second + ..add(3) + ..add(4); await Future(() {}); expect(emittedValues, [1, 2, 3, 4]); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 7cd30f83f..fe6ed1d8d 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -44,7 +44,9 @@ void main() { }); test('lets values through before trigger', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [1, 2]); }); @@ -76,7 +78,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [1, 2]); expect(otherValues, [1, 2]); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 52c79b59b..22bf5b3fc 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -40,7 +40,9 @@ void main() { }); test('swallows values that come faster than duration', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [1]); @@ -91,14 +93,19 @@ void main() { }); test('emits both first and last in a period', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await waitForTimer(5); expect(emittedValues, [1, 2]); }); test('swallows values that are not the latest in a period', () async { - values..add(1)..add(2)..add(3); + values + ..add(1) + ..add(2) + ..add(3); await values.close(); await waitForTimer(5); expect(emittedValues, [1, 3]); @@ -106,7 +113,9 @@ void main() { test('waits to output the last value even if the stream closes', () async { - values..add(1)..add(2); + values + ..add(1) + ..add(2); await values.close(); await Future(() {}); expect(isDone, false); @@ -128,7 +137,9 @@ void main() { test('multiple listeners all get values', () async { var otherValues = []; transformed.listen(otherValues.add); - values..add(1)..add(2); + values + ..add(1) + ..add(2); await Future(() {}); expect(emittedValues, [1]); expect(otherValues, [1]); diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart index 03e259ab1..1a65dd6ac 100644 --- a/pkgs/stream_transform/test/where_type_test.dart +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -25,8 +25,14 @@ void main() { var filtered = values.stream.whereType(); var firstValues = []; var secondValues = []; - filtered..listen(firstValues.add)..listen(secondValues.add); - values..add(1)..add('a')..add(2)..add('b'); + filtered + ..listen(firstValues.add) + ..listen(secondValues.add); + values + ..add(1) + ..add('a') + ..add(2) + ..add('b'); await Future(() {}); expect(firstValues, ['a', 'b']); expect(secondValues, ['a', 'b']); @@ -40,7 +46,9 @@ void main() { filtered ..listen(null, onDone: () => firstDone = true) ..listen(null, onDone: () => secondDone = true); - values..add(1)..add('a'); + values + ..add(1) + ..add('a'); await values.close(); expect(firstDone, true); expect(secondDone, true); From 10424b0d7df9d8f7f5aa304732e1e6409373143f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 15 Jul 2021 10:30:10 -0700 Subject: [PATCH 0804/1215] use latest deps, drop dep overrides (dart-lang/timing#18) --- pkgs/timing/lib/src/timing.g.dart | 23 ++++++++++------------- pkgs/timing/pubspec.yaml | 9 ++------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/pkgs/timing/lib/src/timing.g.dart b/pkgs/timing/lib/src/timing.g.dart index 64b64eff1..679c082ff 100644 --- a/pkgs/timing/lib/src/timing.g.dart +++ b/pkgs/timing/lib/src/timing.g.dart @@ -6,25 +6,22 @@ part of 'timing.dart'; // JsonSerializableGenerator // ************************************************************************** -TimeSlice _$TimeSliceFromJson(Map json) { - return TimeSlice( - DateTime.parse(json['startTime'] as String), - DateTime.parse(json['stopTime'] as String), - ); -} +TimeSlice _$TimeSliceFromJson(Map json) => TimeSlice( + DateTime.parse(json['startTime'] as String), + DateTime.parse(json['stopTime'] as String), + ); Map _$TimeSliceToJson(TimeSlice instance) => { 'startTime': instance.startTime.toIso8601String(), 'stopTime': instance.stopTime.toIso8601String(), }; -TimeSliceGroup _$TimeSliceGroupFromJson(Map json) { - return TimeSliceGroup( - (json['slices'] as List) - .map((e) => TimeSlice.fromJson(e as Map)) - .toList(), - ); -} +TimeSliceGroup _$TimeSliceGroupFromJson(Map json) => + TimeSliceGroup( + (json['slices'] as List) + .map((e) => TimeSlice.fromJson(e as Map)) + .toList(), + ); Map _$TimeSliceGroupToJson(TimeSliceGroup instance) => { diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 08e24421c..16588b9b1 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -12,12 +12,7 @@ dependencies: json_annotation: ^4.0.0 dev_dependencies: - build_runner: ^1.0.0 - json_serializable: ^4.0.0 + build_runner: ^2.0.0 + json_serializable: ^5.0.0 pedantic: ^1.1.0 test: ^1.0.0 - -dependency_overrides: - # Remove these when they are updated to support the latest pkg:timing - build_runner: ^1.0.0 - build_runner_core: ^6.0.0 From 7e3a9d88082eaf49e8208b2d60ac5f8985c09b30 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 15 Jul 2021 17:45:01 -0700 Subject: [PATCH 0805/1215] Update CI (dart-lang/timing#19) --- pkgs/timing/.github/workflows/test-package.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 173d3f49f..763cf3203 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -27,13 +27,10 @@ jobs: with: sdk: ${{ matrix.sdk }} - id: install - name: Install dependencies run: dart pub get - - name: Check formatting - run: dart format --output=none --set-exit-if-changed . + - run: dart format --output=none --set-exit-if-changed . if: always() && steps.install.outcome == 'success' - - name: Analyze code - run: dart analyze --fatal-infos + - run: dart analyze --fatal-infos if: always() && steps.install.outcome == 'success' # Run tests on a matrix consisting of two dimensions: @@ -54,7 +51,6 @@ jobs: with: sdk: ${{ matrix.sdk }} - id: install - run: pub get - - name: Run VM tests - run: dart test --platform vm + run: dart pub get + - run: dart test --platform vm if: always() && steps.install.outcome == 'success' From fbe7e40c89119c69a010a51c6c5063d41def859e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 23 Jul 2021 11:22:41 -0700 Subject: [PATCH 0806/1215] Fix hosted uri test (dart-lang/pubspec_parse#71) --- pkgs/pubspec_parse/test/dependency_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index c6f2dc50b..9ccd61434 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -109,11 +109,11 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v test('map w/ version and hosted as Map', () { final dep = _dependency({ 'version': '^1.0.0', - 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} + 'hosted': {'name': 'hosted_name', 'url': 'https://hosted_url'} }); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted!.name, 'hosted_name'); - expect(dep.hosted!.url.toString(), 'hosted_url'); + expect(dep.hosted!.url.toString(), 'https://hosted_url'); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); From e58f0ca25b3bad89f7b28a3099cbd88e9bff3181 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 23 Jul 2021 12:26:50 -0700 Subject: [PATCH 0807/1215] Bump dependency on json_serializable (dart-lang/pubspec_parse#72) --- pkgs/pubspec_parse/build.yaml | 4 +- pkgs/pubspec_parse/lib/src/dependency.dart | 2 +- pkgs/pubspec_parse/lib/src/dependency.g.dart | 97 +++++++++++--------- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 83 ++++++++--------- pkgs/pubspec_parse/pubspec.yaml | 4 +- 5 files changed, 102 insertions(+), 88 deletions(-) diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index 3e642b8f1..ddec84e33 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -19,5 +19,5 @@ targets: options: ignore_for_file: - deprecated_member_use_from_same_package - - lines_longer_than_80_chars - - prefer_expression_function_bodies + # https://github.com/google/json_serializable.dart/issues/945 + - unnecessary_cast diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index e4996c58e..20e7eb642 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -207,7 +207,7 @@ class HostedDetails { HostedDetails(this.name, this.url); - factory HostedDetails.fromJson(Object? data) { + factory HostedDetails.fromJson(Object data) { if (data is String) { data = {'name': data}; } diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 95b177993..b91756320 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, prefer_expression_function_bodies +// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_cast part of 'dependency.dart'; @@ -8,51 +8,64 @@ part of 'dependency.dart'; // JsonSerializableGenerator // ************************************************************************** -SdkDependency _$SdkDependencyFromJson(Map json) { - return $checkedNew('SdkDependency', json, () { - final val = SdkDependency( - $checkedConvert(json, 'sdk', (v) => v as String), - version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String?)), +SdkDependency _$SdkDependencyFromJson(Map json) => $checkedCreate( + 'SdkDependency', + json, + ($checkedConvert) { + final val = SdkDependency( + $checkedConvert('sdk', (v) => v as String), + version: $checkedConvert( + 'version', (v) => _constraintFromString(v as String?)), + ); + return val; + }, ); - return val; - }); -} -GitDependency _$GitDependencyFromJson(Map json) { - return $checkedNew('GitDependency', json, () { - final val = GitDependency( - $checkedConvert(json, 'url', (v) => parseGitUri(v as String)), - ref: $checkedConvert(json, 'ref', (v) => v as String?), - path: $checkedConvert(json, 'path', (v) => v as String?), +GitDependency _$GitDependencyFromJson(Map json) => $checkedCreate( + 'GitDependency', + json, + ($checkedConvert) { + final val = GitDependency( + $checkedConvert('url', (v) => parseGitUri(v as String)), + ref: $checkedConvert('ref', (v) => v as String?), + path: $checkedConvert('path', (v) => v as String?), + ); + return val; + }, ); - return val; - }); -} -HostedDependency _$HostedDependencyFromJson(Map json) { - return $checkedNew('HostedDependency', json, () { - $checkKeys(json, - allowedKeys: const ['version', 'hosted'], - disallowNullValues: const ['hosted']); - final val = HostedDependency( - version: $checkedConvert( - json, 'version', (v) => _constraintFromString(v as String?)), - hosted: $checkedConvert(json, 'hosted', - (v) => v == null ? null : HostedDetails.fromJson(v as Object)), +HostedDependency _$HostedDependencyFromJson(Map json) => $checkedCreate( + 'HostedDependency', + json, + ($checkedConvert) { + $checkKeys( + json, + allowedKeys: const ['version', 'hosted'], + disallowNullValues: const ['hosted'], + ); + final val = HostedDependency( + version: $checkedConvert( + 'version', (v) => _constraintFromString(v as String?)), + hosted: $checkedConvert('hosted', + (v) => v == null ? null : HostedDetails.fromJson(v as Object)), + ); + return val; + }, ); - return val; - }); -} -HostedDetails _$HostedDetailsFromJson(Map json) { - return $checkedNew('HostedDetails', json, () { - $checkKeys(json, - allowedKeys: const ['name', 'url'], disallowNullValues: const ['url']); - final val = HostedDetails( - $checkedConvert(json, 'name', (v) => v as String), - $checkedConvert(json, 'url', (v) => parseGitUriOrNull(v as String?)), +HostedDetails _$HostedDetailsFromJson(Map json) => $checkedCreate( + 'HostedDetails', + json, + ($checkedConvert) { + $checkKeys( + json, + allowedKeys: const ['name', 'url'], + disallowNullValues: const ['url'], + ); + final val = HostedDetails( + $checkedConvert('name', (v) => v as String), + $checkedConvert('url', (v) => parseGitUriOrNull(v as String?)), + ); + return val; + }, ); - return val; - }); -} diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 72ed2a264..0231c97fa 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, prefer_expression_function_bodies +// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_cast part of 'pubspec.dart'; @@ -8,44 +8,45 @@ part of 'pubspec.dart'; // JsonSerializableGenerator // ************************************************************************** -Pubspec _$PubspecFromJson(Map json) { - return $checkedNew('Pubspec', json, () { - final val = Pubspec( - $checkedConvert(json, 'name', (v) => v as String), - version: $checkedConvert( - json, 'version', (v) => _versionFromString(v as String?)), - publishTo: $checkedConvert(json, 'publish_to', (v) => v as String?), - author: $checkedConvert(json, 'author', (v) => v as String?), - authors: $checkedConvert(json, 'authors', - (v) => (v as List?)?.map((e) => e as String).toList()), - environment: $checkedConvert( - json, 'environment', (v) => _environmentMap(v as Map?)), - homepage: $checkedConvert(json, 'homepage', (v) => v as String?), - repository: $checkedConvert( - json, 'repository', (v) => v == null ? null : Uri.parse(v as String)), - issueTracker: $checkedConvert(json, 'issue_tracker', - (v) => v == null ? null : Uri.parse(v as String)), - documentation: - $checkedConvert(json, 'documentation', (v) => v as String?), - description: $checkedConvert(json, 'description', (v) => v as String?), - dependencies: - $checkedConvert(json, 'dependencies', (v) => parseDeps(v as Map?)), - devDependencies: $checkedConvert( - json, 'dev_dependencies', (v) => parseDeps(v as Map?)), - dependencyOverrides: $checkedConvert( - json, 'dependency_overrides', (v) => parseDeps(v as Map?)), - flutter: $checkedConvert( - json, - 'flutter', - (v) => (v as Map?)?.map( - (k, e) => MapEntry(k as String, e), - )), +Pubspec _$PubspecFromJson(Map json) => $checkedCreate( + 'Pubspec', + json, + ($checkedConvert) { + final val = Pubspec( + $checkedConvert('name', (v) => v as String), + version: $checkedConvert( + 'version', (v) => _versionFromString(v as String?)), + publishTo: $checkedConvert('publish_to', (v) => v as String?), + author: $checkedConvert('author', (v) => v as String?), + authors: $checkedConvert('authors', + (v) => (v as List?)?.map((e) => e as String).toList()), + environment: + $checkedConvert('environment', (v) => _environmentMap(v as Map?)), + homepage: $checkedConvert('homepage', (v) => v as String?), + repository: $checkedConvert( + 'repository', (v) => v == null ? null : Uri.parse(v as String)), + issueTracker: $checkedConvert('issue_tracker', + (v) => v == null ? null : Uri.parse(v as String)), + documentation: $checkedConvert('documentation', (v) => v as String?), + description: $checkedConvert('description', (v) => v as String?), + dependencies: + $checkedConvert('dependencies', (v) => parseDeps(v as Map?)), + devDependencies: + $checkedConvert('dev_dependencies', (v) => parseDeps(v as Map?)), + dependencyOverrides: $checkedConvert( + 'dependency_overrides', (v) => parseDeps(v as Map?)), + flutter: $checkedConvert( + 'flutter', + (v) => (v as Map?)?.map( + (k, e) => MapEntry(k as String, e), + )), + ); + return val; + }, + fieldKeyMap: const { + 'publishTo': 'publish_to', + 'issueTracker': 'issue_tracker', + 'devDependencies': 'dev_dependencies', + 'dependencyOverrides': 'dependency_overrides' + }, ); - return val; - }, fieldKeyMap: const { - 'publishTo': 'publish_to', - 'issueTracker': 'issue_tracker', - 'devDependencies': 'dev_dependencies', - 'dependencyOverrides': 'dependency_overrides' - }); -} diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index c5577b04d..3ca66711e 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -11,14 +11,14 @@ environment: dependencies: checked_yaml: ^2.0.1 collection: ^1.15.0 - json_annotation: ^4.0.0 + json_annotation: ^4.1.0 pub_semver: ^2.0.0 yaml: ^3.0.0 dev_dependencies: build_runner: ^2.0.3 build_verify: ^2.0.0 - json_serializable: ^4.0.2 + json_serializable: ^5.0.0 path: ^1.5.1 pedantic: ^1.4.0 # Needed because we are configuring `combining_builder` From a8d719c87ff167fba3dd01e00be95886e5078ba2 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Tue, 3 Aug 2021 19:20:17 +0200 Subject: [PATCH 0808/1215] Wait for cancel before next listen in switchLatest (dart-lang/stream_transform#137) If a stream is performing resource cleanup on cancel it may be a problem to listen to the next stream and start consuming resources before the cleanup is done. Propagate errors during the cancel to the result stream. --- pkgs/stream_transform/CHANGELOG.md | 5 ++ pkgs/stream_transform/lib/src/switch.dart | 77 ++++++++++++++++----- pkgs/stream_transform/pubspec.yaml | 4 +- pkgs/stream_transform/test/switch_test.dart | 65 +++++++++++++++++ 4 files changed, 131 insertions(+), 20 deletions(-) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 5a59f6f94..e1ea482da 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,8 @@ +## 2.0.1-dev + +- Wait for the future returned from `StreamSubscription.cancel()` before + listening to the subsequent stream in `switchLatest` and `switchMap`. + ## 2.0.0 - Migrate to null safety. diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 17fbb811d..53a839488 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -47,11 +47,12 @@ extension Switch on Stream { extension SwitchLatest on Stream> { /// Emits values from the most recently emitted Stream. /// - /// When the source emits a stream the output will switch to emitting events + /// When the source emits a stream, the output will switch to emitting events /// from that stream. /// - /// If the source stream is a broadcast stream, the result stream will be as - /// well, regardless of the types of streams emitted. + /// Whether the source stream is a single-subscription stream or a + /// broadcast stream, the result stream will be the same kind of stream, + /// regardless of the types of streams emitted. Stream switchLatest() { var controller = isBroadcast ? StreamController.broadcast(sync: true) @@ -61,20 +62,56 @@ extension SwitchLatest on Stream> { StreamSubscription? innerSubscription; var outerStreamDone = false; - final outerSubscription = listen( - (innerStream) { - innerSubscription?.cancel(); - innerSubscription = innerStream.listen(controller.add, - onError: controller.addError, onDone: () { - innerSubscription = null; - if (outerStreamDone) controller.close(); + void listenToInnerStream(Stream innerStream) { + assert(innerSubscription == null); + var subscription = innerStream + .listen(controller.add, onError: controller.addError, onDone: () { + innerSubscription = null; + if (outerStreamDone) controller.close(); + }); + // If a pause happens during an innerSubscription.cancel, + // we still listen to the next stream when the cancel is done. + // Then we immediately pause it again here. + if (controller.isPaused) subscription.pause(); + innerSubscription = subscription; + } + + var addError = controller.addError; + final outerSubscription = listen(null, onError: addError, onDone: () { + outerStreamDone = true; + if (innerSubscription == null) controller.close(); + }); + outerSubscription.onData((innerStream) { + var currentSubscription = innerSubscription; + if (currentSubscription != null) { + innerSubscription = null; + try { + currentSubscription.cancel().catchError(addError).whenComplete(() { + if (!isBroadcast && !controller.hasListener) { + // Result single-subscription stream subscription was cancelled + // while waiting for previous innerStream cancel. + // + // Ensure that the last received stream is also listened to and + // cancelled, then do nothing further. + // TODO(lrn): When SDK 2.14 is available, use `.ignore()`. + innerStream + .listen(null) + .cancel() + .then(_ignore, onError: _ignore); + return; + } + outerSubscription.resume(); + listenToInnerStream(innerStream); }); - }, - onError: controller.addError, - onDone: () { - outerStreamDone = true; - if (innerSubscription == null) controller.close(); - }); + outerSubscription.pause(); + return; + } catch (error, stack) { + // The cancel call threw synchronously. + controller.addError(error, stack); + } + } + listenToInnerStream(innerStream); + }); if (!isBroadcast) { controller ..onPause = () { @@ -87,16 +124,20 @@ extension SwitchLatest on Stream> { }; } controller.onCancel = () { + var _innerSubscription = innerSubscription; var cancels = [ if (!outerStreamDone) outerSubscription.cancel(), - if (innerSubscription != null) innerSubscription!.cancel(), + if (_innerSubscription != null) _innerSubscription.cancel(), ] // Handle opt-out nulls ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; - return Future.wait(cancels).then((_) => null); + return Future.wait(cancels).then(_ignore); }; }; return controller.stream; } } + +/// Helper function to ignore future callback +void _ignore(_, [__]) {} diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 98086c539..6e90b66d6 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,10 +1,10 @@ name: stream_transform description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/stream_transform -version: 2.0.0 +version: 2.0.1-dev environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dev_dependencies: async: ^2.5.0 diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index e35cb0ace..00f196a9e 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -15,6 +15,7 @@ void main() { group('Outer type: [$outerType], Inner type: [$innerType]', () { late StreamController first; late StreamController second; + late StreamController third; late StreamController> outer; late List emittedValues; @@ -36,6 +37,7 @@ void main() { firstCanceled = true; }; second = createController(innerType); + third = createController(innerType); emittedValues = []; errors = []; isDone = false; @@ -113,6 +115,69 @@ void main() { expect(firstCanceled, true); }); + if (innerType != 'broadcast') { + test('waits for cancel before listening to subsequent stream', + () async { + var cancelWork = Completer(); + first.onCancel = () => cancelWork.future; + outer.add(first.stream); + await Future(() {}); + + var cancelDone = false; + second.onListen = expectAsync0(() { + expect(cancelDone, true); + }); + outer.add(second.stream); + await Future(() {}); + cancelWork.complete(); + cancelDone = true; + }); + + test('all streams are listened to, even while cancelling', () async { + var cancelWork = Completer(); + first.onCancel = () => cancelWork.future; + outer.add(first.stream); + await Future(() {}); + + var cancelDone = false; + second.onListen = expectAsync0(() { + expect(cancelDone, true); + }); + third.onListen = expectAsync0(() { + expect(cancelDone, true); + }); + outer + ..add(second.stream) + ..add(third.stream); + await Future(() {}); + cancelWork.complete(); + cancelDone = true; + }); + } + + if (outerType != 'broadcast' && innerType != 'broadcast') { + test('pausing while cancelling an inner stream is respected', + () async { + var cancelWork = Completer(); + first.onCancel = () => cancelWork.future; + outer.add(first.stream); + await Future(() {}); + + var cancelDone = false; + second.onListen = expectAsync0(() { + expect(cancelDone, true); + }); + outer.add(second.stream); + await Future(() {}); + subscription.pause(); + cancelWork.complete(); + cancelDone = true; + await Future(() {}); + expect(second.isPaused, true); + subscription.resume(); + }); + } + test('cancels listener on current and outer stream on cancel', () async { outer.add(first.stream); From e6972ca2acd3eee4f382aeef710b80b825e74ceb Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 27 Aug 2021 12:23:43 -0700 Subject: [PATCH 0809/1215] Ignore deprecations --- pkgs/pubspec_parse/test/test_utils.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index b66adba87..132ef647d 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.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. +// ignore: deprecated_member_use import 'dart:cli'; import 'dart:convert'; @@ -65,6 +66,7 @@ Pubspec parse( ProcResult? pubResult; if (!skipTryPub) { + // ignore: deprecated_member_use pubResult = waitFor(tryPub(encoded)); expect(pubResult, isNotNull); } From ddc0e4346cf52dc04bb7c573cb90eaa582ed3ca5 Mon Sep 17 00:00:00 2001 From: Konstantin Scheglov Date: Wed, 1 Sep 2021 14:31:11 -0600 Subject: [PATCH 0810/1215] Fix pre-existing HintCode.UNNECESSARY_TYPE_CHECK_TRUE (dart-lang/test_reflective_loader#36) --- pkgs/test_reflective_loader/lib/test_reflective_loader.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 3528a43f3..fe78b9de8 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -111,7 +111,7 @@ void defineReflectiveTests(Type type) { classMirror.instanceMembers .forEach((Symbol symbol, MethodMirror memberMirror) { // we need only methods - if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) { + if (!memberMirror.isRegularMethod) { return; } // prepare information about the method From 82dd9795f646b26355512dcc969f76dcf45205ac Mon Sep 17 00:00:00 2001 From: Evan Weible Date: Wed, 15 Sep 2021 08:59:24 -0600 Subject: [PATCH 0811/1215] Export the `HostedDetails` type (dart-lang/pubspec_parse#73) This type is used by the public `HostedDependency` type, so it too should be public. --- pkgs/pubspec_parse/CHANGELOG.md | 6 ++++-- pkgs/pubspec_parse/lib/pubspec_parse.dart | 1 + pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 0c72a39d0..98fbbbf35 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.0.1-dev +## 1.1.0 + +- Export `HostedDetails` publicly. ## 1.0.0 @@ -26,7 +28,7 @@ ## 0.1.4 -- Added `lenient` named argument to `Pubspec.fromJson` to ignore format and type errors. +- Added `lenient` named argument to `Pubspec.fromJson` to ignore format and type errors. ## 0.1.3 diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart index 132263a8a..63c1e30e4 100644 --- a/pkgs/pubspec_parse/lib/pubspec_parse.dart +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -6,6 +6,7 @@ export 'src/dependency.dart' show Dependency, HostedDependency, + HostedDetails, GitDependency, SdkDependency, PathDependency; diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 3ca66711e..afaa952d7 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.0.1-dev +version: 1.1.0 repository: https://github.com/dart-lang/pubspec_parse environment: From 94f545ce6e1dda69ab6a11bcb441219c933ae211 Mon Sep 17 00:00:00 2001 From: Jacob MacDonald Date: Thu, 30 Sep 2021 09:29:36 -0700 Subject: [PATCH 0812/1215] drop package:pedantic, use package:lints (dart-lang/watcher#120) Fixes dart-lang/watcher#119 --- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/analysis_options.yaml | 3 ++- pkgs/watcher/pubspec.yaml | 6 +++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 6b7785cc1..fd5efe3a4 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.1 + +* Drop package:pedantic and use package:lints instead. + # 1.0.0 * Stable null safety release. diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index 6eccbf845..b9b528743 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: implicit-casts: false @@ -12,6 +12,7 @@ analyzer: linter: rules: # comment_references # https://github.com/dart-lang/sdk/issues/39467 + - depend_on_referenced_packages - prefer_generic_function_type_aliases - prefer_typing_uninitialized_variables - unnecessary_const diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index bbb07a311..19e572cc3 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.0.0 +version: 1.0.1 description: >- A file system watcher. It monitors changes to contents of directories and @@ -7,14 +7,14 @@ description: >- repository: https://github.com/dart-lang/watcher environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: async: ^2.5.0 path: ^1.8.0 - pedantic: ^1.10.0 dev_dependencies: + lints: ^1.0.0 benchmark_harness: ^2.0.0 test: ^1.16.0 test_descriptor: ^2.0.0-nullsafety From 2e592b85da1dd25b402d87786b265ffa4a05aff9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 2 Oct 2021 20:59:06 -0700 Subject: [PATCH 0813/1215] Move to pkg:lints (dart-lang/term_glyph#25) --- pkgs/term_glyph/analysis_options.yaml | 2 +- pkgs/term_glyph/pubspec.yaml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index acbc3d01c..a7d6f2d46 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 428f76665..e1b26bb95 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -10,4 +10,5 @@ environment: dev_dependencies: csv: ^5.0.0 dart_style: ^2.0.0 + lints: ^1.0.0 test: ^1.16.0 From 94659c477bb5f654f288e0f566118323ec995455 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sat, 2 Oct 2021 20:59:12 -0700 Subject: [PATCH 0814/1215] Move to pkg:lints (dart-lang/string_scanner#41) --- pkgs/string_scanner/analysis_options.yaml | 2 +- pkgs/string_scanner/pubspec.yaml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 60abe63e6..c6528bb46 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 9eee52bfd..02136e394 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -5,10 +5,11 @@ description: A class for parsing strings using a sequence of patterns. homepage: https://github.com/dart-lang/string_scanner environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: source_span: ^1.8.0 dev_dependencies: - test: ^1.16.0-nullsafety + lints: ^1.0.0 + test: ^1.16.0 \ No newline at end of file From 66cf4d30a346fb858ebbe7b7deec6db026b1cfd9 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 5 Oct 2021 09:00:28 -0700 Subject: [PATCH 0815/1215] Fix lints/pedantic, require Dart 2.14 (dart-lang/watcher#122) --- pkgs/watcher/.github/workflows/test-package.yml | 2 +- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/lib/src/async_queue.dart | 1 - pkgs/watcher/lib/src/directory_watcher/mac_os.dart | 6 ++---- pkgs/watcher/lib/src/directory_watcher/windows.dart | 8 +++----- pkgs/watcher/lib/src/file_watcher/polling.dart | 2 -- pkgs/watcher/lib/src/watch_event.dart | 3 +++ pkgs/watcher/pubspec.yaml | 4 ++-- pkgs/watcher/test/no_subscription/shared.dart | 3 ++- pkgs/watcher/test/ready/shared.dart | 3 ++- pkgs/watcher/test/utils.dart | 2 +- 11 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 36c2478d8..971c6f0c5 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index fd5efe3a4..d987225e7 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.2-dev + +- Require Dart SDK >= 2.14 + # 1.0.1 * Drop package:pedantic and use package:lints instead. diff --git a/pkgs/watcher/lib/src/async_queue.dart b/pkgs/watcher/lib/src/async_queue.dart index eca28ad57..f6c76a9cb 100644 --- a/pkgs/watcher/lib/src/async_queue.dart +++ b/pkgs/watcher/lib/src/async_queue.dart @@ -66,6 +66,5 @@ class AsyncQueue { // We have drained the queue, stop processing and wait until something // has been enqueued. _isProcessing = false; - return null; } } diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 4ad94d44e..2046ce0d5 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,8 +7,8 @@ import 'dart:io'; import 'package:path/path.dart' as p; -import '../directory_watcher.dart'; import '../constructable_file_system_event.dart'; +import '../directory_watcher.dart'; import '../path_set.dart'; import '../resubscribable.dart'; import '../utils.dart'; @@ -78,9 +78,7 @@ class _MacOSDirectoryWatcher /// events (see issue 14373). late Timer _bogusEventTimer; - _MacOSDirectoryWatcher(String path) - : path = path, - _files = PathSet(path) { + _MacOSDirectoryWatcher(this.path) : _files = PathSet(path) { _startWatch(); // Before we're ready to emit events, wait for [_listDir] to complete and diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index a8200eed9..09b4b36b0 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -26,14 +26,14 @@ class WindowsDirectoryWatcher extends ResubscribableWatcher } class _EventBatcher { - static const Duration _BATCH_DELAY = Duration(milliseconds: 100); + static const Duration _batchDelay = Duration(milliseconds: 100); final List events = []; Timer? timer; void addEvent(FileSystemEvent event, void Function() callback) { events.add(event); timer?.cancel(); - timer = Timer(_BATCH_DELAY, callback); + timer = Timer(_batchDelay, callback); } void cancelTimer() { @@ -87,9 +87,7 @@ class _WindowsDirectoryWatcher final Set> _listSubscriptions = HashSet>(); - _WindowsDirectoryWatcher(String path) - : path = path, - _files = PathSet(path) { + _WindowsDirectoryWatcher(this.path) : _files = PathSet(path) { // Before we're ready to emit events, wait for [_listDir] to complete. _listDir().then((_) { _startWatch(); diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 9b9ac5be3..d0b219f36 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -5,8 +5,6 @@ import 'dart:async'; import 'dart:io'; -import 'package:pedantic/pedantic.dart'; - import '../file_watcher.dart'; import '../resubscribable.dart'; import '../stat.dart'; diff --git a/pkgs/watcher/lib/src/watch_event.dart b/pkgs/watcher/lib/src/watch_event.dart index 8b3fabb77..b65afc2bd 100644 --- a/pkgs/watcher/lib/src/watch_event.dart +++ b/pkgs/watcher/lib/src/watch_event.dart @@ -19,12 +19,15 @@ class WatchEvent { /// Enum for what kind of change has happened to a file. class ChangeType { /// A new file has been added. + // ignore: constant_identifier_names static const ADD = ChangeType('add'); /// A file has been removed. + // ignore: constant_identifier_names static const REMOVE = ChangeType('remove'); /// The contents of a file have changed. + // ignore: constant_identifier_names static const MODIFY = ChangeType('modify'); final String _name; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 19e572cc3..b4102c5cf 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.0.1 +version: 1.0.2-dev description: >- A file system watcher. It monitors changes to contents of directories and @@ -17,5 +17,5 @@ dev_dependencies: lints: ^1.0.0 benchmark_harness: ^2.0.0 test: ^1.16.0 - test_descriptor: ^2.0.0-nullsafety + test_descriptor: ^2.0.0 diff --git a/pkgs/watcher/test/no_subscription/shared.dart b/pkgs/watcher/test/no_subscription/shared.dart index bcdba5f16..e7a614454 100644 --- a/pkgs/watcher/test/no_subscription/shared.dart +++ b/pkgs/watcher/test/no_subscription/shared.dart @@ -2,8 +2,9 @@ // 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. +import 'dart:async'; + import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index ebe2f0cf4..b6b3cce08 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -2,7 +2,8 @@ // 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. -import 'package:pedantic/pedantic.dart'; +import 'dart:async'; + import 'package:test/test.dart'; import '../utils.dart'; diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index aa23d50a5..8d8981c39 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -2,11 +2,11 @@ // 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. +import 'dart:async'; import 'dart:io'; import 'package:async/async.dart'; import 'package:path/path.dart' as p; -import 'package:pedantic/pedantic.dart'; import 'package:test/test.dart'; import 'package:test_descriptor/test_descriptor.dart' as d; import 'package:watcher/src/stat.dart'; From 270c69a07458d0fecfdbab9c38826224ccc13882 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 15 Oct 2021 11:38:21 -0700 Subject: [PATCH 0816/1215] lints: migrate to pkg:lints, enable and fix two more lints --- pkgs/pubspec_parse/CHANGELOG.md | 2 + pkgs/pubspec_parse/analysis_options.yaml | 35 +--------- pkgs/pubspec_parse/build.yaml | 2 + pkgs/pubspec_parse/lib/src/dependency.dart | 19 ++++-- pkgs/pubspec_parse/lib/src/dependency.g.dart | 2 +- pkgs/pubspec_parse/lib/src/pubspec.dart | 6 +- pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 4 +- pkgs/pubspec_parse/test/dependency_test.dart | 70 +++++++++++++------- pkgs/pubspec_parse/test/git_uri_test.dart | 3 +- pkgs/pubspec_parse/test/parse_test.dart | 64 +++++++++++------- pkgs/pubspec_parse/test/pub_utils.dart | 24 ++++--- pkgs/pubspec_parse/test/test_utils.dart | 36 ++++++---- 13 files changed, 156 insertions(+), 113 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 98fbbbf35..9cc4b52f6 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.1.1-dev + ## 1.1.0 - Export `HostedDetails` publicly. diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 39be54abb..67e23cbf6 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: @@ -9,70 +9,41 @@ linter: - avoid_bool_literals_in_conditional_expressions - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_function_literals_in_foreach_calls + - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_renaming_method_parameters - avoid_returning_null - avoid_returning_null_for_future - - avoid_returning_null_for_void - avoid_returning_this - - avoid_single_cascade_in_expression_statements - avoid_unused_constructor_parameters - avoid_void_async - - await_only_futures - - camel_case_types - cancel_subscriptions - cascade_invocations - comment_references - - constant_identifier_names - - control_flow_in_finally - directives_ordering - - empty_statements - - file_names - - hash_and_equals - - implementation_imports - invariant_booleans - - iterable_contains_unrelated_type - join_return_with_assignment - lines_longer_than_80_chars - - list_remove_unrelated_type - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - non_constant_identifier_names - only_throw_errors - - overridden_fields - package_api_docs - - package_names - - package_prefixed_library_names - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_function_declarations_over_variables - - prefer_initializing_formals - - prefer_inlined_adds - prefer_interpolation_to_compose_strings - - prefer_is_not_operator - - prefer_null_aware_operators - prefer_relative_imports - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message + - require_trailing_commas - sort_pub_dependencies - test_types_in_equals - throw_in_finally - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - unnecessary_lambdas - unnecessary_null_aware_assignments - - unnecessary_overrides - unnecessary_parenthesis - unnecessary_statements - - unnecessary_string_interpolations - use_string_buffers - - void_checks diff --git a/pkgs/pubspec_parse/build.yaml b/pkgs/pubspec_parse/build.yaml index ddec84e33..2003bc29e 100644 --- a/pkgs/pubspec_parse/build.yaml +++ b/pkgs/pubspec_parse/build.yaml @@ -19,5 +19,7 @@ targets: options: ignore_for_file: - deprecated_member_use_from_same_package + - lines_longer_than_80_chars + - require_trailing_commas # https://github.com/google/json_serializable.dart/issues/945 - unnecessary_cast diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 20e7eb642..f8d3ecdc3 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -27,7 +27,11 @@ Map parseDeps(Map? source) => if (value == null) { throw CheckedFromJsonException( - source, key, 'Pubspec', 'Not a valid dependency value.'); + source, + key, + 'Pubspec', + 'Not a valid dependency value.', + ); } return MapEntry(key, value); }) ?? @@ -54,11 +58,18 @@ Dependency? _fromJson(Object? data) { return $checkedNew('Dependency', data, () { if (firstUnrecognizedKey != null) { throw UnrecognizedKeysException( - [firstUnrecognizedKey], data, _sourceKeys); + [firstUnrecognizedKey], + data, + _sourceKeys, + ); } if (matchedKeys.length > 1) { - throw CheckedFromJsonException(data, matchedKeys[1], 'Dependency', - 'A dependency may only have one source.'); + throw CheckedFromJsonException( + data, + matchedKeys[1], + 'Dependency', + 'A dependency may only have one source.', + ); } final key = matchedKeys.single; diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index b91756320..4e9d399b8 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_cast +// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, require_trailing_commas, unnecessary_cast part of 'dependency.dart'; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index b851486ec..8cc7b09c1 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -195,7 +195,11 @@ Map? _environmentMap(Map? source) => return MapEntry(key, constraint); } else { throw CheckedFromJsonException( - source, key, 'VersionConstraint', '`$value` is not a String.'); + source, + key, + 'VersionConstraint', + '`$value` is not a String.', + ); } return MapEntry(key, constraint); diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 0231c97fa..cadd38e41 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -1,6 +1,6 @@ // GENERATED CODE - DO NOT MODIFY BY HAND -// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_cast +// ignore_for_file: deprecated_member_use_from_same_package, lines_longer_than_80_chars, require_trailing_commas, unnecessary_cast part of 'pubspec.dart'; diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index afaa952d7..5e51c29ab 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.1.0 +version: 1.1.1-dev repository: https://github.com/dart-lang/pubspec_parse environment: @@ -19,8 +19,8 @@ dev_dependencies: build_runner: ^2.0.3 build_verify: ^2.0.0 json_serializable: ^5.0.0 + lints: ^1.0.0 path: ^1.5.1 - pedantic: ^1.4.0 # Needed because we are configuring `combining_builder` source_gen: ^1.0.0 stack_trace: ^1.9.2 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 9ccd61434..20053a87a 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -56,12 +56,15 @@ line 6, column 11: Unsupported value for "git". A dependency may only have one s }); test('map with unsupported keys', () { - _expectThrows({'bob': 'a', 'jones': 'b'}, r''' + _expectThrows( + {'bob': 'a', 'jones': 'b'}, + r''' line 5, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ 5 │ "bob": "a", │ ^^^^^ - ╵'''); + ╵''', + ); }); }); } @@ -133,21 +136,25 @@ line 5, column 15: Unsupported value for "version". Could not parse version "not }); test('map w/ extra keys should fail', () { - _expectThrows({ - 'version': '^1.0.0', - 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, - 'not_supported': null - }, r''' + _expectThrows( + { + 'version': '^1.0.0', + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, + 'not_supported': null + }, + r''' line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git, path, hosted] ╷ 10 │ "not_supported": null │ ^^^^^^^^^^^^^^^ - ╵'''); + ╵''', + ); }); test('map w/ version and hosted as String', () { final dep = _dependency( - {'version': '^1.0.0', 'hosted': 'hosted_name'}); + {'version': '^1.0.0', 'hosted': 'hosted_name'}, + ); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted!.name, 'hosted_name'); expect(dep.hosted!.url, isNull); @@ -192,7 +199,8 @@ void _sdkDependency() { test('with version', () { final dep = _dependency( - {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}); + {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}, + ); expect(dep.sdk, 'flutter'); expect(dep.version.toString(), '>=1.2.3 <2.0.0'); expect(dep.toString(), 'SdkDependency: flutter'); @@ -250,8 +258,10 @@ void _gitDependency() { if (skipTryParse) { print('FYI: not validating git@ URI on travis due to failure'); } - final dep = _dependency({'git': 'git@localhost:dep.git'}, - skipTryPub: skipTryParse); + final dep = _dependency( + {'git': 'git@localhost:dep.git'}, + skipTryPub: skipTryParse, + ); expect(dep.url.toString(), 'ssh://git@localhost/dep.git'); expect(dep.path, isNull); expect(dep.ref, isNull); @@ -259,12 +269,15 @@ void _gitDependency() { }); test('string with random extra key fails', () { - _expectThrows({'git': 'url', 'bob': '^1.2.3'}, r''' + _expectThrows( + {'git': 'url', 'bob': '^1.2.3'}, + r''' line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ 6 │ "bob": "^1.2.3" │ ^^^^^ - ╵'''); + ╵''', + ); }); test('map', () { @@ -365,12 +378,15 @@ void _pathDependency() { }); test('valid with random extra key fails', () { - _expectThrows({'path': '../path', 'bob': '^1.2.3'}, r''' + _expectThrows( + {'path': '../path', 'bob': '^1.2.3'}, + r''' line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hosted] ╷ 6 │ "bob": "^1.2.3" │ ^^^^^ - ╵'''); + ╵''', + ); }); test('null content', () { @@ -403,20 +419,26 @@ line 5, column 12: Unsupported value for "path". Must be a String. } void _expectThrows(Object content, String expectedError) { - expectParseThrows({ - 'name': 'sample', - 'dependencies': {'dep': content} - }, expectedError); + expectParseThrows( + { + 'name': 'sample', + 'dependencies': {'dep': content} + }, + expectedError, + ); } T _dependency( Object? content, { bool skipTryPub = false, }) { - final value = parse({ - ...defaultPubspec, - 'dependencies': {'dep': content} - }, skipTryPub: skipTryPub); + final value = parse( + { + ...defaultPubspec, + 'dependencies': {'dep': content} + }, + skipTryPub: skipTryPub, + ); expect(value.name, 'sample'); expect(value.dependencies, hasLength(1)); diff --git a/pkgs/pubspec_parse/test/git_uri_test.dart b/pkgs/pubspec_parse/test/git_uri_test.dart index 36e55a84c..be89ba8a0 100644 --- a/pkgs/pubspec_parse/test/git_uri_test.dart +++ b/pkgs/pubspec_parse/test/git_uri_test.dart @@ -16,7 +16,8 @@ void main() { final uri = parseGitUri(item.key); printOnFailure( - [uri.scheme, uri.userInfo, uri.host, uri.port, uri.path].join('\n')); + [uri.scheme, uri.userInfo, uri.host, uri.port, uri.path].join('\n'), + ); expect(uri, Uri.parse(item.value)); }); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 52df370d0..5f70de8ba 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -62,8 +62,10 @@ void main() { expect(value.devDependencies, isEmpty); expect(value.dependencyOverrides, isEmpty); expect(value.repository, Uri.parse('https://github.com/example/repo')); - expect(value.issueTracker, - Uri.parse('https://github.com/example/repo/issues')); + expect( + value.issueTracker, + Uri.parse('https://github.com/example/repo/issues'), + ); }); test('environment values can be null', () { @@ -212,12 +214,15 @@ line 1, column 1: Not a map ); }); test('array', () { - expectParseThrows([], r''' + expectParseThrows( + [], + r''' line 1, column 1: Not a map ╷ 1 │ [] │ ^^ - ╵'''); + ╵''', + ); }); test('missing name', () { @@ -257,15 +262,18 @@ line 2, column 10: Unsupported value for "name". "name" cannot be empty. }); test('"dart" is an invalid environment key', () { - expectParseThrows({ - 'name': 'sample', - 'environment': {'dart': 'cool'} - }, r''' + expectParseThrows( + { + 'name': 'sample', + 'environment': {'dart': 'cool'} + }, + r''' line 4, column 3: Use "sdk" to for Dart SDK constraints. ╷ 4 │ "dart": "cool" │ ^^^^^^ - ╵'''); + ╵''', + ); }); test('environment values cannot be int', () { @@ -298,15 +306,18 @@ line 3, column 13: Unsupported value for "version". Could not parse "invalid". }); test('invalid environment value', () { - expectParseThrows({ - 'name': 'sample', - 'environment': {'sdk': 'silly'} - }, r''' + expectParseThrows( + { + 'name': 'sample', + 'environment': {'sdk': 'silly'} + }, + r''' line 4, column 10: Unsupported value for "sdk". Could not parse version "silly". Unknown text at "silly". ╷ 4 │ "sdk": "silly" │ ^^^^^^^ - ╵'''); + ╵''', + ); }); test('bad repository url', () { @@ -426,16 +437,21 @@ line 1, column 1: Missing key "name". type 'Null' is not a subtype of type 'Stri test('deep error throws with lenient', () { expect( - () => parse({ - 'name': 'sample', - 'dependencies': { - 'foo': { - 'git': {'url': 1} - }, - }, - 'issue_tracker': {'x': 'y'}, - }, skipTryPub: true, lenient: true), - throwsException); + () => parse( + { + 'name': 'sample', + 'dependencies': { + 'foo': { + 'git': {'url': 1} + }, + }, + 'issue_tracker': {'x': 'y'}, + }, + skipTryPub: true, + lenient: true, + ), + throwsException, + ); }); }); } diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart index 17e8970f7..5871b1b9c 100644 --- a/pkgs/pubspec_parse/test/pub_utils.dart +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -23,21 +23,25 @@ Future tryPub(String content) async { final result = await ProcResult.fromTestProcess(proc); - printOnFailure([ - '-----BEGIN pub output-----', - result.toString().trim(), - '-----END pub output-----', - ].join('\n')); + printOnFailure( + [ + '-----BEGIN pub output-----', + result.toString().trim(), + '-----END pub output-----', + ].join('\n'), + ); if (result.exitCode == 0) { final lockContent = File(p.join(d.sandbox, 'pubspec.lock')).readAsStringSync(); - printOnFailure([ - '-----BEGIN pubspec.lock-----', - lockContent.trim(), - '-----END pubspec.lock-----', - ].join('\n')); + printOnFailure( + [ + '-----BEGIN pubspec.lock-----', + lockContent.trim(), + '-----END pubspec.lock-----', + ].join('\n'), + ); } return result; diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 132ef647d..72d214242 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -22,13 +22,18 @@ const defaultPubspec = { String _encodeJson(Object? input) => const JsonEncoder.withIndent(' ').convert(input); -Matcher _throwsParsedYamlException(String prettyValue) => - throwsA(const TypeMatcher().having((e) { - final message = e.formattedMessage; - printOnFailure("Actual error format:\nr'''\n$message'''"); - _printDebugParsedYamlException(e); - return message; - }, 'formattedMessage', prettyValue)); +Matcher _throwsParsedYamlException(String prettyValue) => throwsA( + const TypeMatcher().having( + (e) { + final message = e.formattedMessage; + printOnFailure("Actual error format:\nr'''\n$message'''"); + _printDebugParsedYamlException(e); + return message; + }, + 'formattedMessage', + prettyValue, + ), + ); void _printDebugParsedYamlException(ParsedYamlException e) { var innerError = e.innerError; @@ -76,18 +81,23 @@ Pubspec parse( if (pubResult != null) { addTearDown(() { - expect(pubResult!.cleanParse, isTrue, - reason: - 'On success, parsing from the pub client should also succeed.'); + expect( + pubResult!.cleanParse, + isTrue, + reason: + 'On success, parsing from the pub client should also succeed.', + ); }); } return value; } catch (e) { if (pubResult != null) { addTearDown(() { - expect(pubResult!.cleanParse, isFalse, - reason: - 'On failure, parsing from the pub client should also fail.'); + expect( + pubResult!.cleanParse, + isFalse, + reason: 'On failure, parsing from the pub client should also fail.', + ); }); } if (e is ParsedYamlException) { From 920a12be7eb1c326a0b735e4e3e3d6cd68e6060d Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 15 Oct 2021 11:45:22 -0700 Subject: [PATCH 0817/1215] Update to the latest pkg:json_serializable --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 2 ++ pkgs/pubspec_parse/pubspec.yaml | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index df7aeb463..a818a1b94 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 9cc4b52f6..2601ee4ed 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.1.1-dev +- Require Dart SDK >= 2.14.0 + ## 1.1.0 - Export `HostedDetails` publicly. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 5e51c29ab..d19201e05 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -6,19 +6,19 @@ version: 1.1.1-dev repository: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: checked_yaml: ^2.0.1 collection: ^1.15.0 - json_annotation: ^4.1.0 + json_annotation: ^4.3.0 pub_semver: ^2.0.0 yaml: ^3.0.0 dev_dependencies: build_runner: ^2.0.3 build_verify: ^2.0.0 - json_serializable: ^5.0.0 + json_serializable: ^6.0.0 lints: ^1.0.0 path: ^1.5.1 # Needed because we are configuring `combining_builder` From 94086ccad8c3ddac2397c9687a3d8a455e6568a5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 26 Oct 2021 16:35:19 -0700 Subject: [PATCH 0818/1215] Update dependencies, move to pkg:lints (dart-lang/timing#20) --- .../timing/.github/workflows/test-package.yml | 4 +- pkgs/timing/CHANGELOG.md | 4 ++ pkgs/timing/analysis_options.yaml | 62 +------------------ pkgs/timing/pubspec.yaml | 10 +-- 4 files changed, 12 insertions(+), 68 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 763cf3203..5178d2807 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 @@ -44,7 +44,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1.0 diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 0ceb3d793..b3bf18fa2 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.1-dev + +- Require Dart `2.14`. + ## 1.0.0 - Enable null safety. diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index 9f7e9212b..9f4dae73d 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: @@ -7,90 +7,30 @@ analyzer: linter: rules: - always_declare_return_types - - annotate_overrides - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - avoid_dynamic_calls - - avoid_empty_else - - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - avoid_returning_null - - avoid_returning_null_for_void - avoid_returning_this - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - cancel_subscriptions - cascade_invocations - comment_references - - constant_identifier_names - - control_flow_in_finally - - curly_braces_in_flow_control_structures - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - file_names - - hash_and_equals - - implementation_imports - invariant_booleans - - iterable_contains_unrelated_type - join_return_with_assignment - - library_names - - library_prefixes - - list_remove_unrelated_type - literal_only_boolean_expressions - - no_duplicate_case_values - - non_constant_identifier_names - - null_closures - omit_local_variable_types - only_throw_errors - - overridden_fields - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - prefer_final_locals - - prefer_generic_function_type_aliases - - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_iterable_whereType - - prefer_is_empty - - prefer_is_not_empty - - prefer_null_aware_operators - prefer_single_quotes - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - recursive_getters - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - unawaited_futures - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - - unnecessary_null_in_if_null_operators - unnecessary_parenthesis - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - use_rethrow_when_possible - - valid_regexps - - void_checks diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 16588b9b1..8c1905357 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,18 +1,18 @@ name: timing -version: 1.0.0 +version: 1.0.1-dev description: >- A simple package for tracking the performance of synchronous and asynchronous actions. repository: https://github.com/dart-lang/timing environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.14.0 <3.0.0" dependencies: - json_annotation: ^4.0.0 + json_annotation: ^4.3.0 dev_dependencies: build_runner: ^2.0.0 - json_serializable: ^5.0.0 - pedantic: ^1.1.0 + lints: ^1.0.0 + json_serializable: ^6.0.0 test: ^1.0.0 From 517e7d9703dd5b35559368188c62430cb4c8a7f5 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Thu, 4 Nov 2021 10:20:38 +0100 Subject: [PATCH 0819/1215] Match hosted shorthand syntax from Dart 2.15 (dart-lang/pubspec_parse#74) * Match hosted shorthand syntax from Dart 2.15 --- pkgs/pubspec_parse/CHANGELOG.md | 9 ++++++ pkgs/pubspec_parse/lib/src/dependency.dart | 28 ++++++++++++++---- pkgs/pubspec_parse/lib/src/dependency.g.dart | 3 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/dependency_test.dart | 30 ++++++++++++++++---- 5 files changed, 58 insertions(+), 14 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 2601ee4ed..8f2d28897 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,12 @@ +## 1.2.0-dev + +- Update `HostedDetails` to reflect how `hosted` dependencies are parsed in + Dart 2.15: + - Add `HostedDetails.declaredName` as the (optional) `name` property in a + `hosted` block. + - `HostedDetails.name` now falls back to the name of the dependency if no + name is declared in the block. + ## 1.1.1-dev - Require Dart SDK >= 2.14.0 diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index f8d3ecdc3..8b59f7367 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -14,7 +14,7 @@ Map parseDeps(Map? source) => final key = k as String; Dependency? value; try { - value = _fromJson(v); + value = _fromJson(v, k); } on CheckedFromJsonException catch (e) { if (e.map is! YamlMap) { // This is likely a "synthetic" map created from a String value @@ -40,7 +40,7 @@ Map parseDeps(Map? source) => const _sourceKeys = ['sdk', 'git', 'path', 'hosted']; /// Returns `null` if the data could not be parsed. -Dependency? _fromJson(Object? data) { +Dependency? _fromJson(Object? data, String name) { if (data is String || data == null) { return _$HostedDependencyFromJson({'version': data}); } @@ -82,7 +82,9 @@ Dependency? _fromJson(Object? data) { case 'sdk': return _$SdkDependencyFromJson(data); case 'hosted': - return _$HostedDependencyFromJson(data); + final hosted = _$HostedDependencyFromJson(data); + hosted.hosted?._nameOfPackage = name; + return hosted; } throw StateError('There is a bug in pubspec_parse.'); }); @@ -211,16 +213,30 @@ class HostedDependency extends Dependency { @JsonSerializable(disallowUnrecognizedKeys: true) class HostedDetails { - final String name; + /// The name of the target dependency as declared in a `hosted` block. + /// + /// This may be null if no explicit name is present, for instance because the + /// hosted dependency was declared as a string (`hosted: pub.example.org`). + @JsonKey(name: 'name') + final String? declaredName; @JsonKey(fromJson: parseGitUriOrNull, disallowNullValue: true) final Uri? url; - HostedDetails(this.name, this.url); + @JsonKey(ignore: true) + String? _nameOfPackage; + + /// The name of this package on the package repository. + /// + /// If this hosted block has a [declaredName], that one will be used. + /// Otherwise, the name will be inferred from the surrounding package name. + String get name => declaredName ?? _nameOfPackage!; + + HostedDetails(this.declaredName, this.url); factory HostedDetails.fromJson(Object data) { if (data is String) { - data = {'name': data}; + data = {'url': data}; } if (data is Map) { diff --git a/pkgs/pubspec_parse/lib/src/dependency.g.dart b/pkgs/pubspec_parse/lib/src/dependency.g.dart index 4e9d399b8..1a504f1fd 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.g.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.g.dart @@ -63,9 +63,10 @@ HostedDetails _$HostedDetailsFromJson(Map json) => $checkedCreate( disallowNullValues: const ['url'], ); final val = HostedDetails( - $checkedConvert('name', (v) => v as String), + $checkedConvert('name', (v) => v as String?), $checkedConvert('url', (v) => parseGitUriOrNull(v as String?)), ); return val; }, + fieldKeyMap: const {'declaredName': 'name'}, ); diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index d19201e05..90ae1fef6 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.1.1-dev +version: 1.2.0-dev repository: https://github.com/dart-lang/pubspec_parse environment: diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 20053a87a..da7badcee 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -120,6 +120,21 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); + test('map /w hosted as a map without name', () { + final dep = _dependency( + { + 'version': '^1.0.0', + 'hosted': {'url': 'https://hosted_url'} + }, + skipTryPub: true, // todo: Unskip once pub supports this syntax + ); + expect(dep.version.toString(), '^1.0.0'); + expect(dep.hosted!.declaredName, isNull); + expect(dep.hosted!.name, 'dep'); + expect(dep.hosted!.url.toString(), 'https://hosted_url'); + expect(dep.toString(), 'HostedDependency: ^1.0.0'); + }); + test('map w/ bad version value', () { _expectThrows( { @@ -153,19 +168,22 @@ line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git test('map w/ version and hosted as String', () { final dep = _dependency( - {'version': '^1.0.0', 'hosted': 'hosted_name'}, + {'version': '^1.0.0', 'hosted': 'hosted_url'}, + skipTryPub: true, // todo: Unskip once put supports this ); expect(dep.version.toString(), '^1.0.0'); - expect(dep.hosted!.name, 'hosted_name'); - expect(dep.hosted!.url, isNull); + expect(dep.hosted!.declaredName, isNull); + expect(dep.hosted!.name, 'dep'); + expect(dep.hosted!.url, Uri.parse('hosted_url')); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); test('map w/ hosted as String', () { - final dep = _dependency({'hosted': 'hosted_name'}); + final dep = _dependency({'hosted': 'hosted_url'}); expect(dep.version, VersionConstraint.any); - expect(dep.hosted!.name, 'hosted_name'); - expect(dep.hosted!.url, isNull); + expect(dep.hosted!.declaredName, isNull); + expect(dep.hosted!.name, 'dep'); + expect(dep.hosted!.url, Uri.parse('hosted_url')); expect(dep.toString(), 'HostedDependency: any'); }); From 942fd9b85c9b051a0698e83dc94aa4eabb2a65d1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 11 Nov 2021 14:13:27 -0800 Subject: [PATCH 0820/1215] Migrate to pkg:lints recommended (dart-lang/stream_transform#138) Drop duplicative lints --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_transform/CHANGELOG.md | 1 + pkgs/stream_transform/analysis_options.yaml | 64 ++----------------- pkgs/stream_transform/pubspec.yaml | 4 +- .../test/combine_latest_test.dart | 1 - pkgs/stream_transform/test/scan_test.dart | 1 - 6 files changed, 8 insertions(+), 65 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 84369c1f8..1937fdd3c 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1 diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index e1ea482da..a00b3ba31 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,5 +1,6 @@ ## 2.0.1-dev +- Require Dart 2.14 or greater. - Wait for the future returned from `StreamSubscription.cancel()` before listening to the subsequent stream in `switchLatest` and `switchMap`. diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 39d5c5e03..46018f07d 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -1,90 +1,34 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false language: strict-raw-types: true - errors: - todo: ignore + linter: rules: - - annotate_overrides + - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - - avoid_empty_else - - avoid_function_literals_in_foreach_calls - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports - - avoid_renaming_method_parameters - - avoid_return_types_on_setters - avoid_returning_null - - avoid_returning_null_for_void - avoid_returning_this - - avoid_shadowing_type_parameters - - avoid_single_cascade_in_expression_statements - - avoid_types_as_parameter_names - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - cascade_invocations - comment_references - - constant_identifier_names - - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - - empty_statements - - file_names - - hash_and_equals - - implementation_imports - invariant_booleans - - iterable_contains_unrelated_type - join_return_with_assignment - - library_names - - library_prefixes - - list_remove_unrelated_type - no_adjacent_strings_in_list - - no_duplicate_case_values - - non_constant_identifier_names - - null_closures - omit_local_variable_types - only_throw_errors - - overridden_fields - - package_names - - package_prefixed_library_names - - prefer_adjacent_string_concatenation - - prefer_collection_literals - - prefer_conditional_assignment - prefer_const_constructors - - prefer_contains - - prefer_equal_for_default_values - - prefer_final_fields - - prefer_generic_function_type_aliases - - prefer_initializing_formals - prefer_interpolation_to_compose_strings - - prefer_is_empty - - prefer_is_not_empty - - prefer_null_aware_operators - prefer_single_quotes - - prefer_typing_uninitialized_variables - - recursive_getters - - slash_for_doc_comments - test_types_in_equals - throw_in_finally - - type_init_formals - unawaited_futures - - unnecessary_brace_in_string_interps - - unnecessary_const - - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements - - unnecessary_this - - unnecessary_overrides - - unrelated_type_equality_checks - - use_rethrow_when_possible - - valid_regexps - - void_checks diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 6e90b66d6..4b58ddffa 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -4,9 +4,9 @@ repository: https://github.com/dart-lang/stream_transform version: 2.0.1-dev environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.14.0 <3.0.0" dev_dependencies: async: ^2.5.0 - pedantic: ^1.10.0 + lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index a463bce2b..d2c6003dc 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 49bb8b8c7..3a126ec04 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; From 1996879bda283a1a6672277525046ba54342ec0a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 11 Nov 2021 14:14:13 -0800 Subject: [PATCH 0821/1215] Migrate to pkg:lints recommended (dart-lang/stream_channel#76) * Migrate to pkg:lints recommended * require dart 2.13, drop prerelease changelog entries --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 21 ++++--------------- pkgs/stream_channel/analysis_options.yaml | 10 +++++---- pkgs/stream_channel/pubspec.yaml | 6 +++--- .../test/disconnector_test.dart | 1 - .../test/isolate_channel_test.dart | 2 -- .../test/multi_channel_test.dart | 3 ++- .../test/stream_channel_completer_test.dart | 1 - .../test/stream_channel_test.dart | 1 - .../test/with_close_guarantee_test.dart | 1 - .../test/with_guarantees_test.dart | 1 - 11 files changed, 16 insertions(+), 33 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index bd93fbed8..17c7d20d2 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.14.0, dev] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2bb6c1f26..89736d95f 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,23 +1,10 @@ -## 2.1.0 - -* Stable release for null safety. - -## 2.1.0-nullsafety.3 - -* Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release - guidelines. +## 2.1.1-dev -## 2.1.0-nullsafety.2 +* Require Dart 2.14 -* Allow prerelease versions of the 2.12 sdk. - -## 2.1.0-nullsafety.1 - -* Allow 2.10 stable and 2.11.0 dev SDK versions. - -## 2.1.0-nullsafety +## 2.1.0 -* Migrate to null safety. +* Stable release for null safety. ## 2.0.0 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index b36c8749b..8465834c4 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,4 +1,5 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false @@ -11,7 +12,8 @@ analyzer: linter: rules: - - annotate_overrides - comment_references - - prefer_generic_function_type_aliases - - prefer_typing_uninitialized_variables + - always_declare_return_types + - omit_local_variable_types + - prefer_single_quotes + - unawaited_futures diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index d4a717361..17948bcfa 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.0 +version: 2.1.1-dev description: >- An abstraction for two-way communication channels based on the Dart Stream @@ -7,11 +7,11 @@ description: >- homepage: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - pedantic: ^1.10.0 + lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 4f16012bf..66773b59c 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index a1ec37eaf..a754421a9 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -3,11 +3,9 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') - import 'dart:async'; import 'dart:isolate'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/isolate_channel.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 00bcabe3b..763e6b829 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -2,7 +2,8 @@ // 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. -import 'package:pedantic/pedantic.dart'; +import 'dart:async'; + import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index a87492500..22db01a76 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index e101d206d..76edbdf91 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index decc2b448..a18f09fe1 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index a19dc58c2..849e30491 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -4,7 +4,6 @@ import 'dart:async'; -import 'package:pedantic/pedantic.dart'; import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; From c5b8af56bed7a2e3a1cc978aecb4c725c9bd7910 Mon Sep 17 00:00:00 2001 From: Jonathan Rezende Date: Fri, 3 Dec 2021 17:10:03 -0300 Subject: [PATCH 0822/1215] Add zoneValues to Chain.capture (dart-lang/stack_trace#113) Allows using fewer zones when there is a need for both custom zone values and stack trace chaining. --- pkgs/stack_trace/CHANGELOG.md | 4 +++- pkgs/stack_trace/lib/src/chain.dart | 17 +++++++++++------ pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 6 ++++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 779532810..348c50702 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.10.1-dev +## 1.11.0-dev +* Added the param `zoneValues` to `Chain.capture` to be able to use + custom zone values with the `runZoned` internal calls ## 1.10.0 diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index b685be9dc..8a03b6cef 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -72,20 +72,23 @@ class Chain implements StackTrace { /// If [errorZone] is `false`, [onError] must be `null`. /// /// If [callback] returns a value, it will be returned by [capture] as well. + /// + /// [zoneValues] is added to the [runZoned] calls. static T capture(T Function() callback, {void Function(Object error, Chain)? onError, bool when = true, - bool errorZone = true}) { + bool errorZone = true, + Map? zoneValues}) { if (!errorZone && onError != null) { throw ArgumentError.value( onError, 'onError', 'must be null if errorZone is false'); } if (!when) { - if (onError == null) return runZoned(callback); + if (onError == null) return runZoned(callback, zoneValues: zoneValues); return runZonedGuarded(callback, (error, stackTrace) { onError(error, Chain.forTrace(stackTrace)); - }) as T; + }, zoneValues: zoneValues) as T; } var spec = StackZoneSpecification(onError, errorZone: errorZone); @@ -102,9 +105,11 @@ class Chain implements StackTrace { // where T is a nullable type continue to work. return null as T; } - }, - zoneSpecification: spec.toSpec(), - zoneValues: {_specKey: spec, StackZoneSpecification.disableKey: false}); + }, zoneSpecification: spec.toSpec(), zoneValues: { + ...?zoneValues, + _specKey: spec, + StackZoneSpecification.disableKey: false + }); } /// If [when] is `true` and this is called within a [Chain.capture] zone, runs diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index bd4065c15..2775c0d9f 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.10.1-dev +version: 1.11.0-dev description: A package for manipulating stack traces and printing them readably. homepage: https://github.com/dart-lang/stack_trace diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 0931951f6..892738f00 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -117,6 +117,12 @@ void main() { }); }); + test('Chain.capture() with custom zoneValues', () { + return Chain.capture(() { + expect(Zone.current[#enabled], true); + }, zoneValues: {#enabled: true}); + }); + group('Chain.disable()', () { test('disables chain-tracking', () { return Chain.disable(() { From 411e9462ce5cc12c67006589a9c801952e5b66d6 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 7 Dec 2021 13:07:49 +0100 Subject: [PATCH 0823/1215] Add support for 'screenshots' field (dart-lang/pubspec_parse#78) --- pkgs/pubspec_parse/CHANGELOG.md | 6 +- pkgs/pubspec_parse/lib/pubspec_parse.dart | 1 + pkgs/pubspec_parse/lib/src/pubspec.dart | 6 + pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 + pkgs/pubspec_parse/lib/src/screenshot.dart | 65 +++++++++ pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 161 +++++++++++++++++++++ 7 files changed, 238 insertions(+), 5 deletions(-) create mode 100644 pkgs/pubspec_parse/lib/src/screenshot.dart diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 8f2d28897..5f3d5d6ec 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,14 +1,12 @@ -## 1.2.0-dev +## 1.2.0 +- Added support for `screenshots` field. - Update `HostedDetails` to reflect how `hosted` dependencies are parsed in Dart 2.15: - Add `HostedDetails.declaredName` as the (optional) `name` property in a `hosted` block. - `HostedDetails.name` now falls back to the name of the dependency if no name is declared in the block. - -## 1.1.1-dev - - Require Dart SDK >= 2.14.0 ## 1.1.0 diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart index 63c1e30e4..7360d1ac9 100644 --- a/pkgs/pubspec_parse/lib/pubspec_parse.dart +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -11,3 +11,4 @@ export 'src/dependency.dart' SdkDependency, PathDependency; export 'src/pubspec.dart' show Pubspec; +export 'src/screenshot.dart' show Screenshot; diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 8cc7b09c1..82c78aa7c 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -7,6 +7,7 @@ import 'package:json_annotation/json_annotation.dart'; import 'package:pub_semver/pub_semver.dart'; import 'dependency.dart'; +import 'screenshot.dart'; part 'pubspec.g.dart'; @@ -39,6 +40,10 @@ class Pubspec { /// view existing ones. final Uri? issueTracker; + /// Optional field for specifying included screenshot files. + @JsonKey(fromJson: parseScreenshots) + final List? screenshots; + /// If there is exactly 1 value in [authors], returns it. /// /// If there are 0 or more than 1, returns `null`. @@ -96,6 +101,7 @@ class Pubspec { this.homepage, this.repository, this.issueTracker, + this.screenshots, this.documentation, this.description, Map? dependencies, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index cadd38e41..221cc8347 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -27,6 +27,8 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( 'repository', (v) => v == null ? null : Uri.parse(v as String)), issueTracker: $checkedConvert('issue_tracker', (v) => v == null ? null : Uri.parse(v as String)), + screenshots: $checkedConvert( + 'screenshots', (v) => parseScreenshots(v as List?)), documentation: $checkedConvert('documentation', (v) => v as String?), description: $checkedConvert('description', (v) => v as String?), dependencies: diff --git a/pkgs/pubspec_parse/lib/src/screenshot.dart b/pkgs/pubspec_parse/lib/src/screenshot.dart new file mode 100644 index 000000000..f5f0be2ea --- /dev/null +++ b/pkgs/pubspec_parse/lib/src/screenshot.dart @@ -0,0 +1,65 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'package:json_annotation/json_annotation.dart'; + +@JsonSerializable() +class Screenshot { + final String description; + final String path; + + Screenshot(this.description, this.path); +} + +List parseScreenshots(List? input) { + final res = []; + if (input == null) { + return res; + } + + for (final e in input) { + if (e is! Map) continue; + + final description = e['description']; + if (description == null) { + throw CheckedFromJsonException( + e, + 'description', + 'Screenshot', + 'Missing required key `description`', + ); + } + + if (description is! String) { + throw CheckedFromJsonException( + e, + 'description', + 'Screenshot', + '`$description` is not a String', + ); + } + + final path = e['path']; + if (path == null) { + throw CheckedFromJsonException( + e, + 'path', + 'Screenshot', + 'Missing required key `path`', + ); + } + + if (path is! String) { + throw CheckedFromJsonException( + e, + 'path', + 'Screenshot', + '`$path` is not a String', + ); + } + + res.add(Screenshot(description, path)); + } + return res; +} diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 90ae1fef6..ae7a03f96 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.0-dev +version: 1.2.0 repository: https://github.com/dart-lang/pubspec_parse environment: diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 5f70de8ba..e8d24c624 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -31,6 +31,7 @@ void main() { expect(value.flutter, isNull); expect(value.repository, isNull); expect(value.issueTracker, isNull); + expect(value.screenshots, isEmpty); }); test('all fields set', () { @@ -47,6 +48,9 @@ void main() { 'documentation': 'documentation', 'repository': 'https://github.com/example/repo', 'issue_tracker': 'https://github.com/example/repo/issues', + 'screenshots': [ + {'description': 'my screenshot', 'path': 'path/to/screenshot'} + ], }); expect(value.name, 'sample'); expect(value.version, version); @@ -66,6 +70,9 @@ void main() { value.issueTracker, Uri.parse('https://github.com/example/repo/issues'), ); + expect(value.screenshots, hasLength(1)); + expect(value.screenshots!.first.description, 'my screenshot'); + expect(value.screenshots!.first.path, 'path/to/screenshot'); }); test('environment values can be null', () { @@ -357,6 +364,160 @@ line 3, column 19: Unsupported value for "issue_tracker". type 'YamlMap' is not }); }); + group('screenshots', () { + test('one screenshot', () { + final value = parse({ + ...defaultPubspec, + 'screenshots': [ + {'description': 'my screenshot', 'path': 'path/to/screenshot'} + ], + }); + expect(value.screenshots, hasLength(1)); + expect(value.screenshots!.first.description, 'my screenshot'); + expect(value.screenshots!.first.path, 'path/to/screenshot'); + }); + + test('many screenshots', () { + final value = parse({ + ...defaultPubspec, + 'screenshots': [ + {'description': 'my screenshot', 'path': 'path/to/screenshot'}, + { + 'description': 'my second screenshot', + 'path': 'path/to/screenshot2' + }, + ], + }); + expect(value.screenshots, hasLength(2)); + expect(value.screenshots!.first.description, 'my screenshot'); + expect(value.screenshots!.first.path, 'path/to/screenshot'); + expect(value.screenshots!.last.description, 'my second screenshot'); + expect(value.screenshots!.last.path, 'path/to/screenshot2'); + }); + + test('one screenshot plus invalid entries', () { + final value = parse({ + ...defaultPubspec, + 'screenshots': [ + 42, + { + 'description': 'my screenshot', + 'path': 'path/to/screenshot', + 'extraKey': 'not important' + }, + 'not a screenshot', + ], + }); + expect(value.screenshots, hasLength(1)); + expect(value.screenshots!.first.description, 'my screenshot'); + expect(value.screenshots!.first.path, 'path/to/screenshot'); + }); + + test('invalid entries', () { + final value = parse({ + ...defaultPubspec, + 'screenshots': [ + 42, + 'not a screenshot', + ], + }); + expect(value.screenshots, isEmpty); + }); + + test('missing key `dessription', () { + expectParseThrows( + { + ...defaultPubspec, + 'screenshots': [ + {'path': 'my/path'}, + ], + }, + r''' +line 7, column 3: Missing key "description". Missing required key `description` + ╷ +7 │ ┌ { +8 │ │ "path": "my/path" +9 │ └ } + ╵''', + skipTryPub: true, + ); + }); + + test('missing key `path`', () { + expectParseThrows( + { + ...defaultPubspec, + 'screenshots': [ + {'description': 'my screenshot'}, + ], + }, + r''' +line 7, column 3: Missing key "path". Missing required key `path` + ╷ +7 │ ┌ { +8 │ │ "description": "my screenshot" +9 │ └ } + ╵''', + skipTryPub: true, + ); + }); + + test('Value of description not a String`', () { + expectParseThrows( + { + ...defaultPubspec, + 'screenshots': [ + {'description': 42}, + ], + }, + r''' +line 8, column 19: Unsupported value for "description". `42` is not a String + ╷ +8 │ "description": 42 + │ ┌───────────────────^ +9 │ │ } + │ └──^ + ╵''', + skipTryPub: true, + ); + }); + + test('Value of path not a String`', () { + expectParseThrows( + { + ...defaultPubspec, + 'screenshots': [ + { + 'description': '', + 'path': 42, + }, + ], + }, + r''' +line 9, column 12: Unsupported value for "path". `42` is not a String + ╷ +9 │ "path": 42 + │ ┌────────────^ +10 │ │ } + │ └──^ + ╵''', + skipTryPub: true, + ); + }); + + test('invalid screenshot - lenient', () { + final value = parse( + { + ...defaultPubspec, + 'screenshots': 'Invalid value', + }, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.screenshots, isEmpty); + }); + }); + group('lenient', () { test('null', () { expectParseThrows( From fcf4b0f4747457a58f4c9a40293dc39db7f0523d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 20 Dec 2021 10:01:43 -0800 Subject: [PATCH 0824/1215] Refactor a callback to async/await (dart-lang/stream_transform#139) Use a try/finally block over using `whenComplete`. This also allows combining the async and sync error handling with a single `catch` instead of using `catch` for sync errors and `catchError` for async errors. Switch the early return to the shorter case of immediately listening on the first stream, and leaving the more complex logic (and more common case) with one less level of nesting. This does move the call to `outerSubscription.pause()` to come before the all to `currentSubscription.cancel()`, but this ordering should not be meaningful even though it can be observed. Fix a TODO about using `Future.ignore()`. --- pkgs/stream_transform/lib/src/switch.dart | 49 ++++++++++------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 53a839488..1fa07da4f 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -81,36 +81,31 @@ extension SwitchLatest on Stream> { outerStreamDone = true; if (innerSubscription == null) controller.close(); }); - outerSubscription.onData((innerStream) { + outerSubscription.onData((innerStream) async { var currentSubscription = innerSubscription; - if (currentSubscription != null) { - innerSubscription = null; - try { - currentSubscription.cancel().catchError(addError).whenComplete(() { - if (!isBroadcast && !controller.hasListener) { - // Result single-subscription stream subscription was cancelled - // while waiting for previous innerStream cancel. - // - // Ensure that the last received stream is also listened to and - // cancelled, then do nothing further. - // TODO(lrn): When SDK 2.14 is available, use `.ignore()`. - innerStream - .listen(null) - .cancel() - .then(_ignore, onError: _ignore); - return; - } - outerSubscription.resume(); - listenToInnerStream(innerStream); - }); - outerSubscription.pause(); - return; - } catch (error, stack) { - // The cancel call threw synchronously. - controller.addError(error, stack); + if (currentSubscription == null) { + listenToInnerStream(innerStream); + return; + } + innerSubscription = null; + outerSubscription.pause(); + try { + await currentSubscription.cancel(); + } catch (error, stack) { + controller.addError(error, stack); + } finally { + if (!isBroadcast && !controller.hasListener) { + // Result single-subscription stream subscription was cancelled + // while waiting for previous innerStream cancel. + // + // Ensure that the last received stream is also listened to and + // cancelled, then do nothing further. + innerStream.listen(null).cancel().ignore(); + } else { + outerSubscription.resume(); + listenToInnerStream(innerStream); } } - listenToInnerStream(innerStream); }); if (!isBroadcast) { controller From 0edf0946d2651627cb0a9b5328a34c93d3749081 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 12 Jan 2022 08:41:49 -0800 Subject: [PATCH 0825/1215] Support latest pkg:build_verify (dart-lang/pubspec_parse#79) --- pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/ensure_build_test.dart | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index ae7a03f96..c2be3dc78 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: dev_dependencies: build_runner: ^2.0.3 - build_verify: ^2.0.0 + build_verify: '>=2.0.0 <4.0.0' json_serializable: ^6.0.0 lints: ^1.0.0 path: ^1.5.1 diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index d64fa4f66..612b837e9 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.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. +@Timeout.factor(2) @TestOn('vm') @Tags(['presubmit-only']) import 'package:build_verify/build_verify.dart'; From a30730a7d203bfeb365ac06320ee0cb4c846ce46 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 12 Jan 2022 17:35:26 +0000 Subject: [PATCH 0826/1215] Ensure ready future completes (with error) in the case the watcher fails and closes. (dart-lang/watcher#123) See dart-lang/watcher#115. --- pkgs/watcher/CHANGELOG.md | 1 + .../lib/src/directory_watcher/linux.dart | 61 +++++++++++++------ .../lib/src/directory_watcher/mac_os.dart | 17 +++++- .../lib/src/directory_watcher/polling.dart | 12 ++-- .../lib/src/directory_watcher/windows.dart | 8 ++- pkgs/watcher/lib/src/utils.dart | 2 +- pkgs/watcher/lib/watcher.dart | 3 + pkgs/watcher/test/ready/shared.dart | 13 ++++ 8 files changed, 88 insertions(+), 29 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index d987225e7..af54045f6 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,6 +1,7 @@ # 1.0.2-dev - Require Dart SDK >= 2.14 +- Ensure `DirectoryWatcher.ready` completes even when errors occur that close the watcher. # 1.0.1 diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index 1bf5efd33..dafaeb19a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -82,20 +82,32 @@ class _LinuxDirectoryWatcher // Batch the inotify changes together so that we can dedup events. var innerStream = _nativeEvents.stream.batchEvents(); - _listen(innerStream, _onBatch, onError: _eventsController.addError); - - _listen(Directory(path).list(recursive: true), (FileSystemEntity entity) { - if (entity is Directory) { - _watchSubdir(entity.path); - } else { - _files.add(entity.path); + _listen(innerStream, _onBatch, + onError: (Object error, StackTrace stackTrace) { + // Guarantee that ready always completes. + if (!isReady) { + _readyCompleter.complete(); } - }, onError: (Object error, StackTrace stackTrace) { _eventsController.addError(error, stackTrace); - close(); - }, onDone: () { - _readyCompleter.complete(); - }, cancelOnError: true); + }); + + _listen( + Directory(path).list(recursive: true), + (FileSystemEntity entity) { + if (entity is Directory) { + _watchSubdir(entity.path); + } else { + _files.add(entity.path); + } + }, + onError: _emitError, + onDone: () { + if (!isReady) { + _readyCompleter.complete(); + } + }, + cancelOnError: true, + ); } @override @@ -195,15 +207,15 @@ class _LinuxDirectoryWatcher // contents, if (files.contains(path) && _files.contains(path)) continue; for (var file in _files.remove(path)) { - _emit(ChangeType.REMOVE, file); + _emitEvent(ChangeType.REMOVE, file); } } for (var file in files) { if (_files.contains(file)) { - _emit(ChangeType.MODIFY, file); + _emitEvent(ChangeType.MODIFY, file); } else { - _emit(ChangeType.ADD, file); + _emitEvent(ChangeType.ADD, file); _files.add(file); } } @@ -221,15 +233,14 @@ class _LinuxDirectoryWatcher _watchSubdir(entity.path); } else { _files.add(entity.path); - _emit(ChangeType.ADD, entity.path); + _emitEvent(ChangeType.ADD, entity.path); } }, onError: (Object error, StackTrace stackTrace) { // Ignore an exception caused by the dir not existing. It's fine if it // was added and then quickly removed. if (error is FileSystemException) return; - _eventsController.addError(error, stackTrace); - close(); + _emitError(error, stackTrace); }, cancelOnError: true); } @@ -242,7 +253,7 @@ class _LinuxDirectoryWatcher // caused by a MOVE, we need to manually emit events. if (isReady) { for (var file in _files.paths) { - _emit(ChangeType.REMOVE, file); + _emitEvent(ChangeType.REMOVE, file); } } @@ -251,12 +262,22 @@ class _LinuxDirectoryWatcher /// Emits a [WatchEvent] with [type] and [path] if this watcher is in a state /// to emit events. - void _emit(ChangeType type, String path) { + void _emitEvent(ChangeType type, String path) { if (!isReady) return; if (_eventsController.isClosed) return; _eventsController.add(WatchEvent(type, path)); } + /// Emit an error, then close the watcher. + void _emitError(Object error, StackTrace stackTrace) { + // Guarantee that ready always completes. + if (!isReady) { + _readyCompleter.complete(); + } + _eventsController.addError(error, stackTrace); + close(); + } + /// Like [Stream.listen], but automatically adds the subscription to /// [_subscriptions] so that it can be canceled when [close] is called. void _listen(Stream stream, void Function(T) onData, diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 2046ce0d5..12648c8a6 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -87,8 +87,11 @@ class _MacOSDirectoryWatcher // // If we do receive a batch of events, [_onBatch] will ensure that these // futures don't fire and that the directory is re-listed. - Future.wait([_listDir(), _waitForBogusEvents()]) - .then((_) => _readyCompleter.complete()); + Future.wait([_listDir(), _waitForBogusEvents()]).then((_) { + if (!isReady) { + _readyCompleter.complete(); + } + }); } @override @@ -115,7 +118,11 @@ class _MacOSDirectoryWatcher // Cancel the timer because bogus events only occur in the first batch, so // we can fire [ready] as soon as we're done listing the directory. _bogusEventTimer.cancel(); - _listDir().then((_) => _readyCompleter.complete()); + _listDir().then((_) { + if (!isReady) { + _readyCompleter.complete(); + } + }); return; } @@ -396,6 +403,10 @@ class _MacOSDirectoryWatcher /// Emit an error, then close the watcher. void _emitError(Object error, StackTrace stackTrace) { + // Guarantee that ready always completes. + if (!isReady) { + _readyCompleter.complete(); + } _eventsController.addError(error, stackTrace); close(); } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 2a43937b8..3dcec05a3 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -43,11 +43,11 @@ class _PollingDirectoryWatcher final _events = StreamController.broadcast(); @override - bool get isReady => _ready.isCompleted; + bool get isReady => _readyCompleter.isCompleted; @override - Future get ready => _ready.future; - final _ready = Completer(); + Future get ready => _readyCompleter.future; + final _readyCompleter = Completer(); /// The amount of time the watcher pauses between successive polls of the /// directory contents. @@ -119,6 +119,10 @@ class _PollingDirectoryWatcher if (entity is! File) return; _filesToProcess.add(entity.path); }, onError: (Object error, StackTrace stackTrace) { + // Guarantee that ready always completes. + if (!isReady) { + _readyCompleter.complete(); + } if (!isDirectoryNotFoundException(error)) { // It's some unknown error. Pipe it over to the event stream so the // user can see it. @@ -177,7 +181,7 @@ class _PollingDirectoryWatcher _lastModifieds.remove(removed); } - if (!isReady) _ready.complete(); + if (!isReady) _readyCompleter.complete(); // Wait and then poll again. await Future.delayed(_pollingDelay); diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 09b4b36b0..710caf54a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -92,7 +92,9 @@ class _WindowsDirectoryWatcher _listDir().then((_) { _startWatch(); _startParentWatcher(); - _readyCompleter.complete(); + if (!isReady) { + _readyCompleter.complete(); + } }); } @@ -427,6 +429,10 @@ class _WindowsDirectoryWatcher /// Emit an error, then close the watcher. void _emitError(Object error, StackTrace stackTrace) { + // Guarantee that ready always completes. + if (!isReady) { + _readyCompleter.complete(); + } _eventsController.addError(error, stackTrace); close(); } diff --git a/pkgs/watcher/lib/src/utils.dart b/pkgs/watcher/lib/src/utils.dart index ecf4e105c..c2e71b3c1 100644 --- a/pkgs/watcher/lib/src/utils.dart +++ b/pkgs/watcher/lib/src/utils.dart @@ -3,8 +3,8 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; -import 'dart:io'; import 'dart:collection'; +import 'dart:io'; /// Returns `true` if [error] is a [FileSystemException] for a missing /// directory. diff --git a/pkgs/watcher/lib/watcher.dart b/pkgs/watcher/lib/watcher.dart index 22e0d6e04..12a536961 100644 --- a/pkgs/watcher/lib/watcher.dart +++ b/pkgs/watcher/lib/watcher.dart @@ -42,6 +42,9 @@ abstract class Watcher { /// /// If the watcher is already monitoring, this returns an already complete /// future. + /// + /// This future always completes successfully as errors are provided through + /// the [events] stream. Future get ready; /// Creates a new [DirectoryWatcher] or [FileWatcher] monitoring [path], diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index b6b3cce08..6578c52cb 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -61,4 +61,17 @@ void sharedTests() { // Should be back to not ready. expect(watcher.ready, doesNotComplete); }); + + test('completes even if directory does not exist', () async { + var watcher = createWatcher(path: 'does/not/exist'); + + // Subscribe to the events (else ready will never fire). + var subscription = watcher.events.listen((event) {}, onError: (error) {}); + + // Expect ready still completes. + await watcher.ready; + + // Now unsubscribe. + await subscription.cancel(); + }); } From 0b51a2dbed8c4c17d01811a395fd00de55125453 Mon Sep 17 00:00:00 2001 From: Michael Thomsen Date: Mon, 17 Jan 2022 16:13:22 +0100 Subject: [PATCH 0827/1215] Remove stale travis job --- pkgs/test_reflective_loader/tool/travis.sh | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100755 pkgs/test_reflective_loader/tool/travis.sh diff --git a/pkgs/test_reflective_loader/tool/travis.sh b/pkgs/test_reflective_loader/tool/travis.sh deleted file mode 100755 index ea0f1c495..000000000 --- a/pkgs/test_reflective_loader/tool/travis.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file -# 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. - -# Fast fail the script on failures. -set -e - -# Verify that the libraries are error free. -dartanalyzer --fatal-warnings \ - lib/test_reflective_loader.dart \ - test/test_reflective_loader_test.dart - -# Run the tests. -dart test/test_reflective_loader_test.dart From 67c6d6526dfdd6ccd69818e5bcd06c72d7385643 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 19 Jan 2022 16:10:14 +0000 Subject: [PATCH 0828/1215] Add/enable Windows tests (dart-lang/watcher#124) --- pkgs/watcher/test/directory_watcher/shared.dart | 5 ++++- .../test/directory_watcher/windows_test.dart | 4 +--- .../test/no_subscription/windows_test.dart | 17 +++++++++++++++++ pkgs/watcher/test/ready/shared.dart | 8 ++++++-- pkgs/watcher/test/ready/windows_test.dart | 17 +++++++++++++++++ pkgs/watcher/test/utils.dart | 12 ++++++++++++ 6 files changed, 57 insertions(+), 6 deletions(-) create mode 100644 pkgs/watcher/test/no_subscription/windows_test.dart create mode 100644 pkgs/watcher/test/ready/windows_test.dart diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index ebce488db..07fbf9cf2 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -134,6 +134,8 @@ void sharedTests() { renameFile('from.txt', 'to.txt'); await inAnyOrder([isRemoveEvent('from.txt'), isModifyEvent('to.txt')]); + }, onPlatform: { + 'windows': Skip('https://github.com/dart-lang/watcher/issues/125') }); }); @@ -276,7 +278,8 @@ void sharedTests() { isAddEvent('new') ]); }, onPlatform: { - 'mac-os': Skip('https://github.com/dart-lang/watcher/issues/21') + 'mac-os': Skip('https://github.com/dart-lang/watcher/issues/21'), + 'windows': Skip('https://github.com/dart-lang/watcher/issues/21') }); test('emits events for many nested files added at once', () async { diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 6ea412f77..3ddb47e03 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -14,11 +14,9 @@ import '../utils.dart'; void main() { watcherFactory = (dir) => WindowsDirectoryWatcher(dir); - // TODO(grouma) - renable when https://github.com/dart-lang/sdk/issues/31760 - // is resolved. group('Shared Tests:', () { sharedTests(); - }, skip: 'SDK issue see - https://github.com/dart-lang/sdk/issues/31760'); + }); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { expect(DirectoryWatcher('.'), TypeMatcher()); diff --git a/pkgs/watcher/test/no_subscription/windows_test.dart b/pkgs/watcher/test/no_subscription/windows_test.dart new file mode 100644 index 000000000..eb381d025 --- /dev/null +++ b/pkgs/watcher/test/no_subscription/windows_test.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('windows') + +import 'package:test/test.dart'; +import 'package:watcher/src/directory_watcher/windows.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +void main() { + watcherFactory = (dir) => WindowsDirectoryWatcher(dir); + + sharedTests(); +} diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index 6578c52cb..d9bb5aefa 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -21,19 +21,21 @@ void sharedTests() { expect(ready, isFalse); // Subscribe to the events. - watcher.events.listen((event) {}); + var subscription = watcher.events.listen((event) {}); await watcher.ready; // Should eventually be ready. expect(watcher.isReady, isTrue); + + await subscription.cancel(); }); test('ready completes immediately when already ready', () async { var watcher = createWatcher(); // Subscribe to the events. - watcher.events.listen((event) {}); + var subscription = watcher.events.listen((event) {}); // Allow watcher to become ready await watcher.ready; @@ -43,6 +45,8 @@ void sharedTests() { watcher.ready.timeout(Duration(milliseconds: 0), onTimeout: () => throw 'Does not complete immedately'), completes); + + await subscription.cancel(); }); test('ready returns a future that does not complete after unsubscribing', diff --git a/pkgs/watcher/test/ready/windows_test.dart b/pkgs/watcher/test/ready/windows_test.dart new file mode 100644 index 000000000..eb381d025 --- /dev/null +++ b/pkgs/watcher/test/ready/windows_test.dart @@ -0,0 +1,17 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. + +@TestOn('windows') + +import 'package:test/test.dart'; +import 'package:watcher/src/directory_watcher/windows.dart'; + +import 'shared.dart'; +import '../utils.dart'; + +void main() { + watcherFactory = (dir) => WindowsDirectoryWatcher(dir); + + sharedTests(); +} diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 8d8981c39..23adcbc40 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -48,6 +48,12 @@ Watcher createWatcher({String? path}) { /// The stream of events from the watcher started with [startWatcher]. late StreamQueue _watcherEvents; +/// Whether the event stream has been closed. +/// +/// If this is not done by a test (by calling [startClosingEventStream]) it will +/// be done automatically via [addTearDown] in [startWatcher]. +var _hasClosedStream = true; + /// Creates a new [Watcher] that watches a temporary file or directory and /// starts monitoring it for events. /// @@ -70,6 +76,10 @@ Future startWatcher({String? path}) async { _watcherEvents = StreamQueue(watcher.events); // Forces a subscription to the underlying stream. unawaited(_watcherEvents.hasNext); + + _hasClosedStream = false; + addTearDown(startClosingEventStream); + await watcher.ready; } @@ -80,6 +90,8 @@ Future startWatcher({String? path}) async { /// indefinitely because they might in the future and because the watcher is /// normally only closed after the test completes. void startClosingEventStream() async { + if (_hasClosedStream) return; + _hasClosedStream = true; await pumpEventQueue(); await _watcherEvents.cancel(immediate: true); } From 5ec88b8bbb7c5e010a984ee0bea758dde2b27da9 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 1 Feb 2022 20:56:40 -0800 Subject: [PATCH 0829/1215] Change a TODO to a permanent comment (dart-lang/stack_trace#114) https://github.com/dart-lang/sdk/issues/19566 is closed and no changes to the behavior are planned. Remove the TODO since this won't ever be actionable, and change to an explanatory comment. --- pkgs/stack_trace/lib/src/chain.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 8a03b6cef..628b8fae2 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -96,7 +96,8 @@ class Chain implements StackTrace { try { return callback(); } on Object catch (error, stackTrace) { - // TODO(nweiz): Don't special-case this when issue 19566 is fixed. + // Forward synchronous errors through the async error path to match the + // behavior of `runZonedGuarded`. Zone.current.handleUncaughtError(error, stackTrace); // If the expected return type of capture() is not nullable, this will From a274a38b7eb49ee817434d64a7afe8115132f0fc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 6 Feb 2022 15:31:30 -0800 Subject: [PATCH 0830/1215] Fix test due to recent pub change Support SDKs are new checked --- pkgs/pubspec_parse/test/parse_test.dart | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index e8d24c624..397a728e9 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -76,13 +76,16 @@ void main() { }); test('environment values can be null', () { - final value = parse({ - 'name': 'sample', - 'environment': { - 'sdk': '>=2.7.0 <3.0.0', - 'bob': null, - } - }); + final value = parse( + { + 'name': 'sample', + 'environment': { + 'sdk': '>=2.7.0 <3.0.0', + 'bob': null, + } + }, + skipTryPub: true, + ); expect(value.name, 'sample'); expect(value.environment, hasLength(2)); expect(value.environment, containsPair('bob', isNull)); From 20b42094d4047025d7371446d21b34ed3e0a1541 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 6 Feb 2022 15:33:36 -0800 Subject: [PATCH 0831/1215] Update readme version link and bump version in changelog/pubspec --- pkgs/pubspec_parse/CHANGELOG.md | 2 ++ pkgs/pubspec_parse/README.md | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 5f3d5d6ec..6b5a04d22 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.1-dev + ## 1.2.0 - Added support for `screenshots` field. diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index ed00eed97..eca3610fd 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,5 +1,5 @@ [![Build Status](https://github.com/dart-lang/pubspec_parse/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/pubspec_parse/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) -[![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/pubspec_parse) +[![pub package](https://img.shields.io/pub/v/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse) Supports parsing `pubspec.yaml` files with robust error reporting and support for most of the documented features. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index c2be3dc78..3932fd90f 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.0 +version: 1.2.1-dev repository: https://github.com/dart-lang/pubspec_parse environment: From 539845c90add4e8c2ab446aa14e8224b8ae383fc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 6 Feb 2022 15:37:29 -0800 Subject: [PATCH 0832/1215] Bump min version of json_annotation --- pkgs/pubspec_parse/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 3932fd90f..bb9636969 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -11,7 +11,7 @@ environment: dependencies: checked_yaml: ^2.0.1 collection: ^1.15.0 - json_annotation: ^4.3.0 + json_annotation: ^4.4.0 pub_semver: ^2.0.0 yaml: ^3.0.0 From 8aa107ec75c59c069bd1efc69f6155a9411cdc05 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 14 Feb 2022 12:06:52 -0800 Subject: [PATCH 0833/1215] fix pub usage in tests (dart-lang/pubspec_parse#81) --- pkgs/pubspec_parse/test/pub_utils.dart | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/pkgs/pubspec_parse/test/pub_utils.dart b/pkgs/pubspec_parse/test/pub_utils.dart index 5871b1b9c..a60aa2a99 100644 --- a/pkgs/pubspec_parse/test/pub_utils.dart +++ b/pkgs/pubspec_parse/test/pub_utils.dart @@ -14,8 +14,8 @@ Future tryPub(String content) async { await d.file('pubspec.yaml', content).create(); final proc = await TestProcess.start( - _pubPath, - ['get', '--offline'], + Platform.resolvedExecutable, + ['pub', 'get', '--offline'], workingDirectory: d.sandbox, // Don't pass current process VM options to child environment: Map.from(Platform.environment)..remove('DART_VM_OPTIONS'), @@ -86,15 +86,3 @@ class ProcLine { @override String toString() => '${isError ? 'err' : 'out'} $line'; } - -/// The path to the root directory of the SDK. -final String _sdkDir = () { - // The Dart executable is in "/path/to/sdk/bin/dart", so two levels up is - // "/path/to/sdk". - final aboveExecutable = p.dirname(p.dirname(Platform.resolvedExecutable)); - assert(FileSystemEntity.isFileSync(p.join(aboveExecutable, 'version'))); - return aboveExecutable; -}(); - -final String _pubPath = - p.join(_sdkDir, 'bin', Platform.isWindows ? 'pub.bat' : 'pub'); From 4fc12445aa811aafae0eda3157afba21ffde976a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 19:25:13 -0800 Subject: [PATCH 0834/1215] Bump actions/checkout from 2 to 3 (dart-lang/string_scanner#42) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index bd93fbed8..9bf684586 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From 06fe43d7415d76b29c850900c0ddf3e86f9ca499 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Mar 2022 19:25:42 -0800 Subject: [PATCH 0835/1215] Bump actions/checkout from 2 to 3 (dart-lang/stream_transform#141) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 1937fdd3c..02bf25d38 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From 8ebfdaecdabae533af70a6f19391cd08b3faac57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:15:55 -0800 Subject: [PATCH 0836/1215] Bump actions/checkout from 2 to 3 (dart-lang/stream_channel#78) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 17c7d20d2..9de6d54aa 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From ccf576ef2b52dfecb4fb70557b74a365a67856b4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 29 Apr 2022 22:17:28 -0700 Subject: [PATCH 0837/1215] populate the pubspec repository field (dart-lang/test_reflective_loader#39) populate the pubspec repository field dart-lang/test_reflective_loader#39 --- pkgs/test_reflective_loader/CHANGELOG.md | 5 +++++ pkgs/test_reflective_loader/analysis_options.yaml | 2 +- .../lib/test_reflective_loader.dart | 2 +- pkgs/test_reflective_loader/pubspec.yaml | 8 ++++---- .../test/test_reflective_loader_test.dart | 2 ++ 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index bb0f5ab88..039585882 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.2.1-dev + +- Use package:lints for analysis. +- Populate the pubspec `repository` field. + ## 0.2.0 - Stable null safety release. diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml index 180004e7c..31466c374 100644 --- a/pkgs/test_reflective_loader/analysis_options.yaml +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -1,4 +1,4 @@ -analyzer: +include: package:lints/core.yaml linter: rules: diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index fe78b9de8..e03eb7afb 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -278,7 +278,7 @@ Future _runTest(ClassMirror classMirror, Symbol symbol) { .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); } -typedef dynamic _TestFunction(); +typedef _TestFunction = dynamic Function(); /** * A marker annotation used to annotate test methods which are expected to fail. diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 1a727331e..51cb753ac 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,11 +1,11 @@ name: test_reflective_loader -version: 0.2.0 - +version: 0.2.1-dev description: Support for discovering tests and test suites using reflection. -homepage: https://github.com/dart-lang/test_reflective_loader +repository: https://github.com/dart-lang/test_reflective_loader environment: - sdk: '>=2.12.0-0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' dependencies: + lints: ^1.0.0 test: '>=1.16.0 <2.0.0' diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index 2c69ccebd..d303a75ba 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -2,6 +2,8 @@ // 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. +// ignore_for_file: non_constant_identifier_names + import 'dart:async'; import 'package:test/test.dart'; From 3ec468e3536cb3f000aa6c9ec57d2c919740b3c0 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 20:08:41 +0000 Subject: [PATCH 0838/1215] populate the pubspec repository field --- pkgs/stream_channel/CHANGELOG.md | 2 ++ pkgs/stream_channel/README.md | 4 ++++ pkgs/stream_channel/pubspec.yaml | 3 +-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 89736d95f..0f8da1548 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,8 @@ ## 2.1.1-dev * Require Dart 2.14 +* Migrate to `package:lints`. +* Populate the pubspec `repository` field. ## 2.1.0 diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index 2ec970b8e..ae1ea219d 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) +[![package publisher](https://img.shields.io/pub/publisher/stream_channel.svg)](https://pub.dev/packages/stream_channel/publisher) + This package exposes the `StreamChannel` interface, which represents a two-way communication channel. Each `StreamChannel` exposes a `Stream` for receiving data and a `StreamSink` for sending it. diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 17948bcfa..5e86fc3eb 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,10 +1,9 @@ name: stream_channel version: 2.1.1-dev - description: >- An abstraction for two-way communication channels based on the Dart Stream class. -homepage: https://github.com/dart-lang/stream_channel +repository: https://github.com/dart-lang/stream_channel environment: sdk: '>=2.14.0 <3.0.0' From 4e6e73b42b1bf12b260bfa7d7f9ae4b36aad5281 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 20:18:23 +0000 Subject: [PATCH 0839/1215] populate the pubspec repository field --- pkgs/stack_trace/CHANGELOG.md | 6 ++++-- pkgs/stack_trace/pubspec.yaml | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 348c50702..f31c0238b 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,6 +1,8 @@ ## 1.11.0-dev -* Added the param `zoneValues` to `Chain.capture` to be able to use - custom zone values with the `runZoned` internal calls + +* Added the param `zoneValues` to `Chain.capture` to be able to use custom zone + values with the `runZoned` internal calls +* Populate the pubspec `repository` field. ## 1.10.0 diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 2775c0d9f..67302bfa3 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,14 +1,14 @@ name: stack_trace version: 1.11.0-dev description: A package for manipulating stack traces and printing them readably. -homepage: https://github.com/dart-lang/stack_trace +repository: https://github.com/dart-lang/stack_trace environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: path: ^1.8.0 dev_dependencies: - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + pedantic: ^1.10.0 + test: ^1.16.0 From bb9864184cd345fe72c425bd486502afeed8fcef Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 20:19:23 +0000 Subject: [PATCH 0840/1215] add markdown badges --- pkgs/stack_trace/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 19c6daa69..a76dfc327 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/stack_trace/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stack_trace/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/stack_trace.svg)](https://pub.dev/packages/stack_trace) +[![package publisher](https://img.shields.io/pub/publisher/stack_trace.svg)](https://pub.dev/packages/stack_trace/publisher) + This library provides the ability to parse, inspect, and manipulate stack traces produced by the underlying Dart implementation. It also provides functions to produce string representations of stack traces in a more readable format than From 9a785bec2b71a0b8c0dcbb5610a8795c8576d33f Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 20:22:31 +0000 Subject: [PATCH 0841/1215] switch to package:lints --- pkgs/stack_trace/CHANGELOG.md | 1 + pkgs/stack_trace/analysis_options.yaml | 3 ++- pkgs/stack_trace/pubspec.yaml | 2 +- pkgs/stack_trace/test/chain/vm_test.dart | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index f31c0238b..aa4300425 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -3,6 +3,7 @@ * Added the param `zoneValues` to `Chain.capture` to be able to use custom zone values with the `runZoned` internal calls * Populate the pubspec `repository` field. +* Switch to `package:lints`. ## 1.10.0 diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 2e022f6bc..05c4b4c69 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,4 +1,5 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 67302bfa3..326e2d447 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -10,5 +10,5 @@ dependencies: path: ^1.8.0 dev_dependencies: - pedantic: ^1.10.0 + lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 9d82b2cd9..efcee3d88 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -459,7 +459,7 @@ void main() { test('called for an unregistered stack trace uses the current chain', () async { - var trace; + late StackTrace trace; var chain = await Chain.capture(() async { try { throw 'error'; From 5244f50a955c582ce3e520637a3e378c5c0447ba Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 15:15:55 -0700 Subject: [PATCH 0842/1215] populate the repository field (dart-lang/term_glyph#26) --- pkgs/term_glyph/CHANGELOG.md | 3 +++ pkgs/term_glyph/pubspec.yaml | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index f2cd28f40..7100d1b39 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,5 +1,8 @@ ## 1.2.1-dev +* Migrate to `package:lints`. +* Populate the pubspec `repository` field. + ## 1.2.0 * Stable release for null safety. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index e1b26bb95..d1313a4a1 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,8 +1,7 @@ name: term_glyph version: 1.2.1-dev - description: Useful Unicode glyphs and ASCII substitutes. -homepage: https://github.com/dart-lang/term_glyph +repository: https://github.com/dart-lang/term_glyph environment: sdk: ">=2.12.0 <3.0.0" From 23f9f8193076a4221b29cac148cebc77db521859 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 3 May 2022 15:16:03 -0700 Subject: [PATCH 0843/1215] populate the pubspec repository field (dart-lang/string_scanner#44) --- pkgs/string_scanner/CHANGELOG.md | 2 ++ pkgs/string_scanner/pubspec.yaml | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 2a76ec94d..d1a0e88e6 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.1.1-dev +* Populate the pubspec `repository` field. + ## 1.1.0 * Stable release for null safety. diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 02136e394..872d47c5b 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,8 +1,7 @@ name: string_scanner version: 1.1.1-dev - description: A class for parsing strings using a sequence of patterns. -homepage: https://github.com/dart-lang/string_scanner +repository: https://github.com/dart-lang/string_scanner environment: sdk: ">=2.12.0 <3.0.0" @@ -12,4 +11,4 @@ dependencies: dev_dependencies: lints: ^1.0.0 - test: ^1.16.0 \ No newline at end of file + test: ^1.16.0 From 99e9344a0d7e22bb7db987b4cd9c5f2fba152db3 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 12 May 2022 10:09:18 -0700 Subject: [PATCH 0844/1215] rev to 1.1.1 in preparation for publishing (dart-lang/string_scanner#45) --- pkgs/string_scanner/CHANGELOG.md | 4 +++- pkgs/string_scanner/README.md | 4 ++++ pkgs/string_scanner/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index d1a0e88e6..cb4d29710 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,6 +1,8 @@ -## 1.1.1-dev +## 1.1.1 * Populate the pubspec `repository` field. +* Switch to `package:lints`. +* Remove a dependency on `package:charcode`. ## 1.1.0 diff --git a/pkgs/string_scanner/README.md b/pkgs/string_scanner/README.md index 6427218c2..b7a49c363 100644 --- a/pkgs/string_scanner/README.md +++ b/pkgs/string_scanner/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/string_scanner/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/string_scanner/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/string_scanner.svg)](https://pub.dev/packages/string_scanner) +[![package publisher](https://img.shields.io/pub/publisher/string_scanner.svg)](https://pub.dev/packages/string_scanner/publisher) + This package exposes a `StringScanner` type that makes it easy to parse a string using a series of `Pattern`s. For example: diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 872d47c5b..421a22739 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.1.1-dev +version: 1.1.1 description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner From 3e2beca4db9468e99e999d36f806cecfb557ba4e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 19 May 2022 09:23:22 -0700 Subject: [PATCH 0845/1215] prep to publish 0.2.1 (dart-lang/test_reflective_loader#40) prep to publish 0.2.1 --- pkgs/test_reflective_loader/.status | 4 --- pkgs/test_reflective_loader/CHANGELOG.md | 2 +- pkgs/test_reflective_loader/README.md | 3 +- .../analysis_options.yaml | 6 +++- .../lib/test_reflective_loader.dart | 33 ++++++++++--------- pkgs/test_reflective_loader/pubspec.yaml | 4 +-- .../test/test_reflective_loader_test.dart | 2 +- 7 files changed, 28 insertions(+), 26 deletions(-) delete mode 100644 pkgs/test_reflective_loader/.status diff --git a/pkgs/test_reflective_loader/.status b/pkgs/test_reflective_loader/.status deleted file mode 100644 index 364ca4b46..000000000 --- a/pkgs/test_reflective_loader/.status +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -# 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. - diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 039585882..05195a8f4 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.2.1-dev +## 0.2.1 - Use package:lints for analysis. - Populate the pubspec `repository` field. diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index b7f5e19a7..f7d07dbe3 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -1,6 +1,5 @@ -# test_reflective_loader - [![Build Status](https://github.com/dart-lang/test_reflective_loader/workflows/Dart/badge.svg)](https://github.com/dart-lang/test_reflective_loader/actions) +[![pub package](https://img.shields.io/pub/v/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader) Support for discovering tests and test suites using reflection. diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml index 31466c374..fc2a9d30e 100644 --- a/pkgs/test_reflective_loader/analysis_options.yaml +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -1,4 +1,8 @@ -include: package:lints/core.yaml +include: package:lints/recommended.yaml + +analyzer: + errors: + slash_for_doc_comments: ignore linter: rules: diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index e03eb7afb..6237f676c 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -13,28 +13,28 @@ import 'package:test/test.dart' as test_package; * A marker annotation used to annotate test methods which are expected to fail * when asserts are enabled. */ -const _AssertFailingTest assertFailingTest = const _AssertFailingTest(); +const _AssertFailingTest assertFailingTest = _AssertFailingTest(); /** * A marker annotation used to annotate test methods which are expected to fail. */ -const FailingTest failingTest = const FailingTest(); +const FailingTest failingTest = FailingTest(); /** * A marker annotation used to instruct dart2js to keep reflection information * for the annotated classes. */ -const _ReflectiveTest reflectiveTest = const _ReflectiveTest(); +const _ReflectiveTest reflectiveTest = _ReflectiveTest(); /** * A marker annotation used to annotate test methods that should be skipped. */ -const SkippedTest skippedTest = const SkippedTest(); +const SkippedTest skippedTest = SkippedTest(); /** * A marker annotation used to annotate "solo" groups and tests. */ -const _SoloTest soloTest = const _SoloTest(); +const _SoloTest soloTest = _SoloTest(); final List<_Group> _currentGroups = <_Group>[]; int _currentSuiteLevel = 0; @@ -58,7 +58,7 @@ final bool _isCheckedMode = () { * create embedded suites. If the current suite is the top-level one, perform * check for "solo" groups and tests, and run all or only "solo" items. */ -void defineReflectiveSuite(void define(), {String name = ''}) { +void defineReflectiveSuite(void Function() define, {String name = ''}) { String groupName = _currentSuiteName; _currentSuiteLevel++; try { @@ -96,7 +96,7 @@ void defineReflectiveTests(Type type) { if (!classMirror.metadata.any((InstanceMirror annotation) => annotation.type.reflectedType == _ReflectiveTest)) { String name = MirrorSystem.getName(classMirror.qualifiedName); - throw new Exception('Class $name must have annotation "@reflectiveTest" ' + throw Exception('Class $name must have annotation "@reflectiveTest" ' 'in order to be run by runReflectiveTests.'); } @@ -104,7 +104,7 @@ void defineReflectiveTests(Type type) { { bool isSolo = _hasAnnotationInstance(classMirror, soloTest); String className = MirrorSystem.getName(classMirror.simpleName); - group = new _Group(isSolo, _combineNames(_currentSuiteName, className)); + group = _Group(isSolo, _combineNames(_currentSuiteName, className)); _currentGroups.add(group); } @@ -229,16 +229,18 @@ bool _hasSkippedTestAnnotation(MethodMirror method) => Future _invokeSymbolIfExists( InstanceMirror instanceMirror, Symbol symbol) { - Object? invocationResult = null; + Object? invocationResult; InstanceMirror? closure; try { closure = instanceMirror.getField(symbol); - } on NoSuchMethodError {} + } on NoSuchMethodError { + // ignore + } if (closure is ClosureMirror) { invocationResult = closure.apply([]).reflectee; } - return new Future.value(invocationResult); + return Future.value(invocationResult); } /** @@ -252,7 +254,8 @@ Future _invokeSymbolIfExists( Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { bool passed = false; return runZonedGuarded(() { - return new Future.sync(() => _runTest(classMirror, symbol)).then((_) { + // ignore: void_checks + return Future.sync(() => _runTest(classMirror, symbol)).then((_) { passed = true; test_package.fail('Test passed - expected to fail.'); }).catchError((e) { @@ -272,7 +275,7 @@ Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { } Future _runTest(ClassMirror classMirror, Symbol symbol) { - InstanceMirror instanceMirror = classMirror.newInstance(new Symbol(''), []); + InstanceMirror instanceMirror = classMirror.newInstance(Symbol(''), []); return _invokeSymbolIfExists(instanceMirror, #setUp) .then((_) => instanceMirror.invoke(symbol, []).reflectee) .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); @@ -341,7 +344,7 @@ class _Group { void addSkippedTest(String name) { var fullName = _combineNames(this.name, name); - tests.add(new _Test.skipped(isSolo, fullName)); + tests.add(_Test.skipped(isSolo, fullName)); } void addTest(bool isSolo, String name, MethodMirror memberMirror, @@ -349,7 +352,7 @@ class _Group { var fullName = _combineNames(this.name, name); var timeout = _getAnnotationInstance(memberMirror, TestTimeout) as TestTimeout?; - tests.add(new _Test(isSolo, fullName, function, timeout?._timeout)); + tests.add(_Test(isSolo, fullName, function, timeout?._timeout)); } } diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 51cb753ac..57cf02b92 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.2.1-dev +version: 0.2.1 description: Support for discovering tests and test suites using reflection. repository: https://github.com/dart-lang/test_reflective_loader @@ -8,4 +8,4 @@ environment: dependencies: lints: ^1.0.0 - test: '>=1.16.0 <2.0.0' + test: ^1.16.0 diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index d303a75ba..ea7911f7f 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -33,7 +33,7 @@ class TestReflectiveLoaderTest { @failingTest Future test_fails_throws_async() { - return new Future.error('foo'); + return Future.error('foo'); } @skippedTest From da50cb8ae946485665eb14c59b135535180a0447 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 19 May 2022 14:39:06 -0700 Subject: [PATCH 0846/1215] Make a separate library for async expand methods (dart-lang/stream_transform#144) Pull `concurrentAsyncExpand` out from the merge extensions into a new extension. We will add `asyncExpandSample` in a followup, so having these in a dedicated library will make it easier for editors to find. This could be breaking, but only for code that references the extension name directly, which is an unlikely pattern. No usages of that pattern exist in Dart code on Github. Inline the implementation of `concurrentAsyncExpand` instead of implementing a separate extension on `Stream` --- .../lib/src/async_expand.dart | 90 +++++++++++++++++++ pkgs/stream_transform/lib/src/merge.dart | 81 ----------------- pkgs/stream_transform/lib/src/switch.dart | 2 +- .../lib/stream_transform.dart | 1 + ...xpand_test.dart => async_expand_test.dart} | 0 5 files changed, 92 insertions(+), 82 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/async_expand.dart rename pkgs/stream_transform/test/{concurrent_async_expand_test.dart => async_expand_test.dart} (100%) diff --git a/pkgs/stream_transform/lib/src/async_expand.dart b/pkgs/stream_transform/lib/src/async_expand.dart new file mode 100644 index 000000000..265f4819c --- /dev/null +++ b/pkgs/stream_transform/lib/src/async_expand.dart @@ -0,0 +1,90 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'switch.dart'; + +/// Alternatives to [asyncExpand]. +/// +/// The built in [asyncExpand] will not overlap the inner streams and every +/// event will be sent to the callback individually. +/// +/// - [concurrentAsyncExpand] allow overlap and merges inner streams without +/// ordering guarantees. +extension AsyncExpand on Stream { + /// Like [asyncExpand] but the [convert] callback may be called for an element + /// before the [Stream] emitted by the previous element has closed. + /// + /// Events on the result stream will be emitted in the order they are emitted + /// by the sub streams, which may not match the order of the original stream. + /// + /// Errors from [convert], the source stream, or any of the sub streams are + /// forwarded to the result stream. + /// + /// The result stream will not close until the source stream closes and all + /// sub streams have closed. + /// + /// If the source stream is a broadcast stream, the result will be as well, + /// regardless of the types of streams created by [convert]. In this case, + /// some care should be taken: + /// - If [convert] returns a single subscription stream it may be listened to + /// and never canceled. + /// - For any period of time where there are no listeners on the result + /// stream, any sub streams from previously emitted events will be ignored, + /// regardless of whether they emit further events after a listener is added + /// back. + /// + /// See also: + /// + /// * [switchMap], which cancels subscriptions to the previous sub + /// stream instead of concurrently emitting events from all sub streams. + Stream concurrentAsyncExpand(Stream Function(T) convert) { + final controller = isBroadcast + ? StreamController.broadcast(sync: true) + : StreamController(sync: true); + + controller.onListen = () { + final subscriptions = >[]; + final outerSubscription = map(convert).listen((inner) { + if (isBroadcast && !inner.isBroadcast) { + inner = inner.asBroadcastStream(); + } + final subscription = + inner.listen(controller.add, onError: controller.addError); + subscription.onDone(() { + subscriptions.remove(subscription); + if (subscriptions.isEmpty) controller.close(); + }); + subscriptions.add(subscription); + }, onError: controller.addError); + outerSubscription.onDone(() { + subscriptions.remove(outerSubscription); + if (subscriptions.isEmpty) controller.close(); + }); + subscriptions.add(outerSubscription); + if (!isBroadcast) { + controller + ..onPause = () { + for (final subscription in subscriptions) { + subscription.pause(); + } + } + ..onResume = () { + for (final subscription in subscriptions) { + subscription.resume(); + } + }; + } + controller.onCancel = () { + if (subscriptions.isEmpty) return null; + var cancels = [for (var s in subscriptions) s.cancel()] + // Handle opt-out nulls + ..removeWhere((Object? f) => f == null); + return Future.wait(cancels).then((_) => null); + }; + }; + return controller.stream; + } +} diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 55fe40951..7784bdbe0 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -4,8 +4,6 @@ import 'dart:async'; -import 'package:stream_transform/src/switch.dart'; - /// Utilities to interleave events from multiple streams. extension Merge on Stream { /// Returns a stream which emits values and errors from the source stream and @@ -101,83 +99,4 @@ extension Merge on Stream { }; return controller.stream; } - - /// Like [asyncExpand] but the [convert] callback may be called for an element - /// before the [Stream] emitted by the previous element has closed. - /// - /// Events on the result stream will be emitted in the order they are emitted - /// by the sub streams, which may not match the order of the original stream. - /// - /// Errors from [convert], the source stream, or any of the sub streams are - /// forwarded to the result stream. - /// - /// The result stream will not close until the source stream closes and all - /// sub streams have closed. - /// - /// If the source stream is a broadcast stream, the result will be as well, - /// regardless of the types of streams created by [convert]. In this case, - /// some care should be taken: - /// - If [convert] returns a single subscription stream it may be listened to - /// and never canceled. - /// - For any period of time where there are no listeners on the result - /// stream, any sub streams from previously emitted events will be ignored, - /// regardless of whether they emit further events after a listener is added - /// back. - /// - /// See also: - /// - /// * [switchMap], which cancels subscriptions to the previous sub - /// stream instead of concurrently emitting events from all sub streams. - Stream concurrentAsyncExpand(Stream Function(T) convert) => - map(convert).mergeExpanded(); -} - -extension _MergeExpanded on Stream> { - Stream mergeExpanded() { - final controller = isBroadcast - ? StreamController.broadcast(sync: true) - : StreamController(sync: true); - - controller.onListen = () { - final subscriptions = >[]; - final outerSubscription = listen((inner) { - if (isBroadcast && !inner.isBroadcast) { - inner = inner.asBroadcastStream(); - } - final subscription = - inner.listen(controller.add, onError: controller.addError); - subscription.onDone(() { - subscriptions.remove(subscription); - if (subscriptions.isEmpty) controller.close(); - }); - subscriptions.add(subscription); - }, onError: controller.addError); - outerSubscription.onDone(() { - subscriptions.remove(outerSubscription); - if (subscriptions.isEmpty) controller.close(); - }); - subscriptions.add(outerSubscription); - if (!isBroadcast) { - controller - ..onPause = () { - for (final subscription in subscriptions) { - subscription.pause(); - } - } - ..onResume = () { - for (final subscription in subscriptions) { - subscription.resume(); - } - }; - } - controller.onCancel = () { - if (subscriptions.isEmpty) return null; - var cancels = [for (var s in subscriptions) s.cancel()] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); - return Future.wait(cancels).then((_) => null); - }; - }; - return controller.stream; - } } diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 1fa07da4f..c749fbfa0 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -4,7 +4,7 @@ import 'dart:async'; -import 'package:stream_transform/src/merge.dart'; +import 'async_expand.dart'; /// A utility to take events from the most recent sub stream returned by a /// callback. diff --git a/pkgs/stream_transform/lib/stream_transform.dart b/pkgs/stream_transform/lib/stream_transform.dart index d04c4dd77..edf4df9e4 100644 --- a/pkgs/stream_transform/lib/stream_transform.dart +++ b/pkgs/stream_transform/lib/stream_transform.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. +export 'src/async_expand.dart'; export 'src/async_map.dart'; export 'src/combine_latest.dart'; export 'src/concatenate.dart'; diff --git a/pkgs/stream_transform/test/concurrent_async_expand_test.dart b/pkgs/stream_transform/test/async_expand_test.dart similarity index 100% rename from pkgs/stream_transform/test/concurrent_async_expand_test.dart rename to pkgs/stream_transform/test/async_expand_test.dart From 2a73eacc13f487b86056ef52c791f885c5e0ff17 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 23 May 2022 11:06:15 -0700 Subject: [PATCH 0847/1215] Start table with comparisons to ReactiveX (dart-lang/stream_transform#146) Towards dart-lang/stream_transform#99 Add in the `RateLimit` extension methods from this package, as well as the Rx operators they correspond to, and similar ones for which we don't yet have an equivalent. --- pkgs/stream_transform/README.md | 50 +++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 187a43b14..d3c71c643 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -79,6 +79,56 @@ Blocks events for a duration after an event is successfully emitted. Like `Iterable.whereType` for a stream. +### Comparison to Rx Operators + +The semantics and naming in this package have some overlap, and some conflict, +with the [ReactiveX](https://reactivex.io/) suite of libraries. Some of the +conflict is intentional - Dart `Stream` predates `Observable` and coherence with +the Dart ecosystem semantics and naming is a strictly higher priority than +consistency with ReactiveX. + +Rx Operator Category | variation | `stream_transform` +------------------------- | ------------------------------------------------------ | ------------------ +[`sample`][rx_sample] | `sample/throttleLast(Duration)` | No equivalent +​ | `throttleFirst(Duration)` | [`throttle`][throttle] +​ | `sample(Observable)` | No equivalent +[`debounce`][rx_debounce] | `debounce/throttleWithTimeout(Duration)` | [`debounce`][debounce] +​ | `debounce(Observable)` | No equivalent +[`buffer`][rx_buffer] | `buffer(boundary)`, `bufferWithTime`,`bufferWithCount` | No equivalent +​ | `buffer(boundaryClosingSelector)` | No equivalent[^1] +RxJs extensions | [`audit(callback)`][rxjs_audit] | No equivalent +​ | [`auditTime(Duration)`][rxjs_auditTime] | [`audit`][audit] +​ | [`exhaustMap`][rxjs_exhaustMap] | No equivalent +​ | [`throttleTime(trailing: true)`][rxjs_throttleTime] | `throttle(trailing: true)` +​ | `throttleTime(leading: false, trailing: true)` | No equivalent +No equivalent? | | [`asyncMapBuffer`][asyncMapBuffer] +​ | | [`asyncMapSample`][asyncMapSample] +​ | | [`buffer`][buffer][^1] +​ | | [`debounceBuffer`][debounceBuffer] +​ | | `debounce(leading: true, trailing: false)` +​ | | `debounce(leading: true, trailing: true)` + +[rx_sample]:https://reactivex.io/documentation/operators/sample.html +[rx_debounce]:https://reactivex.io/documentation/operators/debounce.html +[rx_buffer]:https://reactivex.io/documentation/operators/buffer.html +[rxjs_audit]:https://rxjs.dev/api/operators/audit +[rxjs_auditTime]:https://rxjs.dev/api/operators/auditTime +[rxjs_throttleTime]:https://rxjs.dev/api/operators/throttleTime +[rxjs_exhaustMap]:https://rxjs.dev/api/operators/exhaustMap +[asyncMapBuffer]:https://pub.dev/documentation/stream_transform/latest/stream_transform/AsyncMap/asyncMapBuffer.html +[asyncMapSample]:https://pub.dev/documentation/stream_transform/latest/stream_transform/AsyncMap/asyncMapSample.html +[audit]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/audit.html +[buffer]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/buffer.html +[debounceBuffer]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/debounceBuffer.html +[debounce]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/debounce.html +[throttle]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/throttle.html +[^1]: `stream_transform` `buffer` is closest to + [`buffer(bufferClosingSelector)`][rx_buffer], except where the trigger + emits while no events are buffered. ReactiveX will immediately emit and + empty list, while `stream_transform` will wait and emit a single element + list when the next event occurs. You can think of it like + `stream_transform` implemeting the "long polling" version of `buffer`. + # Getting a `StreamTransformer` instance It may be useful to pass an instance of `StreamTransformer` so that it can be From dab46d196ab452d399e04d382854e758841b33bd Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 25 May 2022 18:32:25 -0700 Subject: [PATCH 0848/1215] Implement `sample`, add `longPoll` to `buffer` (dart-lang/stream_transform#147) Closes dart-lang/stream_transform#145 Add `longPoll` support to `aggregateSample`. This method is a package private implementation detail. - Refactor to named arguments to make changes smoother. - Add `longPoll` boolean argument and conditional behavior in each stream callback. - Add `onEmpty` callback to let the caller decide whether to emit some default (empty list in the `buffer` case) or not emit at all (in the `sample` case) for triggers which do no set up a long poll and have no prior aggregated events. - Switch `waitingForTrigger` to the inverted condition `activeLongPoll` since it is a closer match to how the behavior is described in the docs. Add `longPoll` argument to `buffer` and update the doc to describe the conditional behavior. Add a section in the docs discussing the end of stream behavior. Add a `sample` method which is similar to `buffer`. Cross reference each method in the docs. Update the comparison table with Rx. Show that `buffer` is equivalent to `buffer(longPoll: false)`, that `sample` is `sampel(longPoll: false)`. I cannot find an equivalent Rx method to the `longPoll: true` behavior. --- pkgs/stream_transform/README.md | 16 +- .../lib/src/aggregate_sample.dart | 60 +++- pkgs/stream_transform/lib/src/async_map.dart | 7 +- pkgs/stream_transform/lib/src/rate_limit.dart | 73 +++- pkgs/stream_transform/test/buffer_test.dart | 330 ++++++++++-------- pkgs/stream_transform/test/sample_test.dart | 291 +++++++++++++++ 6 files changed, 602 insertions(+), 175 deletions(-) create mode 100644 pkgs/stream_transform/test/sample_test.dart diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index d3c71c643..ee0ac2ee5 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -89,13 +89,13 @@ consistency with ReactiveX. Rx Operator Category | variation | `stream_transform` ------------------------- | ------------------------------------------------------ | ------------------ -[`sample`][rx_sample] | `sample/throttleLast(Duration)` | No equivalent +[`sample`][rx_sample] | `sample/throttleLast(Duration)` | `sample(Stream.periodic(Duration), longPoll: false)` ​ | `throttleFirst(Duration)` | [`throttle`][throttle] -​ | `sample(Observable)` | No equivalent +​ | `sample(Observable)` | `sample(trigger, longPoll: false)` [`debounce`][rx_debounce] | `debounce/throttleWithTimeout(Duration)` | [`debounce`][debounce] ​ | `debounce(Observable)` | No equivalent [`buffer`][rx_buffer] | `buffer(boundary)`, `bufferWithTime`,`bufferWithCount` | No equivalent -​ | `buffer(boundaryClosingSelector)` | No equivalent[^1] +​ | `buffer(boundaryClosingSelector)` | `buffer(trigger, longPoll: false)` RxJs extensions | [`audit(callback)`][rxjs_audit] | No equivalent ​ | [`auditTime(Duration)`][rxjs_auditTime] | [`audit`][audit] ​ | [`exhaustMap`][rxjs_exhaustMap] | No equivalent @@ -103,7 +103,8 @@ RxJs extensions | [`audit(callback)`][rxjs_audit] ​ | `throttleTime(leading: false, trailing: true)` | No equivalent No equivalent? | | [`asyncMapBuffer`][asyncMapBuffer] ​ | | [`asyncMapSample`][asyncMapSample] -​ | | [`buffer`][buffer][^1] +​ | | [`buffer`][buffer] +​ | | [`sample`][sample] ​ | | [`debounceBuffer`][debounceBuffer] ​ | | `debounce(leading: true, trailing: false)` ​ | | `debounce(leading: true, trailing: true)` @@ -119,15 +120,10 @@ No equivalent? | [asyncMapSample]:https://pub.dev/documentation/stream_transform/latest/stream_transform/AsyncMap/asyncMapSample.html [audit]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/audit.html [buffer]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/buffer.html +[sample]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/sample.html [debounceBuffer]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/debounceBuffer.html [debounce]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/debounce.html [throttle]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/throttle.html -[^1]: `stream_transform` `buffer` is closest to - [`buffer(bufferClosingSelector)`][rx_buffer], except where the trigger - emits while no events are buffered. ReactiveX will immediately emit and - empty list, while `stream_transform` will wait and emit a single element - list when the next event occurs. You can think of it like - `stream_transform` implemeting the "long polling" version of `buffer`. # Getting a `StreamTransformer` instance diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index 0eea768ff..aa47c1e68 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -5,41 +5,67 @@ import 'dart:async'; extension AggregateSample on Stream { - /// Aggregates values and emits when it sees a value on [trigger]. + /// Computes a value based on sequences of events, then emits that value when + /// [trigger] emits an event. /// - /// If there are no pending values when [trigger] emits, the next value on the - /// source Stream will be passed to [aggregate] and emitted on the result - /// stream immediately. Otherwise, the pending values are released when - /// [trigger] emits. + /// Every time this stream emits an event, an intermediate value is created + /// by combining the new event with the previous intermediate value, or with + /// `null` if there is no previous value, using the [aggregate] function. /// + /// When [trigger] emits value, the returned stream emits the current + /// intermediate value and clears it. + /// + /// If [longPoll] is `false`, if there is no intermediate value when [trigger] + /// emits an event, the [onEmpty] function is called with a [Sink] which can + /// add events to the returned stream. + /// + /// If [longPoll] is `true`, and there is no intermediate value when [trigger] + /// emits one or more events, then the *next* event from this stream is + /// immediately put through [aggregate] and emitted on the returned stream. + /// Subsequent events on [trigger] while there have been no events on this + /// stream are ignored. + /// In that case, [onEmpty] is never used. + /// + /// The result stream will close as soon as there is a guarantee it will not + /// emit any more events. There will not be any more events emitted if: + /// - [trigger] is closed and there is no waiting long poll. + /// - Or, the source stream is closed and there are no buffered events. + /// + /// If the source stream is a broadcast stream, the result will be as well. /// Errors from the source stream or the trigger are immediately forwarded to /// the output. Stream aggregateSample( - Stream trigger, S Function(T, S?) aggregate) { + {required Stream trigger, + required S Function(T, S?) aggregate, + required bool longPoll, + required void Function(Sink) onEmpty}) { var controller = isBroadcast ? StreamController.broadcast(sync: true) : StreamController(sync: true); S? currentResults; var hasCurrentResults = false; - var waitingForTrigger = true; + var activeLongPoll = false; var isTriggerDone = false; var isValueDone = false; StreamSubscription? valueSub; StreamSubscription? triggerSub; - void emit() { - controller.add(currentResults as S); + void emit(S results) { currentResults = null; hasCurrentResults = false; - waitingForTrigger = true; + controller.add(results); } void onValue(T value) { currentResults = aggregate(value, currentResults); hasCurrentResults = true; + if (!longPoll) return; - if (!waitingForTrigger) emit(); + if (activeLongPoll) { + activeLongPoll = false; + emit(currentResults as S); + } if (isTriggerDone) { valueSub!.cancel(); @@ -56,9 +82,13 @@ extension AggregateSample on Stream { } void onTrigger(_) { - waitingForTrigger = false; - - if (hasCurrentResults) emit(); + if (hasCurrentResults) { + emit(currentResults as S); + } else if (longPoll) { + activeLongPoll = true; + } else { + onEmpty(controller); + } if (isValueDone) { triggerSub!.cancel(); @@ -68,7 +98,7 @@ extension AggregateSample on Stream { void onTriggerDone() { isTriggerDone = true; - if (waitingForTrigger) { + if (!activeLongPoll) { valueSub?.cancel(); controller.close(); } diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index f6022525f..c7898274e 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -67,7 +67,11 @@ extension AsyncMap on Stream { var workFinished = StreamController() // Let the first event through. ..add(null); - return aggregateSample(workFinished.stream, _dropPrevious) + return aggregateSample( + trigger: workFinished.stream, + aggregate: _dropPrevious, + longPoll: true, + onEmpty: _ignore) ._asyncMapThen(convert, workFinished.add); } @@ -128,3 +132,4 @@ extension AsyncMap on Stream { } T _dropPrevious(T event, _) => event; +void _ignore(Sink sink) {} diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index b29f4f561..1d3133917 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -221,18 +221,75 @@ extension RateLimit on Stream { }); } - /// Returns a Stream which collects values and emits when it sees a value on - /// [trigger]. + /// Buffers the values emitted on this stream and emits them when [trigger] + /// emits an event. /// - /// If there are no pending values when [trigger] emits, the next value on the - /// source Stream will immediately flow through. Otherwise, the pending values - /// are released when [trigger] emits. + /// If [longPoll] is `false`, if there are no buffered values when [trigger] + /// emits an empty list is immediately emitted. + /// + /// If [longPoll] is `true`, and there are no buffered values when [trigger] + /// emits one or more events, then the *next* value from this stream is + /// immediately emitted on the returned stream as a single element list. + /// Subsequent events on [trigger] while there have been no events on this + /// stream are ignored. + /// + /// The result stream will close as soon as there is a guarantee it will not + /// emit any more events. There will not be any more events emitted if: + /// - [trigger] is closed and there is no waiting long poll. + /// - Or, the source stream is closed and previously buffered events have been + /// delivered. /// /// If the source stream is a broadcast stream, the result will be as well. /// Errors from the source stream or the trigger are immediately forwarded to /// the output. - Stream> buffer(Stream trigger) => - aggregateSample>(trigger, _collect); + /// + /// See also: + /// - [sample] which use a [trigger] stream in the same way, but keeps only + /// the most recent source event. + Stream> buffer(Stream trigger, {bool longPoll = true}) => + aggregateSample( + trigger: trigger, + aggregate: _collect, + longPoll: longPoll, + onEmpty: _empty); + + /// Creates a stream which emits the most recent new value from the source + /// stream when it sees a value on [trigger]. + /// + /// If [longPoll] is `false`, then an event on [trigger] when there is no + /// pending source event will be ignored. + /// If [longPoll] is `true` (the default), then an event on [trigger] when + /// there is no pending source event will cause the next source event + /// to immediately flow to the result stream. + /// + /// If [longPoll] is `false`, if there is no pending source event when + /// [trigger] emits, then the trigger event will be ignored. + /// + /// If [longPoll] is `true`, and there are no buffered values when [trigger] + /// emits one or more events, then the *next* value from this stream is + /// immediately emitted on the returned stream as a single element list. + /// Subsequent events on [trigger] while there have been no events on this + /// stream are ignored. + /// + /// The result stream will close as soon as there is a guarantee it will not + /// emit any more events. There will not be any more events emitted if: + /// - [trigger] is closed and there is no waiting long poll. + /// - Or, the source stream is closed and any pending source event has been + /// delivered. + /// + /// If the source stream is a broadcast stream, the result will be as well. + /// Errors from the source stream or the trigger are immediately forwarded to + /// the output. + /// + /// See also: + /// - [buffer] which use [trigger] stream in the same way, but keeps a list of + /// pending source events. + Stream sample(Stream trigger, {bool longPoll = true}) => + aggregateSample( + trigger: trigger, + aggregate: _dropPrevious, + longPoll: longPoll, + onEmpty: _ignore); /// Aggregates values until the source stream does not emit for [duration], /// then emits the aggregated values. @@ -279,3 +336,5 @@ extension RateLimit on Stream { T _dropPrevious(T element, _) => element; List _collect(T event, List? soFar) => (soFar ?? [])..add(event); +void _empty(Sink> sink) => sink.add([]); +void _ignore(Sink sink) {} diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index fc17f4ba3..1675c287e 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -20,7 +20,8 @@ void main() { late Stream> transformed; late StreamSubscription> subscription; - void setUpForStreamTypes(String triggerType, String valuesType) { + void setUpForStreamTypes(String triggerType, String valuesType, + {required bool longPoll}) { valuesCanceled = false; triggerCanceled = false; triggerPaused = false; @@ -40,7 +41,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = values.stream.buffer(trigger.stream); + transformed = values.stream.buffer(trigger.stream, longPoll: longPoll); subscription = transformed.listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; @@ -50,182 +51,227 @@ void main() { for (var triggerType in streamTypes) { for (var valuesType in streamTypes) { group('Trigger type: [$triggerType], Values type: [$valuesType]', () { - setUp(() { - setUpForStreamTypes(triggerType, valuesType); - }); + group('general behavior', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: true); + }); - test('does not emit before `trigger`', () async { - values.add(1); - await Future(() {}); - expect(emittedValues, isEmpty); - trigger.add(null); - await Future(() {}); - expect(emittedValues, [ - [1] - ]); - }); + test('does not emit before `trigger`', () async { + values.add(1); + await Future(() {}); + expect(emittedValues, isEmpty); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); - test('emits immediately if trigger emits before a value', () async { - trigger.add(null); - await Future(() {}); - expect(emittedValues, isEmpty); - values.add(1); - await Future(() {}); - expect(emittedValues, [ - [1] - ]); - }); + test('groups values between trigger', () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger.add(null); + values + ..add(3) + ..add(4); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [ + [1, 2], + [3, 4] + ]); + }); - test('two triggers in a row - emit then emit next value', () async { - values - ..add(1) - ..add(2); - await Future(() {}); - trigger - ..add(null) - ..add(null); - await Future(() {}); - values.add(3); - await Future(() {}); - expect(emittedValues, [ - [1, 2], - [3] - ]); - }); + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); - test('pre-emptive trigger then trigger after values', () async { - trigger.add(null); - await Future(() {}); - values - ..add(1) - ..add(2); - await Future(() {}); - trigger.add(null); - await Future(() {}); - expect(emittedValues, [ - [1], - [2] - ]); - }); + test('closes when trigger ends', () async { + expect(isDone, false); + await trigger.close(); + await Future(() {}); + expect(isDone, true); + }); - test('multiple pre-emptive triggers, only emits first value', () async { - trigger - ..add(null) - ..add(null); - await Future(() {}); - values - ..add(1) - ..add(2); - await Future(() {}); - expect(emittedValues, [ - [1] - ]); - }); + test('closes after outputting final values when source closes', + () async { + expect(isDone, false); + values.add(1); + await values.close(); + expect(isDone, false); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [ + [1] + ]); + expect(isDone, true); + }); - test('groups values between trigger', () async { - values - ..add(1) - ..add(2); - await Future(() {}); - trigger.add(null); - values - ..add(3) - ..add(4); - await Future(() {}); - trigger.add(null); - await Future(() {}); - expect(emittedValues, [ - [1, 2], - [3, 4] - ]); - }); + test('closes when source closes and there are no buffered', () async { + expect(isDone, false); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); - test('cancels value subscription when output canceled', () async { - expect(valuesCanceled, false); - await subscription.cancel(); - expect(valuesCanceled, true); - }); + test('forwards errors from trigger', () async { + trigger.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); - test('closes when trigger ends', () async { - expect(isDone, false); - await trigger.close(); - await Future(() {}); - expect(isDone, true); + test('forwards errors from values', () async { + values.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); }); - test('closes after outputting final values when source closes', - () async { - expect(isDone, false); - values.add(1); - await values.close(); - expect(isDone, false); - trigger.add(null); - await Future(() {}); - expect(emittedValues, [ - [1] - ]); - expect(isDone, true); - }); + group('long polling', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: true); + }); - test('closes if there are no pending values when source closes', - () async { - expect(isDone, false); - values.add(1); - trigger.add(null); - await values.close(); - await Future(() {}); - expect(isDone, true); - }); + test('emits immediately if trigger emits before a value', () async { + trigger.add(null); + await Future(() {}); + expect(emittedValues, isEmpty); + values.add(1); + await Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); - test('waits to emit if there is a pending trigger when trigger closes', - () async { - trigger.add(null); - await trigger.close(); - expect(isDone, false); - values.add(1); - await Future(() {}); - expect(emittedValues, [ - [1] - ]); - expect(isDone, true); - }); + test('two triggers in a row - emit buffere then emit next value', + () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger + ..add(null) + ..add(null); + await Future(() {}); + values.add(3); + await Future(() {}); + expect(emittedValues, [ + [1, 2], + [3] + ]); + }); + + test('pre-emptive trigger then trigger after values', () async { + trigger.add(null); + await Future(() {}); + values + ..add(1) + ..add(2); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [ + [1], + [2] + ]); + }); - test('forwards errors from trigger', () async { - trigger.addError('error'); - await Future(() {}); - expect(errors, ['error']); + test('multiple pre-emptive triggers, only emits first value', + () async { + trigger + ..add(null) + ..add(null); + await Future(() {}); + values + ..add(1) + ..add(2); + await Future(() {}); + expect(emittedValues, [ + [1] + ]); + }); + + test('closes if there is no waiting long poll when source closes', + () async { + expect(isDone, false); + values.add(1); + trigger.add(null); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); + + test('waits to emit if there waiting long poll when trigger closes', + () async { + trigger.add(null); + await trigger.close(); + expect(isDone, false); + values.add(1); + await Future(() {}); + expect(emittedValues, [ + [1] + ]); + expect(isDone, true); + }); }); - test('forwards errors from values', () async { - values.addError('error'); - await Future(() {}); - expect(errors, ['error']); + group('immediate polling', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: false); + }); + + test('emits empty list before values', () async { + trigger.add(null); + await Future(() {}); + expect(emittedValues, [[]]); + }); + + test('emits empty list after emitting values', () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger + ..add(null) + ..add(null); + await Future(() {}); + expect(emittedValues, [ + [1, 2], + [] + ]); + }); }); }); } } test('always cancels trigger if values is singlesubscription', () async { - setUpForStreamTypes('broadcast', 'single subscription'); + setUpForStreamTypes('broadcast', 'single subscription', longPoll: true); expect(triggerCanceled, false); await subscription.cancel(); expect(triggerCanceled, true); - setUpForStreamTypes('single subscription', 'single subscription'); + setUpForStreamTypes('single subscription', 'single subscription', + longPoll: true); expect(triggerCanceled, false); await subscription.cancel(); expect(triggerCanceled, true); }); test('cancels trigger if trigger is broadcast', () async { - setUpForStreamTypes('broadcast', 'broadcast'); + setUpForStreamTypes('broadcast', 'broadcast', longPoll: true); expect(triggerCanceled, false); await subscription.cancel(); expect(triggerCanceled, true); }); test('pauses single subscription trigger for broadcast values', () async { - setUpForStreamTypes('single subscription', 'broadcast'); + setUpForStreamTypes('single subscription', 'broadcast', longPoll: true); expect(triggerCanceled, false); expect(triggerPaused, false); await subscription.cancel(); @@ -235,7 +281,7 @@ void main() { for (var triggerType in streamTypes) { test('cancel and relisten with [$triggerType] trigger', () async { - setUpForStreamTypes(triggerType, 'broadcast'); + setUpForStreamTypes(triggerType, 'broadcast', longPoll: true); values.add(1); trigger.add(null); await Future(() {}); diff --git a/pkgs/stream_transform/test/sample_test.dart b/pkgs/stream_transform/test/sample_test.dart new file mode 100644 index 000000000..66ca09db8 --- /dev/null +++ b/pkgs/stream_transform/test/sample_test.dart @@ -0,0 +1,291 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; + +import 'utils.dart'; + +void main() { + late StreamController trigger; + late StreamController values; + late List emittedValues; + late bool valuesCanceled; + late bool triggerCanceled; + late bool triggerPaused; + late bool isDone; + late List errors; + late Stream transformed; + late StreamSubscription subscription; + + void setUpForStreamTypes(String triggerType, String valuesType, + {required bool longPoll}) { + valuesCanceled = false; + triggerCanceled = false; + triggerPaused = false; + trigger = createController(triggerType) + ..onCancel = () { + triggerCanceled = true; + }; + if (triggerType == 'single subscription') { + trigger.onPause = () { + triggerPaused = true; + }; + } + values = createController(valuesType) + ..onCancel = () { + valuesCanceled = true; + }; + emittedValues = []; + errors = []; + isDone = false; + transformed = values.stream.sample(trigger.stream, longPoll: longPoll); + subscription = + transformed.listen(emittedValues.add, onError: errors.add, onDone: () { + isDone = true; + }); + } + + for (var triggerType in streamTypes) { + for (var valuesType in streamTypes) { + group('Trigger type: [$triggerType], Values type: [$valuesType]', () { + group('general behavior', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: true); + }); + + test('does not emit before `trigger`', () async { + values.add(1); + await Future(() {}); + expect(emittedValues, isEmpty); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [1]); + }); + + test('keeps most recent event between triggers', () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger.add(null); + values + ..add(3) + ..add(4); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [2, 4]); + }); + + test('cancels value subscription when output canceled', () async { + expect(valuesCanceled, false); + await subscription.cancel(); + expect(valuesCanceled, true); + }); + + test('closes when trigger ends', () async { + expect(isDone, false); + await trigger.close(); + await Future(() {}); + expect(isDone, true); + }); + + test('closes after outputting final values when source closes', + () async { + expect(isDone, false); + values.add(1); + await values.close(); + expect(isDone, false); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [1]); + expect(isDone, true); + }); + + test('closes when source closes and there is no pending', () async { + expect(isDone, false); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); + + test('forwards errors from trigger', () async { + trigger.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); + + test('forwards errors from values', () async { + values.addError('error'); + await Future(() {}); + expect(errors, ['error']); + }); + }); + + group('long polling', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: true); + }); + + test('emits immediately if trigger emits before a value', () async { + trigger.add(null); + await Future(() {}); + expect(emittedValues, isEmpty); + values.add(1); + await Future(() {}); + expect(emittedValues, [1]); + }); + + test('two triggers in a row - emit buffere then emit next value', + () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger + ..add(null) + ..add(null); + await Future(() {}); + values.add(3); + await Future(() {}); + expect(emittedValues, [2, 3]); + }); + + test('pre-emptive trigger then trigger after values', () async { + trigger.add(null); + await Future(() {}); + values + ..add(1) + ..add(2); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [1, 2]); + }); + + test('multiple pre-emptive triggers, only emits first value', + () async { + trigger + ..add(null) + ..add(null); + await Future(() {}); + values + ..add(1) + ..add(2); + await Future(() {}); + expect(emittedValues, [1]); + }); + + test('closes if there is no waiting long poll when source closes', + () async { + expect(isDone, false); + values.add(1); + trigger.add(null); + await values.close(); + await Future(() {}); + expect(isDone, true); + }); + + test('waits to emit if there waiting long poll when trigger closes', + () async { + trigger.add(null); + await trigger.close(); + expect(isDone, false); + values.add(1); + await Future(() {}); + expect(emittedValues, [1]); + expect(isDone, true); + }); + }); + + group('immediate polling', () { + setUp(() { + setUpForStreamTypes(triggerType, valuesType, longPoll: false); + }); + + test('ignores trigger before values', () async { + trigger.add(null); + await Future(() {}); + values + ..add(1) + ..add(2); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [2]); + }); + + test('ignores trigger if no pending values', () async { + values + ..add(1) + ..add(2); + await Future(() {}); + trigger + ..add(null) + ..add(null); + await Future(() {}); + values + ..add(3) + ..add(4); + await Future(() {}); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [2, 4]); + }); + }); + }); + } + } + + test('always cancels trigger if values is singlesubscription', () async { + setUpForStreamTypes('broadcast', 'single subscription', longPoll: true); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + + setUpForStreamTypes('single subscription', 'single subscription', + longPoll: true); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + }); + + test('cancels trigger if trigger is broadcast', () async { + setUpForStreamTypes('broadcast', 'broadcast', longPoll: true); + expect(triggerCanceled, false); + await subscription.cancel(); + expect(triggerCanceled, true); + }); + + test('pauses single subscription trigger for broadcast values', () async { + setUpForStreamTypes('single subscription', 'broadcast', longPoll: true); + expect(triggerCanceled, false); + expect(triggerPaused, false); + await subscription.cancel(); + expect(triggerCanceled, false); + expect(triggerPaused, true); + }); + + for (var triggerType in streamTypes) { + test('cancel and relisten with [$triggerType] trigger', () async { + setUpForStreamTypes(triggerType, 'broadcast', longPoll: true); + values.add(1); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [1]); + await subscription.cancel(); + values.add(2); + trigger.add(null); + await Future(() {}); + subscription = transformed.listen(emittedValues.add); + values.add(3); + trigger.add(null); + await Future(() {}); + expect(emittedValues, [1, 3]); + }); + } +} From 8cdeeecfa60b86bf3ebbfce62e527186de8f67d0 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 25 May 2022 19:36:01 -0700 Subject: [PATCH 0849/1215] Rephrase "Returns a stream" docs (dart-lang/stream_transform#149) Following up on a recent PR comment about this phrasing in the docs for `buffer` and `sample`. Rewrite all doc headers that started with "Returns a stream" to instead focus on the action on the stream. Reference `debounce` and `audit` from the `throttle` docs. Move the paragraphs with comparisons to `throttle` and `debounce` to a "See also" section in the `audit` docs. Replace some "the original stream" and "the source stream" with "this stream". Where some comments had to reflow anyway, separate sentences onto their own lines to reduce churn in the future in any sentence changes. Remove some unnecessary `Stream.` prefixes in dartdoc references. --- .../lib/src/async_expand.dart | 7 +- pkgs/stream_transform/lib/src/async_map.dart | 45 +++---- .../lib/src/combine_latest.dart | 4 +- .../stream_transform/lib/src/concatenate.dart | 41 +++---- pkgs/stream_transform/lib/src/merge.dart | 18 +-- pkgs/stream_transform/lib/src/rate_limit.dart | 114 ++++++++++-------- pkgs/stream_transform/lib/src/scan.dart | 9 +- pkgs/stream_transform/lib/src/switch.dart | 3 +- pkgs/stream_transform/lib/src/take_until.dart | 4 +- pkgs/stream_transform/lib/src/tap.dart | 14 +-- pkgs/stream_transform/lib/src/where.dart | 12 +- 11 files changed, 145 insertions(+), 126 deletions(-) diff --git a/pkgs/stream_transform/lib/src/async_expand.dart b/pkgs/stream_transform/lib/src/async_expand.dart index 265f4819c..98d8bb773 100644 --- a/pkgs/stream_transform/lib/src/async_expand.dart +++ b/pkgs/stream_transform/lib/src/async_expand.dart @@ -18,7 +18,7 @@ extension AsyncExpand on Stream { /// before the [Stream] emitted by the previous element has closed. /// /// Events on the result stream will be emitted in the order they are emitted - /// by the sub streams, which may not match the order of the original stream. + /// by the sub streams, which may not match the order of this stream. /// /// Errors from [convert], the source stream, or any of the sub streams are /// forwarded to the result stream. @@ -37,9 +37,8 @@ extension AsyncExpand on Stream { /// back. /// /// See also: - /// - /// * [switchMap], which cancels subscriptions to the previous sub - /// stream instead of concurrently emitting events from all sub streams. + /// - [switchMap], which cancels subscriptions to the previous sub stream + /// instead of concurrently emitting events from all sub streams. Stream concurrentAsyncExpand(Stream Function(T) convert) { final controller = isBroadcast ? StreamController.broadcast(sync: true) diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index c7898274e..c2ea253ca 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -22,21 +22,22 @@ extension AsyncMap on Stream { /// Like [asyncMap] but events are buffered until previous events have been /// processed by [convert]. /// - /// If the source stream is a broadcast stream the result will be as well. When - /// used with a broadcast stream behavior also differs from [Stream.asyncMap] in - /// that the [convert] function is only called once per event, rather than once - /// per listener per event. + /// If this stream is a broadcast stream the result will be as well. + /// When used with a broadcast stream behavior also differs from [asyncMap] in + /// that the [convert] function is only called once per event, rather than + /// once per listener per event. /// - /// The first event from the source stream is always passed to [convert] as a - /// List with a single element. After that events are buffered until the - /// previous Future returned from [convert] has fired. + /// The first event from this stream is always passed to [convert] as a + /// list with a single element. + /// After that, events are buffered until the previous Future returned from + /// [convert] has completed. /// - /// Errors from the source stream are forwarded directly to the result stream. + /// Errors from this stream are forwarded directly to the result stream. /// Errors during the conversion are also forwarded to the result stream and /// are considered completing work so the next values are let through. /// - /// The result stream will not close until the source stream closes and all - /// pending conversions have finished. + /// The result stream will not close until this stream closes and all pending + /// conversions have finished. Stream asyncMapBuffer(Future Function(List) convert) { var workFinished = StreamController() // Let the first event through. @@ -47,22 +48,22 @@ extension AsyncMap on Stream { /// Like [asyncMap] but events are discarded while work is happening in /// [convert]. /// - /// If the source stream is a broadcast stream the result will be as well. When - /// used with a broadcast stream behavior also differs from [Stream.asyncMap] in - /// that the [convert] function is only called once per event, rather than once - /// per listener per event. + /// If this stream is a broadcast stream the result will be as well. + /// When used with a broadcast stream behavior also differs from [asyncMap] in + /// that the [convert] function is only called once per event, rather than + /// once per listener per event. /// /// If no work is happening when an event is emitted it will be immediately /// passed to [convert]. If there is ongoing work when an event is emitted it /// will be held until the work is finished. New events emitted will replace a /// pending event. /// - /// Errors from the source stream are forwarded directly to the result stream. + /// Errors from this stream are forwarded directly to the result stream. /// Errors during the conversion are also forwarded to the result stream and are /// considered completing work so the next values are let through. /// - /// The result stream will not close until the source stream closes and all - /// pending conversions have finished. + /// The result stream will not close until this stream closes and all pending + /// conversions have finished. Stream asyncMapSample(Future Function(T) convert) { var workFinished = StreamController() // Let the first event through. @@ -79,19 +80,19 @@ extension AsyncMap on Stream { /// before processing for the previous element is finished. /// /// Events on the result stream will be emitted in the order that [convert] - /// completed which may not match the order of the original stream. + /// completed which may not match the order of this stream. /// - /// If the source stream is a broadcast stream the result will be as well. + /// If this stream is a broadcast stream the result will be as well. /// When used with a broadcast stream behavior also differs from [asyncMap] in /// that the [convert] function is only called once per event, rather than /// once per listener per event. The [convert] callback won't be called for /// events while a broadcast stream has no listener. /// - /// Errors from [convert] or the source stream are forwarded directly to the + /// Errors from [convert] or this stream are forwarded directly to the /// result stream. /// - /// The result stream will not close until the source stream closes and all - /// pending conversions have finished. + /// The result stream will not close until this stream closes and all pending + /// conversions have finished. Stream concurrentAsyncMap(FutureOr Function(T) convert) { var valuesWaiting = 0; var sourceDone = false; diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index dcaf672b5..5fbdbf520 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -7,8 +7,8 @@ import 'dart:async'; /// Utilities to combine events from multiple streams through a callback or into /// a list. extension CombineLatest on Stream { - /// Returns a stream which combines the latest value from the source stream - /// with the latest value from [other] using [combine]. + /// Combines the latest values from this stream with the latest values from + /// [other] using [combine]. /// /// No event will be emitted until both the source stream and [other] have /// each emitted at least one event. If either the source stream or [other] diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index 37a4d96f7..3277dcdd6 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -6,21 +6,21 @@ import 'dart:async'; /// Utilities to append or prepend to a stream. extension Concatenate on Stream { - /// Returns a stream which emits values and errors from [next] after the - /// original stream is complete. + /// Emits all values and errors from [next] following all values and errors + /// from this stream. /// - /// If the source stream never finishes, the [next] stream will never be - /// listened to. + /// If this stream never finishes, the [next] stream will never get a + /// listener. /// - /// If the source stream is a broadcast stream, the result will be as well. + /// If this stream is a broadcast stream, the result will be as well. /// If a single-subscription follows a broadcast stream it may be listened /// to and never canceled since there may be broadcast listeners added later. /// /// If a broadcast stream follows any other stream it will miss any events or - /// errors which occur before the original stream is done. If a broadcast - /// stream follows a single-subscription stream, pausing the stream while it - /// is listening to the second stream will cause events to be dropped rather - /// than buffered. + /// errors which occur before this stream is done. + /// If a broadcast stream follows a single-subscription stream, pausing the + /// stream while it is listening to the second stream will cause events to be + /// dropped rather than buffered. Stream followedBy(Stream next) { var controller = isBroadcast ? StreamController.broadcast(sync: true) @@ -79,28 +79,27 @@ extension Concatenate on Stream { return controller.stream; } - /// Returns a stream which emits [initial] before any values from the original - /// stream. + /// Emits [initial] before any values or errors from the this stream. /// - /// If the original stream is a broadcast stream the result will be as well. + /// If this stream is a broadcast stream the result will be as well. Stream startWith(T initial) => startWithStream(Future.value(initial).asStream()); - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. + /// Emits all values in [initial] before any values or errors from this + /// stream. /// - /// If the original stream is a broadcast stream the result will be as well. - /// If the original stream is a broadcast stream it will miss any events which + /// If this stream is a broadcast stream the result will be as well. + /// If this stream is a broadcast stream it will miss any events which /// occur before the initial values are all emitted. Stream startWithMany(Iterable initial) => startWithStream(Stream.fromIterable(initial)); - /// Returns a stream which emits all values in [initial] before any values - /// from the original stream. + /// Emits all values and errors in [initial] before any values or errors from + /// this stream. /// - /// If the original stream is a broadcast stream the result will be as well. If - /// the original stream is a broadcast stream it will miss any events which - /// occur before [initial] closes. + /// If this stream is a broadcast stream the result will be as well. + /// If this stream is a broadcast stream it will miss any events which occur + /// before [initial] closes. Stream startWithStream(Stream initial) { if (isBroadcast && !initial.isBroadcast) { initial = initial.asBroadcastStream(); diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 7784bdbe0..2725d5e63 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -6,11 +6,11 @@ import 'dart:async'; /// Utilities to interleave events from multiple streams. extension Merge on Stream { - /// Returns a stream which emits values and errors from the source stream and - /// [other] in any order as they arrive. + /// Merges values and errors from this stream and [other] in any order as they + /// arrive. /// - /// The result stream will not close until both the source stream and [other] - /// have closed. + /// The result stream will not close until both this stream and [other] have + /// closed. /// /// For example: /// @@ -20,7 +20,7 @@ extension Merge on Stream { /// other: ------4-------5--| /// result: 1--2--4--3----5--| /// - /// If the source stream is a broadcast stream, the result stream will be as + /// If this stream is a broadcast stream, the result stream will be as /// well, regardless of [other]'s type. If a single subscription stream is /// merged into a broadcast stream it may never be canceled since there may be /// broadcast listeners added later. @@ -30,10 +30,10 @@ extension Merge on Stream { /// be discarded. Stream merge(Stream other) => mergeAll([other]); - /// Returns a stream which emits values and errors from the source stream and - /// any stream in [others] in any order as they arrive. + /// Merges values and errors from this stream and any stream in [others] in + /// any order as they arrive. /// - /// The result stream will not close until the source stream and all streams + /// The result stream will not close until this stream and all streams /// in [others] have closed. /// /// For example: @@ -45,7 +45,7 @@ extension Merge on Stream { /// third: ------6---------------7--| /// result: 1--2--6--4--3----5----7--| /// - /// If the source stream is a broadcast stream, the result stream will be as + /// If this stream is a broadcast stream, the result stream will be as /// well, regardless the types of streams in [others]. If a single /// subscription stream is merged into a broadcast stream it may never be /// canceled since there may be broadcast listeners added later. diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 1d3133917..347919bde 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -17,8 +17,7 @@ import 'from_handlers.dart'; /// - [audit] - emit the _last_ event at the _end_ of the period. /// - [buffer] - emit _all_ events on a _trigger_. extension RateLimit on Stream { - /// Returns a Stream which suppresses events with less inter-event spacing - /// than [duration]. + /// Suppresses events with less inter-event spacing than [duration]. /// /// Events which are emitted with less than [duration] elapsed between them /// are considered to be part of the same "series". If [leading] is `true`, @@ -28,13 +27,13 @@ extension RateLimit on Stream { /// must be specified with `leading: true, trailing: false` to emit only /// leading events. /// - /// If the source stream is a broadcast stream, the result will be as well. + /// If this stream is a broadcast stream, the result will be as well. /// Errors are forwarded immediately. /// /// If there is a trailing event waiting during the debounce period when the /// source stream closes the returned stream will wait to emit it following /// the debounce period before closing. If there is no pending debounced event - /// when the source stream closes the returned stream will close immediately. + /// when this stream closes the returned stream will close immediately. /// /// For example: /// @@ -59,47 +58,49 @@ extension RateLimit on Stream { _debounceAggregate(duration, _dropPrevious, leading: leading, trailing: trailing); - /// Returns a Stream which collects values until the source stream does not - /// emit for [duration] then emits the collected values. + /// Buffers values until this stream does not emit for [duration] then emits + /// the collected values. /// /// Values will always be delayed by at least [duration], and values which /// come within this time will be aggregated into the same list. /// - /// If the source stream is a broadcast stream, the result will be as well. + /// If this stream is a broadcast stream, the result will be as well. /// Errors are forwarded immediately. /// - /// If there are events waiting during the debounce period when the source - /// stream closes the returned stream will wait to emit them following the - /// debounce period before closing. If there are no pending debounced events - /// when the source stream closes the returned stream will close immediately. + /// If there are events waiting during the debounce period when this stream + /// closes the returned stream will wait to emit them following the debounce + /// period before closing. If there are no pending debounced events when this + /// stream closes the returned stream will close immediately. /// /// To keep only the most recent event during the debounce period see /// [debounce]. Stream> debounceBuffer(Duration duration) => _debounceAggregate(duration, _collect, leading: false, trailing: true); - /// Returns a stream which only emits once per [duration], at the beginning of - /// the period. + /// Reduces the rate that events are emitted to at most once per [duration]. /// /// No events will ever be emitted within [duration] of another event on the /// result stream. - /// If the source stream is a broadcast stream, the result will be as well. + /// If this stream is a broadcast stream, the result will be as well. /// Errors are forwarded immediately. /// /// If [trailing] is `false`, source events emitted during the [duration] - /// period following a result event are discarded. The result stream will not - /// emit an event until the source stream emits an event following the - /// throttled period. If the source stream is consistently emitting events - /// with less than [duration] between events, the time between events on the - /// result stream may still be more than [duration]. The result stream will - /// close immediately when the source stream closes. + /// period following a result event are discarded. + /// The result stream will not emit an event until this stream emits an event + /// following the throttled period. + /// If this stream is consistently emitting events with less than + /// [duration] between events, the time between events on the result stream + /// may still be more than [duration]. + /// The result stream will close immediately when this stream closes. /// /// If [trailing] is `true`, the latest source event emitted during the /// [duration] period following an result event is held and emitted following - /// the period. If the source stream is consistently emitting events with less - /// than [duration] between events, the time between events on the result - /// stream will be [duration]. If the source stream closes the result stream - /// will wait to emit a pending event before closing. + /// the period. + /// If this stream is consistently emitting events with less than [duration] + /// between events, the time between events on the result stream will be + /// [duration]. + /// If this stream closes the result stream will wait to emit a pending event + /// before closing. /// /// For example: /// @@ -117,6 +118,14 @@ extension RateLimit on Stream { /// /// source: 1-2-----------3| /// result: 1-----2-------3| + /// + /// See also: + /// - [audit], which emits the most recent event at the end of the period. + /// Compared to `audit`, `throttle` will not introduce delay to forwarded + /// elements, except for the [trailing] events. + /// - [debounce], which uses inter-event spacing instead of a fixed period + /// from the first event in a window. Compared to `debouce`, `throttle` cannot + /// be starved by having events emitted continuously within [duration]. Stream throttle(Duration duration, {bool trailing = false}) => trailing ? _throttleTrailing(duration) : _throttle(duration); @@ -171,26 +180,25 @@ extension RateLimit on Stream { }); } - /// Returns a Stream which only emits once per [duration], at the end of the - /// period. + /// Audit a single event from each [duration] length period where there are + /// events on this stream. /// - /// If the source stream is a broadcast stream, the result will be as well. + /// No events will ever be emitted within [duration] of another event on the + /// result stream. + /// If this stream is a broadcast stream, the result will be as well. /// Errors are forwarded immediately. /// - /// If there is no pending event when the source stream closes the output - /// stream will close immediately. If there is a pending event the output - /// stream will wait to emit it before closing. + /// The first event will begin the audit period. At the end of the audit + /// period the most recent event is emitted, and the next event restarts the + /// audit period. /// - /// Differs from `throttle` in that it always emits the most recently received - /// event rather than the first in the period. The events that are emitted are - /// always delayed by some amount. If the event that started the period is the - /// one that is emitted it will be delayed by [duration]. If a later event - /// comes in within the period it's delay will be shorter by the difference in - /// arrival times. + /// If the event that started the period is the one that is emitted it will be + /// delayed by [duration]. If a later event comes in within the period it's + /// delay will be shorter by the difference in arrival times. /// - /// Differs from `debounce` in that a value will always be emitted after - /// [duration], the output will not be starved by values coming in repeatedly - /// within [duration]. + /// If there is no pending event when this stream closes the output + /// stream will close immediately. If there is a pending event the output + /// stream will wait to emit it before closing. /// /// For example: /// @@ -198,6 +206,14 @@ extension RateLimit on Stream { /// /// source: a------b--c----d--| /// output: -----a------c--------d| + /// + /// See also: + /// - [throttle], which emits the _first_ event during the window, instead of + /// the last event in the window. Compared to `throttle`, `audit` will + /// introduce delay to forwarded events. + /// - [debounce], which only emits after the stream has not emitted for some + /// period. Compared to `debouce`, `audit` cannot be starved by having events + /// emitted continuously within [duration]. Stream audit(Duration duration) { Timer? timer; var shouldClose = false; @@ -236,12 +252,12 @@ extension RateLimit on Stream { /// The result stream will close as soon as there is a guarantee it will not /// emit any more events. There will not be any more events emitted if: /// - [trigger] is closed and there is no waiting long poll. - /// - Or, the source stream is closed and previously buffered events have been + /// - Or, this stream is closed and previously buffered events have been /// delivered. /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors from the source stream or the trigger are immediately forwarded to - /// the output. + /// If this stream is a broadcast stream, the result will be as well. + /// Errors from this stream or the trigger are immediately forwarded to the + /// output. /// /// See also: /// - [sample] which use a [trigger] stream in the same way, but keeps only @@ -253,8 +269,8 @@ extension RateLimit on Stream { longPoll: longPoll, onEmpty: _empty); - /// Creates a stream which emits the most recent new value from the source - /// stream when it sees a value on [trigger]. + /// Emits the most recent new value from this stream when [trigger] emits an + /// event. /// /// If [longPoll] is `false`, then an event on [trigger] when there is no /// pending source event will be ignored. @@ -274,11 +290,11 @@ extension RateLimit on Stream { /// The result stream will close as soon as there is a guarantee it will not /// emit any more events. There will not be any more events emitted if: /// - [trigger] is closed and there is no waiting long poll. - /// - Or, the source stream is closed and any pending source event has been + /// - Or, this source stream is closed and any pending source event has been /// delivered. /// - /// If the source stream is a broadcast stream, the result will be as well. - /// Errors from the source stream or the trigger are immediately forwarded to + /// If this source stream is a broadcast stream, the result will be as well. + /// Errors from this source stream or the trigger are immediately forwarded to /// the output. /// /// See also: @@ -291,7 +307,7 @@ extension RateLimit on Stream { longPoll: longPoll, onEmpty: _ignore); - /// Aggregates values until the source stream does not emit for [duration], + /// Aggregates values until this source stream does not emit for [duration], /// then emits the aggregated values. Stream _debounceAggregate( Duration duration, S Function(T element, S? soFar) collect, diff --git a/pkgs/stream_transform/lib/src/scan.dart b/pkgs/stream_transform/lib/src/scan.dart index d14381cb1..acd3c7676 100644 --- a/pkgs/stream_transform/lib/src/scan.dart +++ b/pkgs/stream_transform/lib/src/scan.dart @@ -6,13 +6,16 @@ import 'dart:async'; /// A utility similar to [fold] which emits intermediate accumulations. extension Scan on Stream { + /// Emits a sequence of the accumulated values from repeatedly applying + /// [combine]. + /// /// Like [fold], but instead of producing a single value it yields each - /// intermediate accumulation. + /// intermediate result. /// - /// If [combine] returns a Future it will not be called again for subsequent + /// If [combine] returns a future it will not be called again for subsequent /// events from the source until it completes, therefore [combine] is always /// called for elements in order, and the result stream always maintains the - /// same order as the original. + /// same order as this stream. Stream scan( S initialValue, FutureOr Function(S soFar, T element) combine) { var accumulated = initialValue; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index c749fbfa0..4b4cdac17 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -35,8 +35,7 @@ extension Switch on Stream { /// and never canceled. /// /// See also: - /// - /// * [concurrentAsyncExpand], which emits events from all sub streams + /// - [concurrentAsyncExpand], which emits events from all sub streams /// concurrently instead of cancelling subscriptions to previous subs streams. Stream switchMap(Stream Function(T) convert) { return map(convert).switchLatest(); diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 32366edba..8f63d94b4 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -6,8 +6,8 @@ import 'dart:async'; /// A utility to end a stream based on an external trigger. extension TakeUntil on Stream { - /// Returns a stream which emits values from the source stream until [trigger] - /// fires. + /// Takes values from this stream which are emitted before [trigger] + /// completes. /// /// Completing [trigger] differs from canceling a subscription in that values /// which are emitted before the trigger, but have further asynchronous delays diff --git a/pkgs/stream_transform/lib/src/tap.dart b/pkgs/stream_transform/lib/src/tap.dart index 05ab32f0d..4b16ab5fd 100644 --- a/pkgs/stream_transform/lib/src/tap.dart +++ b/pkgs/stream_transform/lib/src/tap.dart @@ -8,15 +8,15 @@ extension Tap on Stream { /// Taps into this stream to allow additional handling on a single-subscriber /// stream without first wrapping as a broadcast stream. /// - /// The [onValue] callback will be called with every value from the source - /// stream before it is forwarded to listeners on the resulting stream. May be - /// null if only [onError] or [onDone] callbacks are needed. + /// The [onValue] callback will be called with every value from this stream + /// before it is forwarded to listeners on the resulting stream. + /// May be null if only [onError] or [onDone] callbacks are needed. /// - /// The [onError] callback will be called with every error from the source - /// stream before it is forwarded to listeners on the resulting stream. + /// The [onError] callback will be called with every error from this stream + /// before it is forwarded to listeners on the resulting stream. /// - /// The [onDone] callback will be called after the source stream closes and - /// before the resulting stream is closed. + /// The [onDone] callback will be called after this stream closes and before + /// the resulting stream is closed. /// /// Errors from any of the callbacks are caught and ignored. /// diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index ed3532e25..569dc3168 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -8,7 +8,7 @@ import 'from_handlers.dart'; /// Utilities to filter events. extension Where on Stream { - /// Returns a stream which emits only the events which have type [S]. + /// Discards events from this stream that are not of type [S]. /// /// If the source stream is a broadcast stream the result will be as well. /// @@ -21,15 +21,17 @@ extension Where on Stream { if (event is S) sink.add(event); }); + /// Discards events from this stream based on an asynchronous [test] callback. + /// /// Like [where] but allows the [test] to return a [Future]. /// /// Events on the result stream will be emitted in the order that [test] - /// completes which may not match the order of the original stream. + /// completes which may not match the order of this stream. /// /// If the source stream is a broadcast stream the result will be as well. When - /// used with a broadcast stream behavior also differs from [Stream.where] in - /// that the [test] function is only called once per event, rather than once - /// per listener per event. + /// used with a broadcast stream behavior also differs from [where] in that + /// the [test] function is only called once per event, rather than once per + /// listener per event. /// /// Errors from the source stream are forwarded directly to the result stream. /// Errors from [test] are also forwarded to the result stream. From 9e63a33afb0fc9c3f9c3975297fccbbb7e4825bd Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Thu, 2 Jun 2022 15:22:54 -0700 Subject: [PATCH 0850/1215] Add better support for dealing with supplemental-plane code units (dart-lang/string_scanner#46) --- pkgs/string_scanner/CHANGELOG.md | 14 ++ .../lib/src/eager_span_scanner.dart | 3 +- pkgs/string_scanner/lib/src/line_scanner.dart | 3 +- .../lib/src/string_scanner.dart | 64 +++++++- pkgs/string_scanner/lib/src/utils.dart | 64 ++++++++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/line_scanner_test.dart | 86 ++++++++++ .../test/span_scanner_test.dart | 68 ++++++-- .../test/string_scanner_test.dart | 148 ++++++++++++++++++ 9 files changed, 436 insertions(+), 16 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index cb4d29710..5963ce8e0 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,17 @@ +## 1.2.0 + +* Add better support for reading code points in the Unicode supplementary plane: + + * Added `StringScanner.readCodePoint()`, which consumes an entire Unicode code + point even if it's represented by two UTF-16 code units. + + * Added `StringScanner.peekCodePoint()`, which returns an entire Unicode code + point even if it's represented by two UTF-16 code units. + + * `StringScanner.scanChar()` and `StringScanner.expectChar()` will now + properly consume two UTF-16 code units if they're passed Unicode code points + in the supplementary plane. + ## 1.1.1 * Populate the pubspec `repository` field. diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index d27a818fa..3bf5416d2 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -5,6 +5,7 @@ import 'charcode.dart'; import 'line_scanner.dart'; import 'span_scanner.dart'; +import 'utils.dart'; // TODO(nweiz): Currently this duplicates code in line_scanner.dart. Once // sdk#23770 is fully complete, we should move the shared code into a mixin. @@ -90,7 +91,7 @@ class EagerSpanScanner extends SpanScanner { _line += 1; _column = 0; } else { - _column += 1; + _column += inSupplementaryPlane(character) ? 2 : 1; } } diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index af6b6e705..4f0673c9e 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -4,6 +4,7 @@ import 'charcode.dart'; import 'string_scanner.dart'; +import 'utils.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. @@ -95,7 +96,7 @@ class LineScanner extends StringScanner { _line += 1; _column = 0; } else { - _column += 1; + _column += inSupplementaryPlane(character) ? 2 : 1; } } diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index d254b044b..de566a5b6 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -90,16 +90,35 @@ class StringScanner { /// If the next character in the string is [character], consumes it. /// + /// If [character] is a Unicode code point in a supplementary plane, this will + /// consume two code units. Dart's string representation is UTF-16, which + /// represents supplementary-plane code units as two code units. + /// /// Returns whether or not [character] was consumed. bool scanChar(int character) { - if (isDone) return false; - if (string.codeUnitAt(_position) != character) return false; - _position++; - return true; + if (inSupplementaryPlane(character)) { + if (_position + 1 >= string.length || + string.codeUnitAt(_position) != highSurrogate(character) || + string.codeUnitAt(_position + 1) != lowSurrogate(character)) { + return false; + } else { + _position += 2; + return true; + } + } else { + if (isDone) return false; + if (string.codeUnitAt(_position) != character) return false; + _position++; + return true; + } } /// If the next character in the string is [character], consumes it. /// + /// If [character] is a Unicode code point in a supplementary plane, this will + /// consume two code units. Dart's string representation is UTF-16, which + /// represents supplementary-plane code units as two code units. + /// /// If [character] could not be consumed, throws a [FormatException] /// describing the position of the failure. [name] is used in this error as /// the expected name of the character being matched; if it's `null`, the @@ -120,6 +139,43 @@ class StringScanner { _fail(name); } + /// Consumes a single Unicode code unit and returns it. + /// + /// This works like [readChar], except that it automatically handles UTF-16 + /// surrogate pairs. Specifically, if the next two code units form a surrogate + /// pair, consumes them both and returns the corresponding Unicode code point. + /// + /// If next two characters are not a surrogate pair, the next code unit is + /// returned as-is, even if it's an unpaired surrogate. + int readCodePoint() { + final first = readChar(); + if (!isHighSurrogate(first)) return first; + + final next = peekChar(); + if (next == null || !isLowSurrogate(next)) return first; + + readChar(); + return decodeSurrogatePair(first, next); + } + + /// Returns the Unicode code point immediately after [position]. + /// + /// This works like [peekChar], except that it automatically handles UTF-16 + /// surrogate pairs. Specifically, if the next two code units form a surrogate + /// pair, returns the corresponding Unicode code point. + /// + /// If next two characters are not a surrogate pair, the next code unit is + /// returned as-is, even if it's an unpaired surrogate. + int? peekCodePoint() { + final first = peekChar(); + if (first == null || !isHighSurrogate(first)) return first; + + final next = peekChar(1); + if (next == null || !isLowSurrogate(next)) return first; + + return decodeSurrogatePair(first, next); + } + /// If [pattern] matches at the current position of the string, scans forward /// until the end of the match. /// diff --git a/pkgs/string_scanner/lib/src/utils.dart b/pkgs/string_scanner/lib/src/utils.dart index 52dfb6360..39891a16a 100644 --- a/pkgs/string_scanner/lib/src/utils.dart +++ b/pkgs/string_scanner/lib/src/utils.dart @@ -29,3 +29,67 @@ void validateErrorArgs( 'the string.'); } } + +// See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF +// for documentation on how UTF-16 encoding works and definitions of various +// related terms. + +/// The inclusive lower bound of Unicode's supplementary plane. +const _supplementaryPlaneLowerBound = 0x10000; + +/// The inclusive upper bound of Unicode's supplementary plane. +const _supplementaryPlaneUpperBound = 0x10FFFF; + +/// The inclusive lower bound of the UTF-16 high surrogate block. +const _highSurrogateLowerBound = 0xD800; + +/// The inclusive lower bound of the UTF-16 low surrogate block. +const _lowSurrogateLowerBound = 0xDC00; + +/// The number of low bits in each code unit of a surrogate pair that goes into +/// determining which code point it encodes. +const _surrogateBits = 10; + +/// A bit mask that covers the lower [_surrogateBits] of a code point, which can +/// be used to extract the value of a surrogate or the low surrogate value of a +/// code unit. +const _surrogateValueMask = (1 << _surrogateBits) - 1; + +/// Returns whether [codePoint] is in the Unicode supplementary plane, and thus +/// must be represented as a surrogate pair in UTF-16. +bool inSupplementaryPlane(int codePoint) => + codePoint >= _supplementaryPlaneLowerBound && + codePoint <= _supplementaryPlaneUpperBound; + +/// Returns whether [codeUnit] is a UTF-16 high surrogate. +bool isHighSurrogate(int codeUnit) => + (codeUnit & ~_surrogateValueMask) == _highSurrogateLowerBound; + +/// Returns whether [codeUnit] is a UTF-16 low surrogate. +bool isLowSurrogate(int codeUnit) => + (codeUnit >> _surrogateBits) == (_lowSurrogateLowerBound >> _surrogateBits); + +/// Returns the high surrogate needed to encode the supplementary-plane +/// [codePoint]. +int highSurrogate(int codePoint) { + assert(inSupplementaryPlane(codePoint)); + return ((codePoint - _supplementaryPlaneLowerBound) >> _surrogateBits) + + _highSurrogateLowerBound; +} + +/// Returns the low surrogate needed to encode the supplementary-plane +/// [codePoint]. +int lowSurrogate(int codePoint) { + assert(inSupplementaryPlane(codePoint)); + return ((codePoint - _supplementaryPlaneLowerBound) & _surrogateValueMask) + + _lowSurrogateLowerBound; +} + +/// Converts a UTF-16 surrogate pair into the Unicode code unit it represents. +int decodeSurrogatePair(int highSurrogate, int lowSurrogate) { + assert(isHighSurrogate(highSurrogate)); + assert(isLowSurrogate(lowSurrogate)); + return _supplementaryPlaneLowerBound + + (((highSurrogate & _surrogateValueMask) << _surrogateBits) | + (lowSurrogate & _surrogateValueMask)); +} diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 421a22739..c38f3bfe4 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.1.1 +version: 1.2.0 description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index a3deff1b7..d31d313a3 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -81,6 +81,39 @@ void main() { }); }); + group('readCodePoint()', () { + test('on a non-newline character increases the column but not the line', + () { + scanner.readCodePoint(); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(1)); + }); + + test('consuming a newline resets the column and increases the line', () { + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.readCodePoint(); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test("consuming halfway through a CR LF doesn't count as a line", () { + scanner.expect('foo\nbar'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(3)); + + scanner.readCodePoint(); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + + scanner.readCodePoint(); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); + }); + group('scanChar()', () { test('on a non-newline character increases the column but not the line', () { @@ -114,6 +147,59 @@ void main() { }); }); + group('before a surrogate pair', () { + final codePoint = '\uD83D\uDC6D'.runes.first; + const highSurrogate = 0xD83D; + + late LineScanner scanner; + setUp(() { + scanner = LineScanner('foo: \uD83D\uDC6D'); + expect(scanner.scan('foo: '), isTrue); + }); + + test('readChar returns the high surrogate and moves into the pair', () { + expect(scanner.readChar(), equals(highSurrogate)); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('readCodePoint returns the code unit and moves past the pair', () { + expect(scanner.readCodePoint(), equals(codePoint)); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + + test('scanChar with the high surrogate moves into the pair', () { + expect(scanner.scanChar(highSurrogate), isTrue); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('scanChar with the code point moves past the pair', () { + expect(scanner.scanChar(codePoint), isTrue); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + + test('expectChar with the high surrogate moves into the pair', () { + scanner.expectChar(highSurrogate); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('expectChar with the code point moves past the pair', () { + scanner.expectChar(codePoint); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + }); + group('position=', () { test('forward through newlines sets the line and column', () { scanner.position = 10; // "foo\nbar\r\nb" diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 828745fe1..0e20c36a5 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -139,15 +139,6 @@ void testForImplementation( expect(span.text, equals('o\nbar\nba')); }); - test('.spanFrom() handles surrogate pairs correctly', () { - scanner = create('fo\u{12345}o'); - scanner.scan('fo'); - final state = scanner.state; - scanner.scan('\u{12345}o'); - final span = scanner.spanFrom(state); - expect(span.text, equals('\u{12345}o')); - }); - test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); @@ -164,5 +155,64 @@ void testForImplementation( expect(span.text, equals('')); }); + + group('before a surrogate pair', () { + final codePoint = '\uD83D\uDC6D'.runes.first; + const highSurrogate = 0xD83D; + + late SpanScanner scanner; + setUp(() { + scanner = create('foo: \uD83D\uDC6D bar'); + expect(scanner.scan('foo: '), isTrue); + }); + + test('readChar returns the high surrogate and moves into the pair', () { + expect(scanner.readChar(), equals(highSurrogate)); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('readCodePoint returns the code unit and moves past the pair', () { + expect(scanner.readCodePoint(), equals(codePoint)); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + + test('scanChar with the high surrogate moves into the pair', () { + expect(scanner.scanChar(highSurrogate), isTrue); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('scanChar with the code point moves past the pair', () { + expect(scanner.scanChar(codePoint), isTrue); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + + test('expectChar with the high surrogate moves into the pair', () { + scanner.expectChar(highSurrogate); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(6)); + expect(scanner.position, equals(6)); + }); + + test('expectChar with the code point moves past the pair', () { + scanner.expectChar(codePoint); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(7)); + expect(scanner.position, equals(7)); + }); + + test('spanFrom covers the surrogate pair', () { + final state = scanner.state; + scanner.scan('\uD83D\uDC6D b'); + expect(scanner.spanFrom(state).text, equals('\uD83D\uDC6D b')); + }); + }); }); } diff --git a/pkgs/string_scanner/test/string_scanner_test.dart b/pkgs/string_scanner/test/string_scanner_test.dart index 34176b8a3..36a737e36 100644 --- a/pkgs/string_scanner/test/string_scanner_test.dart +++ b/pkgs/string_scanner/test/string_scanner_test.dart @@ -36,12 +36,24 @@ void main() { expect(scanner.position, equals(0)); }); + test("readCodePoint fails and doesn't change the state", () { + expect(scanner.readCodePoint, throwsFormatException); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("peekChar returns null and doesn't change the state", () { expect(scanner.peekChar(), isNull); expect(scanner.lastMatch, isNull); expect(scanner.position, equals(0)); }); + test("peekCodePoint returns null and doesn't change the state", () { + expect(scanner.peekCodePoint(), isNull); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test("scanChar returns false and doesn't change the state", () { expect(scanner.scanChar($f), isFalse); expect(scanner.lastMatch, isNull); @@ -118,6 +130,12 @@ void main() { expect(scanner.position, equals(1)); }); + test('readCodePoint returns the first character and moves forward', () { + expect(scanner.readCodePoint(), equals(0x66)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(1)); + }); + test('peekChar returns the first character', () { expect(scanner.peekChar(), equals(0x66)); expect(scanner.lastMatch, isNull); @@ -130,6 +148,12 @@ void main() { expect(scanner.position, equals(0)); }); + test('peekCodePoint returns the first character', () { + expect(scanner.peekCodePoint(), equals(0x66)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(0)); + }); + test('a matching scanChar returns true moves forward', () { expect(scanner.scanChar($f), isTrue); expect(scanner.lastMatch, isNull); @@ -275,6 +299,13 @@ void main() { expect(scanner.position, equals(4)); }); + test('readCodePoint returns the first character and unsets the last match', + () { + expect(scanner.readCodePoint(), equals($space)); + expect(scanner.lastMatch, isNull); + expect(scanner.position, equals(4)); + }); + test('a matching scanChar returns true and unsets the last match', () { expect(scanner.scanChar($space), isTrue); expect(scanner.lastMatch, isNull); @@ -314,12 +345,24 @@ void main() { expect(scanner.position, equals(7)); }); + test("readCodePoint fails and doesn't change the state", () { + expect(scanner.readCodePoint, throwsFormatException); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + test("peekChar returns null and doesn't change the state", () { expect(scanner.peekChar(), isNull); expect(scanner.lastMatch, isNotNull); expect(scanner.position, equals(7)); }); + test("peekCodePoint returns null and doesn't change the state", () { + expect(scanner.peekCodePoint(), isNull); + expect(scanner.lastMatch, isNotNull); + expect(scanner.position, equals(7)); + }); + test("scanChar returns false and doesn't change the state", () { expect(scanner.scanChar($f), isFalse); expect(scanner.lastMatch, isNotNull); @@ -393,6 +436,111 @@ void main() { }); }); + group('before a surrogate pair', () { + final codePoint = '\uD83D\uDC6D'.runes.first; + const highSurrogate = 0xD83D; + + late StringScanner scanner; + setUp(() { + scanner = StringScanner('foo: \uD83D\uDC6D'); + expect(scanner.scan('foo: '), isTrue); + }); + + test('readChar returns the high surrogate and moves into the pair', () { + expect(scanner.readChar(), equals(highSurrogate)); + expect(scanner.position, equals(6)); + }); + + test('readCodePoint returns the code unit and moves past the pair', () { + expect(scanner.readCodePoint(), equals(codePoint)); + expect(scanner.position, equals(7)); + }); + + test('peekChar returns the high surrogate', () { + expect(scanner.peekChar(), equals(highSurrogate)); + expect(scanner.position, equals(5)); + }); + + test('peekCodePoint returns the code unit', () { + expect(scanner.peekCodePoint(), equals(codePoint)); + expect(scanner.position, equals(5)); + }); + + test('scanChar with the high surrogate moves into the pair', () { + expect(scanner.scanChar(highSurrogate), isTrue); + expect(scanner.position, equals(6)); + }); + + test('scanChar with the code point moves past the pair', () { + expect(scanner.scanChar(codePoint), isTrue); + expect(scanner.position, equals(7)); + }); + + test('expectChar with the high surrogate moves into the pair', () { + scanner.expectChar(highSurrogate); + expect(scanner.position, equals(6)); + }); + + test('expectChar with the code point moves past the pair', () { + scanner.expectChar(codePoint); + expect(scanner.position, equals(7)); + }); + }); + + group('before an invalid surrogate pair', () { + // This surrogate pair is invalid because U+E000 is just outside the range + // of low surrogates. If it were interpreted as a surrogate pair anyway, the + // value would be U+110000, which is outside of the Unicode gamut. + const codePoint = 0x110000; + const highSurrogate = 0xD800; + + late StringScanner scanner; + setUp(() { + scanner = StringScanner('foo: \uD800\uE000'); + expect(scanner.scan('foo: '), isTrue); + }); + + test('readChar returns the high surrogate and moves into the pair', () { + expect(scanner.readChar(), equals(highSurrogate)); + expect(scanner.position, equals(6)); + }); + + test('readCodePoint returns the high surrogate and moves past the pair', + () { + expect(scanner.readCodePoint(), equals(highSurrogate)); + expect(scanner.position, equals(6)); + }); + + test('peekChar returns the high surrogate', () { + expect(scanner.peekChar(), equals(highSurrogate)); + expect(scanner.position, equals(5)); + }); + + test('peekCodePoint returns the high surrogate', () { + expect(scanner.peekCodePoint(), equals(highSurrogate)); + expect(scanner.position, equals(5)); + }); + + test('scanChar with the high surrogate moves into the pair', () { + expect(scanner.scanChar(highSurrogate), isTrue); + expect(scanner.position, equals(6)); + }); + + test('scanChar with the fake code point returns false', () { + expect(scanner.scanChar(codePoint), isFalse); + expect(scanner.position, equals(5)); + }); + + test('expectChar with the high surrogate moves into the pair', () { + scanner.expectChar(highSurrogate); + expect(scanner.position, equals(6)); + }); + + test('expectChar with the fake code point fails', () { + expect(() => scanner.expectChar(codePoint), throwsRangeError); + }); + }); + group('a scanner constructed with a custom position', () { test('starts scanning from that position', () { final scanner = StringScanner('foo bar', position: 1); From 613b13a7e4734882f6a7f4c25760003ecb1a39f7 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 15 Jun 2022 13:33:55 -0700 Subject: [PATCH 0851/1215] prep to publish 1.2.1 (dart-lang/term_glyph#27) * prep for publishing 1.2.1 * update markdown badges --- pkgs/term_glyph/CHANGELOG.md | 2 +- pkgs/term_glyph/README.md | 4 ++++ pkgs/term_glyph/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 7100d1b39..4f9037660 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.2.1-dev +## 1.2.1 * Migrate to `package:lints`. * Populate the pubspec `repository` field. diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md index 0d64ced35..3a75d0606 100644 --- a/pkgs/term_glyph/README.md +++ b/pkgs/term_glyph/README.md @@ -1,3 +1,7 @@ +[![Dart CI](https://github.com/dart-lang/term_glyph/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/term_glyph/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/term_glyph.svg)](https://pub.dev/packages/term_glyph) +[![package publisher](https://img.shields.io/pub/publisher/term_glyph.svg)](https://pub.dev/packages/term_glyph/publisher) + This library contains getters for useful Unicode glyphs as well as plain ASCII alternatives. It's intended to be used in command-line applications that may run in places where Unicode isn't well-supported and libraries that may be used by diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index d1313a4a1..7019e2db6 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.2.1-dev +version: 1.2.1 description: Useful Unicode glyphs and ASCII substitutes. repository: https://github.com/dart-lang/term_glyph From a36adf0c15f07350de1cac7b951a0ddf6e5ac8fa Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 25 Jul 2022 10:06:26 -0700 Subject: [PATCH 0852/1215] Update analysis_options.yaml (dart-lang/timing#21) --- pkgs/timing/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index 9f4dae73d..dd1616fe5 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -17,7 +17,6 @@ linter: - cascade_invocations - comment_references - directives_ordering - - invariant_booleans - join_return_with_assignment - literal_only_boolean_expressions - omit_local_variable_types From aa3ac4429ede421714cb91ce83edac90896056ed Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 25 Jul 2022 13:25:35 -0700 Subject: [PATCH 0853/1215] Remove deprecated experimental invariant_booleans lint rule (dart-lang/string_scanner#47) --- pkgs/string_scanner/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index c6528bb46..a4495f2e0 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -30,7 +30,6 @@ linter: - file_names - hash_and_equals - implementation_imports - - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment - lines_longer_than_80_chars From 2930843ceebc932108cbe72498a967376ec2eed1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 25 Jul 2022 13:26:06 -0700 Subject: [PATCH 0854/1215] Remove deprecated experimental invariant_booleans lint rule (dart-lang/term_glyph#28) --- pkgs/term_glyph/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index a7d6f2d46..99b42ff11 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -32,7 +32,6 @@ linter: - file_names - hash_and_equals - implementation_imports - - invariant_booleans - iterable_contains_unrelated_type - join_return_with_assignment #- lines_longer_than_80_chars From b11feadf03df5fb85924ee447889ad6955061bfa Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 25 Jul 2022 13:30:00 -0700 Subject: [PATCH 0855/1215] Remove deprecated experimental invariant_booleans lint rule (dart-lang/stream_transform#153) --- pkgs/stream_transform/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 46018f07d..0256c7096 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -17,7 +17,6 @@ linter: - cascade_invocations - comment_references - directives_ordering - - invariant_booleans - join_return_with_assignment - no_adjacent_strings_in_list - omit_local_variable_types From e282122579b45fed1cbec83c11a26b8e8901c696 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 28 Jul 2022 12:20:56 -0700 Subject: [PATCH 0856/1215] Extend timing buffer in audit test (dart-lang/stream_transform#154) This test relies on the particular interleaving of creating one `Timer` and two `Future.delayed`. The 5 millisecond timer must fire after the first 3 millisecond delay, and before the subsequent 3 millisecond delay. On the web this timing became unreliable - the `Timer` may not fire until after the full 6 milliseconds of both delays. Extend the delays to 6 for the `Timer`, and 4 + 4 for the `Future.delayed`. The extra millisecond of padding improves behavior on the web. --- pkgs/stream_transform/test/audit_test.dart | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index cc8f08a9e..907d873e8 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -30,7 +30,7 @@ void main() { emittedValues = []; errors = []; isDone = false; - transformed = values.stream.audit(const Duration(milliseconds: 5)); + transformed = values.stream.audit(const Duration(milliseconds: 6)); subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; @@ -80,11 +80,11 @@ void main() { test('does not starve output if many values come closer than duration', () async { values.add(1); - await Future.delayed(const Duration(milliseconds: 3)); + await Future.delayed(const Duration(milliseconds: 4)); values.add(2); - await Future.delayed(const Duration(milliseconds: 3)); + await Future.delayed(const Duration(milliseconds: 4)); values.add(3); - await waitForTimer(5); + await waitForTimer(6); expect(emittedValues, [2, 3]); }); From 622fee46fd6ace80c5e816591b9b22de693f0c86 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 1 Aug 2022 09:41:14 -0700 Subject: [PATCH 0857/1215] Drop invariant booleans (dart-lang/pubspec_parse#82) Move to "newer" language check in analysis options --- pkgs/pubspec_parse/analysis_options.yaml | 6 +++--- pkgs/pubspec_parse/test/dependency_test.dart | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 67e23cbf6..fdc60e0db 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -1,8 +1,9 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-inference: true linter: rules: @@ -21,7 +22,6 @@ linter: - cascade_invocations - comment_references - directives_ordering - - invariant_booleans - join_return_with_assignment - lines_longer_than_80_chars - literal_only_boolean_expressions diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index da7badcee..8fb48e867 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -338,7 +338,7 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. test('git - empty map', () { _expectThrows( - {'git': {}}, + {'git': {}}, r''' line 5, column 11: Missing key "url". type 'Null' is not a subtype of type 'String' in type cast ╷ From 615f8bbe04ba761d936de07e75ac6cbade33e097 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20So=C3=B3s?= Date: Thu, 18 Aug 2022 15:20:46 +0200 Subject: [PATCH 0858/1215] Support the 'funding' field. (dart-lang/pubspec_parse#83) --- pkgs/pubspec_parse/CHANGELOG.md | 4 ++ pkgs/pubspec_parse/lib/src/pubspec.dart | 5 ++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 5 ++ pkgs/pubspec_parse/pubspec.yaml | 4 +- pkgs/pubspec_parse/test/parse_test.dart | 59 +++++++++++++++++++++++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 6b5a04d22..069e81ceb 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,5 +1,9 @@ ## 1.2.1-dev +## 1.2.1 + +- Added support for `funding` field. + ## 1.2.0 - Added support for `screenshots` field. diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 82c78aa7c..9943da8a4 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -40,6 +40,10 @@ class Pubspec { /// view existing ones. final Uri? issueTracker; + /// Optional field to list the URLs where the package authors accept + /// support or funding. + final List? funding; + /// Optional field for specifying included screenshot files. @JsonKey(fromJson: parseScreenshots) final List? screenshots; @@ -101,6 +105,7 @@ class Pubspec { this.homepage, this.repository, this.issueTracker, + this.funding, this.screenshots, this.documentation, this.description, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 221cc8347..a1312a556 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -27,6 +27,11 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( 'repository', (v) => v == null ? null : Uri.parse(v as String)), issueTracker: $checkedConvert('issue_tracker', (v) => v == null ? null : Uri.parse(v as String)), + funding: $checkedConvert( + 'funding', + (v) => (v as List?) + ?.map((e) => Uri.parse(e as String)) + .toList()), screenshots: $checkedConvert( 'screenshots', (v) => parseScreenshots(v as List?)), documentation: $checkedConvert('documentation', (v) => v as String?), diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index bb9636969..23f15c160 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.1-dev +version: 1.2.1 repository: https://github.com/dart-lang/pubspec_parse environment: @@ -11,7 +11,7 @@ environment: dependencies: checked_yaml: ^2.0.1 collection: ^1.15.0 - json_annotation: ^4.4.0 + json_annotation: ^4.6.0 pub_semver: ^2.0.0 yaml: ^3.0.0 diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 397a728e9..a12d034fd 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -48,6 +48,9 @@ void main() { 'documentation': 'documentation', 'repository': 'https://github.com/example/repo', 'issue_tracker': 'https://github.com/example/repo/issues', + 'funding': [ + 'https://patreon.com/example', + ], 'screenshots': [ {'description': 'my screenshot', 'path': 'path/to/screenshot'} ], @@ -70,6 +73,8 @@ void main() { value.issueTracker, Uri.parse('https://github.com/example/repo/issues'), ); + expect(value.funding, hasLength(1)); + expect(value.funding!.single.toString(), 'https://patreon.com/example'); expect(value.screenshots, hasLength(1)); expect(value.screenshots!.first.description, 'my screenshot'); expect(value.screenshots!.first.path, 'path/to/screenshot'); @@ -367,6 +372,60 @@ line 3, column 19: Unsupported value for "issue_tracker". type 'YamlMap' is not }); }); + group('funding', () { + test('not a list', () { + expectParseThrows( + { + ...defaultPubspec, + 'funding': 1, + }, + r''' +line 6, column 13: Unsupported value for "funding". type 'int' is not a subtype of type 'List?' in type cast + ╷ +6 │ "funding": 1 + │ ^ + ╵''', + skipTryPub: true, + ); + }); + + test('not an uri', () { + expectParseThrows( + { + ...defaultPubspec, + 'funding': [1], + }, + r''' +line 6, column 13: Unsupported value for "funding". type 'int' is not a subtype of type 'String' in type cast + ╷ +6 │ "funding": [ + │ ┌─────────────^ +7 │ │ 1 +8 │ └ ] + ╵''', + skipTryPub: true, + ); + }); + + test('not an uri', () { + expectParseThrows( + { + ...defaultPubspec, + 'funding': ['ht tps://example.com/'], + }, + r''' +line 6, column 13: Unsupported value for "funding". Illegal scheme character at offset 2. + ╷ +6 │ "funding": [ + │ ┌─────────────^ +7 │ │ "ht tps://example.com/" +8 │ └ ] + ╵''', + skipTryPub: true, + ); + }); + }); + group('screenshots', () { test('one screenshot', () { final value = parse({ From eede1d6616b85d2483bf1533827a9b321f187b36 Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 14 Sep 2022 14:18:15 -0700 Subject: [PATCH 0859/1215] update to lints 2.0.0; prep for publishing --- .../lib/test_reflective_loader.dart | 10 +++++----- pkgs/test_reflective_loader/pubspec.yaml | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 6237f676c..3881cf1c2 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -13,28 +13,28 @@ import 'package:test/test.dart' as test_package; * A marker annotation used to annotate test methods which are expected to fail * when asserts are enabled. */ -const _AssertFailingTest assertFailingTest = _AssertFailingTest(); +const Object assertFailingTest = _AssertFailingTest(); /** * A marker annotation used to annotate test methods which are expected to fail. */ -const FailingTest failingTest = FailingTest(); +const Object failingTest = FailingTest(); /** * A marker annotation used to instruct dart2js to keep reflection information * for the annotated classes. */ -const _ReflectiveTest reflectiveTest = _ReflectiveTest(); +const Object reflectiveTest = _ReflectiveTest(); /** * A marker annotation used to annotate test methods that should be skipped. */ -const SkippedTest skippedTest = SkippedTest(); +const Object skippedTest = SkippedTest(); /** * A marker annotation used to annotate "solo" groups and tests. */ -const _SoloTest soloTest = _SoloTest(); +const Object soloTest = _SoloTest(); final List<_Group> _currentGroups = <_Group>[]; int _currentSuiteLevel = 0; diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 57cf02b92..3919f780c 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -7,5 +7,7 @@ environment: sdk: '>=2.12.0 <3.0.0' dependencies: - lints: ^1.0.0 test: ^1.16.0 + +dev_dependencies: + lints: ^2.0.0 From 79407a893c8fbfd7fa5376d91dabe0ca47eeebcb Mon Sep 17 00:00:00 2001 From: pq Date: Wed, 14 Sep 2022 14:19:00 -0700 Subject: [PATCH 0860/1215] ++ --- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 3919f780c..e4de919ee 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.2.1 +version: 0.2.2 description: Support for discovering tests and test suites using reflection. repository: https://github.com/dart-lang/test_reflective_loader From 11038d6a558833bb30f59eb343cf060bf8d183bd Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:25:31 -0700 Subject: [PATCH 0861/1215] drop beta container --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 2ac752518..050ea78a3 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -13,9 +13,6 @@ jobs: build: runs-on: ubuntu-latest - container: - image: google/dart:beta - steps: - uses: actions/checkout@v2 From bcec3ea0c4237a42ed8281a90683a7be6f564f0c Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:28:28 -0700 Subject: [PATCH 0862/1215] fix setup --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 050ea78a3..18269d413 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -15,6 +15,9 @@ jobs: steps: - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v1 + with: + sdk: dev - name: pub get run: pub get From 5217d3d2eb9afffa251eb34eb4d016a7841a1879 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:30:49 -0700 Subject: [PATCH 0863/1215] + PUB_ENV --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 18269d413..48fa6c7df 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -9,6 +9,9 @@ on: # “At 00:00 (UTC) on Sunday.” - cron: '0 0 * * 0' +env: + PUB_ENVIRONMENT: bot.github + jobs: build: runs-on: ubuntu-latest From 629213de62cd01337e90a22b98d988fc42ee84d5 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:32:51 -0700 Subject: [PATCH 0864/1215] + dart pub call --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 48fa6c7df..b3754c7a0 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -23,7 +23,7 @@ jobs: sdk: dev - name: pub get - run: pub get + run: dart pub get - name: dart format run: dart format --output=none --set-exit-if-changed . From 92c6271f136820ef390dc12d8f566da8587d7e27 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:37:47 -0700 Subject: [PATCH 0865/1215] 0.2.2 --- pkgs/test_reflective_loader/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 05195a8f4..e233fef89 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.2 + +- Update to package:lints 2.0.0 and move it to a dev dependency. + ## 0.2.1 - Use package:lints for analysis. From 9695157811df716d9b5dda87fbada51b64ca4572 Mon Sep 17 00:00:00 2001 From: Phil Quitslund Date: Wed, 14 Sep 2022 14:44:50 -0700 Subject: [PATCH 0866/1215] + matrix --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index b3754c7a0..9728c9492 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -15,13 +15,17 @@ env: jobs: build: runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [dev, stable] steps: - uses: actions/checkout@v2 - uses: dart-lang/setup-dart@v1 with: - sdk: dev - + sdk: ${{ matrix.sdk }} + - name: pub get run: dart pub get From 1183418e47c1d28dfa3c5db6f466910cd7c1c87a Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 20 Sep 2022 12:16:54 -0700 Subject: [PATCH 0867/1215] Handle non-int multichannel message IDs (dart-lang/stream_channel#80) When running in wasm, a number in a `List` will be parsed as a `double`. On the web the `as int` cast succeeds, but in dart2wasm it fails. Cast to `num` and use `toInt()` to more reliably get an `int` value. --- pkgs/stream_channel/CHANGELOG.md | 3 +++ pkgs/stream_channel/lib/src/multi_channel.dart | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0f8da1548..badeaf737 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -3,6 +3,9 @@ * Require Dart 2.14 * Migrate to `package:lints`. * Populate the pubspec `repository` field. +* Handle multichannel messages where the ID element is a `double` at runtime + instead of an `int`. When reading an array with `dart2wasm` numbers within the + array are parsed as `double`. ## 2.1.0 diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index e1e25ea04..a78ddbcf4 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -141,7 +141,7 @@ class _MultiChannel extends StreamChannelMixin onDone: () => _closeChannel(0, 0)); _innerStreamSubscription = _inner!.stream.cast().listen((message) { - var id = message[0] as int; + var id = (message[0] as num).toInt(); // If the channel was closed before an incoming message was processed, // ignore that message. From 5ad2e2ddf016f54053ea5b7cf880e4d2ac8a4181 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 21 Sep 2022 12:31:46 -0700 Subject: [PATCH 0868/1215] Prepare to publish (dart-lang/stream_channel#81) Drop changelog entry for non-user-facing change. Drop `-dev` suffix from version. --- pkgs/stream_channel/CHANGELOG.md | 3 +-- pkgs/stream_channel/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index badeaf737..2b90a0a76 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,6 @@ -## 2.1.1-dev +## 2.1.1 * Require Dart 2.14 -* Migrate to `package:lints`. * Populate the pubspec `repository` field. * Handle multichannel messages where the ID element is a `double` at runtime instead of an `int`. When reading an array with `dart2wasm` numbers within the diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5e86fc3eb..ff6a50c68 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.1-dev +version: 2.1.1 description: >- An abstraction for two-way communication channels based on the Dart Stream class. From 354a02b3e3de703c0e1859b4417d6ac303ad0691 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 4 Oct 2022 13:14:45 -0700 Subject: [PATCH 0869/1215] update CI; add markdown badges --- pkgs/watcher/.github/dependabot.yaml | 8 ++++++++ pkgs/watcher/.github/workflows/test-package.yml | 8 ++++---- pkgs/watcher/CHANGELOG.md | 2 +- pkgs/watcher/README.md | 10 ++++++++-- pkgs/watcher/analysis_options.yaml | 1 + pkgs/watcher/pubspec.yaml | 3 +-- 6 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 pkgs/watcher/.github/dependabot.yaml diff --git a/pkgs/watcher/.github/dependabot.yaml b/pkgs/watcher/.github/dependabot.yaml new file mode 100644 index 000000000..214481934 --- /dev/null +++ b/pkgs/watcher/.github/dependabot.yaml @@ -0,0 +1,8 @@ +# Dependabot configuration file. +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 971c6f0c5..c63ec37f9 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -48,8 +48,8 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index af54045f6..a2e3e0bc5 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.0.2-dev +# 1.0.2 - Require Dart SDK >= 2.14 - Ensure `DirectoryWatcher.ready` completes even when errors occur that close the watcher. diff --git a/pkgs/watcher/README.md b/pkgs/watcher/README.md index 61cc1f9f9..677ca35b2 100644 --- a/pkgs/watcher/README.md +++ b/pkgs/watcher/README.md @@ -1,4 +1,10 @@ +[![Dart CI](https://github.com/dart-lang/watcher/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/watcher/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/watcher.svg)](https://pub.dev/packages/watcher) +[![package publisher](https://img.shields.io/pub/publisher/watcher.svg)](https://pub.dev/packages/watcher/publisher) + A file system watcher. -It monitors changes to contents of directories and sends notifications when -files have been added, removed, or modified. +## What's this? + +`package:watcher` monitors changes to contents of directories and sends +notifications when files have been added, removed, or modified. diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index b9b528743..29327a49a 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,4 +1,5 @@ include: package:lints/recommended.yaml + analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index b4102c5cf..947237407 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,6 +1,5 @@ name: watcher -version: 1.0.2-dev - +version: 1.0.2 description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. From 61320128b4606eee3a4240c1479236ea7291d6bd Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 4 Oct 2022 13:15:22 -0700 Subject: [PATCH 0870/1215] add markdown badges --- pkgs/watcher/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index a2e3e0bc5..9104504d6 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -2,6 +2,7 @@ - Require Dart SDK >= 2.14 - Ensure `DirectoryWatcher.ready` completes even when errors occur that close the watcher. +- Add markdown badges to the readme. # 1.0.1 From 1f4638d0e06fa842d19850c56da9c9418f8801e2 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 5 Oct 2022 09:50:12 -0700 Subject: [PATCH 0871/1215] update CI; prep for publishing (dart-lang/stream_transform#155) --- pkgs/stream_transform/.github/dependabot.yaml | 8 ++++ pkgs/stream_transform/.github/dependabot.yml | 11 ------ .../.github/workflows/test-package.yml | 8 ++-- pkgs/stream_transform/CHANGELOG.md | 2 +- pkgs/stream_transform/README.md | 37 ++++++++++--------- pkgs/stream_transform/pubspec.yaml | 2 +- 6 files changed, 33 insertions(+), 35 deletions(-) create mode 100644 pkgs/stream_transform/.github/dependabot.yaml delete mode 100644 pkgs/stream_transform/.github/dependabot.yml diff --git a/pkgs/stream_transform/.github/dependabot.yaml b/pkgs/stream_transform/.github/dependabot.yaml new file mode 100644 index 000000000..214481934 --- /dev/null +++ b/pkgs/stream_transform/.github/dependabot.yaml @@ -0,0 +1,8 @@ +# Dependabot configuration file. +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/stream_transform/.github/dependabot.yml b/pkgs/stream_transform/.github/dependabot.yml deleted file mode 100644 index 430a85e7d..000000000 --- a/pkgs/stream_transform/.github/dependabot.yml +++ /dev/null @@ -1,11 +0,0 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - -version: 2 -updates: - -- package-ecosystem: "github-actions" - directory: "/" - schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 02bf25d38..3aa30d4e8 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index a00b3ba31..f425a1ad1 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.0.1-dev +## 2.0.1 - Require Dart 2.14 or greater. - Wait for the future returned from `StreamSubscription.cancel()` before diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index ee0ac2ee5..b57429346 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,11 +1,12 @@ [![Build Status](https://travis-ci.org/dart-lang/stream_transform.svg?branch=master)](https://travis-ci.org/dart-lang/stream_transform) [![Pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) +[![package publisher](https://img.shields.io/pub/publisher/stream_transform.svg)](https://pub.dev/packages/stream_transform/publisher) Extension methods on `Stream` adding common transform operators. -# Operators +## Operators -## asyncMapBuffer, asyncMapSample, concurrentAsyncMap +### asyncMapBuffer, asyncMapSample, concurrentAsyncMap Alternatives to `asyncMap`. `asyncMapBuffer` prevents the callback from overlapping execution and collects events while it is executing. @@ -16,70 +17,70 @@ for higher throughput. Like `asyncMap` but events are buffered in a List until previous events have been processed rather than being called for each element individually. -## asyncWhere +### asyncWhere Like `where` but allows an asynchronous predicate. -## audit +### audit Waits for a period of time after receiving a value and then only emits the most recent value. -## buffer +### buffer Collects values from a source stream until a `trigger` stream fires and the collected values are emitted. -## combineLatest, combineLatestAll +### combineLatest, combineLatestAll Combine the most recent event from multiple streams through a callback or into a list. -## debounce, debounceBuffer +### debounce, debounceBuffer Prevents a source stream from emitting too frequently by dropping or collecting values that occur within a given duration. -## followedBy +### followedBy Appends the values of a stream after another stream finishes. -## merge, mergeAll, concurrentAsyncExpand +### merge, mergeAll, concurrentAsyncExpand Interleaves events from multiple streams into a single stream. -## scan +### scan Scan is like fold, but instead of producing a single value it yields each intermediate accumulation. -## startWith, startWithMany, startWithStream +### startWith, startWithMany, startWithStream Prepend a value, an iterable, or a stream to the beginning of another stream. -## switchMap, switchLatest +### switchMap, switchLatest Flatten a Stream of Streams into a Stream which forwards values from the most recent Stream -## takeUntil +### takeUntil Let values through until a Future fires. -## tap +### tap Taps into a single-subscriber stream to react to values as they pass, without being a real subscriber. -## throttle +### throttle Blocks events for a duration after an event is successfully emitted. -## whereType +### whereType Like `Iterable.whereType` for a stream. -### Comparison to Rx Operators +## Comparison to Rx Operators The semantics and naming in this package have some overlap, and some conflict, with the [ReactiveX](https://reactivex.io/) suite of libraries. Some of the @@ -125,7 +126,7 @@ No equivalent? | [debounce]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/debounce.html [throttle]:https://pub.dev/documentation/stream_transform/latest/stream_transform/RateLimit/throttle.html -# Getting a `StreamTransformer` instance +## Getting a `StreamTransformer` instance It may be useful to pass an instance of `StreamTransformer` so that it can be used with `stream.transform` calls rather than reference the specific operator diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 4b58ddffa..181517869 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform +version: 2.0.1 description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/stream_transform -version: 2.0.1-dev environment: sdk: ">=2.14.0 <3.0.0" From 7718e7849af4c24a6fa77623d3dc2acf038b7412 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 10 Oct 2022 12:34:29 -0700 Subject: [PATCH 0872/1215] A bunch of cleanup, prepare for v1.11.0 (dart-lang/stack_trace#118) Require Dart 2.18 Bump lints dep Enable and fix lints and language bits Add an example --- .../.github/workflows/test-package.yml | 10 +- pkgs/stack_trace/CHANGELOG.md | 8 +- pkgs/stack_trace/README.md | 108 ++++++------------ pkgs/stack_trace/analysis_options.yaml | 25 +++- pkgs/stack_trace/example/example.dart | 15 +++ pkgs/stack_trace/lib/src/chain.dart | 13 +-- pkgs/stack_trace/lib/src/frame.dart | 4 +- pkgs/stack_trace/lib/src/lazy_chain.dart | 2 +- .../lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/lib/src/trace.dart | 15 +-- pkgs/stack_trace/pubspec.yaml | 6 +- pkgs/stack_trace/test/chain/dart2js_test.dart | 2 +- pkgs/stack_trace/test/chain/utils.dart | 4 +- pkgs/stack_trace/test/chain/vm_test.dart | 7 +- pkgs/stack_trace/test/frame_test.dart | 58 ++++------ pkgs/stack_trace/test/trace_test.dart | 22 ++-- pkgs/stack_trace/test/utils.dart | 10 +- 17 files changed, 146 insertions(+), 165 deletions(-) create mode 100644 pkgs/stack_trace/example/example.dart diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index e47bf6600..1b823da8a 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.18.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index aa4300425..6291d735d 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,9 +1,9 @@ -## 1.11.0-dev +## 1.11.0 -* Added the param `zoneValues` to `Chain.capture` to be able to use custom zone - values with the `runZoned` internal calls +* Added the parameter `zoneValues` to `Chain.capture` to be able to use custom + zone values with the `runZoned` internal calls. * Populate the pubspec `repository` field. -* Switch to `package:lints`. +* Require Dart 2.18 or greater ## 1.10.0 diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index a76dfc327..83bae61d1 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -80,35 +80,25 @@ Here's an example of some code that doesn't capture its stack chains: import 'dart:async'; void main() { - scheduleAsync(); + _scheduleAsync(); } -void scheduleAsync() { - return new Future.delayed(new Duration(seconds: 1)) - .then((_) => runAsync()); +void _scheduleAsync() { + Future.delayed(Duration(seconds: 1)).then((_) => _runAsync()); } -void runAsync() { +void _runAsync() { throw 'oh no!'; } ``` If we run this, it prints the following: - Uncaught Error: oh no! - Stack Trace: - #0 runAsync (file:///usr/local/google-old/home/goog/dart/dart/test.dart:13:3) - #1 scheduleAsync. (file:///usr/local/google-old/home/goog/dart/dart/test.dart:9:28) - #2 _rootRunUnary (dart:async/zone.dart:717) - #3 _RootZone.runUnary (dart:async/zone.dart:854) - #4 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:488) - #5 _Future._propagateToListeners (dart:async/future_impl.dart:571) - #6 _Future._complete (dart:async/future_impl.dart:317) - #7 _SyncCompleter.complete (dart:async/future_impl.dart:44) - #8 Future.Future.delayed. (dart:async/future.dart:219) - #9 _createTimer. (dart:async-patch/timer_patch.dart:11) - #10 _handleTimeout (dart:io/timer_impl.dart:292) - #11 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:115) + Unhandled exception: + oh no! + #0 _runAsync (file:///Users/kevmoo/github/stack_trace/example/example.dart:12:3) + #1 _scheduleAsync. (file:///Users/kevmoo/github/stack_trace/example/example.dart:8:52) + Notice how there's no mention of `main` in that stack trace. All we know is that the error was in `runAsync`; we don't know why `runAsync` was called. @@ -121,72 +111,42 @@ import 'dart:async'; import 'package:stack_trace/stack_trace.dart'; void main() { - Chain.capture(() { - scheduleAsync(); - }); + Chain.capture(_scheduleAsync); } -void scheduleAsync() { - new Future.delayed(new Duration(seconds: 1)) - .then((_) => runAsync()); +void _scheduleAsync() { + Future.delayed(Duration(seconds: 1)).then((_) => _runAsync()); } -void runAsync() { +void _runAsync() { throw 'oh no!'; } ``` Now if we run it, it prints this: - Uncaught Error: oh no! - Stack Trace: - test.dart 17:3 runAsync - test.dart 13:28 scheduleAsync. - package:stack_trace/src/stack_zone_specification.dart 129:26 registerUnaryCallback.. - package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run - package:stack_trace/src/stack_zone_specification.dart 177:7 StackZoneSpecification._run - package:stack_trace/src/stack_zone_specification.dart 175:7 StackZoneSpecification._run - package:stack_trace/src/stack_zone_specification.dart 129:18 registerUnaryCallback. - dart:async/zone.dart 717 _rootRunUnary - dart:async/zone.dart 449 _ZoneDelegate.runUnary - dart:async/zone.dart 654 _CustomizedZone.runUnary - dart:async/future_impl.dart 488 _Future._propagateToListeners.handleValueCallback - dart:async/future_impl.dart 571 _Future._propagateToListeners - dart:async/future_impl.dart 317 _Future._complete - dart:async/future_impl.dart 44 _SyncCompleter.complete - dart:async/future.dart 219 Future.Future.delayed. - package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run - package:stack_trace/src/stack_zone_specification.dart 119:52 registerCallback. - dart:async/zone.dart 706 _rootRun - dart:async/zone.dart 440 _ZoneDelegate.run - dart:async/zone.dart 650 _CustomizedZone.run - dart:async/zone.dart 561 _BaseZone.runGuarded - dart:async/zone.dart 586 _BaseZone.bindCallback. - package:stack_trace/src/stack_zone_specification.dart 174:15 StackZoneSpecification._run - package:stack_trace/src/stack_zone_specification.dart 119:52 registerCallback. - dart:async/zone.dart 710 _rootRun - dart:async/zone.dart 440 _ZoneDelegate.run - dart:async/zone.dart 650 _CustomizedZone.run - dart:async/zone.dart 561 _BaseZone.runGuarded - dart:async/zone.dart 586 _BaseZone.bindCallback. - dart:async-patch/timer_patch.dart 11 _createTimer. - dart:io/timer_impl.dart 292 _handleTimeout - dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage + Unhandled exception: + oh no! + example/example.dart 14:3 _runAsync + example/example.dart 10:52 _scheduleAsync. + package:stack_trace/src/stack_zone_specification.dart 126:26 StackZoneSpecification._registerUnaryCallback.. + package:stack_trace/src/stack_zone_specification.dart 208:15 StackZoneSpecification._run + package:stack_trace/src/stack_zone_specification.dart 126:14 StackZoneSpecification._registerUnaryCallback. + dart:async/zone.dart 1406:47 _rootRunUnary + dart:async/zone.dart 1307:19 _CustomZone.runUnary ===== asynchronous gap =========================== - dart:async/zone.dart 476 _ZoneDelegate.registerUnaryCallback - dart:async/zone.dart 666 _CustomizedZone.registerUnaryCallback - dart:async/future_impl.dart 164 _Future._Future._then - dart:async/future_impl.dart 187 _Future.then - test.dart 13:12 scheduleAsync - test.dart 7:18 main. - dart:async/zone.dart 710 _rootRun - dart:async/zone.dart 440 _ZoneDelegate.run - dart:async/zone.dart 650 _CustomizedZone.run - dart:async/zone.dart 944 runZoned - package:stack_trace/src/chain.dart 93:20 Chain.capture - test.dart 6:16 main - dart:isolate-patch/isolate_patch.dart 216 _startIsolate.isolateStartHandler - dart:isolate-patch/isolate_patch.dart 115 _RawReceivePortImpl._handleMessage + dart:async/zone.dart 1328:19 _CustomZone.registerUnaryCallback + dart:async/future_impl.dart 315:23 Future.then + example/example.dart 10:40 _scheduleAsync + package:stack_trace/src/chain.dart 97:24 Chain.capture. + dart:async/zone.dart 1398:13 _rootRun + dart:async/zone.dart 1300:19 _CustomZone.run + dart:async/zone.dart 1803:10 _runZoned + dart:async/zone.dart 1746:10 runZoned + package:stack_trace/src/chain.dart 95:12 Chain.capture + example/example.dart 6:9 main + dart:isolate-patch/isolate_patch.dart 297:19 _delayEntrypointInvocation. + dart:isolate-patch/isolate_patch.dart 192:12 _RawReceivePortImpl._handleMessage That's a lot of text! If you look closely, though, you can see that `main` is listed in the first trace in the chain. diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 05c4b4c69..1efeefc01 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,9 +1,30 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-raw-types: true linter: rules: + - always_declare_return_types - avoid_private_typedef_functions + - 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/pkgs/stack_trace/example/example.dart b/pkgs/stack_trace/example/example.dart new file mode 100644 index 000000000..a65abb120 --- /dev/null +++ b/pkgs/stack_trace/example/example.dart @@ -0,0 +1,15 @@ +import 'dart:async'; + +import 'package:stack_trace/stack_trace.dart'; + +void main() { + Chain.capture(_scheduleAsync); +} + +void _scheduleAsync() { + Future.delayed(Duration(seconds: 1)).then((_) => _runAsync()); +} + +void _runAsync() { + throw 'oh no!'; +} diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 628b8fae2..69f9b0c59 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -28,7 +28,7 @@ final _specKey = Object(); /// /// Stack chains can be automatically tracked using [Chain.capture]. This sets /// up a new [Zone] in which the current stack chain is tracked and can be -/// accessed using [new Chain.current]. Any errors that would be top-leveled in +/// accessed using [Chain.current]. Any errors that would be top-leveled in /// the zone can be handled, along with their associated chains, with the /// `onError` callback. For example: /// @@ -54,8 +54,8 @@ class Chain implements StackTrace { /// stack chain is tracked and automatically associated with (most) errors. /// /// If [when] is `false`, this does not track stack chains. Instead, it's - /// identical to [runZoned], except that it wraps any errors in [new - /// Chain.forTrace]—which will only wrap the trace unless there's a different + /// identical to [runZoned], except that it wraps any errors in + /// [Chain.forTrace]—which will only wrap the trace unless there's a different /// [Chain.capture] active. This makes it easy for the caller to only capture /// stack chains in debug mode or during development. /// @@ -130,7 +130,7 @@ class Chain implements StackTrace { /// exceptions reported with [Completer.completeError] and /// [StreamController.addError] were tracked correctly. @Deprecated('Chain.track is not necessary in Dart 1.7+.') - static dynamic track(futureOrStream) => futureOrStream; + static dynamic track(Object? futureOrStream) => futureOrStream; /// Returns the current stack chain. /// @@ -179,12 +179,11 @@ class Chain implements StackTrace { return Chain(chain .split(vmChainGap) .where((line) => line.isNotEmpty) - .map((trace) => Trace.parseVM(trace))); + .map(Trace.parseVM)); } if (!chain.contains(chainGap)) return Chain([Trace.parse(chain)]); - return Chain( - chain.split(chainGap).map((trace) => Trace.parseFriendly(trace))); + return Chain(chain.split(chainGap).map(Trace.parseFriendly)); } /// Returns a new [Chain] comprised of [traces]. diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index c5b20e1f3..88670a1c7 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -289,8 +289,8 @@ class Frame { var uri = match[1] == 'data:...' ? Uri.dataFromString('') : Uri.parse(match[1]!); - // If there's no scheme, this is a relative URI. We should interpret it as - // relative to the current working directory. + // If there's no scheme, this is a relative URI. We should interpret it + // as relative to the current working directory. if (uri.scheme == '') { uri = path.toUri(path.absolute(path.fromUri(uri))); } diff --git a/pkgs/stack_trace/lib/src/lazy_chain.dart b/pkgs/stack_trace/lib/src/lazy_chain.dart index e2f64a768..063ed59db 100644 --- a/pkgs/stack_trace/lib/src/lazy_chain.dart +++ b/pkgs/stack_trace/lib/src/lazy_chain.dart @@ -27,7 +27,7 @@ class LazyChain implements Chain { Chain foldFrames(bool Function(Frame) predicate, {bool terse = false}) => LazyChain(() => _chain.foldFrames(predicate, terse: terse)); @override - Trace toTrace() => LazyTrace(() => _chain.toTrace()); + Trace toTrace() => LazyTrace(_chain.toTrace); @override String toString() => _chain.toString(); } diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index e13e5d481..8d1b3a78f 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -217,7 +217,7 @@ class StackZoneSpecification { } } - /// Like [new Trace.current], but if the current stack trace has VM chaining + /// Like [Trace.current], but if the current stack trace has VM chaining /// enabled, this only returns the innermost sub-trace. Trace _currentTrace([int? level]) { var stackTrace = StackTrace.current; diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 42371c744..5df7e4dc6 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -156,10 +156,7 @@ class Trace implements StackTrace { return []; } - var frames = lines - .take(lines.length - 1) - .map((line) => Frame.parseVM(line)) - .toList(); + var frames = lines.take(lines.length - 1).map(Frame.parseVM).toList(); // TODO(nweiz): Remove this when issue 23614 is fixed. if (!lines.last.endsWith('.da')) { @@ -179,7 +176,7 @@ class Trace implements StackTrace { // that looks like a V8 trace line, which will screw this up. // Unfortunately, that's impossible to detect. .skipWhile((line) => !line.startsWith(_v8TraceLine)) - .map((line) => Frame.parseV8(line)), + .map(Frame.parseV8), original: trace); /// Parses a string representation of a JavaScriptCore stack trace. @@ -188,7 +185,7 @@ class Trace implements StackTrace { trace .split('\n') .where((line) => line != '\tat ') - .map((line) => Frame.parseV8(line)), + .map(Frame.parseV8), original: trace); /// Parses a string representation of an Internet Explorer stack trace. @@ -204,7 +201,7 @@ class Trace implements StackTrace { .trim() .split('\n') .where((line) => line.isNotEmpty && line != '[native code]') - .map((line) => Frame.parseFirefox(line)), + .map(Frame.parseFirefox), original: trace); /// Parses a string representation of a Safari stack trace. @@ -222,7 +219,7 @@ class Trace implements StackTrace { .trim() .split('\n') .where((line) => line != '[native code]') - .map((line) => Frame.parseFirefox(line)), + .map(Frame.parseFirefox), original: trace); /// Parses this package's string representation of a stack trace. @@ -238,7 +235,7 @@ class Trace implements StackTrace { .split('\n') // Filter out asynchronous gaps from [Chain]s. .where((line) => !line.startsWith('=====')) - .map((line) => Frame.parseFriendly(line)), + .map(Frame.parseFriendly), original: trace); /// Returns a new [Trace] comprised of [frames]. diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 326e2d447..78c27d0ba 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,14 +1,14 @@ name: stack_trace -version: 1.11.0-dev +version: 1.11.0 description: A package for manipulating stack traces and printing them readably. repository: https://github.com/dart-lang/stack_trace environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.18.0 <3.0.0" dependencies: path: ^1.8.0 dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index f7086379d..41eb1ce78 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -113,7 +113,7 @@ void main() { test('passed to a completer with no stack trace', () async { var chain = await captureFuture(() { - inMicrotask(() => completerErrorFuture()); + inMicrotask(completerErrorFuture); }); expect(chain.traces, hasLength(2)); diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index af8e361f4..0a74d9ae6 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -46,7 +46,7 @@ void inSyncFuture(void Function() callback) { /// Returns a Future that completes to an error using a completer. /// /// If [trace] is passed, it's used as the stack trace for the error. -Future completerErrorFuture([StackTrace? trace]) { +Future completerErrorFuture([StackTrace? trace]) { var completer = Completer(); completer.completeError('error', trace); return completer.future; @@ -55,7 +55,7 @@ Future completerErrorFuture([StackTrace? trace]) { /// Returns a Stream that emits an error using a controller. /// /// If [trace] is passed, it's used as the stack trace for the error. -Stream controllerErrorStream([StackTrace? trace]) { +Stream controllerErrorStream([StackTrace? trace]) { var controller = StreamController(); controller.addError('error', trace); return controller.stream; diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index efcee3d88..7c8278bde 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -8,10 +8,9 @@ import 'dart:async'; -import 'package:test/test.dart'; - -import 'package:stack_trace/stack_trace.dart'; import 'package:stack_trace/src/utils.dart'; +import 'package:stack_trace/stack_trace.dart'; +import 'package:test/test.dart'; import '../utils.dart'; import 'utils.dart'; @@ -189,7 +188,7 @@ void main() { test('passed to a completer with no stack trace', () { return captureFuture(() { - inMicrotask(() => completerErrorFuture()); + inMicrotask(completerErrorFuture); }).then((chain) { expect(chain.traces, hasLength(2)); diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 87880395e..6e8df727f 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -71,13 +71,11 @@ void main() { group('.parseV8', () { test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => Frame.parseV8(text), ''); - expectIsUnparsed((text) => Frame.parseV8(text), '#1'); - expectIsUnparsed((text) => Frame.parseV8(text), '#1 Foo'); - expectIsUnparsed((text) => Frame.parseV8(text), - '#1 (dart:async/future.dart:10:15)'); - expectIsUnparsed( - (text) => Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); + expectIsUnparsed(Frame.parseV8, ''); + expectIsUnparsed(Frame.parseV8, '#1'); + expectIsUnparsed(Frame.parseV8, '#1 Foo'); + expectIsUnparsed(Frame.parseV8, '#1 (dart:async/future.dart:10:15)'); + expectIsUnparsed(Frame.parseV8, 'Foo (dart:async/future.dart:10:15)'); }); test('parses a stack frame correctly', () { @@ -219,19 +217,14 @@ void main() { }); test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => Frame.parseV8(text), ''); - expectIsUnparsed((text) => Frame.parseV8(text), ' at'); - expectIsUnparsed((text) => Frame.parseV8(text), ' at Foo'); - expectIsUnparsed( - (text) => Frame.parseV8(text), ' at Foo (dart:async/future.dart)'); - expectIsUnparsed((text) => Frame.parseV8(text), - ' at (dart:async/future.dart:10:15)'); - expectIsUnparsed( - (text) => Frame.parseV8(text), 'Foo (dart:async/future.dart:10:15)'); - expectIsUnparsed( - (text) => Frame.parseV8(text), ' at dart:async/future.dart'); - expectIsUnparsed( - (text) => Frame.parseV8(text), 'dart:async/future.dart:10:15'); + expectIsUnparsed(Frame.parseV8, ''); + expectIsUnparsed(Frame.parseV8, ' at'); + expectIsUnparsed(Frame.parseV8, ' at Foo'); + expectIsUnparsed(Frame.parseV8, ' at Foo (dart:async/future.dart)'); + expectIsUnparsed(Frame.parseV8, ' at (dart:async/future.dart:10:15)'); + expectIsUnparsed(Frame.parseV8, 'Foo (dart:async/future.dart:10:15)'); + expectIsUnparsed(Frame.parseV8, ' at dart:async/future.dart'); + expectIsUnparsed(Frame.parseV8, 'dart:async/future.dart:10:15'); }); }); @@ -381,8 +374,9 @@ baz@https://pub.dev/buz.js:56355:55 }); test('parses a nested anonymous stack frame with parameters correctly', () { - var frame = Frame.parseFirefox('.foo(12, "@)()/<")/.fn<@' - 'https://example.com/stuff.dart.js:560'); + var frame = Frame.parseFirefox( + '.foo(12, "@)()/<")/.fn<@https://example.com/stuff.dart.js:560', + ); expect(frame.uri, equals(Uri.parse('https://example.com/stuff.dart.js'))); expect(frame.line, equals(560)); expect(frame.column, isNull); @@ -401,14 +395,11 @@ baz@https://pub.dev/buz.js:56355:55 }); test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => Frame.parseFirefox(text), ''); - expectIsUnparsed((text) => Frame.parseFirefox(text), '.foo'); - expectIsUnparsed( - (text) => Frame.parseFirefox(text), '.foo@dart:async/future.dart'); - expectIsUnparsed((text) => Frame.parseFirefox(text), - '.foo(@dart:async/future.dart:10'); - expectIsUnparsed( - (text) => Frame.parseFirefox(text), '@dart:async/future.dart'); + expectIsUnparsed(Frame.parseFirefox, ''); + expectIsUnparsed(Frame.parseFirefox, '.foo'); + expectIsUnparsed(Frame.parseFirefox, '.foo@dart:async/future.dart'); + expectIsUnparsed(Frame.parseFirefox, '.foo(@dart:async/future.dart:10'); + expectIsUnparsed(Frame.parseFirefox, '@dart:async/future.dart'); }); test('parses a simple stack frame correctly', () { @@ -494,10 +485,9 @@ baz@https://pub.dev/buz.js:56355:55 }); test('returns an UnparsedFrame for malformed frames', () { - expectIsUnparsed((text) => Frame.parseFriendly(text), ''); - expectIsUnparsed((text) => Frame.parseFriendly(text), 'foo/bar.dart'); - expectIsUnparsed( - (text) => Frame.parseFriendly(text), 'foo/bar.dart 10:11'); + expectIsUnparsed(Frame.parseFriendly, ''); + expectIsUnparsed(Frame.parseFriendly, 'foo/bar.dart'); + expectIsUnparsed(Frame.parseFriendly, 'foo/bar.dart 10:11'); }); test('parses a data url stack frame with no line or column correctly', () { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index ea48e039c..15c86aa99 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -12,7 +12,7 @@ Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); void main() { // This just shouldn't crash. - test('a native stack trace is parseable', () => Trace.current()); + test('a native stack trace is parseable', Trace.current); group('.parse', () { test('.parse parses a V8 stack trace with eval statment correctly', () { @@ -26,10 +26,10 @@ void main() { test('.parse parses a VM stack trace correctly', () { var trace = Trace.parse( - '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' - '#1 zip..zap (dart:async/future.dart:0:2)\n' - '#2 zip..zap (https://pub.dev/thing.' - 'dart:1:100)'); + '#0 Foo._bar (file:///home/nweiz/code/stuff.dart:42:21)\n' + '#1 zip..zap (dart:async/future.dart:0:2)\n' + '#2 zip..zap (https://pub.dev/thing.dart:1:100)', + ); expect(trace.frames[0].uri, equals(Uri.parse('file:///home/nweiz/code/stuff.dart'))); @@ -250,12 +250,12 @@ void main() { }); test('parses a package:stack_trace stack chain with end gap correctly', () { - var trace = - Trace.parse('https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' - 'https://dart.dev/foo/baz.dart Foo..bar\n' - 'https://dart.dev/foo/bang.dart 10:11 Foo..bar\n' - 'https://dart.dev/foo/quux.dart Foo..bar' - '===== asynchronous gap ===========================\n'); + var trace = Trace.parse( + 'https://dart.dev/foo/bar.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/baz.dart Foo..bar\n' + 'https://dart.dev/foo/bang.dart 10:11 Foo..bar\n' + 'https://dart.dev/foo/quux.dart Foo..bar===== asynchronous gap ===========================\n', + ); expect(trace.frames.length, 4); expect(trace.frames[0].uri, diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index 38950c16a..8092efe9b 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -5,11 +5,11 @@ import 'package:test/test.dart'; /// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. -Matcher frameMember(matcher) => +Matcher frameMember(Object? matcher) => transform((frame) => frame.member, matcher, 'member'); /// Returns a matcher that runs [matcher] against a [Frame]'s `library` field. -Matcher frameLibrary(matcher) => +Matcher frameLibrary(Object? matcher) => transform((frame) => frame.library, matcher, 'library'); /// Returns a matcher that runs [transformation] on its input, then matches @@ -17,8 +17,8 @@ Matcher frameLibrary(matcher) => /// /// [description] should be a noun phrase that describes the relation of the /// output of [transformation] to its input. -Matcher transform( - void Function(dynamic) transformation, matcher, String description) => +Matcher transform(void Function(dynamic) transformation, Object? matcher, + String description) => _TransformMatcher(transformation, wrapMatcher(matcher), description); class _TransformMatcher extends Matcher { @@ -29,7 +29,7 @@ class _TransformMatcher extends Matcher { _TransformMatcher(this._transformation, this._matcher, this._description); @override - bool matches(item, Map matchState) => + bool matches(Object? item, Map matchState) => _matcher.matches(_transformation(item), matchState); @override From 159deac7315d4c7bac801e59db7d3dcd7b6cc9f3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 12 Oct 2022 16:09:05 -0700 Subject: [PATCH 0873/1215] Fix comment reference issues, among other new lints (dart-lang/stack_trace#119) --- pkgs/stack_trace/analysis_options.yaml | 14 +++++ pkgs/stack_trace/example/example.dart | 2 +- pkgs/stack_trace/lib/src/chain.dart | 37 +++++++------ .../lib/src/stack_zone_specification.dart | 32 +++++------- pkgs/stack_trace/lib/src/trace.dart | 23 ++++---- pkgs/stack_trace/lib/src/utils.dart | 2 +- pkgs/stack_trace/test/chain/chain_test.dart | 8 +-- pkgs/stack_trace/test/chain/dart2js_test.dart | 52 ++++++++----------- pkgs/stack_trace/test/chain/utils.dart | 2 +- pkgs/stack_trace/test/chain/vm_test.dart | 12 ++--- pkgs/stack_trace/test/utils.dart | 30 ++--------- pkgs/stack_trace/test/vm_test.dart | 2 +- 12 files changed, 97 insertions(+), 119 deletions(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 1efeefc01..48d93f235 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,3 +1,4 @@ +# https://dart.dev/guides/language/analysis-options include: package:lints/recommended.yaml analyzer: @@ -8,9 +9,14 @@ analyzer: linter: rules: - always_declare_return_types + - avoid_catching_errors + - avoid_dynamic_calls - avoid_private_typedef_functions + - avoid_redundant_argument_values - avoid_unused_constructor_parameters + - avoid_void_async - cancel_subscriptions + - comment_references - directives_ordering - lines_longer_than_80_chars - literal_only_boolean_expressions @@ -19,12 +25,20 @@ linter: - no_runtimeType_toString - omit_local_variable_types - package_api_docs + - prefer_asserts_in_initializer_lists + - prefer_const_constructors + - prefer_const_declarations - prefer_relative_imports - prefer_single_quotes + - sort_pub_dependencies - test_types_in_equals - throw_in_finally - type_annotate_public_apis - unawaited_futures - unnecessary_await_in_return - unnecessary_lambdas + - unnecessary_parenthesis + - unnecessary_statements + - use_is_even_rather_than_modulo + - use_string_buffers - use_super_parameters diff --git a/pkgs/stack_trace/example/example.dart b/pkgs/stack_trace/example/example.dart index a65abb120..7d71221ce 100644 --- a/pkgs/stack_trace/example/example.dart +++ b/pkgs/stack_trace/example/example.dart @@ -7,7 +7,7 @@ void main() { } void _scheduleAsync() { - Future.delayed(Duration(seconds: 1)).then((_) => _runAsync()); + Future.delayed(const Duration(seconds: 1)).then((_) => _runAsync()); } void _runAsync() { diff --git a/pkgs/stack_trace/lib/src/chain.dart b/pkgs/stack_trace/lib/src/chain.dart index 69f9b0c59..6a815c6bc 100644 --- a/pkgs/stack_trace/lib/src/chain.dart +++ b/pkgs/stack_trace/lib/src/chain.dart @@ -21,7 +21,7 @@ final _specKey = Object(); /// A chain of stack traces. /// /// A stack chain is a collection of one or more stack traces that collectively -/// represent the path from [main] through nested function calls to a particular +/// represent the path from `main` through nested function calls to a particular /// code location, usually where an error was thrown. Multiple stack traces are /// necessary when using asynchronous functions, since the program's stack is /// reset before each asynchronous callback is run. @@ -189,21 +189,19 @@ class Chain implements StackTrace { /// Returns a new [Chain] comprised of [traces]. Chain(Iterable traces) : traces = List.unmodifiable(traces); - /// Returns a terser version of [this]. + /// Returns a terser version of this chain. /// /// This calls [Trace.terse] on every trace in [traces], and discards any /// trace that contain only internal frames. /// /// This won't do anything with a raw JavaScript trace, since there's no way /// to determine which frames come from which Dart libraries. However, the - /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to - /// convert JavaScript traces into Dart-style traces. - /// - /// [source_map_stack_trace]: https://pub.dev/packages/source_map_stack_trace + /// [`source_map_stack_trace`](https://pub.dev/packages/source_map_stack_trace) + /// package can be used to convert JavaScript traces into Dart-style traces. Chain get terse => foldFrames((_) => false, terse: true); - /// Returns a new [Chain] based on [this] where multiple stack frames matching - /// [predicate] are folded together. + /// Returns a new [Chain] based on this chain where multiple stack frames + /// matching [predicate] are folded together. /// /// This means that whenever there are multiple frames in a row that match /// [predicate], only the last one is kept. In addition, traces that are @@ -239,7 +237,7 @@ class Chain implements StackTrace { return Chain(nonEmptyTraces); } - /// Converts [this] to a [Trace]. + /// Converts this chain to a [Trace]. /// /// The trace version of a chain is just the concatenation of all the traces /// in the chain. @@ -248,18 +246,19 @@ class Chain implements StackTrace { @override String toString() { // Figure out the longest path so we know how much to pad. - var longest = traces.map((trace) { - return trace.frames - .map((frame) => frame.location.length) - .fold(0, math.max); - }).fold(0, math.max); + var longest = traces + .map((trace) => trace.frames + .map((frame) => frame.location.length) + .fold(0, math.max)) + .fold(0, math.max); // Don't call out to [Trace.toString] here because that doesn't ensure that // padding is consistent across all traces. - return traces.map((trace) { - return trace.frames.map((frame) { - return '${frame.location.padRight(longest)} ${frame.member}\n'; - }).join(); - }).join(chainGap); + return traces + .map((trace) => trace.frames + .map((frame) => + '${frame.location.padRight(longest)} ${frame.member}\n') + .join()) + .join(chainGap); } } diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 8d1b3a78f..8408d0490 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -64,15 +64,13 @@ class StackZoneSpecification { StackZoneSpecification(this._onError, {bool errorZone = true}) : _errorZone = errorZone; - /// Converts [this] to a real [ZoneSpecification]. - ZoneSpecification toSpec() { - return ZoneSpecification( - handleUncaughtError: _errorZone ? _handleUncaughtError : null, - registerCallback: _registerCallback, - registerUnaryCallback: _registerUnaryCallback, - registerBinaryCallback: _registerBinaryCallback, - errorCallback: _errorCallback); - } + /// Converts this specification to a real [ZoneSpecification]. + ZoneSpecification toSpec() => ZoneSpecification( + handleUncaughtError: _errorZone ? _handleUncaughtError : null, + registerCallback: _registerCallback, + registerUnaryCallback: _registerUnaryCallback, + registerBinaryCallback: _registerBinaryCallback, + errorCallback: _errorCallback); /// Returns the current stack chain. /// @@ -107,7 +105,7 @@ class StackZoneSpecification { } } - /// Tracks the current stack chain so it can be set to [_currentChain] when + /// Tracks the current stack chain so it can be set to [_currentNode] when /// [f] is run. ZoneCallback _registerCallback( Zone self, ZoneDelegate parent, Zone zone, R Function() f) { @@ -116,27 +114,25 @@ class StackZoneSpecification { return parent.registerCallback(zone, () => _run(f, node)); } - /// Tracks the current stack chain so it can be set to [_currentChain] when + /// Tracks the current stack chain so it can be set to [_currentNode] when /// [f] is run. ZoneUnaryCallback _registerUnaryCallback( Zone self, ZoneDelegate parent, Zone zone, R Function(T) f) { if (_disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); - return parent.registerUnaryCallback(zone, (arg) { - return _run(() => f(arg), node); - }); + return parent.registerUnaryCallback( + zone, (arg) => _run(() => f(arg), node)); } - /// Tracks the current stack chain so it can be set to [_currentChain] when + /// Tracks the current stack chain so it can be set to [_currentNode] when /// [f] is run. ZoneBinaryCallback _registerBinaryCallback( Zone self, ZoneDelegate parent, Zone zone, R Function(T1, T2) f) { if (_disabled) return parent.registerBinaryCallback(zone, f); var node = _createNode(1); - return parent.registerBinaryCallback(zone, (arg1, arg2) { - return _run(() => f(arg1, arg2), node); - }); + return parent.registerBinaryCallback( + zone, (arg1, arg2) => _run(() => f(arg1, arg2), node)); } /// Looks up the chain associated with [stackTrace] and passes it either to diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 5df7e4dc6..2e4427d4b 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -94,12 +94,13 @@ class Trace implements StackTrace { } var trace = Trace.from(StackTrace.current); - return LazyTrace(() { - // JS includes a frame for the call to StackTrace.current, but the VM - // doesn't, so we skip an extra frame in a JS context. - return Trace(trace.frames.skip(level + (inJS ? 2 : 1)), - original: trace.original.toString()); - }); + return LazyTrace( + () => + // JS includes a frame for the call to StackTrace.current, but the VM + // doesn't, so we skip an extra frame in a JS context. + Trace(trace.frames.skip(level + (inJS ? 2 : 1)), + original: trace.original.toString()), + ); } /// Returns a new stack trace containing the same data as [trace]. @@ -250,7 +251,7 @@ class Trace implements StackTrace { /// platform is being used. StackTrace get vmTrace => VMTrace(frames); - /// Returns a terser version of [this]. + /// Returns a terser version of this trace. /// /// This is accomplished by folding together multiple stack frames from the /// core library or from this package, as in [foldFrames]. Remaining core @@ -260,15 +261,13 @@ class Trace implements StackTrace { /// /// This won't do anything with a raw JavaScript trace, since there's no way /// to determine which frames come from which Dart libraries. However, the - /// [`source_map_stack_trace`][source_map_stack_trace] package can be used to - /// convert JavaScript traces into Dart-style traces. - /// - /// [source_map_stack_trace]: https://pub.dev/packages/source_map_stack_trace + /// [`source_map_stack_trace`][https://pub.dev/packages/source_map_stack_trace] + /// package can be used to convert JavaScript traces into Dart-style traces. /// /// For custom folding, see [foldFrames]. Trace get terse => foldFrames((_) => false, terse: true); - /// Returns a new [Trace] based on [this] where multiple stack frames matching + /// Returns a new [Trace] based on `this` where multiple stack frames matching /// [predicate] are folded together. /// /// This means that whenever there are multiple frames in a row that match diff --git a/pkgs/stack_trace/lib/src/utils.dart b/pkgs/stack_trace/lib/src/utils.dart index 0dd1755af..bd971fe56 100644 --- a/pkgs/stack_trace/lib/src/utils.dart +++ b/pkgs/stack_trace/lib/src/utils.dart @@ -12,4 +12,4 @@ final vmChainGap = RegExp(r'^\n?$', multiLine: true); // TODO(nweiz): When cross-platform imports work, use them to set this. /// Whether we're running in a JS context. -final bool inJS = 0.0 is int; +const bool inJS = 0.0 is int; diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 892738f00..6de759bb5 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -103,7 +103,7 @@ void main() { test("doesn't enable chain-tracking", () { return Chain.disable(() { return Chain.capture(() { - var completer = Completer(); + var completer = Completer(); inMicrotask(() { completer.complete(Chain.current()); }); @@ -126,7 +126,7 @@ void main() { group('Chain.disable()', () { test('disables chain-tracking', () { return Chain.disable(() { - var completer = Completer(); + var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { @@ -138,7 +138,7 @@ void main() { test('Chain.capture() re-enables chain-tracking', () { return Chain.disable(() { return Chain.capture(() { - var completer = Completer(); + var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { @@ -173,7 +173,7 @@ void main() { test("with when: false doesn't disable", () { return Chain.capture(() { return Chain.disable(() { - var completer = Completer(); + var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index 41eb1ce78..584146658 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -184,7 +184,7 @@ void main() { group('current() within capture()', () { test('called in a microtask', () async { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inMicrotask(() => completer.complete(Chain.current())); }); @@ -194,7 +194,7 @@ void main() { }); test('called in a one-shot timer', () async { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inOneShotTimer(() => completer.complete(Chain.current())); }); @@ -204,7 +204,7 @@ void main() { }); test('called in a periodic timer', () async { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() => completer.complete(Chain.current())); }); @@ -214,7 +214,7 @@ void main() { }); test('called in a nested series of asynchronous operations', () async { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() { inOneShotTimer(() { @@ -228,7 +228,7 @@ void main() { }); test('called in a long future chain', () async { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inFutureChain(() => completer.complete(Chain.current())); }); @@ -239,11 +239,11 @@ void main() { }); test( - 'current() outside of capture() returns a chain wrapping the current ' - 'trace', () { - // The test runner runs all tests with chains enabled. - return Chain.disable(() async { - var completer = Completer(); + 'current() outside of capture() returns a chain wrapping the current trace', + () => + // The test runner runs all tests with chains enabled. + Chain.disable(() async { + var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); var chain = await completer.future; @@ -251,14 +251,13 @@ void main() { // chain isn't available and it just returns the current stack when // called. expect(chain.traces, hasLength(1)); - }); - }); + }), + ); group('forTrace() within capture()', () { test('called for a stack trace from a microtask', () async { - var chain = await Chain.capture(() { - return chainForTrace(inMicrotask, () => throw 'error'); - }); + var chain = await Chain.capture( + () => chainForTrace(inMicrotask, () => throw 'error')); // Because [chainForTrace] has to set up a future chain to capture the // stack trace while still showing it to the zone specification, it adds @@ -267,17 +266,15 @@ void main() { }); test('called for a stack trace from a one-shot timer', () async { - var chain = await Chain.capture(() { - return chainForTrace(inOneShotTimer, () => throw 'error'); - }); + var chain = await Chain.capture( + () => chainForTrace(inOneShotTimer, () => throw 'error')); expect(chain.traces, hasLength(3)); }); test('called for a stack trace from a periodic timer', () async { - var chain = await Chain.capture(() { - return chainForTrace(inPeriodicTimer, () => throw 'error'); - }); + var chain = await Chain.capture( + () => chainForTrace(inPeriodicTimer, () => throw 'error')); expect(chain.traces, hasLength(3)); }); @@ -285,19 +282,16 @@ void main() { test( 'called for a stack trace from a nested series of asynchronous ' 'operations', () async { - var chain = await Chain.capture(() { - return chainForTrace((callback) { - inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); - }, () => throw 'error'); - }); + var chain = await Chain.capture(() => chainForTrace((callback) { + inPeriodicTimer(() => inOneShotTimer(() => inMicrotask(callback))); + }, () => throw 'error')); expect(chain.traces, hasLength(5)); }); test('called for a stack trace from a long future chain', () async { - var chain = await Chain.capture(() { - return chainForTrace(inFutureChain, () => throw 'error'); - }); + var chain = await Chain.capture( + () => chainForTrace(inFutureChain, () => throw 'error')); expect(chain.traces, hasLength(3)); }); diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 0a74d9ae6..2cc64527f 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -16,7 +16,7 @@ void inOneShotTimer(void Function() callback) => Timer.run(callback); /// Runs [callback] once in a periodic timer callback. void inPeriodicTimer(void Function() callback) { var count = 0; - Timer.periodic(Duration(milliseconds: 1), (timer) { + Timer.periodic(const Duration(milliseconds: 1), (timer) { count++; if (count != 5) return; timer.cancel(); diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 7c8278bde..83e01d4f6 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -282,7 +282,7 @@ void main() { group('current() within capture()', () { test('called in a microtask', () { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inMicrotask(() => completer.complete(Chain.current())); }); @@ -296,7 +296,7 @@ void main() { }); test('called in a one-shot timer', () { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inOneShotTimer(() => completer.complete(Chain.current())); }); @@ -310,7 +310,7 @@ void main() { }); test('called in a periodic timer', () { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() => completer.complete(Chain.current())); }); @@ -324,7 +324,7 @@ void main() { }); test('called in a nested series of asynchronous operations', () { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inPeriodicTimer(() { inOneShotTimer(() { @@ -346,7 +346,7 @@ void main() { }); test('called in a long future chain', () { - var completer = Completer(); + var completer = Completer(); Chain.capture(() { inFutureChain(() => completer.complete(Chain.current())); }); @@ -365,7 +365,7 @@ void main() { 'trace', () { // The test runner runs all tests with chains enabled. return Chain.disable(() { - var completer = Completer(); + var completer = Completer(); inMicrotask(() => completer.complete(Chain.current())); return completer.future.then((chain) { diff --git a/pkgs/stack_trace/test/utils.dart b/pkgs/stack_trace/test/utils.dart index 8092efe9b..98cb5ede0 100644 --- a/pkgs/stack_trace/test/utils.dart +++ b/pkgs/stack_trace/test/utils.dart @@ -2,37 +2,13 @@ // 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. +import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; /// Returns a matcher that runs [matcher] against a [Frame]'s `member` field. Matcher frameMember(Object? matcher) => - transform((frame) => frame.member, matcher, 'member'); + isA().having((p0) => p0.member, 'member', matcher); /// Returns a matcher that runs [matcher] against a [Frame]'s `library` field. Matcher frameLibrary(Object? matcher) => - transform((frame) => frame.library, matcher, 'library'); - -/// Returns a matcher that runs [transformation] on its input, then matches -/// the output against [matcher]. -/// -/// [description] should be a noun phrase that describes the relation of the -/// output of [transformation] to its input. -Matcher transform(void Function(dynamic) transformation, Object? matcher, - String description) => - _TransformMatcher(transformation, wrapMatcher(matcher), description); - -class _TransformMatcher extends Matcher { - final Function _transformation; - final Matcher _matcher; - final String _description; - - _TransformMatcher(this._transformation, this._matcher, this._description); - - @override - bool matches(Object? item, Map matchState) => - _matcher.matches(_transformation(item), matchState); - - @override - Description describe(Description description) => - description.add(_description).add(' ').addDescriptionOf(_matcher); -} + isA().having((p0) => p0.library, 'library', matcher); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index c9f819a9b..e0dbcff39 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -67,7 +67,7 @@ void main() { }); test('at level 0 returns a trace starting at the current frame', () { - var trace = Trace.current(0); + var trace = Trace.current(); expect(trace.frames.first.member, equals('main...')); }); From 71fd07beffa0ce0931b808dd7aade2b2608ea400 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 12 Oct 2022 16:56:12 -0700 Subject: [PATCH 0874/1215] Enable browser testing on CI, fix one test with browser-specific issues (dart-lang/stack_trace#120) --- pkgs/stack_trace/.github/workflows/test-package.yml | 3 +++ pkgs/stack_trace/test/chain/chain_test.dart | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 1b823da8a..23916f38c 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -59,3 +59,6 @@ jobs: - name: Run VM tests run: dart test --platform vm if: always() && steps.install.outcome == 'success' + - name: Run browser tests + run: dart test --platform chrome + if: always() && steps.install.outcome == 'success' diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index 6de759bb5..aa4256bfc 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -48,8 +48,13 @@ void main() { expect(chain.traces[0].frames[0].toString(), equals('package:my_lib.dart 134:5 in MyClass.run')); expect(chain.traces[1].frames, hasLength(1)); - expect(chain.traces[1].frames[0].toString(), - equals('/my_app.dart 9:3 in main')); + expect( + chain.traces[1].frames[0].toString(), + anyOf( + equals('/my_app.dart 9:3 in main'), // VM + equals('file:///my_app.dart 9:3 in main'), // Browser + ), + ); }); }); From 3a55d4c26124ec9d381ec05b9e3426f69b70b601 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 14 Oct 2022 18:00:11 -0700 Subject: [PATCH 0875/1215] Add whereNotNull (dart-lang/stream_transform#156) This is useful during null safety migrations for the same reason as `Iterable.whereNotNull` from `package:collection`. --- pkgs/stream_transform/CHANGELOG.md | 4 ++ pkgs/stream_transform/lib/src/where.dart | 11 ++++ pkgs/stream_transform/pubspec.yaml | 2 +- .../test/where_not_null_test.dart | 56 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 pkgs/stream_transform/test/where_not_null_test.dart diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index f425a1ad1..3d2cd6964 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.0 + +- Add `whereNotNull`. + ## 2.0.1 - Require Dart 2.14 or greater. diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 569dc3168..6d210eabb 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -58,3 +58,14 @@ extension Where on Stream { }); } } + +extension WhereNotNull on Stream { + /// Discards `null` events from this stream. + /// + /// If the source stream is a broadcast stream the result will be as well. + /// + /// Errors from the source stream are forwarded directly to the result stream. + Stream whereNotNull() => transformByHandlers(onData: (event, sink) { + if (event != null) sink.add(event); + }); +} diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 181517869..a53112271 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_transform -version: 2.0.1 +version: 2.1.0 description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/stream_transform diff --git a/pkgs/stream_transform/test/where_not_null_test.dart b/pkgs/stream_transform/test/where_not_null_test.dart new file mode 100644 index 000000000..c7e4e9b8f --- /dev/null +++ b/pkgs/stream_transform/test/where_not_null_test.dart @@ -0,0 +1,56 @@ +// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; + +import 'package:stream_transform/stream_transform.dart'; +import 'package:test/test.dart'; + +void main() { + test('forwards only events that match the type', () async { + var values = Stream.fromIterable([null, 'a', null, 'b']); + var filtered = values.whereNotNull(); + expect(await filtered.toList(), ['a', 'b']); + }); + + test('can result in empty stream', () async { + var values = Stream.fromIterable([null, null]); + var filtered = values.whereNotNull(); + expect(await filtered.isEmpty, true); + }); + + test('forwards values to multiple listeners', () async { + var values = StreamController.broadcast(); + var filtered = values.stream.whereNotNull(); + var firstValues = []; + var secondValues = []; + filtered + ..listen(firstValues.add) + ..listen(secondValues.add); + values + ..add(null) + ..add('a') + ..add(null) + ..add('b'); + await Future(() {}); + expect(firstValues, ['a', 'b']); + expect(secondValues, ['a', 'b']); + }); + + test('closes streams with multiple listeners', () async { + var values = StreamController.broadcast(); + var filtered = values.stream.whereNotNull(); + var firstDone = false; + var secondDone = false; + filtered + ..listen(null, onDone: () => firstDone = true) + ..listen(null, onDone: () => secondDone = true); + values + ..add(null) + ..add('a'); + await values.close(); + expect(firstDone, true); + expect(secondDone, true); + }); +} From 34a713bb68714df0b1f1c9ac49c8428d2855f052 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Oct 2022 17:28:46 -0700 Subject: [PATCH 0876/1215] fix changelog link --- pkgs/stack_trace/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 6291d735d..43a0f376c 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -320,7 +320,7 @@ * Remove a workaround for [issue 17083][]. -[issue 17083]: http://code.google.com/p/dart/issues/detail?id=17083 +[issue 17083]: https://github.com/dart-lang/sdk/issues/17083 ## 1.0.1 From dcbb21f24e3d21296f557848d86e7e2c73311822 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 25 Oct 2022 09:15:34 -0700 Subject: [PATCH 0877/1215] Update minimum SDK, latest pkg:lints, update CI actions (dart-lang/string_scanner#48) --- .../.github/workflows/test-package.yml | 10 ++-- pkgs/string_scanner/CHANGELOG.md | 2 + pkgs/string_scanner/analysis_options.yaml | 50 ++++++------------- .../lib/src/eager_span_scanner.dart | 3 +- pkgs/string_scanner/lib/src/exception.dart | 4 +- pkgs/string_scanner/lib/src/line_scanner.dart | 3 +- pkgs/string_scanner/lib/src/span_scanner.dart | 7 ++- .../lib/src/string_scanner.dart | 4 +- pkgs/string_scanner/pubspec.yaml | 4 +- 9 files changed, 33 insertions(+), 54 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 9bf684586..bc4359926 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -47,10 +47,10 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.18.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 5963ce8e0..b5346b063 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.2.0 +* Require Dart 2.18.0 + * Add better support for reading code points in the Unicode supplementary plane: * Added `StringScanner.readCodePoint()`, which consumes an entire Unicode code diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index a4495f2e0..b507c06db 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -1,75 +1,55 @@ +# https://dart.dev/guides/language/analysis-options include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-inference: true + strict-raw-types: true linter: rules: + - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_function_literals_in_foreach_calls + - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_renaming_method_parameters - avoid_returning_null_for_future - - avoid_returning_null_for_void - avoid_returning_this - - avoid_single_cascade_in_expression_statements - avoid_unused_constructor_parameters - avoid_void_async - - await_only_futures - - camel_case_types - cancel_subscriptions - comment_references - - constant_identifier_names - - control_flow_in_finally - directives_ordering - - empty_statements - - file_names - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - join_return_with_assignment - lines_longer_than_80_chars - - list_remove_unrelated_type - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - non_constant_identifier_names + - omit_local_variable_types - only_throw_errors - - overridden_fields - package_api_docs - - package_names - - package_prefixed_library_names - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_function_declarations_over_variables - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_interpolation_to_compose_strings - - prefer_is_not_operator - - prefer_null_aware_operators - prefer_relative_imports - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message + - prefer_single_quotes - sort_pub_dependencies - test_types_in_equals - throw_in_finally + - type_annotate_public_apis + - unawaited_futures - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_overrides - unnecessary_parenthesis + - unnecessary_raw_strings - unnecessary_statements - - unnecessary_string_interpolations + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings - use_string_buffers - - void_checks + - use_super_parameters diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index 3bf5416d2..db06127e4 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -68,8 +68,7 @@ class EagerSpanScanner extends SpanScanner { } } - EagerSpanScanner(String string, {sourceUrl, int? position}) - : super(string, sourceUrl: sourceUrl, position: position); + EagerSpanScanner(super.string, {super.sourceUrl, super.position}); @override bool scanChar(int character) { diff --git a/pkgs/string_scanner/lib/src/exception.dart b/pkgs/string_scanner/lib/src/exception.dart index 8aa7aabea..57af541ff 100644 --- a/pkgs/string_scanner/lib/src/exception.dart +++ b/pkgs/string_scanner/lib/src/exception.dart @@ -16,6 +16,6 @@ class StringScannerException extends SourceSpanFormatException { /// This may be `null`, indicating that the source URL is unknown. Uri? get sourceUrl => span?.sourceUrl; - StringScannerException(String message, SourceSpan span, String source) - : super(message, span, source); + StringScannerException( + super.message, SourceSpan super.span, String super.source); } diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 4f0673c9e..5bf701c09 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -73,8 +73,7 @@ class LineScanner extends StringScanner { } } - LineScanner(String string, {sourceUrl, int? position}) - : super(string, sourceUrl: sourceUrl, position: position); + LineScanner(super.string, {super.sourceUrl, super.position}); @override bool scanChar(int character) { diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 806a8f8ea..413a43331 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -59,13 +59,12 @@ class SpanScanner extends StringScanner implements LineScanner { /// [sourceUrl] is used as [SourceLocation.sourceUrl] for the returned /// [FileSpan]s as well as for error reporting. It can be a [String], a /// [Uri], or `null`. - SpanScanner(String string, {sourceUrl, int? position}) - : _sourceFile = SourceFile.fromString(string, url: sourceUrl), - super(string, sourceUrl: sourceUrl, position: position); + SpanScanner(super.string, {super.sourceUrl, super.position}) + : _sourceFile = SourceFile.fromString(string, url: sourceUrl); /// Creates a new [SpanScanner] that eagerly computes line and column numbers. /// - /// In general [new SpanScanner] will be more efficient, since it avoids extra + /// In general [SpanScanner.new] will be more efficient, since it avoids extra /// computation on every scan. However, eager scanning can be useful for /// situations where the normal course of parsing frequently involves /// accessing the current line and column numbers. diff --git a/pkgs/string_scanner/lib/src/string_scanner.dart b/pkgs/string_scanner/lib/src/string_scanner.dart index de566a5b6..146694432 100644 --- a/pkgs/string_scanner/lib/src/string_scanner.dart +++ b/pkgs/string_scanner/lib/src/string_scanner.dart @@ -56,7 +56,7 @@ class StringScanner { /// [position] defaults to 0, the beginning of the string. [sourceUrl] is the /// URL of the source of the string being scanned, if available. It can be /// a [String], a [Uri], or `null`. - StringScanner(this.string, {sourceUrl, int? position}) + StringScanner(this.string, {Object? sourceUrl, int? position}) : sourceUrl = sourceUrl == null ? null : sourceUrl is String @@ -205,7 +205,7 @@ class StringScanner { name = '/$source/'; } else { name = - pattern.toString().replaceAll('\\', '\\\\').replaceAll('"', '\\"'); + pattern.toString().replaceAll(r'\', r'\\').replaceAll('"', r'\"'); name = '"$name"'; } } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index c38f3bfe4..6f14e81c7 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -4,11 +4,11 @@ description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.18.0 <3.0.0" dependencies: source_span: ^1.8.0 dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.16.0 From dfed9c2c185fb4d4fcd83b1861694bd6a15be089 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 31 Oct 2022 12:17:54 -0700 Subject: [PATCH 0878/1215] Make code in readme consistent with example (dart-lang/string_scanner#49) --- pkgs/string_scanner/README.md | 4 ++-- pkgs/string_scanner/example/example.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/string_scanner/README.md b/pkgs/string_scanner/README.md index b7a49c363..e06e32567 100644 --- a/pkgs/string_scanner/README.md +++ b/pkgs/string_scanner/README.md @@ -24,11 +24,11 @@ num parseNumber(String source) { // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. - var number = num.parse(scanner.lastMatch[0]); + var number = num.parse(scanner.lastMatch![0]!); if (scanner.scan('.')) { scanner.expect(RegExp(r'\d+')); - final decimal = scanner.lastMatch[0]; + final decimal = scanner.lastMatch![0]!; number += int.parse(decimal) / math.pow(10, decimal.length); } diff --git a/pkgs/string_scanner/example/example.dart b/pkgs/string_scanner/example/example.dart index fd36a73c1..ec9dd7660 100644 --- a/pkgs/string_scanner/example/example.dart +++ b/pkgs/string_scanner/example/example.dart @@ -24,7 +24,7 @@ num parseNumber(String source) { // [Scanner.lastMatch] holds the [MatchData] for the most recent call to // [Scanner.scan], [Scanner.expect], or [Scanner.matches]. - var number = num.parse((scanner.lastMatch![0])!); + var number = num.parse(scanner.lastMatch![0]!); if (scanner.scan('.')) { scanner.expect(RegExp(r'\d+')); From f7a9b1d31a07592936244f582911c4465f191230 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 9 Nov 2022 15:26:32 -0800 Subject: [PATCH 0879/1215] blast_repo fixes (dart-lang/pubspec_parse#85) Dependabot GitHub Action --- pkgs/pubspec_parse/.github/dependabot.yml | 9 +++++++++ pkgs/pubspec_parse/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkgs/pubspec_parse/.github/dependabot.yml diff --git a/pkgs/pubspec_parse/.github/dependabot.yml b/pkgs/pubspec_parse/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/pubspec_parse/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index a818a1b94..53753996a 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -48,8 +48,8 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 2b76fa0fa737f892acb6156db35980649f823582 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 9 Nov 2022 15:30:56 -0800 Subject: [PATCH 0880/1215] blast_repo fixes (dart-lang/timing#22) Dependabot GitHub Action --- pkgs/timing/.github/dependabot.yml | 9 +++++++++ pkgs/timing/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkgs/timing/.github/dependabot.yml diff --git a/pkgs/timing/.github/dependabot.yml b/pkgs/timing/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/timing/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 5178d2807..e26ea5e4e 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -46,8 +46,8 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 34bf35867217b0df4afde8e5e47b1b9547777dbd Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 10 Nov 2022 03:30:31 -0800 Subject: [PATCH 0881/1215] blast_repo fixes (dart-lang/stream_channel#82) Dependabot GitHub Action --- pkgs/stream_channel/.github/dependabot.yml | 16 +++++++--------- .../.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 430a85e7d..1603cdd9e 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -1,11 +1,9 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates version: 2 -updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9de6d54aa..4e2ee9d50 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 29a7bf053ebbe238828b79d5d1221553740425b1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 15 Nov 2022 14:30:33 -0800 Subject: [PATCH 0882/1215] blast_repo fixes (dart-lang/term_glyph#29) Dependabot GitHub Action --- pkgs/term_glyph/.github/dependabot.yml | 9 +++++++++ pkgs/term_glyph/.github/workflows/test-package.yml | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) create mode 100644 pkgs/term_glyph/.github/dependabot.yml diff --git a/pkgs/term_glyph/.github/dependabot.yml b/pkgs/term_glyph/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/term_glyph/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index e47bf6600..81ebfebcd 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1.0 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 8d668a813cba1aa6448f5261cf87bff1ace18f08 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 15 Nov 2022 14:30:53 -0800 Subject: [PATCH 0883/1215] blast_repo fixes (dart-lang/test_reflective_loader#42) Dependabot GitHub Action --- pkgs/test_reflective_loader/.github/dependabot.yml | 9 +++++++++ pkgs/test_reflective_loader/.github/workflows/build.yaml | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 pkgs/test_reflective_loader/.github/dependabot.yml diff --git a/pkgs/test_reflective_loader/.github/dependabot.yml b/pkgs/test_reflective_loader/.github/dependabot.yml new file mode 100644 index 000000000..1603cdd9e --- /dev/null +++ b/pkgs/test_reflective_loader/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 9728c9492..10913c69f 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,8 +21,8 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From ea580398c46541974e0918f5298ba728b9cbb045 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 1 Dec 2022 12:24:45 -0800 Subject: [PATCH 0884/1215] blast_repo fixes (dart-lang/stack_trace#123) Dependabot GitHub Action --- pkgs/stack_trace/.github/dependabot.yml | 9 +++++++++ pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 pkgs/stack_trace/.github/dependabot.yml diff --git a/pkgs/stack_trace/.github/dependabot.yml b/pkgs/stack_trace/.github/dependabot.yml new file mode 100644 index 000000000..952351121 --- /dev/null +++ b/pkgs/stack_trace/.github/dependabot.yml @@ -0,0 +1,9 @@ +# Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates + +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 23916f38c..1149cbb1f 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 27b9483ca71422bc6e05c8d226ee15ff764cf716 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 12 Dec 2022 10:24:25 -0800 Subject: [PATCH 0885/1215] Fix test compatibility with Dart 3 (dart-lang/stream_transform#159) Move opt out test to separate directory so they will not run by default. Collapse the chrome and VM tests into a single workflow step. Add a separate workflow step to run the chrome and VM opt out tests for only the oldest supported SDK. --- .../.github/workflows/test-package.yml | 11 ++++++----- .../{test => legacy_test}/opt_out_test.dart | 0 2 files changed, 6 insertions(+), 5 deletions(-) rename pkgs/stream_transform/{test => legacy_test}/opt_out_test.dart (100%) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 3aa30d4e8..ac6cb6923 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -47,6 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] + # Bump SDK for Legacy tets when changning min SDK. sdk: [2.14.0, dev] steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 @@ -56,9 +57,9 @@ jobs: - id: install name: Install dependencies run: dart pub get - - name: Run VM tests - run: dart test --platform vm --test-randomize-ordering-seed=random - if: always() && steps.install.outcome == 'success' - - name: Run Chrome tests - run: dart test --platform chrome --test-randomize-ordering-seed=random + - name: Run tests + run: dart test -p chrome,vm --test-randomize-ordering-seed=random if: always() && steps.install.outcome == 'success' + - name: Run Legacy tests + run: dart test -p chrome,vm --test-randomize-ordering-seed=random legacy_test + if: always() && matrix.sdk == '2.14.0' && steps.install.outcome == 'success' diff --git a/pkgs/stream_transform/test/opt_out_test.dart b/pkgs/stream_transform/legacy_test/opt_out_test.dart similarity index 100% rename from pkgs/stream_transform/test/opt_out_test.dart rename to pkgs/stream_transform/legacy_test/opt_out_test.dart From da1376283ea31817d855805e275b2318568a8983 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 12 Dec 2022 14:14:19 -0800 Subject: [PATCH 0886/1215] fix the unit tests for Dart 3.0 (dart-lang/pubspec_parse#86) * fix the unit tests for Dart 3.0 * update the package version --- .../.github/workflows/test-package.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 5 +- pkgs/pubspec_parse/LICENSE | 2 +- pkgs/pubspec_parse/README.md | 7 +- pkgs/pubspec_parse/pubspec.yaml | 6 +- pkgs/pubspec_parse/test/dependency_test.dart | 63 +++++--------- pkgs/pubspec_parse/test/parse_test.dart | 86 +++++-------------- pkgs/pubspec_parse/test/test_utils.dart | 35 +++++++- 8 files changed, 90 insertions(+), 116 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 53753996a..c46df3002 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.14.0, dev] + sdk: [2.17.0, dev] steps: - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 069e81ceb..117fd129e 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,4 +1,7 @@ -## 1.2.1-dev +## 1.2.2-dev + +- Update SDK requirement to `2.17.0`. +- Fix the unit tests for Dart 3.0.0. ## 1.2.1 diff --git a/pkgs/pubspec_parse/LICENSE b/pkgs/pubspec_parse/LICENSE index 9972f6e70..4d1ad40a1 100644 --- a/pkgs/pubspec_parse/LICENSE +++ b/pkgs/pubspec_parse/LICENSE @@ -1,4 +1,4 @@ -Copyright 2018, the Dart project authors. +Copyright 2018, the Dart project authors. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index eca3610fd..916742a63 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,7 +1,12 @@ -[![Build Status](https://github.com/dart-lang/pubspec_parse/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/pubspec_parse/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Dart CI](https://github.com/dart-lang/pubspec_parse/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/pubspec_parse/actions/workflows/test-package.yml) [![pub package](https://img.shields.io/pub/v/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse) +[![package publisher](https://img.shields.io/pub/publisher/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse/publisher) + +## What's this? Supports parsing `pubspec.yaml` files with robust error reporting and support for most of the documented features. +## More information + Read more about the [pubspec format](https://dart.dev/tools/pub/pubspec). diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 23f15c160..03f61bd80 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,11 +2,11 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.1 +version: 1.2.2-dev repository: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.14.0 <3.0.0' + sdk: '>=2.17.0 <3.0.0' dependencies: checked_yaml: ^2.0.1 @@ -19,7 +19,7 @@ dev_dependencies: build_runner: ^2.0.3 build_verify: '>=2.0.0 <4.0.0' json_serializable: ^6.0.0 - lints: ^1.0.0 + lints: ^2.0.0 path: ^1.5.1 # Needed because we are configuring `combining_builder` source_gen: ^1.0.0 diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 8fb48e867..b366887a3 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -225,30 +225,16 @@ void _sdkDependency() { }); test('null content', () { - _expectThrows( + _expectThrowsContaining( {'sdk': null}, - r''' -line 5, column 11: Unsupported value for "sdk". type 'Null' is not a subtype of type 'String' in type cast - ╷ -5 │ "sdk": null - │ ┌───────────^ -6 │ │ } - │ └──^ - ╵''', + r"type 'Null' is not a subtype of type 'String'", ); }); test('number content', () { - _expectThrows( + _expectThrowsContaining( {'sdk': 42}, - r''' -line 5, column 11: Unsupported value for "sdk". type 'int' is not a subtype of type 'String' in type cast - ╷ -5 │ "sdk": 42 - │ ┌───────────^ -6 │ │ } - │ └──^ - ╵''', + r"type 'int' is not a subtype of type 'String'", ); }); } @@ -337,46 +323,27 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. }); test('git - empty map', () { - _expectThrows( + _expectThrowsContaining( {'git': {}}, - r''' -line 5, column 11: Missing key "url". type 'Null' is not a subtype of type 'String' in type cast - ╷ -5 │ "git": {} - │ ^^ - ╵''', + r"type 'Null' is not a subtype of type 'String'", ); }); test('git - null url', () { - _expectThrows( + _expectThrowsContaining( { 'git': {'url': null} }, - r''' -line 6, column 12: Unsupported value for "url". type 'Null' is not a subtype of type 'String' in type cast - ╷ -6 │ "url": null - │ ┌────────────^ -7 │ │ } - │ └───^ - ╵''', + r"type 'Null' is not a subtype of type 'String'", ); }); test('git - int url', () { - _expectThrows( + _expectThrowsContaining( { 'git': {'url': 42} }, - r''' -line 6, column 12: Unsupported value for "url". type 'int' is not a subtype of type 'String' in type cast - ╷ -6 │ "url": 42 - │ ┌────────────^ -7 │ │ } - │ └───^ - ╵''', + r"type 'int' is not a subtype of type 'String'", ); }); } @@ -446,6 +413,16 @@ void _expectThrows(Object content, String expectedError) { ); } +void _expectThrowsContaining(Object content, String errorText) { + expectParseThrowsContaining( + { + 'name': 'sample', + 'dependencies': {'dep': content} + }, + errorText, + ); +} + T _dependency( Object? content, { bool skipTryPub = false, diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index a12d034fd..f3b4679bb 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. // ignore_for_file: deprecated_member_use_from_same_package +// ignore_for_file: lines_longer_than_80_chars + library parse_test; import 'package:pub_semver/pub_semver.dart'; @@ -22,7 +24,7 @@ void main() { expect(value.authors, isEmpty); expect( value.environment, - {'sdk': VersionConstraint.parse('>=2.7.0 <3.0.0')}, + {'sdk': VersionConstraint.parse('>=2.12.0 <3.0.0')}, ); expect(value.documentation, isNull); expect(value.dependencies, isEmpty); @@ -36,7 +38,7 @@ void main() { test('all fields set', () { final version = Version.parse('1.2.3'); - final sdkConstraint = VersionConstraint.parse('>=2.0.0-dev.54 <3.0.0'); + final sdkConstraint = VersionConstraint.parse('>=2.12.0 <3.0.0'); final value = parse({ 'name': 'sample', 'version': version.toString(), @@ -85,7 +87,7 @@ void main() { { 'name': 'sample', 'environment': { - 'sdk': '>=2.7.0 <3.0.0', + 'sdk': '>=2.12.0 <3.0.0', 'bob': null, } }, @@ -98,12 +100,7 @@ void main() { group('publish_to', () { for (var entry in { - 42: r''' -line 3, column 16: Unsupported value for "publish_to". type 'int' is not a subtype of type 'String?' in type cast - ╷ -3 │ "publish_to": 42 - │ ^^ - ╵''', + 42: "Unsupported value for \"publish_to\". type 'int' is not a subtype of type 'String?'", '##not a uri!': r''' line 3, column 16: Unsupported value for "publish_to". Must be an http or https URL. ╷ @@ -124,7 +121,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https ╵''', }.entries) { test('cannot be `${entry.key}`', () { - expectParseThrows( + expectParseThrowsContaining( {'name': 'sample', 'publish_to': entry.key}, entry.value, skipTryPub: true, @@ -241,26 +238,16 @@ line 1, column 1: Not a map }); test('missing name', () { - expectParseThrows( + expectParseThrowsContaining( {}, - r''' -line 1, column 1: Missing key "name". type 'Null' is not a subtype of type 'String' in type cast - ╷ -1 │ {} - │ ^^ - ╵''', + "Missing key \"name\". type 'Null' is not a subtype of type 'String'", ); }); test('null name value', () { - expectParseThrows( + expectParseThrowsContaining( {'name': null}, - r''' -line 2, column 10: Unsupported value for "name". type 'Null' is not a subtype of type 'String' in type cast - ╷ -2 │ "name": null - │ ^^^^ - ╵''', + "Unsupported value for \"name\". type 'Null' is not a subtype of type 'String'", ); }); @@ -336,37 +323,23 @@ line 4, column 10: Unsupported value for "sdk". Could not parse version "silly". }); test('bad repository url', () { - expectParseThrows( + expectParseThrowsContaining( { ...defaultPubspec, 'repository': {'x': 'y'}, }, - r''' -line 6, column 16: Unsupported value for "repository". type 'YamlMap' is not a subtype of type 'String' in type cast - ╷ -6 │ "repository": { - │ ┌────────────────^ -7 │ │ "x": "y" -8 │ └ } - ╵''', + "Unsupported value for \"repository\". type 'YamlMap' is not a subtype of type 'String'", skipTryPub: true, ); }); test('bad issue_tracker url', () { - expectParseThrows( + expectParseThrowsContaining( { 'name': 'sample', 'issue_tracker': {'x': 'y'}, }, - r''' -line 3, column 19: Unsupported value for "issue_tracker". type 'YamlMap' is not a subtype of type 'String' in type cast - ╷ -3 │ "issue_tracker": { - │ ┌───────────────────^ -4 │ │ "x": "y" -5 │ └ } - ╵''', + "Unsupported value for \"issue_tracker\". type 'YamlMap' is not a subtype of type 'String'", skipTryPub: true, ); }); @@ -374,35 +347,23 @@ line 3, column 19: Unsupported value for "issue_tracker". type 'YamlMap' is not group('funding', () { test('not a list', () { - expectParseThrows( + expectParseThrowsContaining( { ...defaultPubspec, 'funding': 1, }, - r''' -line 6, column 13: Unsupported value for "funding". type 'int' is not a subtype of type 'List?' in type cast - ╷ -6 │ "funding": 1 - │ ^ - ╵''', + "Unsupported value for \"funding\". type 'int' is not a subtype of type 'List?'", skipTryPub: true, ); }); test('not an uri', () { - expectParseThrows( + expectParseThrowsContaining( { ...defaultPubspec, 'funding': [1], }, - r''' -line 6, column 13: Unsupported value for "funding". type 'int' is not a subtype of type 'String' in type cast - ╷ -6 │ "funding": [ - │ ┌─────────────^ -7 │ │ 1 -8 │ └ ] - ╵''', + "Unsupported value for \"funding\". type 'int' is not a subtype of type 'String'", skipTryPub: true, ); }); @@ -608,14 +569,9 @@ line 1, column 1: Not a map }); test('name cannot be empty', () { - expectParseThrows( + expectParseThrowsContaining( {}, - r''' -line 1, column 1: Missing key "name". type 'Null' is not a subtype of type 'String' in type cast - ╷ -1 │ {} - │ ^^ - ╵''', + "Missing key \"name\". type 'Null' is not a subtype of type 'String'", lenient: true, ); }); diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index 72d214242..b573851ad 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -16,7 +16,7 @@ import 'pub_utils.dart'; const defaultPubspec = { 'name': 'sample', - 'environment': {'sdk': '>=2.7.0 <3.0.0'}, + 'environment': {'sdk': '>=2.12.0 <3.0.0'}, }; String _encodeJson(Object? input) => @@ -124,3 +124,36 @@ void expectParseThrows( ), _throwsParsedYamlException(expectedError), ); + +void expectParseThrowsContaining( + Object? content, + String errorFragment, { + bool skipTryPub = false, + bool lenient = false, +}) { + expect( + () => parse( + content, + lenient: lenient, + quietOnError: true, + skipTryPub: skipTryPub, + ), + _throwsParsedYamlExceptionContaining(errorFragment), + ); +} + +// ignore: prefer_expression_function_bodies +Matcher _throwsParsedYamlExceptionContaining(String errorFragment) { + return throwsA( + const TypeMatcher().having( + (e) { + final message = e.formattedMessage; + printOnFailure("Actual error format:\nr'''\n$message'''"); + _printDebugParsedYamlException(e); + return message; + }, + 'formattedMessage', + contains(errorFragment), + ), + ); +} From a42fdf8baa3acda195d5e502cfe72035c8f128a5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Dec 2022 12:12:30 -0800 Subject: [PATCH 0887/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/string_scanner#50) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index bc4359926..cc5abcf3c 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 3062f6558174635706e88fc425657ff2cb56de7f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 28 Dec 2022 16:37:21 -0800 Subject: [PATCH 0888/1215] Remove unnecessary parens (dart-lang/string_scanner#51) --- pkgs/string_scanner/CHANGELOG.md | 2 ++ pkgs/string_scanner/lib/src/eager_span_scanner.dart | 2 +- pkgs/string_scanner/lib/src/line_scanner.dart | 4 ++-- pkgs/string_scanner/pubspec.yaml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index b5346b063..57b31ba8a 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.2.1-dev + ## 1.2.0 * Require Dart 2.18.0 diff --git a/pkgs/string_scanner/lib/src/eager_span_scanner.dart b/pkgs/string_scanner/lib/src/eager_span_scanner.dart index db06127e4..1ccc746ac 100644 --- a/pkgs/string_scanner/lib/src/eager_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/eager_span_scanner.dart @@ -97,7 +97,7 @@ class EagerSpanScanner extends SpanScanner { @override bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - final firstMatch = (lastMatch![0])!; + final firstMatch = lastMatch![0]!; final newlines = _newlinesIn(firstMatch); _line += newlines.length; diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 5bf701c09..2903c4039 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -106,9 +106,9 @@ class LineScanner extends StringScanner { final newlines = _newlinesIn(lastMatch![0]!); _line += newlines.length; if (newlines.isEmpty) { - _column += (lastMatch![0])!.length; + _column += lastMatch![0]!.length; } else { - _column = (lastMatch![0])!.length - newlines.last.end; + _column = lastMatch![0]!.length - newlines.last.end; } return true; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 6f14e81c7..b297e50d2 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.2.0 +version: 1.2.1-dev description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner From 0825a03ac2c3d2a98a69873b269c9e95b0cc74ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:58:28 -0800 Subject: [PATCH 0889/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/timing#23) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index e26ea5e4e..63a6491f6 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 56f1543d690d30eb8e0b9b47d711ba754a55580a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:04:13 -0800 Subject: [PATCH 0890/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/term_glyph#30) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 81ebfebcd..ab056f0b5 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 402a36c2f37e15b7635afd1d9e89a1a88b603750 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:04:27 -0800 Subject: [PATCH 0891/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/stack_trace#125) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 1149cbb1f..a4db5fbbb 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 5b1b2b2227322d3bb0dd8aa58a166049dcc77d55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:04:12 -0800 Subject: [PATCH 0892/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/watcher#132) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index c63ec37f9..908b06154 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 1b08a8b8b33b82150d5a80864394953c7b9aa827 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:04:20 -0800 Subject: [PATCH 0893/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/pubspec_parse#88) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index c46df3002..bdb6946a5 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From d31e1c8b97298fd02144157d2d771165b264a89d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:04:28 -0800 Subject: [PATCH 0894/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/stream_channel#83) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 4e2ee9d50..9c93ba998 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From a6f370c72ac33c51b75ec86d054320cd640e8799 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 13:06:44 -0800 Subject: [PATCH 0895/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/stream_transform#160) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index ac6cb6923..3795fcfdf 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.14.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From c2b153273d4dac0110becafec85f06ae74ece00b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 14:19:26 -0800 Subject: [PATCH 0896/1215] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/test_reflective_loader#43) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 10913c69f..6155687a6 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From d019da9b2f49679353aaf6d8db4366cdc777cdfa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 6 Jan 2023 09:15:48 -0800 Subject: [PATCH 0897/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/string_scanner#52) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index cc5abcf3c..e9d2eb965 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 7c5862d686c5d6b70d13208f474fa0a29400f348 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 13:41:59 -0800 Subject: [PATCH 0898/1215] Migrate from no-implicit-casts to strict-casts (dart-lang/timing#24) * Migrate from no-implicit-casts to strict-casts * Bump GH actions from Dart 2.14 to 2.18. --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- pkgs/timing/analysis_options.yaml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 63a6491f6..5b99fc7d1 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [2.14.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d @@ -44,7 +44,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.14.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index dd1616fe5..0a9072285 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true linter: rules: From 3cc119564734b677884305876b8bad914420667d Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 19:24:38 -0800 Subject: [PATCH 0899/1215] Migrate from no-implicit-casts to strict-casts (dart-lang/term_glyph#31) --- pkgs/term_glyph/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index 99b42ff11..52624aa1b 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true linter: rules: From a6ebf3320c5515f2d1b6d2855600dcb73e0d4f2e Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 19:25:03 -0800 Subject: [PATCH 0900/1215] Migrate from no-implicit-casts to strict-casts (dart-lang/watcher#134) --- pkgs/watcher/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index 29327a49a..43201629b 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true errors: todo: ignore unused_import: error From 1e06bc994c9e3d98779e6d25b212da9aa7d65986 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 21:31:41 -0800 Subject: [PATCH 0901/1215] Migrate from no-implicit-casts to strict-casts (dart-lang/stream_channel#84) --- pkgs/stream_channel/analysis_options.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8465834c4..517b5976f 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,8 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true # These are errors when building in Google errors: unused_import: error From fefc4f88ffb62aac7966d508fc856b0f26dfae3c Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Mon, 9 Jan 2023 21:49:31 -0800 Subject: [PATCH 0902/1215] Migrate from no-implicit-casts to strict-casts (dart-lang/stream_transform#161) --- pkgs/stream_transform/analysis_options.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 0256c7096..6af98d7eb 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -1,9 +1,8 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false language: + strict-casts: true strict-raw-types: true linter: From e0a8088561b88d047433fd9db35e7a4065b5b69c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 15 Jan 2023 15:58:25 -0800 Subject: [PATCH 0903/1215] Fix CI badge in readme --- pkgs/stream_transform/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index b57429346..68d84d9a5 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/dart-lang/stream_transform.svg?branch=master)](https://travis-ci.org/dart-lang/stream_transform) +[![Dart CI](https://github.com/dart-lang/stream_transform/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_transform/actions/workflows/test-package.yml) [![Pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) [![package publisher](https://img.shields.io/pub/publisher/stream_transform.svg)](https://pub.dev/packages/stream_transform/publisher) From e899d5ac3692080275a388a5b6b51e4abf3fb5f3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 17 Jan 2023 07:13:00 -0800 Subject: [PATCH 0904/1215] dependabot: monthly is plenty (dart-lang/string_scanner#54) --- pkgs/string_scanner/.github/dependabot.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/string_scanner/.github/dependabot.yml b/pkgs/string_scanner/.github/dependabot.yml index 430a85e7d..d5262beb1 100644 --- a/pkgs/string_scanner/.github/dependabot.yml +++ b/pkgs/string_scanner/.github/dependabot.yml @@ -8,4 +8,4 @@ updates: directory: "/" schedule: # Check for updates to GitHub Actions every weekday - interval: "daily" + interval: "monthly" From 0d8f173ea55b4538e0456785ee2a84cbdee3f6af Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 17 Jan 2023 11:28:44 -0800 Subject: [PATCH 0905/1215] Drop legacy SDK test, bump min SDK to 2.18, update and fix lints (dart-lang/stream_transform#162) --- .../.github/workflows/test-package.yml | 5 +- pkgs/stream_transform/CHANGELOG.md | 4 ++ pkgs/stream_transform/analysis_options.yaml | 2 - .../legacy_test/opt_out_test.dart | 71 ------------------- pkgs/stream_transform/lib/src/switch.dart | 4 +- pkgs/stream_transform/pubspec.yaml | 6 +- pkgs/stream_transform/test/switch_test.dart | 2 +- 7 files changed, 11 insertions(+), 83 deletions(-) delete mode 100644 pkgs/stream_transform/legacy_test/opt_out_test.dart diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 3795fcfdf..c8964c7cc 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -48,7 +48,7 @@ jobs: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] # Bump SDK for Legacy tets when changning min SDK. - sdk: [2.14.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d @@ -60,6 +60,3 @@ jobs: - name: Run tests run: dart test -p chrome,vm --test-randomize-ordering-seed=random if: always() && steps.install.outcome == 'success' - - name: Run Legacy tests - run: dart test -p chrome,vm --test-randomize-ordering-seed=random legacy_test - if: always() && matrix.sdk == '2.14.0' && steps.install.outcome == 'success' diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 3d2cd6964..7c3437140 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.1-dev + +- Require Dart 2.18 or greater + ## 2.1.0 - Add `whereNotNull`. diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 6af98d7eb..9dc8788ef 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -21,12 +21,10 @@ linter: - omit_local_variable_types - only_throw_errors - prefer_const_constructors - - prefer_interpolation_to_compose_strings - prefer_single_quotes - test_types_in_equals - throw_in_finally - unawaited_futures - unnecessary_lambdas - - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements diff --git a/pkgs/stream_transform/legacy_test/opt_out_test.dart b/pkgs/stream_transform/legacy_test/opt_out_test.dart deleted file mode 100644 index 6bd654b23..000000000 --- a/pkgs/stream_transform/legacy_test/opt_out_test.dart +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file -// 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.9 - -import 'dart:async'; - -import 'package:async/async.dart'; -import 'package:stream_transform/stream_transform.dart'; -import 'package:test/test.dart'; - -void main() { - group('null returned from StreamSubscription.cancel', () { - void testNullCancel( - String name, Stream Function(Stream) transform) { - test(name, () async { - var subscription = transform(_NullOnCancelStream()).listen(null); - await subscription.cancel(); - }); - } - - testNullCancel('asyncMapSample', (s) => s.asyncMapSample((_) async {})); - testNullCancel('buffer', (s) => s.buffer(_nonEndingStream())); - testNullCancel( - 'combineLatestAll', (s) => s.combineLatestAll([_NullOnCancelStream()])); - testNullCancel('combineLatest', - (s) => s.combineLatest(_NullOnCancelStream(), (a, b) {})); - testNullCancel('merge', (s) => s.merge(_NullOnCancelStream())); - - test('switchLatest', () async { - var subscription = - _NullOnCancelStream(Stream>.value(_NullOnCancelStream())) - .switchLatest() - .listen(null); - await Future(() {}); - await subscription.cancel(); - }); - - test('concurrentAsyncExpand', () async { - var subscription = _NullOnCancelStream(Stream.value(null)) - .concurrentAsyncExpand((_) => _NullOnCancelStream()) - .listen(null); - await Future(() {}); - await subscription.cancel(); - }); - }); -} - -class _NullOnCancelStream extends StreamView { - _NullOnCancelStream([Stream stream]) : super(stream ?? _nonEndingStream()); - - @override - StreamSubscription listen(void Function(T) onData, - {Function onError, void Function() onDone, bool cancelOnError}) => - _NullOnCancelSubscription(super.listen(onData, - onError: onError, onDone: onDone, cancelOnError: cancelOnError)); -} - -class _NullOnCancelSubscription extends DelegatingStreamSubscription { - final StreamSubscription _subscription; - _NullOnCancelSubscription(this._subscription) : super(_subscription); - - @override - Future cancel() { - _subscription.cancel(); - return null; - } -} - -Stream _nonEndingStream() => StreamController().stream; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 4b4cdac17..b0fbbad67 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -118,10 +118,10 @@ extension SwitchLatest on Stream> { }; } controller.onCancel = () { - var _innerSubscription = innerSubscription; + var sub = innerSubscription; var cancels = [ if (!outerStreamDone) outerSubscription.cancel(), - if (_innerSubscription != null) _innerSubscription.cancel(), + if (sub != null) sub.cancel(), ] // Handle opt-out nulls ..removeWhere((Object? f) => f == null); diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index a53112271..915dc10f0 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,12 +1,12 @@ name: stream_transform -version: 2.1.0 +version: 2.1.1-dev description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/stream_transform environment: - sdk: ">=2.14.0 <3.0.0" + sdk: ">=2.18.0 <3.0.0" dev_dependencies: async: ^2.5.0 - lints: ^1.0.0 + lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index 00f196a9e..d2f99a8ba 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -197,7 +197,7 @@ void main() { var outer = StreamController>(); var values = []; - outer.stream.switchMap((l) => Stream.fromIterable(l)).listen(values.add); + outer.stream.switchMap(Stream.fromIterable).listen(values.add); outer.add([1, 2, 3]); await Future(() {}); From 4e0b41c52c4346e6146cb2bb77f9462e556463a1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 17 Jan 2023 13:44:03 -0800 Subject: [PATCH 0906/1215] Call out missed events in startWith Doc (dart-lang/stream_transform#151) The listen will not happen until the first event is delivered. --- pkgs/stream_transform/lib/src/concatenate.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/stream_transform/lib/src/concatenate.dart b/pkgs/stream_transform/lib/src/concatenate.dart index 3277dcdd6..0330dd761 100644 --- a/pkgs/stream_transform/lib/src/concatenate.dart +++ b/pkgs/stream_transform/lib/src/concatenate.dart @@ -82,6 +82,9 @@ extension Concatenate on Stream { /// Emits [initial] before any values or errors from the this stream. /// /// If this stream is a broadcast stream the result will be as well. + /// If this stream is a broadcast stream, the returned stream will only + /// contain events of this stream that are emitted after the [initial] value + /// has been emitted on the returned stream. Stream startWith(T initial) => startWithStream(Future.value(initial).asStream()); From 72018cff05a8631330c9f1d6f848b82e765dca5e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 19 Jan 2023 15:00:04 -0800 Subject: [PATCH 0907/1215] add publishing bot; rev version (dart-lang/timing#25) * add publishing bot; rev version * address analysis lints --- pkgs/timing/.github/workflows/publish.yaml | 14 +++++++++ pkgs/timing/CHANGELOG.md | 2 +- pkgs/timing/README.md | 14 +++++++-- pkgs/timing/analysis_options.yaml | 36 +--------------------- pkgs/timing/lib/src/timing.dart | 17 +++++----- pkgs/timing/pubspec.yaml | 4 +-- 6 files changed, 38 insertions(+), 49 deletions(-) create mode 100644 pkgs/timing/.github/workflows/publish.yaml diff --git a/pkgs/timing/.github/workflows/publish.yaml b/pkgs/timing/.github/workflows/publish.yaml new file mode 100644 index 000000000..ef785c75e --- /dev/null +++ b/pkgs/timing/.github/workflows/publish.yaml @@ -0,0 +1,14 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: devoncarew/firehose/.github/workflows/publish.yaml@main diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index b3bf18fa2..f7f3fbd4a 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.0.1-dev +## 1.0.1 - Require Dart `2.14`. diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md index d34648d4b..0b4e87ba6 100644 --- a/pkgs/timing/README.md +++ b/pkgs/timing/README.md @@ -1,7 +1,11 @@ -# [![Build Status](https://github.com/dart-lang/timing/workflows/Dart%20CI/badge.svg)](https://github.com/dart-lang/timing/actions?query=workflow%3A"Dart+CI"+branch%3Amaster) +[![Dart CI](https://github.com/dart-lang/timing/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/timing/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/timing.svg)](https://pub.dev/packages/timing) +[![package publisher](https://img.shields.io/pub/publisher/timing.svg)](https://pub.dev/packages/timing/publisher) Timing is a simple package for tracking performance of both async and sync actions +## Usage + ```dart var tracker = AsyncTimeTracker(); await tracker.track(() async { @@ -12,11 +16,15 @@ await tracker.track(() async { print('${tracker.duration} ${tracker.innerDuration} ${tracker.slices}'); ``` - ## Building Use the following command to re-generate `lib/src/timing.g.dart` file: ```bash -pub run build_runner build +dart pub run build_runner build ``` + +## Publishing automation + +For information about our publishing automation and process, see +https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index 0a9072285..d978f811c 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -1,35 +1 @@ -include: package:lints/recommended.yaml - -analyzer: - language: - strict-casts: true - -linter: - rules: - - always_declare_return_types - - avoid_bool_literals_in_conditional_expressions - - avoid_classes_with_only_static_members - - avoid_dynamic_calls - - avoid_returning_null - - avoid_returning_this - - avoid_unused_constructor_parameters - - cancel_subscriptions - - cascade_invocations - - comment_references - - directives_ordering - - join_return_with_assignment - - literal_only_boolean_expressions - - omit_local_variable_types - - only_throw_errors - - package_api_docs - - prefer_const_constructors - - prefer_final_locals - - prefer_interpolation_to_compose_strings - - prefer_single_quotes - - test_types_in_equals - - throw_in_finally - - unawaited_futures - - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_parenthesis - - unnecessary_statements +include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index 013f2f741..fae19bd4c 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -116,10 +116,10 @@ class SyncTimeTracker implements TimeTracker { _stopTime = now(); } - /// Splits tracker into two slices + /// Splits tracker into two slices. /// - /// Returns new [TimeSlice] started on [startTime] and ended now. - /// Modifies [startTime] of tracker to current time point + /// Returns new [TimeSlice] started on [startTime] and ended now. Modifies + /// [startTime] of tracker to current time point /// /// Don't change state of tracker. Can be called only while [isTracking], and /// tracker will sill be tracking after call. @@ -127,9 +127,9 @@ class SyncTimeTracker implements TimeTracker { if (!isTracking) { throw StateError('Can be only called while tracking'); } - final _now = now(); - final prevSlice = TimeSlice(_startTime!, _now); - _startTime = _now; + final splitPoint = now(); + final prevSlice = TimeSlice(_startTime!, splitPoint); + _startTime = splitPoint; return prevSlice; } @@ -261,7 +261,7 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { try { return action(); } finally { - // Split tracker again and discard slice that was spend in nested tracker + // Split tracker again and discard slice from nested tracker parent.run(zone, timer._split); // Add tracker back to list of slices and continue tracking slices.add(timer); @@ -315,7 +315,8 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { zoneValues: {_zoneKey: this}); if (result is Future) { return result - // Break possible sync processing of future completion, so slice trackers can be finished + // Break possible sync processing of future completion, so slice + // trackers can be finished .whenComplete(() => Future.value()) .whenComplete(() => _tracking = false) as T; } else { diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 8c1905357..323c28e8b 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 1.0.1-dev +version: 1.0.1 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. @@ -13,6 +13,6 @@ dependencies: dev_dependencies: build_runner: ^2.0.0 - lints: ^1.0.0 + dart_flutter_team_lints: ^0.1.0 json_serializable: ^6.0.0 test: ^1.0.0 From b071e9af2f524da9170318b72701baee799433ac Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 23 Jan 2023 10:14:08 -0800 Subject: [PATCH 0908/1215] Update usage of json_annotatoin, bump pkg:lints (dart-lang/pubspec_parse#89) --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 4 ++-- pkgs/pubspec_parse/analysis_options.yaml | 2 -- pkgs/pubspec_parse/lib/src/dependency.dart | 2 +- pkgs/pubspec_parse/pubspec.yaml | 6 +++--- 5 files changed, 7 insertions(+), 9 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index bdb6946a5..0dab9a92d 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.17.0, dev] + sdk: [2.18.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 117fd129e..5cf26e02c 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,7 +1,7 @@ ## 1.2.2-dev -- Update SDK requirement to `2.17.0`. -- Fix the unit tests for Dart 3.0.0. +- Require Dart SDK >= 2.18.0 +- Required `json_annotation: ^4.8.0` ## 1.2.1 diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index fdc60e0db..cf5c91faf 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -35,7 +35,6 @@ linter: - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_interpolation_to_compose_strings - prefer_relative_imports - require_trailing_commas - sort_pub_dependencies @@ -43,7 +42,6 @@ linter: - throw_in_finally - unnecessary_await_in_return - unnecessary_lambdas - - unnecessary_null_aware_assignments - unnecessary_parenthesis - unnecessary_statements - use_string_buffers diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 8b59f7367..e345dfda8 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -223,7 +223,7 @@ class HostedDetails { @JsonKey(fromJson: parseGitUriOrNull, disallowNullValue: true) final Uri? url; - @JsonKey(ignore: true) + @JsonKey(includeFromJson: false, includeToJson: false) String? _nameOfPackage; /// The name of this package on the package repository. diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 03f61bd80..961404487 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -6,19 +6,19 @@ version: 1.2.2-dev repository: https://github.com/dart-lang/pubspec_parse environment: - sdk: '>=2.17.0 <3.0.0' + sdk: '>=2.18.0 <3.0.0' dependencies: checked_yaml: ^2.0.1 collection: ^1.15.0 - json_annotation: ^4.6.0 + json_annotation: ^4.8.0 pub_semver: ^2.0.0 yaml: ^3.0.0 dev_dependencies: build_runner: ^2.0.3 build_verify: '>=2.0.0 <4.0.0' - json_serializable: ^6.0.0 + json_serializable: ^6.6.0 lints: ^2.0.0 path: ^1.5.1 # Needed because we are configuring `combining_builder` From 9b5151f87c599a674a9ca66eebf83a3e4e37f780 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 25 Jan 2023 13:19:36 -0800 Subject: [PATCH 0909/1215] update the publishing script (dart-lang/timing#26) --- pkgs/timing/.github/workflows/publish.yaml | 2 +- pkgs/timing/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/publish.yaml b/pkgs/timing/.github/workflows/publish.yaml index ef785c75e..fcb7ccb89 100644 --- a/pkgs/timing/.github/workflows/publish.yaml +++ b/pkgs/timing/.github/workflows/publish.yaml @@ -11,4 +11,4 @@ on: jobs: publish: if: ${{ github.repository_owner == 'dart-lang' }} - uses: devoncarew/firehose/.github/workflows/publish.yaml@main + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md index 0b4e87ba6..ad7481abc 100644 --- a/pkgs/timing/README.md +++ b/pkgs/timing/README.md @@ -26,5 +26,5 @@ dart pub run build_runner build ## Publishing automation -For information about our publishing automation and process, see +For information about our publishing automation and release process, see https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. From c0e8fe5da51c4403ae201ad2f3bcc17104c8bbfb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 08:41:57 -0800 Subject: [PATCH 0910/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/string_scanner#53) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index e9d2eb965..5a03db3b3 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 956b27e18770b47bd314480ea1e4c373bc5f1686 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 21:51:10 -0800 Subject: [PATCH 0911/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/pubspec_parse#91) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 0dab9a92d..b51b48ab0 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 4a851418acb026f4c1ccde05a04e58017429ceac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 21:54:55 -0800 Subject: [PATCH 0912/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/stream_channel#86) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9c93ba998..bdfd06d55 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 884efe9cd43b2824376df7dddf3cc958d5c7ae0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 21:59:28 -0800 Subject: [PATCH 0913/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/stream_transform#164) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index c8964c7cc..2206422f4 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 9f0a1bd8972f0ca2aefdf654dffe92f5560c2210 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 22:55:38 -0800 Subject: [PATCH 0914/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/timing#27) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 5b99fc7d1..68e7ca824 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 88ae8bdf680579b170ed69a68c932e43995e1361 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:28:10 -0800 Subject: [PATCH 0915/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/pubspec_parse#90) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index b51b48ab0..e78b568f2 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 8e5d50284b032fd52908afd396c6ba66ea97f704 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:29:57 -0800 Subject: [PATCH 0916/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/stream_transform#163) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 2206422f4..9dc5e3e7b 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From a611d3506795ad5c39ea4b1f3bedd1dfea5a31b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:30:52 -0800 Subject: [PATCH 0917/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/timing#28) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 68e7ca824..a21f0225c 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From b4ae743353e14fcc238ee94042dd497f5d61b185 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 23:37:09 -0800 Subject: [PATCH 0918/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/stream_channel#85) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index bdfd06d55..8c8f4ab69 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.14.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 4d585e6d833cde658c98a12fb5dd7854bf2b848c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 07:21:08 -0800 Subject: [PATCH 0919/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/watcher#136) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 908b06154..ea4b20d28 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.14.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From a208546819175283eb78f48ab37c887f0257c854 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 07:35:02 -0800 Subject: [PATCH 0920/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/watcher#135) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index ea4b20d28..6016675b0 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [2.14.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From fa13587588a16e2d8be243d205bba29bbf59784a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:14:47 -0800 Subject: [PATCH 0921/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/term_glyph#33) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index ab056f0b5..3a909ed30 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.12.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 0f952cf19e8df6fdfb1a6ac02b0fe5a4b20330f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:33:38 -0800 Subject: [PATCH 0922/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/test_reflective_loader#44) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 6155687a6..296837e26 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From d73ff18038b519118089eddc9f8c1156a4037206 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:34:04 -0800 Subject: [PATCH 0923/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/term_glyph#32) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 3a909ed30..b552d6ae0 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 9bfc357c810de1254388d5000ae25c3e17717f5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:35:58 -0800 Subject: [PATCH 0924/1215] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/stack_trace#126) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index a4db5fbbb..c1b40020f 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From b9f3fd2316f318086396db8faf90e4445865b459 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:37:00 -0800 Subject: [PATCH 0925/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/test_reflective_loader#45) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 296837e26..5b84b5eb5 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 7ad27b5f48f965f0b9f0b9bc979f4649f67d1f49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:37:25 -0800 Subject: [PATCH 0926/1215] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/stack_trace#127) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index c1b40020f..aa00cf58d 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From b4b07bb95273f0ecbaeca0517f334538bb1fe029 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 12 Feb 2023 09:57:51 -0800 Subject: [PATCH 0927/1215] Fix CI, update lints (dart-lang/term_glyph#34) --- .../.github/workflows/test-package.yml | 2 +- pkgs/term_glyph/CHANGELOG.md | 19 ++------ pkgs/term_glyph/analysis_options.yaml | 46 ++----------------- .../lib/src/generated/glyph_set.dart | 29 +++++++----- .../lib/src/generated/top_level.dart | 17 ++++--- pkgs/term_glyph/pubspec.yaml | 6 +-- pkgs/term_glyph/tool/generate.dart | 6 +-- 7 files changed, 42 insertions(+), 83 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index b552d6ae0..58201d820 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.17.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 4f9037660..1cf47ac41 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.2.2-dev + +* Require Dart 2.17 + ## 1.2.1 * Migrate to `package:lints`. @@ -6,24 +10,9 @@ ## 1.2.0 * Stable release for null safety. - -## 1.2.0-nullsafety.3 - * Update SDK constraints to `>=2.12.0-0 <3.0.0` based on beta release guidelines. -## 1.2.0-nullsafety.2 - -* Allow prerelease versions of the 2.12 sdk. - -## 1.2.0-nullsafety.1 - -* Allow 2.10 stable and 2.11.0 dev SDK versions. - -## 1.2.0-nullsafety - -* Update to null safety. All apis require non-nullable types. - ## 1.1.0 * Add a `GlyphSet` class that can be used to easily choose which set of glyphs diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index 52624aa1b..a4cc65912 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1,77 +1,37 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true + strict-inference: true + strict-raw-types: true linter: rules: - avoid_bool_literals_in_conditional_expressions - - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_function_literals_in_foreach_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_renaming_method_parameters - avoid_returning_null - avoid_returning_null_for_future - - avoid_returning_null_for_void - avoid_returning_this - - avoid_single_cascade_in_expression_statements - avoid_unused_constructor_parameters - avoid_void_async - - await_only_futures - - camel_case_types - cancel_subscriptions #- cascade_invocations - comment_references - - constant_identifier_names - - control_flow_in_finally - - directives_ordering - - empty_statements - - file_names - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - join_return_with_assignment #- lines_longer_than_80_chars - - list_remove_unrelated_type - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - non_constant_identifier_names - - only_throw_errors - - overridden_fields - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_function_declarations_over_variables - - prefer_initializing_formals - - prefer_inlined_adds - - prefer_interpolation_to_compose_strings - - prefer_is_not_operator - - prefer_null_aware_operators - prefer_relative_imports - - prefer_typing_uninitialized_variables - - prefer_void_to_null - - provide_deprecation_message - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - unnecessary_await_in_return - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_overrides - - unnecessary_parenthesis - - unnecessary_statements - - unnecessary_string_interpolations - use_string_buffers - - void_checks diff --git a/pkgs/term_glyph/lib/src/generated/glyph_set.dart b/pkgs/term_glyph/lib/src/generated/glyph_set.dart index 10713b275..be1a668a1 100644 --- a/pkgs/term_glyph/lib/src/generated/glyph_set.dart +++ b/pkgs/term_glyph/lib/src/generated/glyph_set.dart @@ -37,14 +37,14 @@ abstract class GlyphSet { /// A left-pointing arrow. /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in + /// some terminal fonts, and should generally be surrounding by spaces. String get leftArrow; /// A right-pointing arrow. /// - /// Note that the Unicode arrow glyphs may overlap with adjacent characters in some - /// terminal fonts, and should generally be surrounding by spaces. + /// Note that the Unicode arrow glyphs may overlap with adjacent characters in + /// some terminal fonts, and should generally be surrounding by spaces. String get rightArrow; /// An upwards-pointing arrow. @@ -128,13 +128,16 @@ abstract class GlyphSet { /// A bold horizontal box line with a vertical line going up from the middle. String get teeUpBold; - /// A bold horizontal box line with a vertical line going down from the middle. + /// A bold horizontal box line with a vertical line going down from the + /// middle. String get teeDownBold; - /// A bold vertical box line with a horizontal line going left from the middle. + /// A bold vertical box line with a horizontal line going left from the + /// middle. String get teeLeftBold; - /// A bold vertical box line with a horizontal line going right from the middle. + /// A bold vertical box line with a horizontal line going right from the + /// middle. String get teeRightBold; /// The top half of a bold vertical box line. @@ -170,16 +173,20 @@ abstract class GlyphSet { /// An intersection of double vertical and horizontal box lines. String get crossDouble; - /// A double horizontal box line with a vertical line going up from the middle. + /// A double horizontal box line with a vertical line going up from the + /// middle. String get teeUpDouble; - /// A double horizontal box line with a vertical line going down from the middle. + /// A double horizontal box line with a vertical line going down from the + /// middle. String get teeDownDouble; - /// A double vertical box line with a horizontal line going left from the middle. + /// A double vertical box line with a horizontal line going left from the + /// middle. String get teeLeftDouble; - /// A double vertical box line with a horizontal line going right from the middle. + /// A double vertical box line with a horizontal line going right from the + /// middle. String get teeRightDouble; /// A dashed horizontal line that can be used to draw a box. diff --git a/pkgs/term_glyph/lib/src/generated/top_level.dart b/pkgs/term_glyph/lib/src/generated/top_level.dart index c430b33b9..925903eef 100644 --- a/pkgs/term_glyph/lib/src/generated/top_level.dart +++ b/pkgs/term_glyph/lib/src/generated/top_level.dart @@ -14,8 +14,8 @@ String get bullet => glyph.glyphs.bullet; /// A left-pointing arrow. /// -/// Note that the Unicode arrow glyphs may overlap with adjacent characters in some -/// terminal fonts, and should generally be surrounding by spaces. +/// Note that the Unicode arrow glyphs may overlap with adjacent characters in +/// some terminal fonts, and should generally be surrounding by spaces. /// /// If [glyph.ascii] is `false`, this is "←". If it's `true`, this is /// "<" instead. @@ -23,8 +23,8 @@ String get leftArrow => glyph.glyphs.leftArrow; /// A right-pointing arrow. /// -/// Note that the Unicode arrow glyphs may overlap with adjacent characters in some -/// terminal fonts, and should generally be surrounding by spaces. +/// Note that the Unicode arrow glyphs may overlap with adjacent characters in +/// some terminal fonts, and should generally be surrounding by spaces. /// /// If [glyph.ascii] is `false`, this is "→". If it's `true`, this is /// ">" instead. @@ -282,19 +282,22 @@ String get crossDouble => glyph.glyphs.crossDouble; /// "+" instead. String get teeUpDouble => glyph.glyphs.teeUpDouble; -/// A double horizontal box line with a vertical line going down from the middle. +/// A double horizontal box line with a vertical line going down from the +/// middle. /// /// If [glyph.ascii] is `false`, this is "╦". If it's `true`, this is /// "+" instead. String get teeDownDouble => glyph.glyphs.teeDownDouble; -/// A double vertical box line with a horizontal line going left from the middle. +/// A double vertical box line with a horizontal line going left from the +/// middle. /// /// If [glyph.ascii] is `false`, this is "╣". If it's `true`, this is /// "+" instead. String get teeLeftDouble => glyph.glyphs.teeLeftDouble; -/// A double vertical box line with a horizontal line going right from the middle. +/// A double vertical box line with a horizontal line going right from the +/// middle. /// /// If [glyph.ascii] is `false`, this is "╠". If it's `true`, this is /// "+" instead. diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 7019e2db6..6c6a5f1ab 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,13 +1,13 @@ name: term_glyph -version: 1.2.1 +version: 1.2.2-dev description: Useful Unicode glyphs and ASCII substitutes. repository: https://github.com/dart-lang/term_glyph environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dev_dependencies: csv: ^5.0.0 + dart_flutter_team_lints: ^0.1.0 dart_style: ^2.0.0 - lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/term_glyph/tool/generate.dart b/pkgs/term_glyph/tool/generate.dart index 007913b3a..f5cdade9e 100644 --- a/pkgs/term_glyph/tool/generate.dart +++ b/pkgs/term_glyph/tool/generate.dart @@ -27,7 +27,7 @@ void main() { } /// Writes `lib/src/generated/glyph_set.dart`. -void _writeGlyphSetInterface(List data) { +void _writeGlyphSetInterface(List> data) { final file = File('lib/src/generated/glyph_set.dart').openSync(mode: FileMode.write); file.writeStringSync(r''' @@ -82,7 +82,7 @@ void _writeGlyphSetInterface(List data) { /// /// If [ascii] is `true`, this writes the ASCII glyph set. Otherwise it writes /// the Unicode glyph set. -void _writeGlyphSet(List data, {required bool ascii}) { +void _writeGlyphSet(List> data, {required bool ascii}) { final file = File('lib/src/generated/${ascii ? "ascii" : "unicode"}_glyph_set.dart') .openSync(mode: FileMode.write); @@ -120,7 +120,7 @@ void _writeGlyphSet(List data, {required bool ascii}) { } /// Writes `lib/src/generated/top_level.dart`. -void _writeTopLevel(List data) { +void _writeTopLevel(List> data) { final file = File('lib/src/generated/top_level.dart').openSync(mode: FileMode.write); From 91c11ce6b6a848a316ac79eec1cf581d1c58f981 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Tue, 28 Feb 2023 14:44:17 +0100 Subject: [PATCH 0928/1215] Add support for "topics" field (dart-lang/pubspec_parse#93) --- pkgs/pubspec_parse/CHANGELOG.md | 3 +- pkgs/pubspec_parse/lib/src/pubspec.dart | 4 +++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 2 ++ pkgs/pubspec_parse/pubspec.yaml | 2 +- pkgs/pubspec_parse/test/parse_test.dart | 40 +++++++++++++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 5cf26e02c..023e2a13f 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,7 +1,8 @@ -## 1.2.2-dev +## 1.2.2 - Require Dart SDK >= 2.18.0 - Required `json_annotation: ^4.8.0` +- Added support for `topics` field. ## 1.2.1 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 9943da8a4..188af314b 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -44,6 +44,9 @@ class Pubspec { /// support or funding. final List? funding; + /// Optional field to list the topics that this packages belongs to. + final List? topics; + /// Optional field for specifying included screenshot files. @JsonKey(fromJson: parseScreenshots) final List? screenshots; @@ -106,6 +109,7 @@ class Pubspec { this.repository, this.issueTracker, this.funding, + this.topics, this.screenshots, this.documentation, this.description, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index a1312a556..622999437 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -32,6 +32,8 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( (v) => (v as List?) ?.map((e) => Uri.parse(e as String)) .toList()), + topics: $checkedConvert('topics', + (v) => (v as List?)?.map((e) => e as String).toList()), screenshots: $checkedConvert( 'screenshots', (v) => parseScreenshots(v as List?)), documentation: $checkedConvert('documentation', (v) => v as String?), diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 961404487..63742631f 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -2,7 +2,7 @@ name: pubspec_parse description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.2-dev +version: 1.2.2 repository: https://github.com/dart-lang/pubspec_parse environment: diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index f3b4679bb..e181ca6d6 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -53,6 +53,7 @@ void main() { 'funding': [ 'https://patreon.com/example', ], + 'topics': ['widget', 'button'], 'screenshots': [ {'description': 'my screenshot', 'path': 'path/to/screenshot'} ], @@ -77,6 +78,9 @@ void main() { ); expect(value.funding, hasLength(1)); expect(value.funding!.single.toString(), 'https://patreon.com/example'); + expect(value.topics, hasLength(2)); + expect(value.topics!.first, 'widget'); + expect(value.topics!.last, 'button'); expect(value.screenshots, hasLength(1)); expect(value.screenshots!.first.description, 'my screenshot'); expect(value.screenshots!.first.path, 'path/to/screenshot'); @@ -386,6 +390,42 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at ); }); }); + group('topics', () { + test('not a list', () { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'topics': 1, + }, + "Unsupported value for \"topics\". type 'int' is not a subtype of type 'List?'", + skipTryPub: true, + ); + }); + + test('not a string', () { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'topics': [1], + }, + "Unsupported value for \"topics\". type 'int' is not a subtype of type 'String'", + skipTryPub: true, + ); + }); + + test('invalid data - lenient', () { + final value = parse( + { + ...defaultPubspec, + 'topics': [1], + }, + skipTryPub: true, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.topics, isNull); + }); + }); group('screenshots', () { test('one screenshot', () { From 865feb6c88be01d025234f8e0b43699d8fdf2e75 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 28 Feb 2023 10:01:30 -0800 Subject: [PATCH 0929/1215] move to pkg:dart_flutter_team_lints lints, fix code, bump min SDK (dart-lang/stream_channel#87) --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 4 ++++ pkgs/stream_channel/analysis_options.yaml | 9 ++------- .../lib/src/close_guarantee_channel.dart | 4 ++-- pkgs/stream_channel/lib/src/disconnector.dart | 2 +- pkgs/stream_channel/lib/src/guarantee_channel.dart | 4 ++-- pkgs/stream_channel/lib/src/multi_channel.dart | 4 ++-- pkgs/stream_channel/lib/stream_channel.dart | 6 +++--- pkgs/stream_channel/pubspec.yaml | 6 +++--- pkgs/stream_channel/test/disconnector_test.dart | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 2 ++ pkgs/stream_channel/test/multi_channel_test.dart | 14 ++++++++------ 12 files changed, 31 insertions(+), 28 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 8c8f4ab69..20b28dece 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.14.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 2b90a0a76..0d7382839 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.2-dev + +* Require Dart 2.19 + ## 2.1.1 * Require Dart 2.14 diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 517b5976f..8e5d4a792 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -1,14 +1,8 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true - # These are errors when building in Google - errors: - unused_import: error - unused_element: error - unused_local_variable: error - dead_code: error linter: rules: @@ -17,3 +11,4 @@ linter: - omit_local_variable_types - prefer_single_quotes - unawaited_futures + - use_super_parameters diff --git a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart index 25f502235..13432d17d 100644 --- a/pkgs/stream_channel/lib/src/close_guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/close_guarantee_channel.dart @@ -12,7 +12,7 @@ import '../stream_channel.dart'; /// that closing the sink causes the stream to close before it emits any more /// events /// -/// This is exposed via [new StreamChannel.withCloseGuarantee]. +/// This is exposed via [StreamChannel.withCloseGuarantee]. class CloseGuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _stream; @@ -74,7 +74,7 @@ class _CloseGuaranteeSink extends DelegatingStreamSink { /// The [CloseGuaranteeChannel] this belongs to. final CloseGuaranteeChannel _channel; - _CloseGuaranteeSink(StreamSink inner, this._channel) : super(inner); + _CloseGuaranteeSink(super.inner, this._channel); @override Future close() { diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index a424146b8..61969cbf8 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -97,7 +97,7 @@ class _DisconnectorSink implements StreamSink { } @override - void addError(error, [StackTrace? stackTrace]) { + void addError(Object error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 4780b046f..2aa8b7b97 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -10,7 +10,7 @@ import '../stream_channel.dart'; /// A [StreamChannel] that enforces the stream channel guarantees. /// -/// This is exposed via [new StreamChannel.withGuarantees]. +/// This is exposed via [StreamChannel.withGuarantees]. class GuaranteeChannel extends StreamChannelMixin { @override Stream get stream => _streamController.stream; @@ -126,7 +126,7 @@ class _GuaranteeSink implements StreamSink { } @override - void addError(error, [StackTrace? stackTrace]) { + void addError(Object error, [StackTrace? stackTrace]) { if (_closed) throw StateError('Cannot add event after closing.'); if (_inAddStream) { throw StateError('Cannot add event while adding stream.'); diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index a78ddbcf4..82f59c7c9 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -237,7 +237,7 @@ class _MultiChannel extends StreamChannelMixin // Convert this to a list because the close is dispatched synchronously, and // that could conceivably remove a controller from [_controllers]. - for (var controller in List.from(_controllers.values)) { + for (var controller in _controllers.values.toList(growable: false)) { controller.local.sink.close(); } _controllers.clear(); @@ -269,5 +269,5 @@ class VirtualChannel extends StreamChannelMixin VirtualChannel._(this._parent, this.id, this.stream, this.sink); @override - VirtualChannel virtualChannel([id]) => _parent.virtualChannel(id); + VirtualChannel virtualChannel([int? id]) => _parent.virtualChannel(id); } diff --git a/pkgs/stream_channel/lib/stream_channel.dart b/pkgs/stream_channel/lib/stream_channel.dart index 4722aa39c..85f9a9755 100644 --- a/pkgs/stream_channel/lib/stream_channel.dart +++ b/pkgs/stream_channel/lib/stream_channel.dart @@ -6,8 +6,8 @@ import 'dart:async'; import 'package:async/async.dart'; -import 'src/guarantee_channel.dart'; import 'src/close_guarantee_channel.dart'; +import 'src/guarantee_channel.dart'; import 'src/stream_channel_transformer.dart'; export 'src/delegating_stream_channel.dart'; @@ -75,9 +75,9 @@ abstract class StreamChannel { /// Creates a new [StreamChannel] that communicates over [stream] and [sink]. /// - /// Unlike [new StreamChannel], this enforces the guarantees listed in the + /// Unlike [StreamChannel.new], this enforces the guarantees listed in the /// [StreamChannel] documentation. This makes it somewhat less efficient than - /// just wrapping a stream and a sink directly, so [new StreamChannel] should + /// just wrapping a stream and a sink directly, so [StreamChannel.new] should /// be used when the guarantees are provided natively. /// /// If [allowSinkErrors] is `false`, errors are not allowed to be passed to diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index ff6a50c68..5eb57ae41 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,16 +1,16 @@ name: stream_channel -version: 2.1.1 +version: 2.1.2-dev description: >- An abstraction for two-way communication channels based on the Dart Stream class. repository: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.14.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: async: ^2.5.0 dev_dependencies: - lints: ^1.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 66773b59c..28f3fee9a 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -142,7 +142,7 @@ class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. final completer = Completer(); - _CloseCompleterSink(StreamSink inner) : super(inner); + _CloseCompleterSink(super.inner); @override Future close() { diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index a754421a9..1850664cf 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') +library; + import 'dart:async'; import 'dart:isolate'; diff --git a/pkgs/stream_channel/test/multi_channel_test.dart b/pkgs/stream_channel/test/multi_channel_test.dart index 763e6b829..ee6f8d2a1 100644 --- a/pkgs/stream_channel/test/multi_channel_test.dart +++ b/pkgs/stream_channel/test/multi_channel_test.dart @@ -348,8 +348,8 @@ void main() { group('stream channel rules', () { group('for the main stream:', () { test( - 'closing the sink causes the stream to close before it emits any more ' - 'events', () { + 'closing the sink causes the stream to close before it emits any ' + 'more events', () { channel1.sink.add(1); channel1.sink.add(2); channel1.sink.add(3); @@ -370,7 +370,8 @@ void main() { channel2.sink.add(3); unawaited(channel2.sink.close()); - // None of our channel.sink additions should make it to the other endpoint. + // None of our channel.sink additions should make it to the other + // endpoint. channel1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); @@ -415,8 +416,8 @@ void main() { }); test( - 'closing the sink causes the stream to close before it emits any more ' - 'events', () { + 'closing the sink causes the stream to close before it emits any ' + 'more events', () { virtual1.sink.add(1); virtual1.sink.add(2); virtual1.sink.add(3); @@ -437,7 +438,8 @@ void main() { virtual2.sink.add(3); unawaited(virtual2.sink.close()); - // None of our virtual.sink additions should make it to the other endpoint. + // None of our virtual.sink additions should make it to the other + // endpoint. virtual1.stream.listen(expectAsync1((_) {}, count: 0)); await pumpEventQueue(); }); From befcb8816f7b9551f7685723400230aed1a7dc4d Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 28 Feb 2023 17:06:32 -0800 Subject: [PATCH 0930/1215] Use fake_async over waiting for timers with delays (dart-lang/stream_transform#166) On the web the timers may have some variance. Replace all usages of `waitForTimer` utility to use `fakeAsync`. Separate out the call to `Stream.listen` from `setUp` so it happens in the fake async zone. --- pkgs/stream_transform/pubspec.yaml | 1 + pkgs/stream_transform/test/audit_test.dart | 126 +++++--- pkgs/stream_transform/test/debounce_test.dart | 286 +++++++++++------- pkgs/stream_transform/test/throttle_test.dart | 181 ++++++----- pkgs/stream_transform/test/utils.dart | 6 - 5 files changed, 361 insertions(+), 239 deletions(-) diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 915dc10f0..4d1ffbe56 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -8,5 +8,6 @@ environment: dev_dependencies: async: ^2.5.0 + fake_async: ^1.3.0 lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index 907d873e8..e2f8133e2 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:fake_async/fake_async.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; @@ -21,7 +22,7 @@ void main() { late StreamSubscription subscription; group('audit', () { - setUp(() async { + setUp(() { valuesCanceled = false; values = createController(streamType) ..onCancel = () { @@ -31,73 +32,106 @@ void main() { errors = []; isDone = false; transformed = values.stream.audit(const Duration(milliseconds: 6)); + }); + + void listen() { subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); - }); + } test('cancels values', () async { + listen(); await subscription.cancel(); expect(valuesCanceled, true); }); - test('swallows values that come faster than duration', () async { - values - ..add(1) - ..add(2); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [2]); + test('swallows values that come faster than duration', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [2]); + }); }); - test('outputs multiple values spaced further than duration', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('outputs multiple values spaced further than duration', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + }); }); - test('waits for pending value to close', () async { - values.add(1); - await values.close(); - expect(isDone, false); - await waitForTimer(5); - expect(isDone, true); + test('waits for pending value to close', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..close(); + expect(isDone, false); + async.elapse(const Duration(milliseconds: 6)); + expect(isDone, true); + }); }); - test('closes output if there are no pending values', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await values.close(); - expect(isDone, false); - await waitForTimer(5); - expect(isDone, true); + test('closes output if there are no pending values', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values + ..add(2) + ..close(); + expect(isDone, false); + expect(emittedValues, [1]); + async.elapse(const Duration(milliseconds: 6)); + expect(isDone, true); + expect(emittedValues, [1, 2]); + }); }); test('does not starve output if many values come closer than duration', - () async { - values.add(1); - await Future.delayed(const Duration(milliseconds: 4)); - values.add(2); - await Future.delayed(const Duration(milliseconds: 4)); - values.add(3); - await waitForTimer(6); - expect(emittedValues, [2, 3]); + () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 3)); + values.add(2); + async.elapse(const Duration(milliseconds: 3)); + values.add(3); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [2, 3]); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values - ..add(1) - ..add(2); - await waitForTimer(5); - expect(emittedValues, [2]); - expect(otherValues, [2]); + test('multiple listeners all get the values', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 3)); + values.add(2); + var otherValues = []; + transformed.listen(otherValues.add); + values.add(3); + async.elapse(const Duration(milliseconds: 3)); + values.add(4); + async.elapse(const Duration(milliseconds: 3)); + values + ..add(5) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [3, 5]); + expect(otherValues, [3, 5]); + }); }); } }); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index f9c97ebe4..6b9775f84 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:fake_async/fake_async.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; @@ -31,63 +32,83 @@ void main() { errors = []; isDone = false; transformed = values.stream.debounce(const Duration(milliseconds: 5)); + }); + + void listen() { subscription = transformed .listen(emittedValues.add, onError: errors.add, onDone: () { isDone = true; }); - }); + } test('cancels values', () async { + listen(); await subscription.cancel(); expect(valuesCanceled, true); }); - test('swallows values that come faster than duration', () async { - values - ..add(1) - ..add(2); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [2]); + test('swallows values that come faster than duration', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [2]); + }); }); - test('outputs multiple values spaced further than duration', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('outputs multiple values spaced further than duration', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + }); }); - test('waits for pending value to close', () async { - values.add(1); - await waitForTimer(5); - await values.close(); - await Future(() {}); - expect(isDone, true); + test('waits for pending value to close', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.close(); + async.flushMicrotasks(); + expect(isDone, true); + }); }); - test('closes output if there are no pending values', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await Future(() {}); - await values.close(); - expect(isDone, false); - await waitForTimer(5); - expect(isDone, true); + test('closes output if there are no pending values', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values + ..add(2) + ..close(); + async.flushMicrotasks(); + expect(isDone, false); + async.elapse(const Duration(milliseconds: 6)); + expect(isDone, true); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values - ..add(1) - ..add(2); - await waitForTimer(5); - expect(emittedValues, [2]); - expect(otherValues, [2]); + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values + ..add(1) + ..add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [2]); + expect(otherValues, [2]); + }); }); } }); @@ -103,13 +124,17 @@ void main() { emittedValues = []; isDone = false; transformed = values.stream.debounce(const Duration(milliseconds: 5), - leading: true, trailing: false) - ..listen(emittedValues.add, onDone: () { - isDone = true; - }); + leading: true, trailing: false); }); + void listen() { + transformed.listen(emittedValues.add, onDone: () { + isDone = true; + }); + } + test('swallows values that come faster than duration', () async { + listen(); values ..add(1) ..add(2); @@ -117,29 +142,36 @@ void main() { expect(emittedValues, [1]); }); - test('outputs multiple values spaced further than duration', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('outputs multiple values spaced further than duration', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values - ..add(1) - ..add(2); - await waitForTimer(5); - expect(emittedValues, [1]); - expect(otherValues, [1]); + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values + ..add(1) + ..add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1]); + expect(otherValues, [1]); + }); }); } test('closes output immediately if not waiting for trailing value', () async { + listen(); values.add(1); await values.close(); expect(isDone, true); @@ -155,38 +187,49 @@ void main() { values = createController(streamType); emittedValues = []; transformed = values.stream.debounce(const Duration(milliseconds: 5), - leading: true, trailing: true) - ..listen(emittedValues.add); + leading: true, trailing: true); }); + void listen() { + transformed.listen(emittedValues.add); + } - test('swallows values that come faster than duration', () async { - values - ..add(1) - ..add(2) - ..add(3); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [1, 3]); + test('swallows values that come faster than duration', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..add(3) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 3]); + }); }); - test('outputs multiple values spaced further than duration', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('outputs multiple values spaced further than duration', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values - ..add(1) - ..add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); - expect(otherValues, [1, 2]); + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values + ..add(1) + ..add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + expect(otherValues, [1, 2]); + }); }); } }); @@ -201,49 +244,60 @@ void main() { values = createController(streamType); emittedValues = []; errors = []; - transformed = values.stream - .debounceBuffer(const Duration(milliseconds: 5)) - ..listen(emittedValues.add, onError: errors.add); - }); - - test('Emits all values as a list', () async { - values - ..add(1) - ..add(2); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [ - [1, 2] - ]); - }); - - test('separate lists for multiple values spaced further than duration', - () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [ - [1], - [2] - ]); + transformed = + values.stream.debounceBuffer(const Duration(milliseconds: 5)); }); + void listen() { + transformed.listen(emittedValues.add, onError: errors.add); + } - if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); + test('Emits all values as a list', () { + fakeAsync((async) { + listen(); values ..add(1) - ..add(2); - await waitForTimer(5); + ..add(2) + ..close(); + async.elapse(const Duration(milliseconds: 6)); expect(emittedValues, [ [1, 2] ]); - expect(otherValues, [ - [1, 2] + }); + }); + + test('separate lists for multiple values spaced further than duration', + () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [ + [1], + [2] ]); }); + }); + + if (streamType == 'broadcast') { + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values + ..add(1) + ..add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [ + [1, 2] + ]); + expect(otherValues, [ + [1, 2] + ]); + }); + }); } }); }); diff --git a/pkgs/stream_transform/test/throttle_test.dart b/pkgs/stream_transform/test/throttle_test.dart index 22bf5b3fc..07f607a99 100644 --- a/pkgs/stream_transform/test/throttle_test.dart +++ b/pkgs/stream_transform/test/throttle_test.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'package:fake_async/fake_async.dart'; import 'package:stream_transform/stream_transform.dart'; import 'package:test/test.dart'; @@ -29,49 +30,68 @@ void main() { emittedValues = []; isDone = false; transformed = values.stream.throttle(const Duration(milliseconds: 5)); + }); + + void listen() { subscription = transformed.listen(emittedValues.add, onDone: () { isDone = true; }); - }); + } test('cancels values', () async { + listen(); await subscription.cancel(); expect(valuesCanceled, true); }); - test('swallows values that come faster than duration', () async { - values - ..add(1) - ..add(2); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [1]); + test('swallows values that come faster than duration', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1]); + }); }); - test('outputs multiple values spaced further than duration', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('outputs multiple values spaced further than duration', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values.add(2); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + async.elapse(const Duration(milliseconds: 6)); + }); }); - test('closes output immediately', () async { - values.add(1); - await waitForTimer(5); - values.add(2); - await values.close(); - expect(isDone, true); + test('closes output immediately', () { + fakeAsync((async) { + listen(); + values.add(1); + async.elapse(const Duration(milliseconds: 6)); + values + ..add(2) + ..close(); + async.flushMicrotasks(); + expect(isDone, true); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values.add(1); - await Future(() {}); - expect(emittedValues, [1]); - expect(otherValues, [1]); + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values.add(1); + async.flushMicrotasks(); + expect(emittedValues, [1]); + expect(otherValues, [1]); + }); }); } }); @@ -87,65 +107,84 @@ void main() { isDone = false; transformed = values.stream .throttle(const Duration(milliseconds: 5), trailing: true); + }); + void listen() { subscription = transformed.listen(emittedValues.add, onDone: () { isDone = true; }); - }); + } - test('emits both first and last in a period', () async { - values - ..add(1) - ..add(2); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [1, 2]); + test('emits both first and last in a period', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + }); }); - test('swallows values that are not the latest in a period', () async { - values - ..add(1) - ..add(2) - ..add(3); - await values.close(); - await waitForTimer(5); - expect(emittedValues, [1, 3]); + test('swallows values that are not the latest in a period', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..add(3) + ..close(); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 3]); + }); }); test('waits to output the last value even if the stream closes', () async { - values - ..add(1) - ..add(2); - await values.close(); - await Future(() {}); - expect(isDone, false); - expect(emittedValues, [1], - reason: 'Should not be emitted until after duration'); - await waitForTimer(5); - expect(emittedValues, [1, 2]); - expect(isDone, true); + fakeAsync((async) { + listen(); + values + ..add(1) + ..add(2) + ..close(); + async.flushMicrotasks(); + expect(isDone, false); + expect(emittedValues, [1], + reason: 'Should not be emitted until after duration'); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + expect(isDone, true); + async.elapse(const Duration(milliseconds: 6)); + }); }); - test('closes immediately if there is no pending value', () async { - values.add(1); - await values.close(); - await Future(() {}); - expect(isDone, true); + test('closes immediately if there is no pending value', () { + fakeAsync((async) { + listen(); + values + ..add(1) + ..close(); + async.flushMicrotasks(); + expect(isDone, true); + }); }); if (streamType == 'broadcast') { - test('multiple listeners all get values', () async { - var otherValues = []; - transformed.listen(otherValues.add); - values - ..add(1) - ..add(2); - await Future(() {}); - expect(emittedValues, [1]); - expect(otherValues, [1]); - await waitForTimer(5); - expect(emittedValues, [1, 2]); - expect(otherValues, [1, 2]); + test('multiple listeners all get values', () { + fakeAsync((async) { + listen(); + var otherValues = []; + transformed.listen(otherValues.add); + values + ..add(1) + ..add(2); + async.flushMicrotasks(); + expect(emittedValues, [1]); + expect(otherValues, [1]); + async.elapse(const Duration(milliseconds: 6)); + expect(emittedValues, [1, 2]); + expect(otherValues, [1, 2]); + }); }); } }); diff --git a/pkgs/stream_transform/test/utils.dart b/pkgs/stream_transform/test/utils.dart index b6196d687..42d9613ba 100644 --- a/pkgs/stream_transform/test/utils.dart +++ b/pkgs/stream_transform/test/utils.dart @@ -4,12 +4,6 @@ import 'dart:async'; -/// Cycle the event loop to ensure timers are started, then wait for a delay -/// longer than [milliseconds] to allow for the timer to fire. -Future waitForTimer(int milliseconds) => - Future(() {/* ensure Timer is started*/}) - .then((_) => Future.delayed(Duration(milliseconds: milliseconds + 1))); - StreamController createController(String streamType) { switch (streamType) { case 'single subscription': From daf63d8a40c2c232d949bf8d86a52235dbe0ff4f Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Tue, 28 Feb 2023 17:13:41 -0800 Subject: [PATCH 0931/1215] Forward errors from trigger in takeUntil (dart-lang/stream_transform#165) It doesn't make sense to leave the error unhandled in all cases. When we can handle the error through the stream, do so, otherwise ignore it. This also makes `takeUntil` more useful for cases like timeouts. --- pkgs/stream_transform/CHANGELOG.md | 3 +++ pkgs/stream_transform/lib/src/take_until.dart | 12 ++++++++++++ pkgs/stream_transform/test/take_until_test.dart | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 7c3437140..2ef6fdb5b 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,9 @@ ## 2.1.1-dev - Require Dart 2.18 or greater +- Forward errors from the `trigger` future through to the result stream in + `takeUntil`. Previously an error would have not closed the stream, and instead + raised as an unhandled async error. ## 2.1.0 diff --git a/pkgs/stream_transform/lib/src/take_until.dart b/pkgs/stream_transform/lib/src/take_until.dart index 8f63d94b4..e6deaa135 100644 --- a/pkgs/stream_transform/lib/src/take_until.dart +++ b/pkgs/stream_transform/lib/src/take_until.dart @@ -13,6 +13,12 @@ extension TakeUntil on Stream { /// which are emitted before the trigger, but have further asynchronous delays /// in transformations following the takeUtil, will still go through. /// Cancelling a subscription immediately stops values. + /// + /// If [trigger] completes as an error, the error will be forwarded through + /// the result stream before the result stream closes. + /// + /// If [trigger] completes as a value or as an error after this stream has + /// already ended, the completion will be ignored. Stream takeUntil(Future trigger) { var controller = isBroadcast ? StreamController.broadcast(sync: true) @@ -25,6 +31,12 @@ extension TakeUntil on Stream { isDone = true; subscription?.cancel(); controller.close(); + }, onError: (Object error, StackTrace stackTrace) { + if (isDone) return; + isDone = true; + controller + ..addError(error, stackTrace) + ..close(); }); controller.onListen = () { diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index fe6ed1d8d..9c73d092b 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -68,6 +68,21 @@ void main() { expect(isDone, true); }); + test('forwards errors from the close trigger', () async { + closeTrigger.completeError('sad'); + await Future(() {}); + expect(errors, ['sad']); + expect(isDone, true); + }); + + test('ignores errors from the close trigger after stream closed', + () async { + await values.close(); + closeTrigger.completeError('sad'); + await Future(() {}); + expect(errors, []); + }); + test('cancels value subscription when trigger fires', () async { closeTrigger.complete(); await Future(() {}); From 83d040c6540b143cf745c6de929611376084299e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 7 Mar 2023 08:42:04 -0800 Subject: [PATCH 0932/1215] Require Dart 2.19, use new team lints (dart-lang/watcher#138) Enable some tests that now seem to be passing on mac --- pkgs/watcher/.github/workflows/test-package.yml | 2 +- pkgs/watcher/CHANGELOG.md | 4 ++++ pkgs/watcher/analysis_options.yaml | 16 +++------------- pkgs/watcher/benchmark/path_set.dart | 7 +++---- pkgs/watcher/example/watch.dart | 4 +--- .../lib/src/directory_watcher/mac_os.dart | 6 ++---- .../lib/src/directory_watcher/windows.dart | 6 +++--- pkgs/watcher/lib/src/path_set.dart | 2 +- pkgs/watcher/pubspec.yaml | 6 +++--- .../test/custom_watcher_factory_test.dart | 9 ++++++--- .../test/directory_watcher/linux_test.dart | 5 +++-- .../test/directory_watcher/mac_os_test.dart | 5 +++-- .../test/directory_watcher/polling_test.dart | 2 +- pkgs/watcher/test/directory_watcher/shared.dart | 1 - .../test/directory_watcher/windows_test.dart | 9 ++++----- pkgs/watcher/test/file_watcher/native_test.dart | 5 +++-- pkgs/watcher/test/file_watcher/polling_test.dart | 3 ++- .../watcher/test/no_subscription/linux_test.dart | 5 +++-- .../test/no_subscription/mac_os_test.dart | 6 +++--- .../test/no_subscription/polling_test.dart | 4 ++-- .../test/no_subscription/windows_test.dart | 5 +++-- pkgs/watcher/test/ready/linux_test.dart | 5 +++-- pkgs/watcher/test/ready/mac_os_test.dart | 5 +++-- pkgs/watcher/test/ready/polling_test.dart | 4 ++-- pkgs/watcher/test/ready/shared.dart | 9 ++++++--- pkgs/watcher/test/ready/windows_test.dart | 5 +++-- 26 files changed, 71 insertions(+), 69 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 6016675b0..0c0ce4994 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [2.14.0, dev] + sdk: [2.19.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 9104504d6..1271b6370 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,7 @@ +# 1.0.3-dev + +- Require Dart SDK >= 2.19 + # 1.0.2 - Require Dart SDK >= 2.14 diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index 43201629b..a1fc20f55 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,20 +1,10 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true - errors: - todo: ignore - unused_import: error - unused_element: error - unused_local_variable: error - dead_code: error linter: rules: - # comment_references # https://github.com/dart-lang/sdk/issues/39467 - - depend_on_referenced_packages - - prefer_generic_function_type_aliases - - prefer_typing_uninitialized_variables - - unnecessary_const - - unnecessary_new + - comment_references # https://github.com/dart-lang/sdk/issues/39467 + diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index 858df3cc0..82109b0ab 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -10,7 +10,6 @@ import 'dart:math' as math; import 'package:benchmark_harness/benchmark_harness.dart'; import 'package:path/path.dart' as p; - import 'package:watcher/src/path_set.dart'; final String root = Platform.isWindows ? r'C:\root' : '/root'; @@ -31,7 +30,7 @@ abstract class PathSetBenchmark extends BenchmarkBase { /// Each virtual directory contains ten entries: either subdirectories or /// files. void walkTree(int depth, void Function(String) callback) { - void recurse(String path, remainingDepth) { + void recurse(String path, int remainingDepth) { for (var i = 0; i < 10; i++) { var padded = i.toString().padLeft(2, '0'); if (remainingDepth == 0) { @@ -100,7 +99,7 @@ class ContainsBenchmark extends PathSetBenchmark { if (pathSet.contains(path)) contained++; } - if (contained != 10000) throw 'Wrong result: $contained'; + if (contained != 10000) throw StateError('Wrong result: $contained'); } } @@ -119,7 +118,7 @@ class PathsBenchmark extends PathSetBenchmark { count++; } - if (count != 10000) throw 'Wrong result: $count'; + if (count != 10000) throw StateError('Wrong result: $count'); } } diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index 650a4b877..0a0b3577a 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -15,7 +15,5 @@ void main(List arguments) { } var watcher = DirectoryWatcher(p.absolute(arguments[0])); - watcher.events.listen((event) { - print(event); - }); + watcher.events.listen(print); } diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 12648c8a6..415d17a33 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -160,9 +160,7 @@ class _MacOSDirectoryWatcher subscription.onDone(() { _listSubscriptions.remove(subscription); }); - subscription.onError((Object e, StackTrace stackTrace) { - _emitError(e, stackTrace); - }); + subscription.onError(_emitError); _listSubscriptions.add(subscription); } else if (event is FileSystemModifyEvent) { assert(!event.isDirectory); @@ -294,7 +292,7 @@ class _MacOSDirectoryWatcher return ConstructableFileSystemModifyEvent( batch.first.path, isDir, false); default: - throw 'unreachable'; + throw StateError('unreachable'); } } diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 710caf54a..141545b79 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -155,8 +155,7 @@ class _WindowsDirectoryWatcher void _onEvent(FileSystemEvent event) { assert(isReady); - final batcher = - _eventBatchers.putIfAbsent(event.path, () => _EventBatcher()); + final batcher = _eventBatchers.putIfAbsent(event.path, _EventBatcher.new); batcher.addEvent(event, () { _eventBatchers.remove(event.path); _onBatch(batcher.events); @@ -316,7 +315,7 @@ class _WindowsDirectoryWatcher case FileSystemEvent.move: return null; default: - throw 'unreachable'; + throw StateError('unreachable'); } } @@ -397,6 +396,7 @@ class _WindowsDirectoryWatcher _eventsController.addError(error, stackTrace); _startWatch(); } else { + // ignore: only_throw_errors throw error; } }); diff --git a/pkgs/watcher/lib/src/path_set.dart b/pkgs/watcher/lib/src/path_set.dart index 090090eeb..4f41cf924 100644 --- a/pkgs/watcher/lib/src/path_set.dart +++ b/pkgs/watcher/lib/src/path_set.dart @@ -33,7 +33,7 @@ class PathSet { var parts = p.split(path); var entry = _entries; for (var part in parts) { - entry = entry.contents.putIfAbsent(part, () => _Entry()); + entry = entry.contents.putIfAbsent(part, _Entry.new); } entry.isExplicit = true; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 947237407..e64e79d42 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,20 +1,20 @@ name: watcher -version: 1.0.2 +version: 1.0.3-dev description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. repository: https://github.com/dart-lang/watcher environment: - sdk: '>=2.14.0 <3.0.0' + sdk: '>=2.19.0 <3.0.0' dependencies: async: ^2.5.0 path: ^1.8.0 dev_dependencies: - lints: ^1.0.0 benchmark_harness: ^2.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 test_descriptor: ^2.0.0 diff --git a/pkgs/watcher/test/custom_watcher_factory_test.dart b/pkgs/watcher/test/custom_watcher_factory_test.dart index 331d24382..e9d65bb55 100644 --- a/pkgs/watcher/test/custom_watcher_factory_test.dart +++ b/pkgs/watcher/test/custom_watcher_factory_test.dart @@ -50,9 +50,12 @@ void main() { test('registering twice throws', () async { expect( - () => registerCustomWatcher(memFsFactoryId, - (_, {pollingDelay}) => throw 0, (_, {pollingDelay}) => throw 0), - throwsA(isA())); + () => registerCustomWatcher( + memFsFactoryId, + (_, {pollingDelay}) => throw UnimplementedError(), + (_, {pollingDelay}) => throw UnimplementedError()), + throwsA(isA()), + ); }); test('finding two applicable factories throws', () async { diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index b4745a33f..7b638a860 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -3,16 +3,17 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('linux') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => LinuxDirectoryWatcher(dir); + watcherFactory = LinuxDirectoryWatcher.new; sharedTests(); diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 58ba31aaa..347c5e731 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -3,16 +3,17 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('mac-os') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => MacOSDirectoryWatcher(dir); + watcherFactory = MacOSDirectoryWatcher.new; sharedTests(); diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 261d0e998..0cfe738af 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -5,8 +5,8 @@ import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { // Use a short delay to make the tests run quickly. diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 07fbf9cf2..8fd842a8e 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -278,7 +278,6 @@ void sharedTests() { isAddEvent('new') ]); }, onPlatform: { - 'mac-os': Skip('https://github.com/dart-lang/watcher/issues/21'), 'windows': Skip('https://github.com/dart-lang/watcher/issues/21') }); diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index 3ddb47e03..a0bdda7f4 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -3,20 +3,19 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('windows') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => WindowsDirectoryWatcher(dir); + watcherFactory = WindowsDirectoryWatcher.new; - group('Shared Tests:', () { - sharedTests(); - }); + group('Shared Tests:', sharedTests); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { expect(DirectoryWatcher('.'), TypeMatcher()); diff --git a/pkgs/watcher/test/file_watcher/native_test.dart b/pkgs/watcher/test/file_watcher/native_test.dart index b59d4ed95..0d4ad6394 100644 --- a/pkgs/watcher/test/file_watcher/native_test.dart +++ b/pkgs/watcher/test/file_watcher/native_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('linux || mac-os') +library; import 'package:test/test.dart'; import 'package:watcher/src/file_watcher/native.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (file) => NativeFileWatcher(file); + watcherFactory = NativeFileWatcher.new; setUp(() { writeFile('file.txt'); diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index b83d44fd1..1bf9269fe 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -3,12 +3,13 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('linux || mac-os') +library; import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { watcherFactory = (file) => diff --git a/pkgs/watcher/test/no_subscription/linux_test.dart b/pkgs/watcher/test/no_subscription/linux_test.dart index aa5763772..aac08101b 100644 --- a/pkgs/watcher/test/no_subscription/linux_test.dart +++ b/pkgs/watcher/test/no_subscription/linux_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('linux') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => LinuxDirectoryWatcher(dir); + watcherFactory = LinuxDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/mac_os_test.dart b/pkgs/watcher/test/no_subscription/mac_os_test.dart index f2270770c..55a83087c 100644 --- a/pkgs/watcher/test/no_subscription/mac_os_test.dart +++ b/pkgs/watcher/test/no_subscription/mac_os_test.dart @@ -3,16 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('mac-os') -@Skip('Flaky due to sdk#23877') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => MacOSDirectoryWatcher(dir); + watcherFactory = MacOSDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/polling_test.dart b/pkgs/watcher/test/no_subscription/polling_test.dart index 633ca2eb4..bfd29588f 100644 --- a/pkgs/watcher/test/no_subscription/polling_test.dart +++ b/pkgs/watcher/test/no_subscription/polling_test.dart @@ -4,11 +4,11 @@ import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => PollingDirectoryWatcher(dir); + watcherFactory = PollingDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/no_subscription/windows_test.dart b/pkgs/watcher/test/no_subscription/windows_test.dart index eb381d025..9f9e5a9c3 100644 --- a/pkgs/watcher/test/no_subscription/windows_test.dart +++ b/pkgs/watcher/test/no_subscription/windows_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('windows') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => WindowsDirectoryWatcher(dir); + watcherFactory = WindowsDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/ready/linux_test.dart b/pkgs/watcher/test/ready/linux_test.dart index aa5763772..aac08101b 100644 --- a/pkgs/watcher/test/ready/linux_test.dart +++ b/pkgs/watcher/test/ready/linux_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('linux') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/linux.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => LinuxDirectoryWatcher(dir); + watcherFactory = LinuxDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/ready/mac_os_test.dart b/pkgs/watcher/test/ready/mac_os_test.dart index 4bfdc8d3e..55a83087c 100644 --- a/pkgs/watcher/test/ready/mac_os_test.dart +++ b/pkgs/watcher/test/ready/mac_os_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('mac-os') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/mac_os.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => MacOSDirectoryWatcher(dir); + watcherFactory = MacOSDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/ready/polling_test.dart b/pkgs/watcher/test/ready/polling_test.dart index 633ca2eb4..bfd29588f 100644 --- a/pkgs/watcher/test/ready/polling_test.dart +++ b/pkgs/watcher/test/ready/polling_test.dart @@ -4,11 +4,11 @@ import 'package:watcher/watcher.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => PollingDirectoryWatcher(dir); + watcherFactory = PollingDirectoryWatcher.new; sharedTests(); } diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index d9bb5aefa..1b4dbaa0b 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -42,9 +42,12 @@ void sharedTests() { // Ensure ready completes immediately expect( - watcher.ready.timeout(Duration(milliseconds: 0), - onTimeout: () => throw 'Does not complete immedately'), - completes); + watcher.ready.timeout( + Duration(milliseconds: 0), + onTimeout: () => throw StateError('Does not complete immedately'), + ), + completes, + ); await subscription.cancel(); }); diff --git a/pkgs/watcher/test/ready/windows_test.dart b/pkgs/watcher/test/ready/windows_test.dart index eb381d025..9f9e5a9c3 100644 --- a/pkgs/watcher/test/ready/windows_test.dart +++ b/pkgs/watcher/test/ready/windows_test.dart @@ -3,15 +3,16 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('windows') +library; import 'package:test/test.dart'; import 'package:watcher/src/directory_watcher/windows.dart'; -import 'shared.dart'; import '../utils.dart'; +import 'shared.dart'; void main() { - watcherFactory = (dir) => WindowsDirectoryWatcher(dir); + watcherFactory = WindowsDirectoryWatcher.new; sharedTests(); } From 3ff8ef8f2d42bfd850e36a10cb2c64a11331cc69 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 7 Mar 2023 08:47:16 -0800 Subject: [PATCH 0933/1215] blast_repo fixes (dart-lang/watcher#139) auto-publish no-response * changelog tweaks --- .../watcher/.github/workflows/no-response.yml | 34 ++++++++++++ pkgs/watcher/.github/workflows/publish.yaml | 14 +++++ pkgs/watcher/CHANGELOG.md | 54 +++++++++---------- 3 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 pkgs/watcher/.github/workflows/no-response.yml create mode 100644 pkgs/watcher/.github/workflows/publish.yaml diff --git a/pkgs/watcher/.github/workflows/no-response.yml b/pkgs/watcher/.github/workflows/no-response.yml new file mode 100644 index 000000000..ac3e456ec --- /dev/null +++ b/pkgs/watcher/.github/workflows/no-response.yml @@ -0,0 +1,34 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/godofredoc/no-response for docs. + +name: No Response + +# Both `issue_comment` and `scheduled` event types are required. +on: + issue_comment: + types: [created] + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + +jobs: + noResponse: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + with: + responseRequiredLabel: "needs-info" + responseRequiredColor: 4774bc + daysUntilClose: 14 + # Comment to post when closing an Issue for lack of response. + closeComment: > + Without additional information we're not able to resolve this issue, + so it will be closed at this time. You're still free to add more + info and respond to any questions above, though. We'll reopen the + issue if you do. Thanks for your contribution! + token: ${{ github.token }} diff --git a/pkgs/watcher/.github/workflows/publish.yaml b/pkgs/watcher/.github/workflows/publish.yaml new file mode 100644 index 000000000..2239b63d3 --- /dev/null +++ b/pkgs/watcher/.github/workflows/publish.yaml @@ -0,0 +1,14 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 1271b6370..c8aa26648 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,63 +1,59 @@ -# 1.0.3-dev +## 1.0.3-dev - Require Dart SDK >= 2.19 -# 1.0.2 +## 1.0.2 - Require Dart SDK >= 2.14 - Ensure `DirectoryWatcher.ready` completes even when errors occur that close the watcher. - Add markdown badges to the readme. -# 1.0.1 +## 1.0.1 * Drop package:pedantic and use package:lints instead. -# 1.0.0 +## 1.0.0 -* Stable null safety release. - -# 1.0.0-nullsafety.0 - -* Migrate to null safety. +* Require Dart SDK >= 2.12 * Add the ability to create custom Watcher types for specific file paths. -# 0.9.7+15 +## 0.9.7+15 * Fix a bug on Mac where modifying a directory with a path exactly matching a prefix of a modified file would suppress change events for that file. -# 0.9.7+14 +## 0.9.7+14 * Prepare for breaking change in SDK where modified times for not found files becomes meaningless instead of null. -# 0.9.7+13 +## 0.9.7+13 * Catch & forward `FileSystemException` from unexpectedly closed file watchers on windows; the watcher will also be automatically restarted when this occurs. -# 0.9.7+12 +## 0.9.7+12 * Catch `FileSystemException` during `existsSync()` on Windows. * Internal cleanup. -# 0.9.7+11 +## 0.9.7+11 * Fix an analysis hint. -# 0.9.7+10 +## 0.9.7+10 * Set max SDK version to `<3.0.0`, and adjust other dependencies. -# 0.9.7+9 +## 0.9.7+9 * Internal changes only. -# 0.9.7+8 +## 0.9.7+8 * Fix Dart 2.0 type issues on Mac and Windows. -# 0.9.7+7 +## 0.9.7+7 * Updates to support Dart 2.0 core library changes (wave 2.2). See [issue 31847][sdk#31847] for details. @@ -65,37 +61,37 @@ [sdk#31847]: https://github.com/dart-lang/sdk/issues/31847 -# 0.9.7+6 +## 0.9.7+6 * Internal changes only, namely removing dep on scheduled test. -# 0.9.7+5 +## 0.9.7+5 * Fix an analysis warning. -# 0.9.7+4 +## 0.9.7+4 * Declare support for `async` 2.0.0. -# 0.9.7+3 +## 0.9.7+3 * Fix a crashing bug on Linux. -# 0.9.7+2 +## 0.9.7+2 * Narrow the constraint on `async` to reflect the APIs this package is actually using. -# 0.9.7+1 +## 0.9.7+1 * Fix all strong-mode warnings. -# 0.9.7 +## 0.9.7 * Fix a bug in `FileWatcher` where events could be added after watchers were closed. -# 0.9.6 +## 0.9.6 * Add a `Watcher` interface that encompasses watching both files and directories. @@ -105,16 +101,16 @@ * Deprecate `DirectoryWatcher.directory`. Use `DirectoryWatcher.path` instead. -# 0.9.5 +## 0.9.5 * Fix bugs where events could be added after watchers were closed. -# 0.9.4 +## 0.9.4 * Treat add events for known files as modifications instead of discarding them on Mac OS. -# 0.9.3 +## 0.9.3 * Improved support for Windows via `WindowsDirectoryWatcher`. From 8e64e236cdb03119a32ed7e9458f82a53ef5aea5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 23:57:31 +0000 Subject: [PATCH 0934/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/test_reflective_loader#47) --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 5b84b5eb5..f6902d62d 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 6d39477b584638a8ca6994c618bf32998f35ae8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Apr 2023 17:12:11 -0700 Subject: [PATCH 0935/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/test_reflective_loader#46) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Konstantin Scheglov --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index f6902d62d..a253754f8 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 25b9b3a605f5148500c9162e624b6d9d1dc2f42e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:50:07 -0700 Subject: [PATCH 0936/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/string_scanner#55) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 5a03db3b3..63946acf6 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 1c2c48d261a236a00f21a4560220fc9d1d1cb1c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:50:17 -0700 Subject: [PATCH 0937/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/stream_transform#167) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 9dc5e3e7b..e8b379c7c 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From a831fcbdbd7841a42d9d9872f705715e7797014c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:52:45 -0700 Subject: [PATCH 0938/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/stream_channel#89) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 20b28dece..772d53beb 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 0cf059cfdb7864d04174768c8a3497391e0e8f83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:53:09 -0700 Subject: [PATCH 0939/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/timing#30) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index a21f0225c..f875d8abb 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 3964b9748ade19fa93cb150e0d8f290cef52de09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:54:26 -0700 Subject: [PATCH 0940/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/string_scanner#56) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 63946acf6..b70103cd7 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 1a4c1482a10cf28ba7674956196ce10dfd4f8f0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 2 Apr 2023 19:55:38 -0700 Subject: [PATCH 0941/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/stream_transform#168) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index e8b379c7c..abdc4f27b 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e5a306e974a66eb50a36b1ce7c40a071d22ce124 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 13:24:52 -0700 Subject: [PATCH 0942/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/timing#29) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index f875d8abb..ce228de2d 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 871b223fe6c6f33594240c8942bfae7d436fc42c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 14:30:31 -0700 Subject: [PATCH 0943/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/stream_channel#88) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 772d53beb..763267350 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From e3f7c5f256cd455a901d69376b17b5c9a1912fed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:36:32 -0700 Subject: [PATCH 0944/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/term_glyph#36) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 58201d820..a8d9e0928 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.17.0, dev] steps: - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 82f0d595da5c217fb2e3270fc08a86485ad1bb4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:40:15 -0700 Subject: [PATCH 0945/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/stack_trace#129) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index aa00cf58d..d10d07539 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From ea3be5b897b32aac57870c367e8053ebbff776d2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:40:22 -0700 Subject: [PATCH 0946/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/watcher#141) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 0c0ce4994..11d3a7077 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 979d683c7e90eefb88a8385b357b7f9a97ebd574 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:57:20 -0700 Subject: [PATCH 0947/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/stack_trace#128) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index d10d07539..a3dfc40db 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From f1fe85bb2ea4c1fdb57a6e862ac2f4640f6f8e6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:57:27 -0700 Subject: [PATCH 0948/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/watcher#140) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 11d3a7077..d4a42dc62 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 8201a84a45551519b8f40ed7f716d7d4fa536ee3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Apr 2023 11:52:29 -0700 Subject: [PATCH 0949/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/term_glyph#35) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index a8d9e0928..7bcd23232 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e61a97e236e19bdcea1e2e99a0fe9dcf65a5db7d Mon Sep 17 00:00:00 2001 From: Ricardo Amador <32242716+ricardoamador@users.noreply.github.com> Date: Tue, 4 Apr 2023 19:07:13 -0700 Subject: [PATCH 0950/1215] Updating to point to the config. (dart-lang/pubspec_parse#96) --- pkgs/pubspec_parse/.github/autosubmit.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 pkgs/pubspec_parse/.github/autosubmit.yml diff --git a/pkgs/pubspec_parse/.github/autosubmit.yml b/pkgs/pubspec_parse/.github/autosubmit.yml new file mode 100644 index 000000000..a9daaa91a --- /dev/null +++ b/pkgs/pubspec_parse/.github/autosubmit.yml @@ -0,0 +1,6 @@ +# Copyright 2023 The Flutter Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This file will be added to flutter's internal repository. +config_path: 'autosubmit/dart-lang/autosubmit.yml' From 6195b78d4bd3a437d432f8358bdcba7d86333fb3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Apr 2023 12:35:08 -0700 Subject: [PATCH 0951/1215] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/pubspec_parse#94) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index e78b568f2..ee1bbbf7a 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 73f5b89bbbbae25455d7b366c7386063415d25f9 Mon Sep 17 00:00:00 2001 From: Tobe Osakwe Date: Tue, 11 Apr 2023 15:50:57 -0700 Subject: [PATCH 0952/1215] Add example/example.dart (dart-lang/stream_channel#52) --- pkgs/stream_channel/CHANGELOG.md | 1 + pkgs/stream_channel/example/example.dart | 110 +++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 pkgs/stream_channel/example/example.dart diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 0d7382839..893218875 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ ## 2.1.2-dev * Require Dart 2.19 +* Add an example. ## 2.1.1 diff --git a/pkgs/stream_channel/example/example.dart b/pkgs/stream_channel/example/example.dart new file mode 100644 index 000000000..dd16f6750 --- /dev/null +++ b/pkgs/stream_channel/example/example.dart @@ -0,0 +1,110 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// 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. + +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:isolate'; + +import 'package:stream_channel/isolate_channel.dart'; +import 'package:stream_channel/stream_channel.dart'; + +Future main() async { + // A StreamChannel, is in simplest terms, a wrapper around a Stream and + // a StreamSink. For example, you can create a channel that wraps standard + // IO: + var stdioChannel = StreamChannel(stdin, stdout); + stdioChannel.sink.add('Hello!\n'.codeUnits); + + // Like a Stream can be transformed with a StreamTransformer, a + // StreamChannel can be transformed with a StreamChannelTransformer. + // For example, we can handle standard input as strings: + var stringChannel = stdioChannel + .transform(StreamChannelTransformer.fromCodec(utf8)) + .transformStream(LineSplitter()); + stringChannel.sink.add('world!\n'); + + // You can implement StreamChannel by extending StreamChannelMixin, but + // it's much easier to use a StreamChannelController. A controller has two + // StreamChannel members: `local` and `foreign`. The creator of a + // controller should work with the `local` channel, while the recipient should + // work with the `foreign` channel, and usually will not have direct access to + // the underlying controller. + var ctrl = StreamChannelController(); + ctrl.local.stream.listen((event) { + // Do something useful here... + }); + + // You can also pipe events from one channel to another. + ctrl + ..foreign.pipe(stringChannel) + ..local.sink.add('Piped!\n'); + await ctrl.local.sink.close(); + + // The StreamChannel interface provides several guarantees, which can be + // found here: + // https://pub.dev/documentation/stream_channel/latest/stream_channel/StreamChannel-class.html + // + // By calling `StreamChannel.withGuarantees()`, you can create a + // StreamChannel that provides all guarantees. + var dummyCtrl0 = StreamChannelController(); + var guaranteedChannel = StreamChannel.withGuarantees( + dummyCtrl0.foreign.stream, dummyCtrl0.foreign.sink); + + // To close a StreamChannel, use `sink.close()`. + await guaranteedChannel.sink.close(); + + // A MultiChannel multiplexes multiple virtual channels across a single + // underlying transport layer. For example, an application listening over + // standard I/O can still support multiple clients if it has a mechanism to + // separate events from different clients. + // + // A MultiChannel splits events into numbered channels, which are + // instances of VirtualChannel. + var dummyCtrl1 = StreamChannelController(); + var multiChannel = MultiChannel(dummyCtrl1.foreign); + var channel1 = multiChannel.virtualChannel(); + await multiChannel.sink.close(); + + // The client/peer should also create its own MultiChannel, connected to + // the underlying transport, use the corresponding ID's to handle events in + // their respective channels. It is up to you how to communicate channel ID's + // across different endpoints. + var dummyCtrl2 = StreamChannelController(); + var multiChannel2 = MultiChannel(dummyCtrl2.foreign); + var channel2 = multiChannel2.virtualChannel(channel1.id); + await channel2.sink.close(); + await multiChannel2.sink.close(); + + // Multiple instances of a Dart application can communicate easily across + // `SendPort`/`ReceivePort` pairs by means of the `IsolateChannel` class. + // Typically, one endpoint will create a `ReceivePort`, and call the + // `IsolateChannel.connectReceive` constructor. The other endpoint will be + // given the corresponding `SendPort`, and then call + // `IsolateChannel.connectSend`. + var recv = ReceivePort(); + var recvChannel = IsolateChannel.connectReceive(recv); + var sendChannel = IsolateChannel.connectSend(recv.sendPort); + + // You must manually close `IsolateChannel` sinks, however. + await recvChannel.sink.close(); + await sendChannel.sink.close(); + + // You can use the `Disconnector` transformer to cause a channel to act as + // though the remote end of its transport had disconnected. + var disconnector = Disconnector(); + var disconnectable = stringChannel.transform(disconnector); + disconnectable.sink.add('Still connected!'); + await disconnector.disconnect(); + + // Additionally: + // * The `DelegatingStreamController` class can be extended to build a + // basis for wrapping other `StreamChannel` objects. + // * The `jsonDocument` transformer converts events to/from JSON, using + // the `json` codec from `dart:convert`. + // * `package:json_rpc_2` directly builds on top of + // `package:stream_channel`, so any compatible transport can be used to + // create interactive client/server or peer-to-peer applications (i.e. + // language servers, microservices, etc. +} From adcd711141602fb7a1d35c9ca09ecc6926062b0a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 02:34:39 +0000 Subject: [PATCH 0953/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pubspec_parse#95) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.5.1-dev

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use inline classes.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

v0.4

  • Removed previously deprecated input channel. Use the sdk input instead.
  • Added support for specifying the CPU architecture.

v0.3

  • Added support for installing SDKs from the main channel.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.4.0&new-version=1.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index ee1bbbf7a..cafe8ed33 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 17a78c3e72a0a619bf08940c2bae08bddbd88051 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 26 Apr 2023 11:09:28 -0700 Subject: [PATCH 0954/1215] Update dependabot.yml (dart-lang/pubspec_parse#97) --- pkgs/pubspec_parse/.github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/pubspec_parse/.github/dependabot.yml b/pkgs/pubspec_parse/.github/dependabot.yml index 1603cdd9e..cf1a70501 100644 --- a/pkgs/pubspec_parse/.github/dependabot.yml +++ b/pkgs/pubspec_parse/.github/dependabot.yml @@ -7,3 +7,5 @@ updates: directory: "/" schedule: interval: "monthly" + labels: + - "autosubmit" From ead89bcaa5d798e1cafc07fb5303222c7bc21b5a Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 26 Apr 2023 11:16:06 -0700 Subject: [PATCH 0955/1215] Revert "Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pubspec_parse#95)" (dart-lang/pubspec_parse#99) This reverts commit adcd711141602fb7a1d35c9ca09ecc6926062b0a. --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index cafe8ed33..ee1bbbf7a 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From be0701fef5a2ed3ff3dd58d142c93de92d08de5d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:23:08 -0700 Subject: [PATCH 0956/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/pubspec_parse#98) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index ee1bbbf7a..a099cebce 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 6789ce31ca88aa65cd737e94ad3234124edd5eac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:41:53 -0700 Subject: [PATCH 0957/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pubspec_parse#100) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index a099cebce..44a40de01 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From bbf6de3a7920d71acd8078367b4998ef8e1cabd4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 27 Apr 2023 11:54:11 -0700 Subject: [PATCH 0958/1215] Revert "Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pubspec_parse#100)" (dart-lang/pubspec_parse#101) This reverts commit 6789ce31ca88aa65cd737e94ad3234124edd5eac. --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 44a40de01..a099cebce 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From 03fe5ff46c2eba7f0585e0337674cd9f55cd28e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 19:04:20 +0000 Subject: [PATCH 0959/1215] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/pubspec_parse#102) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.5.1-dev

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use inline classes.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

v0.4

  • Removed previously deprecated input channel. Use the sdk input instead.
  • Added support for specifying the CPU architecture.

v0.3

  • Added support for installing SDKs from the main channel.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.4.0&new-version=1.5.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index a099cebce..44a40de01 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 689550987d6f6478a5437a491c2635572c199cfc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:47:50 -0700 Subject: [PATCH 0960/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/watcher#144) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index d4a42dc62..12968232d 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From d9f85e1ef337cebcf2e18b1081fb65201f10f4e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 08:49:26 -0700 Subject: [PATCH 0961/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/timing#31) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index ce228de2d..f689ff513 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e3326e1ab6910b077cb86c7dbfcaf8b7ffe5280d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 10:02:52 -0700 Subject: [PATCH 0962/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/test_reflective_loader#48) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index a253754f8..3b42f4ae5 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 5a13b29cc241112a6eaf4f75e0c61877b92553a7 Mon Sep 17 00:00:00 2001 From: Jonas Finnemann Jensen Date: Thu, 4 May 2023 14:33:13 +0200 Subject: [PATCH 0963/1215] Prepare release with topics. (dart-lang/pubspec_parse#103) --- pkgs/pubspec_parse/CHANGELOG.md | 3 +++ pkgs/pubspec_parse/pubspec.yaml | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 023e2a13f..9ed3837aa 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.2.3 +- Added topics to `pubspec.yaml`. + ## 1.2.2 - Require Dart SDK >= 2.18.0 diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 63742631f..a2b189db5 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,9 +1,11 @@ name: pubspec_parse +version: 1.2.3 description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -version: 1.2.2 repository: https://github.com/dart-lang/pubspec_parse +topics: +- dart-pub environment: sdk: '>=2.18.0 <3.0.0' From 8d3eeef39ff1c20e0ee5b5426968a3c6a878c85c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:24:33 -0700 Subject: [PATCH 0964/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/term_glyph#37) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 7bcd23232..c21c3dde5 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From d426fdeb6cab4433829693dc0c34583b5b7854bb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:27:33 -0700 Subject: [PATCH 0965/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/stack_trace#130) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index a3dfc40db..9ecb00344 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 28c22df54e650925a904612e7341c255e9188000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:30:00 -0700 Subject: [PATCH 0966/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/stream_channel#90) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 763267350..0874bdd38 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 3d1658ee76eca3790fd9045298a9aace2f14e86e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:34:43 -0700 Subject: [PATCH 0967/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/stream_transform#169) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index abdc4f27b..6e238d36f 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 34b26161a343cf2671e765c5baa30fc350b618a7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:34:56 -0700 Subject: [PATCH 0968/1215] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/string_scanner#57) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index b70103cd7..2d36a3b10 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 283ae18b2f882f758f4d864aef8e6a83cc422462 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 9 May 2023 16:37:45 -0700 Subject: [PATCH 0969/1215] Delete autosubmit.yml (dart-lang/pubspec_parse#104) --- pkgs/pubspec_parse/.github/autosubmit.yml | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 pkgs/pubspec_parse/.github/autosubmit.yml diff --git a/pkgs/pubspec_parse/.github/autosubmit.yml b/pkgs/pubspec_parse/.github/autosubmit.yml deleted file mode 100644 index a9daaa91a..000000000 --- a/pkgs/pubspec_parse/.github/autosubmit.yml +++ /dev/null @@ -1,6 +0,0 @@ -# Copyright 2023 The Flutter Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This file will be added to flutter's internal repository. -config_path: 'autosubmit/dart-lang/autosubmit.yml' From aa09575d8c4472faa83e2ad739b4cc419435d544 Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Wed, 10 May 2023 14:06:54 -0700 Subject: [PATCH 0970/1215] Remove unnecessary ConstructableFileSystemEvent classes (dart-lang/watcher#143) --- .../.github/workflows/test-package.yml | 2 +- pkgs/watcher/CHANGELOG.md | 5 ++ .../src/constructable_file_system_event.dart | 71 ------------------- .../lib/src/directory_watcher/mac_os.dart | 22 +++--- .../lib/src/directory_watcher/windows.dart | 22 +++--- pkgs/watcher/pubspec.yaml | 4 +- 6 files changed, 28 insertions(+), 98 deletions(-) delete mode 100644 pkgs/watcher/lib/src/constructable_file_system_event.dart diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 12968232d..bc16dd1c4 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [2.19.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index c8aa26648..17b93f911 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.1.0-dev + +- Require Dart SDK >= 3.0.0 +- Remove usage of redundant ConstructableFileSystemEvent classes. +- ## 1.0.3-dev - Require Dart SDK >= 2.19 diff --git a/pkgs/watcher/lib/src/constructable_file_system_event.dart b/pkgs/watcher/lib/src/constructable_file_system_event.dart deleted file mode 100644 index 0011a8d64..000000000 --- a/pkgs/watcher/lib/src/constructable_file_system_event.dart +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// 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. - -import 'dart:io'; - -abstract class _ConstructableFileSystemEvent implements FileSystemEvent { - @override - final bool isDirectory; - @override - final String path; - @override - int get type; - - _ConstructableFileSystemEvent(this.path, this.isDirectory); -} - -class ConstructableFileSystemCreateEvent extends _ConstructableFileSystemEvent - implements FileSystemCreateEvent { - @override - final type = FileSystemEvent.create; - - ConstructableFileSystemCreateEvent(String path, bool isDirectory) - : super(path, isDirectory); - - @override - String toString() => "FileSystemCreateEvent('$path')"; -} - -class ConstructableFileSystemDeleteEvent extends _ConstructableFileSystemEvent - implements FileSystemDeleteEvent { - @override - final type = FileSystemEvent.delete; - - ConstructableFileSystemDeleteEvent(String path, bool isDirectory) - : super(path, isDirectory); - - @override - String toString() => "FileSystemDeleteEvent('$path')"; -} - -class ConstructableFileSystemModifyEvent extends _ConstructableFileSystemEvent - implements FileSystemModifyEvent { - @override - final bool contentChanged; - @override - final type = FileSystemEvent.modify; - - ConstructableFileSystemModifyEvent( - String path, bool isDirectory, this.contentChanged) - : super(path, isDirectory); - - @override - String toString() => - "FileSystemModifyEvent('$path', contentChanged=$contentChanged)"; -} - -class ConstructableFileSystemMoveEvent extends _ConstructableFileSystemEvent - implements FileSystemMoveEvent { - @override - final String destination; - @override - final type = FileSystemEvent.move; - - ConstructableFileSystemMoveEvent( - String path, bool isDirectory, this.destination) - : super(path, isDirectory); - - @override - String toString() => "FileSystemMoveEvent('$path', '$destination')"; -} diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index 415d17a33..d2db97524 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -7,7 +7,6 @@ import 'dart:io'; import 'package:path/path.dart' as p; -import '../constructable_file_system_event.dart'; import '../directory_watcher.dart'; import '../path_set.dart'; import '../resubscribable.dart'; @@ -285,12 +284,11 @@ class _MacOSDirectoryWatcher // [_eventsBasedOnFileSystem] will handle this correctly by producing a // DELETE event followed by a CREATE event if the directory exists. if (isDir) return null; - return ConstructableFileSystemCreateEvent(batch.first.path, false); + return FileSystemCreateEvent(batch.first.path, false); case FileSystemEvent.delete: - return ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + return FileSystemDeleteEvent(batch.first.path, isDir); case FileSystemEvent.modify: - return ConstructableFileSystemModifyEvent( - batch.first.path, isDir, false); + return FileSystemModifyEvent(batch.first.path, isDir, false); default: throw StateError('unreachable'); } @@ -312,26 +310,26 @@ class _MacOSDirectoryWatcher var events = []; if (fileExisted) { if (fileExists) { - events.add(ConstructableFileSystemModifyEvent(path, false, false)); + events.add(FileSystemModifyEvent(path, false, false)); } else { - events.add(ConstructableFileSystemDeleteEvent(path, false)); + events.add(FileSystemDeleteEvent(path, false)); } } else if (dirExisted) { if (dirExists) { // If we got contradictory events for a directory that used to exist and // still exists, we need to rescan the whole thing in case it was // replaced with a different directory. - events.add(ConstructableFileSystemDeleteEvent(path, true)); - events.add(ConstructableFileSystemCreateEvent(path, true)); + events.add(FileSystemDeleteEvent(path, true)); + events.add(FileSystemCreateEvent(path, true)); } else { - events.add(ConstructableFileSystemDeleteEvent(path, true)); + events.add(FileSystemDeleteEvent(path, true)); } } if (!fileExisted && fileExists) { - events.add(ConstructableFileSystemCreateEvent(path, false)); + events.add(FileSystemCreateEvent(path, false)); } else if (!dirExisted && dirExists) { - events.add(ConstructableFileSystemCreateEvent(path, true)); + events.add(FileSystemCreateEvent(path, true)); } return events; diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index 141545b79..aff7a748a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -9,7 +9,6 @@ import 'dart:io'; import 'package:path/path.dart' as p; -import '../constructable_file_system_event.dart'; import '../directory_watcher.dart'; import '../path_set.dart'; import '../resubscribable.dart'; @@ -306,12 +305,11 @@ class _WindowsDirectoryWatcher switch (type) { case FileSystemEvent.create: - return ConstructableFileSystemCreateEvent(batch.first.path, isDir); + return FileSystemCreateEvent(batch.first.path, isDir); case FileSystemEvent.delete: - return ConstructableFileSystemDeleteEvent(batch.first.path, isDir); + return FileSystemDeleteEvent(batch.first.path, isDir); case FileSystemEvent.modify: - return ConstructableFileSystemModifyEvent( - batch.first.path, isDir, false); + return FileSystemModifyEvent(batch.first.path, isDir, false); case FileSystemEvent.move: return null; default: @@ -342,26 +340,26 @@ class _WindowsDirectoryWatcher var events = []; if (fileExisted) { if (fileExists) { - events.add(ConstructableFileSystemModifyEvent(path, false, false)); + events.add(FileSystemModifyEvent(path, false, false)); } else { - events.add(ConstructableFileSystemDeleteEvent(path, false)); + events.add(FileSystemDeleteEvent(path, false)); } } else if (dirExisted) { if (dirExists) { // If we got contradictory events for a directory that used to exist and // still exists, we need to rescan the whole thing in case it was // replaced with a different directory. - events.add(ConstructableFileSystemDeleteEvent(path, true)); - events.add(ConstructableFileSystemCreateEvent(path, true)); + events.add(FileSystemDeleteEvent(path, true)); + events.add(FileSystemCreateEvent(path, true)); } else { - events.add(ConstructableFileSystemDeleteEvent(path, true)); + events.add(FileSystemDeleteEvent(path, true)); } } if (!fileExisted && fileExists) { - events.add(ConstructableFileSystemCreateEvent(path, false)); + events.add(FileSystemCreateEvent(path, false)); } else if (!dirExisted && dirExists) { - events.add(ConstructableFileSystemCreateEvent(path, true)); + events.add(FileSystemCreateEvent(path, true)); } return events; diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index e64e79d42..5df994fa5 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,12 +1,12 @@ name: watcher -version: 1.0.3-dev +version: 1.1.0-dev description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. repository: https://github.com/dart-lang/watcher environment: - sdk: '>=2.19.0 <3.0.0' + sdk: ^3.0.0 dependencies: async: ^2.5.0 From 1cc846682e8f7b79308caedbd36f4f102388df9c Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Fri, 12 May 2023 11:28:00 -0700 Subject: [PATCH 0971/1215] Update to 1.1.0 in preparation for release. (dart-lang/watcher#145) --- pkgs/watcher/CHANGELOG.md | 4 ++-- pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 17b93f911..b7641e661 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,8 +1,8 @@ -## 1.1.0-dev +## 1.1.0 - Require Dart SDK >= 3.0.0 - Remove usage of redundant ConstructableFileSystemEvent classes. -- + ## 1.0.3-dev - Require Dart SDK >= 2.19 diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 5df994fa5..d86346881 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.1.0-dev +version: 1.1.0 description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. From 997558adc96cdf8729ea071775fe613a57c3edce Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:07:32 -0700 Subject: [PATCH 0972/1215] blast_repo fixes (dart-lang/test_reflective_loader#49) dependabot --- pkgs/test_reflective_loader/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/test_reflective_loader/.github/dependabot.yml b/pkgs/test_reflective_loader/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/test_reflective_loader/.github/dependabot.yml +++ b/pkgs/test_reflective_loader/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From ebdfcfa3a2dc9bde66f553b942d7ff9013baaf00 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:52:27 -0700 Subject: [PATCH 0973/1215] blast_repo fixes (dart-lang/term_glyph#38) dependabot --- pkgs/term_glyph/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/term_glyph/.github/dependabot.yml b/pkgs/term_glyph/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/term_glyph/.github/dependabot.yml +++ b/pkgs/term_glyph/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 419ff8922532b20f8a90794ed4708f6d4b30400d Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:52:39 -0700 Subject: [PATCH 0974/1215] blast_repo fixes (dart-lang/string_scanner#58) dependabot --- pkgs/string_scanner/.github/dependabot.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/string_scanner/.github/dependabot.yml b/pkgs/string_scanner/.github/dependabot.yml index d5262beb1..c84404dc9 100644 --- a/pkgs/string_scanner/.github/dependabot.yml +++ b/pkgs/string_scanner/.github/dependabot.yml @@ -4,8 +4,9 @@ version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" +- package-ecosystem: github-actions + directory: / schedule: - # Check for updates to GitHub Actions every weekday - interval: "monthly" + interval: monthly + labels: + - autosubmit From 50c6c54936e8d86d4ec2f8e35f56e0d6b75ffdb8 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:52:50 -0700 Subject: [PATCH 0975/1215] blast_repo fixes (dart-lang/stream_transform#170) dependabot --- pkgs/stream_transform/.github/dependabot.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_transform/.github/dependabot.yaml b/pkgs/stream_transform/.github/dependabot.yaml index 214481934..439e796b4 100644 --- a/pkgs/stream_transform/.github/dependabot.yaml +++ b/pkgs/stream_transform/.github/dependabot.yaml @@ -2,7 +2,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From eedb3691c7fc61e5899c8e3cabc005dee069bf8e Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:53:01 -0700 Subject: [PATCH 0976/1215] blast_repo fixes (dart-lang/stream_channel#91) dependabot --- pkgs/stream_channel/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From e790e31833eb1e6364a7b553c01cb5c611284f23 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 19 May 2023 09:53:13 -0700 Subject: [PATCH 0977/1215] blast_repo fixes (dart-lang/stack_trace#132) dependabot --- pkgs/stack_trace/.github/dependabot.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/stack_trace/.github/dependabot.yml b/pkgs/stack_trace/.github/dependabot.yml index 952351121..fb01db0e6 100644 --- a/pkgs/stack_trace/.github/dependabot.yml +++ b/pkgs/stack_trace/.github/dependabot.yml @@ -7,3 +7,5 @@ updates: directory: / schedule: interval: monthly + labels: + - autosubmit From 544b07a58d2bfb022ceaf96d5006f019647f4872 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Sun, 21 May 2023 19:57:34 -0700 Subject: [PATCH 0978/1215] Update formatting (dart-lang/pubspec_parse#105) --- pkgs/pubspec_parse/lib/src/pubspec.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 188af314b..3eb73cc3f 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -99,11 +99,11 @@ class Pubspec { @Deprecated( 'See https://dart.dev/tools/pub/pubspec#authorauthors', ) - String? author, + String? author, @Deprecated( 'See https://dart.dev/tools/pub/pubspec#authorauthors', ) - List? authors, + List? authors, Map? environment, this.homepage, this.repository, From 84cd19d95bc059d60e7265711b7fe086bb6dacbf Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 22 May 2023 16:22:46 -0700 Subject: [PATCH 0979/1215] blast_repo fixes (dart-lang/watcher#146) dependabot --- pkgs/watcher/.github/dependabot.yaml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/watcher/.github/dependabot.yaml b/pkgs/watcher/.github/dependabot.yaml index 214481934..439e796b4 100644 --- a/pkgs/watcher/.github/dependabot.yaml +++ b/pkgs/watcher/.github/dependabot.yaml @@ -2,7 +2,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 75d398954def3f2d4d1afd85c6c74a61d042a73d Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 22 May 2023 16:23:17 -0700 Subject: [PATCH 0980/1215] blast_repo fixes (dart-lang/timing#32) dependabot --- pkgs/timing/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/timing/.github/dependabot.yml b/pkgs/timing/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/timing/.github/dependabot.yml +++ b/pkgs/timing/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From 9fb3c990d781fa64f4e87f370d92b6ace2d51708 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Wed, 31 May 2023 09:20:43 -0700 Subject: [PATCH 0981/1215] blast_repo fixes (dart-lang/stack_trace#134) no-response --- .../.github/workflows/no-response.yml | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 pkgs/stack_trace/.github/workflows/no-response.yml diff --git a/pkgs/stack_trace/.github/workflows/no-response.yml b/pkgs/stack_trace/.github/workflows/no-response.yml new file mode 100644 index 000000000..8e5ed57cd --- /dev/null +++ b/pkgs/stack_trace/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! From 88d113b6fdcabf305a06bc3833b4741339f221c1 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 7 Jun 2023 20:31:04 -0700 Subject: [PATCH 0982/1215] Require Dart 3.0, update lints (dart-lang/term_glyph#39) --- pkgs/term_glyph/.github/workflows/test-package.yml | 2 +- pkgs/term_glyph/CHANGELOG.md | 4 ++-- pkgs/term_glyph/analysis_options.yaml | 7 +++++-- pkgs/term_glyph/pubspec.yaml | 6 +++--- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index c21c3dde5..1f8243089 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.17.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 1cf47ac41..657329c98 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,6 +1,6 @@ -## 1.2.2-dev +## 1.2.2-wip -* Require Dart 2.17 +* Require Dart 3.0 ## 1.2.1 diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index a4cc65912..fc4afe346 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -1,3 +1,4 @@ +# https://dart.dev/guides/language/analysis-options include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: @@ -18,10 +19,8 @@ linter: - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - #- cascade_invocations - comment_references - join_return_with_assignment - #- lines_longer_than_80_chars - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list @@ -34,4 +33,8 @@ linter: - prefer_relative_imports - test_types_in_equals - unnecessary_await_in_return + - unnecessary_breaks + - use_if_null_to_convert_nulls_to_bools + - use_raw_strings - use_string_buffers + - use_super_parameters diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 6c6a5f1ab..5a7702044 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,13 +1,13 @@ name: term_glyph -version: 1.2.2-dev +version: 1.2.2-wip description: Useful Unicode glyphs and ASCII substitutes. repository: https://github.com/dart-lang/term_glyph environment: - sdk: ">=2.17.0 <3.0.0" + sdk: ^3.0.0 dev_dependencies: csv: ^5.0.0 - dart_flutter_team_lints: ^0.1.0 + dart_flutter_team_lints: ^1.0.0 dart_style: ^2.0.0 test: ^1.16.0 From 7515328b94297b5430947a159635e25c05ccaa52 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Jun 2023 07:59:25 -0700 Subject: [PATCH 0983/1215] Require Dart 3, update lints (dart-lang/timing#33) --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- pkgs/timing/CHANGELOG.md | 4 ++++ pkgs/timing/lib/src/timing.dart | 2 +- pkgs/timing/lib/timing.dart | 10 +++++----- pkgs/timing/pubspec.yaml | 6 +++--- 5 files changed, 15 insertions(+), 11 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index f689ff513..752aef4ed 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f @@ -44,7 +44,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index f7f3fbd4a..0c38a7661 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.0.2-wip + +- Require Dart `3.0`. + ## 1.0.1 - Require Dart `2.14`. diff --git a/pkgs/timing/lib/src/timing.dart b/pkgs/timing/lib/src/timing.dart index fae19bd4c..049ba8189 100644 --- a/pkgs/timing/lib/src/timing.dart +++ b/pkgs/timing/lib/src/timing.dart @@ -317,7 +317,7 @@ class AsyncTimeTracker extends TimeSliceGroup implements TimeTracker { return result // Break possible sync processing of future completion, so slice // trackers can be finished - .whenComplete(() => Future.value()) + .whenComplete(Future.value) .whenComplete(() => _tracking = false) as T; } else { _tracking = false; diff --git a/pkgs/timing/lib/timing.dart b/pkgs/timing/lib/timing.dart index 0163e8d86..5cb16d423 100644 --- a/pkgs/timing/lib/timing.dart +++ b/pkgs/timing/lib/timing.dart @@ -4,10 +4,10 @@ export 'src/timing.dart' show + AsyncTimeTracker, + NoOpTimeTracker, + SimpleAsyncTimeTracker, + SyncTimeTracker, TimeSlice, TimeSliceGroup, - TimeTracker, - SyncTimeTracker, - SimpleAsyncTimeTracker, - AsyncTimeTracker, - NoOpTimeTracker; + TimeTracker; diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 323c28e8b..f81c2fc9e 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,18 +1,18 @@ name: timing -version: 1.0.1 +version: 1.0.2-wip description: >- A simple package for tracking the performance of synchronous and asynchronous actions. repository: https://github.com/dart-lang/timing environment: - sdk: ">=2.14.0 <3.0.0" + sdk: ^3.0.0 dependencies: json_annotation: ^4.3.0 dev_dependencies: build_runner: ^2.0.0 - dart_flutter_team_lints: ^0.1.0 + dart_flutter_team_lints: ^1.0.0 json_serializable: ^6.0.0 test: ^1.0.0 From ce15656712d2b333bdfaad2793b564f9ce61ea73 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 12 Jun 2023 08:50:44 -0700 Subject: [PATCH 0984/1215] Require Dart 3, update lints (dart-lang/pubspec_parse#106) --- .../.github/workflows/test-package.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 5 +++++ pkgs/pubspec_parse/analysis_options.yaml | 14 ++----------- pkgs/pubspec_parse/lib/pubspec_parse.dart | 6 +++--- pkgs/pubspec_parse/lib/src/dependency.dart | 21 +++++++------------ pkgs/pubspec_parse/pubspec.yaml | 6 +++--- .../pubspec_parse/test/ensure_build_test.dart | 2 ++ pkgs/pubspec_parse/test/parse_test.dart | 2 -- 8 files changed, 24 insertions(+), 34 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 44a40de01..eac88d582 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 9ed3837aa..7444f4f82 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,4 +1,9 @@ +## 1.2.4-wip + +- Require Dart 3.0 + ## 1.2.3 + - Added topics to `pubspec.yaml`. ## 1.2.2 diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index cf5c91faf..af77edcae 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -1,4 +1,5 @@ -include: package:lints/recommended.yaml +# https://dart.dev/guides/language/analysis-options +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -8,9 +9,7 @@ analyzer: linter: rules: - avoid_bool_literals_in_conditional_expressions - - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_returning_null @@ -21,27 +20,18 @@ linter: - cancel_subscriptions - cascade_invocations - comment_references - - directives_ordering - join_return_with_assignment - - lines_longer_than_80_chars - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - prefer_relative_imports - require_trailing_commas - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis - - unnecessary_statements - use_string_buffers diff --git a/pkgs/pubspec_parse/lib/pubspec_parse.dart b/pkgs/pubspec_parse/lib/pubspec_parse.dart index 7360d1ac9..b5c12e414 100644 --- a/pkgs/pubspec_parse/lib/pubspec_parse.dart +++ b/pkgs/pubspec_parse/lib/pubspec_parse.dart @@ -5,10 +5,10 @@ export 'src/dependency.dart' show Dependency, + GitDependency, HostedDependency, HostedDetails, - GitDependency, - SdkDependency, - PathDependency; + PathDependency, + SdkDependency; export 'src/pubspec.dart' show Pubspec; export 'src/screenshot.dart' show Screenshot; diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index e345dfda8..95bbc8ea7 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -74,19 +74,14 @@ Dependency? _fromJson(Object? data, String name) { final key = matchedKeys.single; - switch (key) { - case 'git': - return GitDependency.fromData(data[key]); - case 'path': - return PathDependency.fromData(data[key]); - case 'sdk': - return _$SdkDependencyFromJson(data); - case 'hosted': - final hosted = _$HostedDependencyFromJson(data); - hosted.hosted?._nameOfPackage = name; - return hosted; - } - throw StateError('There is a bug in pubspec_parse.'); + return switch (key) { + 'git' => GitDependency.fromData(data[key]), + 'path' => PathDependency.fromData(data[key]), + 'sdk' => _$SdkDependencyFromJson(data), + 'hosted' => _$HostedDependencyFromJson(data) + ..hosted?._nameOfPackage = name, + _ => throw StateError('There is a bug in pubspec_parse.'), + }; }); } } diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index a2b189db5..9c3b89a0f 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.2.3 +version: 1.2.4-wip description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. @@ -8,7 +8,7 @@ topics: - dart-pub environment: - sdk: '>=2.18.0 <3.0.0' + sdk: ^3.0.0 dependencies: checked_yaml: ^2.0.1 @@ -20,8 +20,8 @@ dependencies: dev_dependencies: build_runner: ^2.0.3 build_verify: '>=2.0.0 <4.0.0' + dart_flutter_team_lints: ^1.0.0 json_serializable: ^6.6.0 - lints: ^2.0.0 path: ^1.5.1 # Needed because we are configuring `combining_builder` source_gen: ^1.0.0 diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index 612b837e9..689f6fe66 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -5,6 +5,8 @@ @Timeout.factor(2) @TestOn('vm') @Tags(['presubmit-only']) +library; + import 'package:build_verify/build_verify.dart'; import 'package:test/test.dart'; diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index e181ca6d6..f4d6476aa 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -5,8 +5,6 @@ // ignore_for_file: deprecated_member_use_from_same_package // ignore_for_file: lines_longer_than_80_chars -library parse_test; - import 'package:pub_semver/pub_semver.dart'; import 'package:test/test.dart'; From 67ed073cbf7ef5d99011718e328bfc903ce34e14 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 20 Jun 2023 15:13:45 -0700 Subject: [PATCH 0985/1215] Fix a race condition in IsolateChannel.connectReceive() (dart-lang/stream_channel#92) --- pkgs/stream_channel/CHANGELOG.md | 4 +++- pkgs/stream_channel/lib/src/isolate_channel.dart | 14 ++++++++++++-- pkgs/stream_channel/pubspec.yaml | 2 +- pkgs/stream_channel/test/isolate_channel_test.dart | 8 ++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 893218875..c78f64f0e 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,7 +1,9 @@ -## 2.1.2-dev +## 2.1.2 * Require Dart 2.19 * Add an example. +* Fix a race condition in `IsolateChannel.connectReceive()` where the channel + could hang forever if its sink was closed before the connection was established. ## 2.1.1 diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 55c98143f..3fbd46d23 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -43,16 +43,26 @@ class IsolateChannel extends StreamChannelMixin { factory IsolateChannel.connectReceive(ReceivePort receivePort) { // We can't use a [StreamChannelCompleter] here because we need the return // value to be an [IsolateChannel]. + var isCompleted = false; var streamCompleter = StreamCompleter(); var sinkCompleter = StreamSinkCompleter(); - var channel = - IsolateChannel._(streamCompleter.stream, sinkCompleter.sink); + + var channel = IsolateChannel._(streamCompleter.stream, sinkCompleter.sink + .transform(StreamSinkTransformer.fromHandlers(handleDone: (sink) { + if (!isCompleted) { + receivePort.close(); + streamCompleter.setSourceStream(Stream.empty()); + sinkCompleter.setDestinationSink(NullStreamSink()); + } + sink.close(); + }))); // The first message across the ReceivePort should be a SendPort pointing to // the remote end. If it's not, we'll make the stream emit an error // complaining. late StreamSubscription subscription; subscription = receivePort.listen((message) { + isCompleted = true; if (message is SendPort) { var controller = StreamChannelController(allowForeignErrors: false, sync: true); diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 5eb57ae41..0b4f62d4e 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.2-dev +version: 2.1.2 description: >- An abstraction for two-way communication channels based on the Dart Stream class. diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 1850664cf..10f1fe53e 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -162,5 +162,13 @@ void main() { expect(connectedChannel.stream.toList(), throwsStateError); expect(connectedChannel.sink.done, completes); }); + + test('the receiving channel closes gracefully without a connection', + () async { + var connectedChannel = IsolateChannel.connectReceive(connectPort); + await connectedChannel.sink.close(); + await expectLater(connectedChannel.stream.toList(), completion(isEmpty)); + await expectLater(connectedChannel.sink.done, completes); + }); }); } From 453f7649112a99f0f03554d703689c2aecddf2d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 00:51:17 +0000 Subject: [PATCH 0986/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/string_scanner#59) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 2d36a3b10..7e593e5ce 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From d9d40eee4ab6a80ec0cf0d75ba9c323c088aab9a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:04:57 +0000 Subject: [PATCH 0987/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/timing#34) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 752aef4ed..df7953179 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From b2e160bc679c59edf6b8451aa8ca753e6c1ba434 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 01:08:52 +0000 Subject: [PATCH 0988/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/stream_transform#172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 6e238d36f..51e290b1a 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From ce71194d432b609d263a6d30430117800e1392fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 03:07:24 +0000 Subject: [PATCH 0989/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/stream_channel#93) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 0874bdd38..4c8399a81 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 2ee9cf52a1bd35b2f9e8ab91d8a3171bc6641e5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 09:01:10 +0000 Subject: [PATCH 0990/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/watcher#148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index bc16dd1c4..5fce4b21b 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From ce82d252081517eef112364e5d7b850d2367b814 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 11:00:18 +0000 Subject: [PATCH 0991/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/stack_trace#136) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 9ecb00344..529a45978 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From ac94099fa613bf722c125ab70967a8568a038e54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 13:37:24 +0000 Subject: [PATCH 0992/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/term_glyph#40) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 1f8243089..325fac8f3 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 993013a718820446276d18bcb17627774b1f200a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 16:03:23 +0000 Subject: [PATCH 0993/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/test_reflective_loader#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 3b42f4ae5..fade1c9e7 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 3fba72ccfb7d6b01759699d1ef5b3060b930497f Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Sat, 1 Jul 2023 16:24:02 -0700 Subject: [PATCH 0994/1215] update formatting for recent lints (dart-lang/pubspec_parse#108) --- pkgs/pubspec_parse/test/dependency_test.dart | 20 +++++++------- pkgs/pubspec_parse/test/parse_test.dart | 28 ++++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index b366887a3..71b148cb6 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -112,7 +112,7 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v test('map w/ version and hosted as Map', () { final dep = _dependency({ 'version': '^1.0.0', - 'hosted': {'name': 'hosted_name', 'url': 'https://hosted_url'} + 'hosted': {'name': 'hosted_name', 'url': 'https://hosted_url'}, }); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted!.name, 'hosted_name'); @@ -124,7 +124,7 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v final dep = _dependency( { 'version': '^1.0.0', - 'hosted': {'url': 'https://hosted_url'} + 'hosted': {'url': 'https://hosted_url'}, }, skipTryPub: true, // todo: Unskip once pub supports this syntax ); @@ -139,7 +139,7 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v _expectThrows( { 'version': 'not a version', - 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'} + 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, }, r''' line 5, column 15: Unsupported value for "version". Could not parse version "not a version". Unknown text at "not a version". @@ -155,7 +155,7 @@ line 5, column 15: Unsupported value for "version". Could not parse version "not { 'version': '^1.0.0', 'hosted': {'name': 'hosted_name', 'url': 'hosted_url'}, - 'not_supported': null + 'not_supported': null, }, r''' line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git, path, hosted] @@ -286,7 +286,7 @@ line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hos test('map', () { final dep = _dependency({ - 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'} + 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'}, }); expect(dep.url.toString(), 'url'); expect(dep.path, 'path'); @@ -332,7 +332,7 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. test('git - null url', () { _expectThrowsContaining( { - 'git': {'url': null} + 'git': {'url': null}, }, r"type 'Null' is not a subtype of type 'String'", ); @@ -341,7 +341,7 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. test('git - int url', () { _expectThrowsContaining( { - 'git': {'url': 42} + 'git': {'url': 42}, }, r"type 'int' is not a subtype of type 'String'", ); @@ -407,7 +407,7 @@ void _expectThrows(Object content, String expectedError) { expectParseThrows( { 'name': 'sample', - 'dependencies': {'dep': content} + 'dependencies': {'dep': content}, }, expectedError, ); @@ -417,7 +417,7 @@ void _expectThrowsContaining(Object content, String errorText) { expectParseThrowsContaining( { 'name': 'sample', - 'dependencies': {'dep': content} + 'dependencies': {'dep': content}, }, errorText, ); @@ -430,7 +430,7 @@ T _dependency( final value = parse( { ...defaultPubspec, - 'dependencies': {'dep': content} + 'dependencies': {'dep': content}, }, skipTryPub: skipTryPub, ); diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index f4d6476aa..99199c7b4 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -53,7 +53,7 @@ void main() { ], 'topics': ['widget', 'button'], 'screenshots': [ - {'description': 'my screenshot', 'path': 'path/to/screenshot'} + {'description': 'my screenshot', 'path': 'path/to/screenshot'}, ], }); expect(value.name, 'sample'); @@ -91,7 +91,7 @@ void main() { 'environment': { 'sdk': '>=2.12.0 <3.0.0', 'bob': null, - } + }, }, skipTryPub: true, ); @@ -135,7 +135,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https null: null, 'http': 'http://example.com', 'https': 'https://example.com', - 'none': 'none' + 'none': 'none', }.entries) { test('can be ${entry.key}', () { final value = parse({ @@ -160,7 +160,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('one author, via authors', () { final value = parse({ ...defaultPubspec, - 'authors': ['name@example.com'] + 'authors': ['name@example.com'], }); expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); @@ -169,7 +169,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https test('many authors', () { final value = parse({ ...defaultPubspec, - 'authors': ['name@example.com', 'name2@example.com'] + 'authors': ['name@example.com', 'name2@example.com'], }); expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); @@ -179,7 +179,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https final value = parse({ ...defaultPubspec, 'author': 'name@example.com', - 'authors': ['name2@example.com'] + 'authors': ['name2@example.com'], }); expect(value.author, isNull); expect(value.authors, ['name@example.com', 'name2@example.com']); @@ -189,7 +189,7 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https final value = parse({ ...defaultPubspec, 'author': 'name@example.com', - 'authors': ['name@example.com', 'name@example.com'] + 'authors': ['name@example.com', 'name@example.com'], }); expect(value.author, 'name@example.com'); expect(value.authors, ['name@example.com']); @@ -269,7 +269,7 @@ line 2, column 10: Unsupported value for "name". "name" cannot be empty. expectParseThrows( { 'name': 'sample', - 'environment': {'dart': 'cool'} + 'environment': {'dart': 'cool'}, }, r''' line 4, column 3: Use "sdk" to for Dart SDK constraints. @@ -284,7 +284,7 @@ line 4, column 3: Use "sdk" to for Dart SDK constraints. expectParseThrows( { 'name': 'sample', - 'environment': {'sdk': 42} + 'environment': {'sdk': 42}, }, r''' line 4, column 10: Unsupported value for "sdk". `42` is not a String. @@ -313,7 +313,7 @@ line 3, column 13: Unsupported value for "version". Could not parse "invalid". expectParseThrows( { 'name': 'sample', - 'environment': {'sdk': 'silly'} + 'environment': {'sdk': 'silly'}, }, r''' line 4, column 10: Unsupported value for "sdk". Could not parse version "silly". Unknown text at "silly". @@ -430,7 +430,7 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at final value = parse({ ...defaultPubspec, 'screenshots': [ - {'description': 'my screenshot', 'path': 'path/to/screenshot'} + {'description': 'my screenshot', 'path': 'path/to/screenshot'}, ], }); expect(value.screenshots, hasLength(1)); @@ -445,7 +445,7 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at {'description': 'my screenshot', 'path': 'path/to/screenshot'}, { 'description': 'my second screenshot', - 'path': 'path/to/screenshot2' + 'path': 'path/to/screenshot2', }, ], }); @@ -464,7 +464,7 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at { 'description': 'my screenshot', 'path': 'path/to/screenshot', - 'extraKey': 'not important' + 'extraKey': 'not important', }, 'not a screenshot', ], @@ -659,7 +659,7 @@ line 1, column 1: Not a map 'name': 'sample', 'dependencies': { 'foo': { - 'git': {'url': 1} + 'git': {'url': 1}, }, }, 'issue_tracker': {'x': 'y'}, From 6c28bdfd1e86a327cc878935b74fd28fa7b5a16c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 23:31:55 +0000 Subject: [PATCH 0995/1215] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/pubspec_parse#107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3.
Release notes

Sourced from actions/checkout's releases.

v3.5.3

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v3.5.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

v2.3.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index eac88d582..0f9e7fa73 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From d4f0591e5133a6ef0555e0991d5a3745057f7001 Mon Sep 17 00:00:00 2001 From: Slava Egorov Date: Tue, 4 Jul 2023 11:22:44 +0200 Subject: [PATCH 0996/1215] Use awaiter-link pragma to guide VM's builtin awaiter stack unwinding (dart-lang/stack_trace#135) --- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 8408d0490..7309ce0ea 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -117,7 +117,10 @@ class StackZoneSpecification { /// Tracks the current stack chain so it can be set to [_currentNode] when /// [f] is run. ZoneUnaryCallback _registerUnaryCallback( - Zone self, ZoneDelegate parent, Zone zone, R Function(T) f) { + Zone self, + ZoneDelegate parent, + Zone zone, + @pragma('vm:awaiter-link') R Function(T) f) { if (_disabled) return parent.registerUnaryCallback(zone, f); var node = _createNode(1); return parent.registerUnaryCallback( From 8a9dc7b0a396bd77ad00a4935792868d14dc99a5 Mon Sep 17 00:00:00 2001 From: Slava Egorov Date: Wed, 5 Jul 2023 10:22:26 +0200 Subject: [PATCH 0997/1215] Prepare 1.11.1 release (dart-lang/stack_trace#137) --- pkgs/stack_trace/CHANGELOG.md | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 43a0f376c..063cc49b2 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,8 @@ +## 1.11.1 + +* Make use of `@pragma('vm:awaiter-link')` to make package work better with + Dart VM's builtin awaiter stack unwinding. No other changes. + ## 1.11.0 * Added the parameter `zoneValues` to `Chain.capture` to be able to use custom diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 78c27d0ba..93fd3e591 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.11.0 +version: 1.11.1 description: A package for manipulating stack traces and printing them readably. repository: https://github.com/dart-lang/stack_trace From d88e5fd574205ced2ca094fc51a472ea180c2a58 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Jul 2023 09:30:20 -0700 Subject: [PATCH 0998/1215] blast_repo fixes (dart-lang/string_scanner#60) auto-publish --- .../.github/workflows/publish.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 pkgs/string_scanner/.github/workflows/publish.yaml diff --git a/pkgs/string_scanner/.github/workflows/publish.yaml b/pkgs/string_scanner/.github/workflows/publish.yaml new file mode 100644 index 000000000..27157a046 --- /dev/null +++ b/pkgs/string_scanner/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From c3f751308b7e035c9d1359b9454b91bee2ec5fe5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 18 Jul 2023 09:30:33 -0700 Subject: [PATCH 0999/1215] Require Dart 3, update lints (dart-lang/string_scanner#61) --- .../.github/workflows/test-package.yml | 2 +- pkgs/string_scanner/CHANGELOG.md | 4 +++- pkgs/string_scanner/analysis_options.yaml | 18 +----------------- pkgs/string_scanner/lib/string_scanner.dart | 2 ++ pkgs/string_scanner/pubspec.yaml | 6 +++--- 5 files changed, 10 insertions(+), 22 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 7e593e5ce..7ad5f74e0 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.0.0, dev] steps: - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 57b31ba8a..fa7af43f3 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,4 +1,6 @@ -## 1.2.1-dev +## 1.2.1-wip + +* Require Dart 3.0.0 ## 1.2.0 diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index b507c06db..0b975913d 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -1,5 +1,5 @@ # https://dart.dev/guides/language/analysis-options -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -9,11 +9,8 @@ analyzer: linter: rules: - - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - - avoid_catching_errors - avoid_classes_with_only_static_members - - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_returning_null_for_future @@ -22,33 +19,20 @@ linter: - avoid_void_async - cancel_subscriptions - comment_references - - directives_ordering - join_return_with_assignment - - 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 - - only_throw_errors - package_api_docs - - prefer_asserts_in_initializer_lists - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unawaited_futures - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis - unnecessary_raw_strings - - unnecessary_statements - use_if_null_to_convert_nulls_to_bools - use_raw_strings - use_string_buffers diff --git a/pkgs/string_scanner/lib/string_scanner.dart b/pkgs/string_scanner/lib/string_scanner.dart index 7f36eef83..e641ae706 100644 --- a/pkgs/string_scanner/lib/string_scanner.dart +++ b/pkgs/string_scanner/lib/string_scanner.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. /// A library for parsing strings using a sequence of patterns. +library; + export 'src/exception.dart'; export 'src/line_scanner.dart'; export 'src/span_scanner.dart'; diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index b297e50d2..40682ecb1 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,14 +1,14 @@ name: string_scanner -version: 1.2.1-dev +version: 1.2.1-wip description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner environment: - sdk: ">=2.18.0 <3.0.0" + sdk: ^3.0.0 dependencies: source_span: ^1.8.0 dev_dependencies: - lints: ^2.0.0 + dart_flutter_team_lints: ^1.0.0 test: ^1.16.0 From e18bdfba0deb28ee344a443e2ddd4b2a7409dd1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 00:39:56 +0000 Subject: [PATCH 1000/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/string_scanner#62) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 7ad5f74e0..24d44c9ac 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 8406831004006cf1285e8b6b3c0ca06e3979d51a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 01:27:05 +0000 Subject: [PATCH 1001/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/stream_transform#173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 51e290b1a..4bd873a22 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From f9ba3b25897f3a1244d4333ae36e7179c8b6096f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 01:47:19 +0000 Subject: [PATCH 1002/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/timing#35) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index df7953179..be7104968 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From e98c5bac7d7af172aa40f7ddf745171af7c4bcb9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 03:51:18 +0000 Subject: [PATCH 1003/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/stream_channel#94) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 4c8399a81..8b1f4d4fb 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 8a100758911707fe1bd667d467508df1d0c28d8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 05:23:22 +0000 Subject: [PATCH 1004/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/pubspec_parse#110) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 0f9e7fa73..bcc9e7139 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 4d48b99af6a0f01414d66fc268837dc07605dfc7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:26:53 +0000 Subject: [PATCH 1005/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/watcher#149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 5fce4b21b..6986f9c90 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From bffd3fa6f17a7630dcf5db357f4edf95f7430f5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:49:11 +0000 Subject: [PATCH 1006/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/stack_trace#140) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 529a45978..b3bab1293 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 8e8317dbadc16ae8c4a80106e5c4f6f3d871ff65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 13:06:36 +0000 Subject: [PATCH 1007/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/term_glyph#41) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 325fac8f3..6e4f6ec13 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From c61ef50399960e92ac4adb131e8c02da7f71f88a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 16:59:57 +0000 Subject: [PATCH 1008/1215] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/test_reflective_loader#51) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0.
Release notes

Sourced from actions/checkout's releases.

v3.6.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3.5.3...v3.6.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

v3.0.1

v3.0.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index fade1c9e7..66f1f151c 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 3583f10a7ce26a7f1d3041733b450d2f1f011017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 00:06:20 +0000 Subject: [PATCH 1009/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/string_scanner#63) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 24d44c9ac..b187c4637 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 5299abb364aabcc2d2ff43da230d5ecd7b4a92d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:16:02 +0000 Subject: [PATCH 1010/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/timing#37) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/timing#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/timing#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index be7104968..3512f3fc2 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 0415b4bca01fe3d8a24f9ac2f0a25402159b789d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 01:41:04 +0000 Subject: [PATCH 1011/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/stream_transform#174) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 4bd873a22..b4bd77d9f 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From d00914acc59a8f42fae5d211b06a610b9abce0c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 03:27:12 +0000 Subject: [PATCH 1012/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/stream_channel#95) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 8b1f4d4fb..282ba5006 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From f5dcb04d5814f9c407c268786efb34913a3b49e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:02:19 +0000 Subject: [PATCH 1013/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/watcher#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 6986f9c90..26f5da2b0 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 51424e392b8441771e0e227487eed9281fbb7e2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:14:19 +0000 Subject: [PATCH 1014/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/stack_trace#143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index b3bab1293..48004ed2c 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 81b1b45414c7952e9ecb739147d4b716bd3f7ead Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 13:03:48 +0000 Subject: [PATCH 1015/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/term_glyph#42) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/term_glyph#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/term_glyph#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 6e4f6ec13..f476e3586 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 4ead479e559b4d964eea68e2622fcd2fe8243ca8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:10:05 +0000 Subject: [PATCH 1016/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/test_reflective_loader#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0.
Release notes

Sourced from actions/checkout's releases.

v4.1.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.0.0...v4.1.0

v4.0.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v3...v4.0.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

v3.1.0

v3.0.2

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 66f1f151c..06dd7db12 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 80518b93542e073cdeb145b88de5dd2a420615e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 06:59:35 -0700 Subject: [PATCH 1017/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/timing#36) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 3512f3fc2..ac2781347 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 2da9f6f0fdb86f9e0f310a4ee4454e605d88421d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:39:47 +0000 Subject: [PATCH 1018/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/test_reflective_loader#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 06dd7db12..0d4b52099 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From bf593770c8402dcdd27b3cb5fdba8b5eff7be6b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 20:58:21 -0700 Subject: [PATCH 1019/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/term_glyph#43) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index f476e3586..8f5c3b290 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 6d31d409827275ab3eb171a4cf731f738f0c69b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:12:23 -0700 Subject: [PATCH 1020/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/stack_trace#142) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 48004ed2c..10cf89297 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From bffc449c5616ea088ff3df0f79b73d53de0b0b83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:12:29 -0700 Subject: [PATCH 1021/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/watcher#152) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 26f5da2b0..6f33e07c9 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From de516dcb3999a6982670d254334b39b1e7af6589 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:14:58 -0700 Subject: [PATCH 1022/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/stream_channel#96) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 282ba5006..367d5dea3 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From bb460696aee4d97bbb7f365d752fba1ace58c6ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:15:26 -0700 Subject: [PATCH 1023/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/stream_transform#175) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index b4bd77d9f..e8d34cf2a 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From de978a54ab0ba6dfe3bd296d0980d98c299208c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:15:40 -0700 Subject: [PATCH 1024/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/string_scanner#64) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index b187c4637..657b236db 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From d96d7cec8117858c7e024a426f4ab4d559852b67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:08:29 -0700 Subject: [PATCH 1025/1215] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/pubspec_parse#111) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index bcc9e7139..db9e1e5e6 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 83007bec00a641ec7f2902b9b5348cb444f25d6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:41:20 -0700 Subject: [PATCH 1026/1215] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/pubspec_parse#112) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index db9e1e5e6..ee3178486 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From b4b92a4eefe7c2dbd4f96723dec73f9815d0e9d3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 3 Oct 2023 13:32:31 -0700 Subject: [PATCH 1027/1215] Drop usage of waitFor (dart-lang/pubspec_parse#114) --- pkgs/pubspec_parse/test/dependency_test.dart | 78 ++++++++++---------- pkgs/pubspec_parse/test/parse_test.dart | 76 +++++++++---------- pkgs/pubspec_parse/test/test_utils.dart | 8 +- 3 files changed, 81 insertions(+), 81 deletions(-) diff --git a/pkgs/pubspec_parse/test/dependency_test.dart b/pkgs/pubspec_parse/test/dependency_test.dart index 71b148cb6..f1e4f5776 100644 --- a/pkgs/pubspec_parse/test/dependency_test.dart +++ b/pkgs/pubspec_parse/test/dependency_test.dart @@ -70,21 +70,21 @@ line 5, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hos } void _hostedDependency() { - test('null', () { - final dep = _dependency(null); + test('null', () async { + final dep = await _dependency(null); expect(dep.version.toString(), 'any'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); - test('empty map', () { - final dep = _dependency({}); + test('empty map', () async { + final dep = await _dependency({}); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); }); - test('string version', () { - final dep = _dependency('^1.0.0'); + test('string version', () async { + final dep = await _dependency('^1.0.0'); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); @@ -102,15 +102,15 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v ); }); - test('map w/ just version', () { - final dep = _dependency({'version': '^1.0.0'}); + test('map w/ just version', () async { + final dep = await _dependency({'version': '^1.0.0'}); expect(dep.version.toString(), '^1.0.0'); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); - test('map w/ version and hosted as Map', () { - final dep = _dependency({ + test('map w/ version and hosted as Map', () async { + final dep = await _dependency({ 'version': '^1.0.0', 'hosted': {'name': 'hosted_name', 'url': 'https://hosted_url'}, }); @@ -120,8 +120,8 @@ line 4, column 10: Unsupported value for "dep". Could not parse version "not a v expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); - test('map /w hosted as a map without name', () { - final dep = _dependency( + test('map /w hosted as a map without name', () async { + final dep = await _dependency( { 'version': '^1.0.0', 'hosted': {'url': 'https://hosted_url'}, @@ -166,8 +166,8 @@ line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git ); }); - test('map w/ version and hosted as String', () { - final dep = _dependency( + test('map w/ version and hosted as String', () async { + final dep = await _dependency( {'version': '^1.0.0', 'hosted': 'hosted_url'}, skipTryPub: true, // todo: Unskip once put supports this ); @@ -178,8 +178,8 @@ line 10, column 4: Unrecognized keys: [not_supported]; supported keys: [sdk, git expect(dep.toString(), 'HostedDependency: ^1.0.0'); }); - test('map w/ hosted as String', () { - final dep = _dependency({'hosted': 'hosted_url'}); + test('map w/ hosted as String', () async { + final dep = await _dependency({'hosted': 'hosted_url'}); expect(dep.version, VersionConstraint.any); expect(dep.hosted!.declaredName, isNull); expect(dep.hosted!.name, 'dep'); @@ -199,8 +199,8 @@ line 5, column 4: These keys had `null` values, which is not allowed: [hosted] ); }); - test('map w/ null version is fine', () { - final dep = _dependency({'version': null}); + test('map w/ null version is fine', () async { + final dep = await _dependency({'version': null}); expect(dep.version, VersionConstraint.any); expect(dep.hosted, isNull); expect(dep.toString(), 'HostedDependency: any'); @@ -208,15 +208,15 @@ line 5, column 4: These keys had `null` values, which is not allowed: [hosted] } void _sdkDependency() { - test('without version', () { - final dep = _dependency({'sdk': 'flutter'}); + test('without version', () async { + final dep = await _dependency({'sdk': 'flutter'}); expect(dep.sdk, 'flutter'); expect(dep.version, VersionConstraint.any); expect(dep.toString(), 'SdkDependency: flutter'); }); - test('with version', () { - final dep = _dependency( + test('with version', () async { + final dep = await _dependency( {'sdk': 'flutter', 'version': '>=1.2.3 <2.0.0'}, ); expect(dep.sdk, 'flutter'); @@ -240,29 +240,30 @@ void _sdkDependency() { } void _gitDependency() { - test('string', () { - final dep = _dependency({'git': 'url'}); + test('string', () async { + final dep = await _dependency({'git': 'url'}); expect(dep.url.toString(), 'url'); expect(dep.path, isNull); expect(dep.ref, isNull); expect(dep.toString(), 'GitDependency: url@url'); }); - test('string with version key is ignored', () { + test('string with version key is ignored', () async { // Regression test for https://github.com/dart-lang/pubspec_parse/issues/13 - final dep = _dependency({'git': 'url', 'version': '^1.2.3'}); + final dep = + await _dependency({'git': 'url', 'version': '^1.2.3'}); expect(dep.url.toString(), 'url'); expect(dep.path, isNull); expect(dep.ref, isNull); expect(dep.toString(), 'GitDependency: url@url'); }); - test('string with user@ URL', () { + test('string with user@ URL', () async { final skipTryParse = Platform.environment.containsKey('TRAVIS'); if (skipTryParse) { print('FYI: not validating git@ URI on travis due to failure'); } - final dep = _dependency( + final dep = await _dependency( {'git': 'git@localhost:dep.git'}, skipTryPub: skipTryParse, ); @@ -284,8 +285,8 @@ line 6, column 4: Unrecognized keys: [bob]; supported keys: [sdk, git, path, hos ); }); - test('map', () { - final dep = _dependency({ + test('map', () async { + final dep = await _dependency({ 'git': {'url': 'url', 'path': 'path', 'ref': 'ref'}, }); expect(dep.url.toString(), 'url'); @@ -349,15 +350,16 @@ line 5, column 11: Unsupported value for "git". Must be a String or a Map. } void _pathDependency() { - test('valid', () { - final dep = _dependency({'path': '../path'}); + test('valid', () async { + final dep = await _dependency({'path': '../path'}); expect(dep.path, '../path'); expect(dep.toString(), 'PathDependency: path@../path'); }); - test('valid with version key is ignored', () { - final dep = - _dependency({'path': '../path', 'version': '^1.2.3'}); + test('valid with version key is ignored', () async { + final dep = await _dependency( + {'path': '../path', 'version': '^1.2.3'}, + ); expect(dep.path, '../path'); expect(dep.toString(), 'PathDependency: path@../path'); }); @@ -423,11 +425,11 @@ void _expectThrowsContaining(Object content, String errorText) { ); } -T _dependency( +Future _dependency( Object? content, { bool skipTryPub = false, -}) { - final value = parse( +}) async { + final value = await parse( { ...defaultPubspec, 'dependencies': {'dep': content}, diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 99199c7b4..31042f1cb 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -11,8 +11,8 @@ import 'package:test/test.dart'; import 'test_utils.dart'; void main() { - test('minimal set values', () { - final value = parse(defaultPubspec); + test('minimal set values', () async { + final value = await parse(defaultPubspec); expect(value.name, 'sample'); expect(value.version, isNull); expect(value.publishTo, isNull); @@ -34,10 +34,10 @@ void main() { expect(value.screenshots, isEmpty); }); - test('all fields set', () { + test('all fields set', () async { final version = Version.parse('1.2.3'); final sdkConstraint = VersionConstraint.parse('>=2.12.0 <3.0.0'); - final value = parse({ + final value = await parse({ 'name': 'sample', 'version': version.toString(), 'publish_to': 'none', @@ -84,8 +84,8 @@ void main() { expect(value.screenshots!.first.path, 'path/to/screenshot'); }); - test('environment values can be null', () { - final value = parse( + test('environment values can be null', () async { + final value = await parse( { 'name': 'sample', 'environment': { @@ -137,8 +137,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https 'https': 'https://example.com', 'none': 'none', }.entries) { - test('can be ${entry.key}', () { - final value = parse({ + test('can be ${entry.key}', () async { + final value = await parse({ ...defaultPubspec, 'publish_to': entry.value, }); @@ -148,8 +148,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https }); group('author, authors', () { - test('one author', () { - final value = parse({ + test('one author', () async { + final value = await parse({ ...defaultPubspec, 'author': 'name@example.com', }); @@ -157,8 +157,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https expect(value.authors, ['name@example.com']); }); - test('one author, via authors', () { - final value = parse({ + test('one author, via authors', () async { + final value = await parse({ ...defaultPubspec, 'authors': ['name@example.com'], }); @@ -166,8 +166,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https expect(value.authors, ['name@example.com']); }); - test('many authors', () { - final value = parse({ + test('many authors', () async { + final value = await parse({ ...defaultPubspec, 'authors': ['name@example.com', 'name2@example.com'], }); @@ -175,8 +175,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https expect(value.authors, ['name@example.com', 'name2@example.com']); }); - test('author and authors', () { - final value = parse({ + test('author and authors', () async { + final value = await parse({ ...defaultPubspec, 'author': 'name@example.com', 'authors': ['name2@example.com'], @@ -185,8 +185,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https expect(value.authors, ['name@example.com', 'name2@example.com']); }); - test('duplicate author values', () { - final value = parse({ + test('duplicate author values', () async { + final value = await parse({ ...defaultPubspec, 'author': 'name@example.com', 'authors': ['name@example.com', 'name@example.com'], @@ -195,8 +195,8 @@ line 3, column 16: Unsupported value for "publish_to". Must be an http or https expect(value.authors, ['name@example.com']); }); - test('flutter', () { - final value = parse({ + test('flutter', () async { + final value = await parse({ ...defaultPubspec, 'flutter': {'key': 'value'}, }); @@ -411,8 +411,8 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at ); }); - test('invalid data - lenient', () { - final value = parse( + test('invalid data - lenient', () async { + final value = await parse( { ...defaultPubspec, 'topics': [1], @@ -426,8 +426,8 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at }); group('screenshots', () { - test('one screenshot', () { - final value = parse({ + test('one screenshot', () async { + final value = await parse({ ...defaultPubspec, 'screenshots': [ {'description': 'my screenshot', 'path': 'path/to/screenshot'}, @@ -438,8 +438,8 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at expect(value.screenshots!.first.path, 'path/to/screenshot'); }); - test('many screenshots', () { - final value = parse({ + test('many screenshots', () async { + final value = await parse({ ...defaultPubspec, 'screenshots': [ {'description': 'my screenshot', 'path': 'path/to/screenshot'}, @@ -456,8 +456,8 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at expect(value.screenshots!.last.path, 'path/to/screenshot2'); }); - test('one screenshot plus invalid entries', () { - final value = parse({ + test('one screenshot plus invalid entries', () async { + final value = await parse({ ...defaultPubspec, 'screenshots': [ 42, @@ -474,8 +474,8 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at expect(value.screenshots!.first.path, 'path/to/screenshot'); }); - test('invalid entries', () { - final value = parse({ + test('invalid entries', () async { + final value = await parse({ ...defaultPubspec, 'screenshots': [ 42, @@ -566,8 +566,8 @@ line 9, column 12: Unsupported value for "path". `42` is not a String ); }); - test('invalid screenshot - lenient', () { - final value = parse( + test('invalid screenshot - lenient', () async { + final value = await parse( { ...defaultPubspec, 'screenshots': 'Invalid value', @@ -614,8 +614,8 @@ line 1, column 1: Not a map ); }); - test('bad repository url', () { - final value = parse( + test('bad repository url', () async { + final value = await parse( { ...defaultPubspec, 'repository': {'x': 'y'}, @@ -626,8 +626,8 @@ line 1, column 1: Not a map expect(value.repository, isNull); }); - test('bad issue_tracker url', () { - final value = parse( + test('bad issue_tracker url', () async { + final value = await parse( { ...defaultPubspec, 'issue_tracker': {'x': 'y'}, @@ -638,8 +638,8 @@ line 1, column 1: Not a map expect(value.issueTracker, isNull); }); - test('multiple bad values', () { - final value = parse( + test('multiple bad values', () async { + final value = await parse( { ...defaultPubspec, 'repository': {'x': 'y'}, diff --git a/pkgs/pubspec_parse/test/test_utils.dart b/pkgs/pubspec_parse/test/test_utils.dart index b573851ad..cc46522b7 100644 --- a/pkgs/pubspec_parse/test/test_utils.dart +++ b/pkgs/pubspec_parse/test/test_utils.dart @@ -2,8 +2,6 @@ // 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. -// ignore: deprecated_member_use -import 'dart:cli'; import 'dart:convert'; import 'package:checked_yaml/checked_yaml.dart'; @@ -61,18 +59,18 @@ void _printDebugParsedYamlException(ParsedYamlException e) { } } -Pubspec parse( +Future parse( Object? content, { bool quietOnError = false, bool skipTryPub = false, bool lenient = false, -}) { +}) async { final encoded = _encodeJson(content); ProcResult? pubResult; if (!skipTryPub) { // ignore: deprecated_member_use - pubResult = waitFor(tryPub(encoded)); + pubResult = await tryPub(encoded); expect(pubResult, isNotNull); } From 059282e85f74857c5cb893bfaaf57c8a28d15364 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 3 Oct 2023 17:29:49 -0700 Subject: [PATCH 1028/1215] Update lints (dart-lang/pubspec_parse#113) --- pkgs/pubspec_parse/analysis_options.yaml | 4 ---- pkgs/pubspec_parse/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index af77edcae..7da0e8962 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -19,19 +19,15 @@ linter: - avoid_void_async - cancel_subscriptions - cascade_invocations - - comment_references - join_return_with_assignment - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_relative_imports - require_trailing_commas - - test_types_in_equals - unnecessary_await_in_return - use_string_buffers diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 9c3b89a0f..4f8eabc9a 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: dev_dependencies: build_runner: ^2.0.3 build_verify: '>=2.0.0 <4.0.0' - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 json_serializable: ^6.6.0 path: ^1.5.1 # Needed because we are configuring `combining_builder` From 1ef1d1ce7900727c9b887b11abfb5d8ee72a39cc Mon Sep 17 00:00:00 2001 From: Parker Lougheed Date: Thu, 19 Oct 2023 10:53:57 -0500 Subject: [PATCH 1029/1215] Migrate to dart_flutter_team_lints v2.1 (dart-lang/watcher#153) - Fix new lints. - Deduplicate lints in local config. - Add some missing generic types on futures and stream controllers. - Fix a typo in a test. - Remove unnecessary library names. --- pkgs/watcher/CHANGELOG.md | 2 ++ pkgs/watcher/analysis_options.yaml | 9 --------- pkgs/watcher/benchmark/path_set.dart | 2 +- pkgs/watcher/example/watch.dart | 2 +- pkgs/watcher/lib/src/directory_watcher/linux.dart | 6 +++--- .../watcher/lib/src/directory_watcher/mac_os.dart | 15 ++++++++------- .../lib/src/directory_watcher/polling.dart | 4 ++-- .../lib/src/directory_watcher/windows.dart | 4 ++-- pkgs/watcher/lib/src/file_watcher/native.dart | 6 +++--- pkgs/watcher/lib/src/file_watcher/polling.dart | 8 ++++---- pkgs/watcher/lib/src/resubscribable.dart | 2 +- pkgs/watcher/pubspec.yaml | 4 ++-- .../test/directory_watcher/linux_test.dart | 2 +- .../test/directory_watcher/mac_os_test.dart | 2 +- .../test/directory_watcher/polling_test.dart | 4 ++-- pkgs/watcher/test/directory_watcher/shared.dart | 4 ++-- .../test/directory_watcher/windows_test.dart | 2 +- pkgs/watcher/test/file_watcher/polling_test.dart | 2 +- pkgs/watcher/test/file_watcher/shared.dart | 2 +- pkgs/watcher/test/ready/shared.dart | 4 ++-- pkgs/watcher/test/utils.dart | 2 +- 21 files changed, 41 insertions(+), 47 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index b7641e661..7743fc7a3 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,3 +1,5 @@ +## 1.1.1-wip + ## 1.1.0 - Require Dart SDK >= 3.0.0 diff --git a/pkgs/watcher/analysis_options.yaml b/pkgs/watcher/analysis_options.yaml index a1fc20f55..d978f811c 100644 --- a/pkgs/watcher/analysis_options.yaml +++ b/pkgs/watcher/analysis_options.yaml @@ -1,10 +1 @@ include: package:dart_flutter_team_lints/analysis_options.yaml - -analyzer: - language: - strict-casts: true - -linter: - rules: - - comment_references # https://github.com/dart-lang/sdk/issues/39467 - diff --git a/pkgs/watcher/benchmark/path_set.dart b/pkgs/watcher/benchmark/path_set.dart index 82109b0ab..e7929d8ec 100644 --- a/pkgs/watcher/benchmark/path_set.dart +++ b/pkgs/watcher/benchmark/path_set.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Benchmarks for the PathSet class. -library watcher.benchmark.path_set; +library; import 'dart:io'; import 'dart:math' as math; diff --git a/pkgs/watcher/example/watch.dart b/pkgs/watcher/example/watch.dart index 0a0b3577a..37931d396 100644 --- a/pkgs/watcher/example/watch.dart +++ b/pkgs/watcher/example/watch.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Watches the given directory and prints each modification to it. -library watch; +library; import 'package:path/path.dart' as p; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/lib/src/directory_watcher/linux.dart b/pkgs/watcher/lib/src/directory_watcher/linux.dart index dafaeb19a..cb1d07781 100644 --- a/pkgs/watcher/lib/src/directory_watcher/linux.dart +++ b/pkgs/watcher/lib/src/directory_watcher/linux.dart @@ -47,8 +47,8 @@ class _LinuxDirectoryWatcher bool get isReady => _readyCompleter.isCompleted; @override - Future get ready => _readyCompleter.future; - final _readyCompleter = Completer(); + Future get ready => _readyCompleter.future; + final _readyCompleter = Completer(); /// A stream group for the [Directory.watch] events of [path] and all its /// subdirectories. @@ -284,7 +284,7 @@ class _LinuxDirectoryWatcher {Function? onError, void Function()? onDone, bool cancelOnError = false}) { - late StreamSubscription subscription; + late StreamSubscription subscription; subscription = stream.listen(onData, onError: onError, onDone: () { _subscriptions.remove(subscription); onDone?.call(); diff --git a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart index d2db97524..b46138347 100644 --- a/pkgs/watcher/lib/src/directory_watcher/mac_os.dart +++ b/pkgs/watcher/lib/src/directory_watcher/mac_os.dart @@ -47,8 +47,8 @@ class _MacOSDirectoryWatcher bool get isReady => _readyCompleter.isCompleted; @override - Future get ready => _readyCompleter.future; - final _readyCompleter = Completer(); + Future get ready => _readyCompleter.future; + final _readyCompleter = Completer(); /// The set of files that are known to exist recursively within the watched /// directory. @@ -367,12 +367,12 @@ class _MacOSDirectoryWatcher /// Starts or restarts listing the watched directory to get an initial picture /// of its state. - Future _listDir() { + Future _listDir() { assert(!isReady); _initialListSubscription?.cancel(); _files.clear(); - var completer = Completer(); + var completer = Completer(); var stream = Directory(path).list(recursive: true); _initialListSubscription = stream.listen((entity) { if (entity is! Directory) _files.add(entity.path); @@ -385,9 +385,10 @@ class _MacOSDirectoryWatcher /// 200ms is short in terms of human interaction, but longer than any Mac OS /// watcher tests take on the bots, so it should be safe to assume that any /// bogus events will be signaled in that time frame. - Future _waitForBogusEvents() { - var completer = Completer(); - _bogusEventTimer = Timer(Duration(milliseconds: 200), completer.complete); + Future _waitForBogusEvents() { + var completer = Completer(); + _bogusEventTimer = + Timer(const Duration(milliseconds: 200), completer.complete); return completer.future; } diff --git a/pkgs/watcher/lib/src/directory_watcher/polling.dart b/pkgs/watcher/lib/src/directory_watcher/polling.dart index 3dcec05a3..207679b1a 100644 --- a/pkgs/watcher/lib/src/directory_watcher/polling.dart +++ b/pkgs/watcher/lib/src/directory_watcher/polling.dart @@ -27,7 +27,7 @@ class PollingDirectoryWatcher extends ResubscribableWatcher PollingDirectoryWatcher(String directory, {Duration? pollingDelay}) : super(directory, () { return _PollingDirectoryWatcher( - directory, pollingDelay ?? Duration(seconds: 1)); + directory, pollingDelay ?? const Duration(seconds: 1)); }); } @@ -184,7 +184,7 @@ class _PollingDirectoryWatcher if (!isReady) _readyCompleter.complete(); // Wait and then poll again. - await Future.delayed(_pollingDelay); + await Future.delayed(_pollingDelay); if (_events.isClosed) return; _poll(); } diff --git a/pkgs/watcher/lib/src/directory_watcher/windows.dart b/pkgs/watcher/lib/src/directory_watcher/windows.dart index aff7a748a..d1c98be1f 100644 --- a/pkgs/watcher/lib/src/directory_watcher/windows.dart +++ b/pkgs/watcher/lib/src/directory_watcher/windows.dart @@ -56,7 +56,7 @@ class _WindowsDirectoryWatcher @override Future get ready => _readyCompleter.future; - final _readyCompleter = Completer(); + final _readyCompleter = Completer(); final Map _eventBatchers = HashMap(); @@ -407,7 +407,7 @@ class _WindowsDirectoryWatcher _initialListSubscription?.cancel(); _files.clear(); - var completer = Completer(); + var completer = Completer(); var stream = Directory(path).list(recursive: true); void handleEntity(FileSystemEntity entity) { if (entity is! Directory) _files.add(entity.path); diff --git a/pkgs/watcher/lib/src/file_watcher/native.dart b/pkgs/watcher/lib/src/file_watcher/native.dart index 48f12e672..502aa1095 100644 --- a/pkgs/watcher/lib/src/file_watcher/native.dart +++ b/pkgs/watcher/lib/src/file_watcher/native.dart @@ -30,10 +30,10 @@ class _NativeFileWatcher implements FileWatcher, ManuallyClosedWatcher { bool get isReady => _readyCompleter.isCompleted; @override - Future get ready => _readyCompleter.future; - final _readyCompleter = Completer(); + Future get ready => _readyCompleter.future; + final _readyCompleter = Completer(); - StreamSubscription? _subscription; + StreamSubscription>? _subscription; _NativeFileWatcher(this.path) { _listen(); diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index d0b219f36..6f1eee4fd 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -15,7 +15,7 @@ class PollingFileWatcher extends ResubscribableWatcher implements FileWatcher { PollingFileWatcher(String path, {Duration? pollingDelay}) : super(path, () { return _PollingFileWatcher( - path, pollingDelay ?? Duration(seconds: 1)); + path, pollingDelay ?? const Duration(seconds: 1)); }); } @@ -31,8 +31,8 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { bool get isReady => _readyCompleter.isCompleted; @override - Future get ready => _readyCompleter.future; - final _readyCompleter = Completer(); + Future get ready => _readyCompleter.future; + final _readyCompleter = Completer(); /// The timer that controls polling. late final Timer _timer; @@ -49,7 +49,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { } /// Checks the mtime of the file and whether it's been removed. - Future _poll() async { + Future _poll() async { // We don't mark the file as removed if this is the first poll (indicated by // [_lastModified] being null). Instead, below we forward the dart:io error // that comes from trying to read the mtime below. diff --git a/pkgs/watcher/lib/src/resubscribable.dart b/pkgs/watcher/lib/src/resubscribable.dart index 91f509079..b99e9d7b4 100644 --- a/pkgs/watcher/lib/src/resubscribable.dart +++ b/pkgs/watcher/lib/src/resubscribable.dart @@ -41,7 +41,7 @@ abstract class ResubscribableWatcher implements Watcher { /// emitted by [_factory]. ResubscribableWatcher(this.path, this._factory) { late ManuallyClosedWatcher watcher; - late StreamSubscription subscription; + late StreamSubscription subscription; _eventsController = StreamController.broadcast( onListen: () async { diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index d86346881..431e99b13 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.1.0 +version: 1.1.1-wip description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. @@ -14,7 +14,7 @@ dependencies: dev_dependencies: benchmark_harness: ^2.0.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.1.0 test: ^1.16.0 test_descriptor: ^2.0.0 diff --git a/pkgs/watcher/test/directory_watcher/linux_test.dart b/pkgs/watcher/test/directory_watcher/linux_test.dart index 7b638a860..a10a72c33 100644 --- a/pkgs/watcher/test/directory_watcher/linux_test.dart +++ b/pkgs/watcher/test/directory_watcher/linux_test.dart @@ -18,7 +18,7 @@ void main() { sharedTests(); test('DirectoryWatcher creates a LinuxDirectoryWatcher on Linux', () { - expect(DirectoryWatcher('.'), TypeMatcher()); + expect(DirectoryWatcher('.'), const TypeMatcher()); }); test('emits events for many nested files moved out then immediately back in', diff --git a/pkgs/watcher/test/directory_watcher/mac_os_test.dart b/pkgs/watcher/test/directory_watcher/mac_os_test.dart index 347c5e731..337662646 100644 --- a/pkgs/watcher/test/directory_watcher/mac_os_test.dart +++ b/pkgs/watcher/test/directory_watcher/mac_os_test.dart @@ -18,7 +18,7 @@ void main() { sharedTests(); test('DirectoryWatcher creates a MacOSDirectoryWatcher on Mac OS', () { - expect(DirectoryWatcher('.'), TypeMatcher()); + expect(DirectoryWatcher('.'), const TypeMatcher()); }); test( diff --git a/pkgs/watcher/test/directory_watcher/polling_test.dart b/pkgs/watcher/test/directory_watcher/polling_test.dart index 0cfe738af..f4ec8f48a 100644 --- a/pkgs/watcher/test/directory_watcher/polling_test.dart +++ b/pkgs/watcher/test/directory_watcher/polling_test.dart @@ -10,8 +10,8 @@ import 'shared.dart'; void main() { // Use a short delay to make the tests run quickly. - watcherFactory = (dir) => - PollingDirectoryWatcher(dir, pollingDelay: Duration(milliseconds: 100)); + watcherFactory = (dir) => PollingDirectoryWatcher(dir, + pollingDelay: const Duration(milliseconds: 100)); sharedTests(); diff --git a/pkgs/watcher/test/directory_watcher/shared.dart b/pkgs/watcher/test/directory_watcher/shared.dart index 8fd842a8e..1ebc78d4b 100644 --- a/pkgs/watcher/test/directory_watcher/shared.dart +++ b/pkgs/watcher/test/directory_watcher/shared.dart @@ -135,7 +135,7 @@ void sharedTests() { renameFile('from.txt', 'to.txt'); await inAnyOrder([isRemoveEvent('from.txt'), isModifyEvent('to.txt')]); }, onPlatform: { - 'windows': Skip('https://github.com/dart-lang/watcher/issues/125') + 'windows': const Skip('https://github.com/dart-lang/watcher/issues/125') }); }); @@ -278,7 +278,7 @@ void sharedTests() { isAddEvent('new') ]); }, onPlatform: { - 'windows': Skip('https://github.com/dart-lang/watcher/issues/21') + 'windows': const Skip('https://github.com/dart-lang/watcher/issues/21') }); test('emits events for many nested files added at once', () async { diff --git a/pkgs/watcher/test/directory_watcher/windows_test.dart b/pkgs/watcher/test/directory_watcher/windows_test.dart index a0bdda7f4..499e7fb16 100644 --- a/pkgs/watcher/test/directory_watcher/windows_test.dart +++ b/pkgs/watcher/test/directory_watcher/windows_test.dart @@ -18,6 +18,6 @@ void main() { group('Shared Tests:', sharedTests); test('DirectoryWatcher creates a WindowsDirectoryWatcher on Windows', () { - expect(DirectoryWatcher('.'), TypeMatcher()); + expect(DirectoryWatcher('.'), const TypeMatcher()); }); } diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index 1bf9269fe..6f2bfbcab 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -13,7 +13,7 @@ import 'shared.dart'; void main() { watcherFactory = (file) => - PollingFileWatcher(file, pollingDelay: Duration(milliseconds: 100)); + PollingFileWatcher(file, pollingDelay: const Duration(milliseconds: 100)); setUp(() { writeFile('file.txt'); diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 9b72f0ed6..1e1718f45 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -62,7 +62,7 @@ void sharedTests() { var sub = watcher.events.listen(null); deleteFile('file.txt'); - await Future.delayed(Duration(milliseconds: 10)); + await Future.delayed(const Duration(milliseconds: 10)); await sub.cancel(); }); } diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index 1b4dbaa0b..c1b47ade0 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -43,8 +43,8 @@ void sharedTests() { // Ensure ready completes immediately expect( watcher.ready.timeout( - Duration(milliseconds: 0), - onTimeout: () => throw StateError('Does not complete immedately'), + const Duration(milliseconds: 0), + onTimeout: () => throw StateError('Does not complete immediately'), ), completes, ); diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 23adcbc40..214d66966 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -119,7 +119,7 @@ StreamMatcher _collectStreamMatcher(void Function() block) { /// it with [_collectStreamMatcher]. /// /// [streamMatcher] can be a [StreamMatcher], a [Matcher], or a value. -Future _expectOrCollect(streamMatcher) { +Future _expectOrCollect(Matcher streamMatcher) { var collectedStreamMatchers = _collectedStreamMatchers; if (collectedStreamMatchers != null) { collectedStreamMatchers.add(emits(streamMatcher)); From b84c6cf7c3d362ba7e090d246a88bd0343f7a49d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 00:30:30 +0000 Subject: [PATCH 1030/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/string_scanner#66) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 657b236db..86a16617d 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From c49647c9d82bbd4fe257f85ed657542bf0481d65 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 01:22:53 +0000 Subject: [PATCH 1031/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/stream_transform#176) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index e8d34cf2a..cc6d606f3 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tets when changning min SDK. sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 672be245dc044827efa5e6fb01f0fba1a609eb8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 01:38:52 +0000 Subject: [PATCH 1032/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/timing#39) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/timing#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/timing#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index ac2781347..60e9c4428 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 011f0f85a4151587e7005cd70bc1175b8af04c74 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 01:39:36 +0000 Subject: [PATCH 1033/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/timing#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 60e9c4428..132c4fc71 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From ef684398b414ffbe6dd1bfed8a3763d9899ada3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:46:35 +0000 Subject: [PATCH 1034/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/stream_channel#97) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 367d5dea3..e0d4f73af 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 913e78ca09df450843fb3de10f46fe1902d37305 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 03:50:53 +0000 Subject: [PATCH 1035/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/stream_channel#98) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index e0d4f73af..02786315a 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From db300b67dbc087162a3e913928c738c18b8fc38c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 04:02:41 +0000 Subject: [PATCH 1036/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/stream_transform#177) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index cc6d606f3..2690a5e28 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From a58e2f58ccc8984ef73752588b94384bcfb4c5bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 05:41:36 +0000 Subject: [PATCH 1037/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/pubspec_parse#116) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index ee3178486..d1b8e0de0 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 432ff8e5b05b1991a0fcfedde9fe30f8c8dd00b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 08:48:01 +0000 Subject: [PATCH 1038/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/watcher#155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 6f33e07c9..f1dc5813e 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 89b0f6b75bed05e922f1aaa990420430cb958863 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:35:02 +0000 Subject: [PATCH 1039/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/stack_trace#144) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 10cf89297..b4615fcac 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [2.18.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 9883125c6940493edc7c1617b7a459c14c616b16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 13:10:59 +0000 Subject: [PATCH 1040/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/term_glyph#44) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 8f5c3b290..9ba65f0e6 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} From 513cae5f98b75b8da4db197de0ada4c78ebb79a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:55:59 +0000 Subject: [PATCH 1041/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/term_glyph#45) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/term_glyph#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/term_glyph#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 9ba65f0e6..38ced1a4f 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 26eae9dbbbfc7f6b1322ee65b7a65f091017da84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 14:58:01 +0000 Subject: [PATCH 1042/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/watcher#154) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/watcher#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/watcher#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index f1dc5813e..d72e17b92 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From a8d2a7f0938d1cd0120bac000035726fbc1586ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:25:03 +0000 Subject: [PATCH 1043/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/pubspec_parse#117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index d1b8e0de0..36ed6216e 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From 8d852b41e6927efcb8a54807ffebbaeb35f6e0e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:28:50 +0000 Subject: [PATCH 1044/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/stack_trace#145) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index b4615fcac..0155ce90e 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.18.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From ed7eaa889239376c4d5d5f69a14a868bbeb8f9e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 15:54:43 +0000 Subject: [PATCH 1045/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/string_scanner#65) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 86a16617d..4cb7d3a73 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From 2460f52e9ad36e7321ea7fd81610946baab67027 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:09:27 +0000 Subject: [PATCH 1046/1215] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/test_reflective_loader#55) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

  • Added a flavor option setup.sh to allow downloading unpublished builds.

v1.0.0

  • Promoted to 1.0 stable.

v0.5

  • Fixed a Windows pub global activate path issue.

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 0d4b52099..3e74adbc1 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From 2867db176a99bf8f934cf56ba7a0a6c6e84edb35 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:12:08 +0000 Subject: [PATCH 1047/1215] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/test_reflective_loader#54) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1.
Release notes

Sourced from actions/checkout's releases.

v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.0...v4.1.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 3e74adbc1..a07546bea 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, stable] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From e826e96aa8e1dba8191bc703ff1db1ca8591f350 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 22 Nov 2023 16:50:36 +0000 Subject: [PATCH 1048/1215] Enable file watcher tests on Windows (dart-lang/watcher#156) * Enable file watcher tests on Windows * Add additional test --- pkgs/watcher/test/file_watcher/polling_test.dart | 3 --- pkgs/watcher/test/file_watcher/shared.dart | 5 +++++ pkgs/watcher/test/ready/shared.dart | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/test/file_watcher/polling_test.dart b/pkgs/watcher/test/file_watcher/polling_test.dart index 6f2bfbcab..861fcb222 100644 --- a/pkgs/watcher/test/file_watcher/polling_test.dart +++ b/pkgs/watcher/test/file_watcher/polling_test.dart @@ -2,9 +2,6 @@ // 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. -@TestOn('linux || mac-os') -library; - import 'package:test/test.dart'; import 'package:watcher/watcher.dart'; diff --git a/pkgs/watcher/test/file_watcher/shared.dart b/pkgs/watcher/test/file_watcher/shared.dart index 1e1718f45..081b92e11 100644 --- a/pkgs/watcher/test/file_watcher/shared.dart +++ b/pkgs/watcher/test/file_watcher/shared.dart @@ -65,4 +65,9 @@ void sharedTests() { await Future.delayed(const Duration(milliseconds: 10)); await sub.cancel(); }); + + test('ready completes even if file does not exist', () async { + // startWatcher awaits 'ready' + await startWatcher(path: 'foo/bar/baz'); + }); } diff --git a/pkgs/watcher/test/ready/shared.dart b/pkgs/watcher/test/ready/shared.dart index c1b47ade0..ab2c3e162 100644 --- a/pkgs/watcher/test/ready/shared.dart +++ b/pkgs/watcher/test/ready/shared.dart @@ -69,7 +69,7 @@ void sharedTests() { expect(watcher.ready, doesNotComplete); }); - test('completes even if directory does not exist', () async { + test('ready completes even if directory does not exist', () async { var watcher = createWatcher(path: 'does/not/exist'); // Subscribe to the events (else ready will never fire). From 3d8fb7f60052f33758a357e0a37fb9d35799be5e Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 Nov 2023 10:23:05 -0800 Subject: [PATCH 1049/1215] Update and fix latest lints, bump min SDK to 3.1 (dart-lang/stream_transform#178) --- .../.github/workflows/test-package.yml | 4 ++-- pkgs/stream_transform/CHANGELOG.md | 4 ++-- pkgs/stream_transform/analysis_options.yaml | 16 +------------ pkgs/stream_transform/lib/src/async_map.dart | 6 ++--- .../lib/src/combine_latest.dart | 10 ++++---- pkgs/stream_transform/lib/src/switch.dart | 6 +++-- pkgs/stream_transform/lib/src/where.dart | 8 +++---- pkgs/stream_transform/pubspec.yaml | 6 ++--- .../test/async_expand_test.dart | 2 +- .../test/async_map_buffer_test.dart | 2 +- .../test/async_map_sample_test.dart | 4 ++-- .../test/async_where_test.dart | 12 +++++----- pkgs/stream_transform/test/audit_test.dart | 2 +- pkgs/stream_transform/test/buffer_test.dart | 4 ++-- .../test/combine_latest_test.dart | 2 +- .../test/concurrent_async_map_test.dart | 2 +- pkgs/stream_transform/test/debounce_test.dart | 8 +++---- .../test/followd_by_test.dart | 4 ++-- pkgs/stream_transform/test/merge_test.dart | 24 +++++++++---------- pkgs/stream_transform/test/scan_test.dart | 6 ++--- pkgs/stream_transform/test/switch_test.dart | 9 +++---- .../test/take_until_test.dart | 4 ++-- pkgs/stream_transform/test/tap_test.dart | 23 +++++++++--------- .../test/where_not_null_test.dart | 4 ++-- .../test/where_type_test.dart | 8 +++---- 25 files changed, 85 insertions(+), 95 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 2690a5e28..b23f0fc46 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -47,8 +47,8 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - # Bump SDK for Legacy tets when changning min SDK. - sdk: [2.18.0, dev] + # Bump SDK for Legacy tests when changing min SDK. + sdk: [3.1, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index 2ef6fdb5b..c1e2c0ea1 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,6 +1,6 @@ -## 2.1.1-dev +## 2.1.1-wip -- Require Dart 2.18 or greater +- Require Dart 3.1 or greater - Forward errors from the `trigger` future through to the result stream in `takeUntil`. Previously an error would have not closed the stream, and instead raised as an unhandled async error. diff --git a/pkgs/stream_transform/analysis_options.yaml b/pkgs/stream_transform/analysis_options.yaml index 9dc8788ef..05f1af1ae 100644 --- a/pkgs/stream_transform/analysis_options.yaml +++ b/pkgs/stream_transform/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -7,24 +7,10 @@ analyzer: linter: rules: - - always_declare_return_types - avoid_bool_literals_in_conditional_expressions - avoid_classes_with_only_static_members - - avoid_returning_null - avoid_returning_this - avoid_unused_constructor_parameters - cascade_invocations - - comment_references - - directives_ordering - join_return_with_assignment - no_adjacent_strings_in_list - - omit_local_variable_types - - only_throw_errors - - prefer_const_constructors - - prefer_single_quotes - - test_types_in_equals - - throw_in_finally - - unawaited_futures - - unnecessary_lambdas - - unnecessary_parenthesis - - unnecessary_statements diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index c2ea253ca..81a176fba 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -59,8 +59,8 @@ extension AsyncMap on Stream { /// pending event. /// /// Errors from this stream are forwarded directly to the result stream. - /// Errors during the conversion are also forwarded to the result stream and are - /// considered completing work so the next values are let through. + /// Errors during the conversion are also forwarded to the result stream and + /// are considered completing work so the next values are let through. /// /// The result stream will not close until this stream closes and all pending /// conversions have finished. @@ -72,7 +72,7 @@ extension AsyncMap on Stream { trigger: workFinished.stream, aggregate: _dropPrevious, longPoll: true, - onEmpty: _ignore) + onEmpty: _ignore) ._asyncMapThen(convert, workFinished.add); } diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 5fbdbf520..15c1b683f 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -152,11 +152,11 @@ extension CombineLatest on Stream { /// at least once, the result stream will emit any time any source stream /// emits. /// - /// The result stream will not close until all source streams have closed. When - /// a source stream closes, the result stream will continue to emit the last - /// value from the closed stream when the other source streams emit until the - /// result stream has closed. If a source stream closes without emitting any - /// value, the result stream will close as well. + /// The result stream will not close until all source streams have closed. + /// When a source stream closes, the result stream will continue to emit the + /// last value from the closed stream when the other source streams emit until + /// the result stream has closed. If a source stream closes without emitting + /// any value, the result stream will close as well. /// /// For example: /// diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index b0fbbad67..d64fc07da 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -19,7 +19,8 @@ extension Switch on Stream { /// /// This means that the source stream is not paused until a sub stream /// returned from the [convert] callback is done. Instead, the subscription - /// to the sub stream is canceled as soon as the source stream emits a new event. + /// to the sub stream is canceled as soon as the source stream emits a new + /// event. /// /// Errors from [convert], the source stream, or any of the sub streams are /// forwarded to the result stream. @@ -36,7 +37,8 @@ extension Switch on Stream { /// /// See also: /// - [concurrentAsyncExpand], which emits events from all sub streams - /// concurrently instead of cancelling subscriptions to previous subs streams. + /// concurrently instead of cancelling subscriptions to previous subs + /// streams. Stream switchMap(Stream Function(T) convert) { return map(convert).switchLatest(); } diff --git a/pkgs/stream_transform/lib/src/where.dart b/pkgs/stream_transform/lib/src/where.dart index 6d210eabb..76aa28a8f 100644 --- a/pkgs/stream_transform/lib/src/where.dart +++ b/pkgs/stream_transform/lib/src/where.dart @@ -28,10 +28,10 @@ extension Where on Stream { /// Events on the result stream will be emitted in the order that [test] /// completes which may not match the order of this stream. /// - /// If the source stream is a broadcast stream the result will be as well. When - /// used with a broadcast stream behavior also differs from [where] in that - /// the [test] function is only called once per event, rather than once per - /// listener per event. + /// If the source stream is a broadcast stream the result will be as well. + /// When used with a broadcast stream behavior also differs from [where] in + /// that the [test] function is only called once per event, rather than once + /// per listener per event. /// /// Errors from the source stream are forwarded directly to the result stream. /// Errors from [test] are also forwarded to the result stream. diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 4d1ffbe56..9cd6584c1 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,13 +1,13 @@ name: stream_transform -version: 2.1.1-dev +version: 2.1.1-wip description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/stream_transform environment: - sdk: ">=2.18.0 <3.0.0" + sdk: ^3.1.0 dev_dependencies: async: ^2.5.0 + dart_flutter_team_lints: ^2.0.0 fake_async: ^1.3.0 - lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stream_transform/test/async_expand_test.dart b/pkgs/stream_transform/test/async_expand_test.dart index 379416567..8d84300ec 100644 --- a/pkgs/stream_transform/test/async_expand_test.dart +++ b/pkgs/stream_transform/test/async_expand_test.dart @@ -13,7 +13,7 @@ void main() { test('forwards errors from the convert callback', () async { var errors = []; var source = Stream.fromIterable([1, 2, 3]); - source.concurrentAsyncExpand((i) { + source.concurrentAsyncExpand((i) { // ignore: only_throw_errors throw 'Error: $i'; }).listen((_) {}, onError: errors.add); diff --git a/pkgs/stream_transform/test/async_map_buffer_test.dart b/pkgs/stream_transform/test/async_map_buffer_test.dart index b43c617cf..238621760 100644 --- a/pkgs/stream_transform/test/async_map_buffer_test.dart +++ b/pkgs/stream_transform/test/async_map_buffer_test.dart @@ -158,7 +158,7 @@ void main() { if (streamType == 'broadcast') { test('multiple listeners all get values', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values.add(1); await Future(() {}); diff --git a/pkgs/stream_transform/test/async_map_sample_test.dart b/pkgs/stream_transform/test/async_map_sample_test.dart index 6cab7d085..62b1b92cf 100644 --- a/pkgs/stream_transform/test/async_map_sample_test.dart +++ b/pkgs/stream_transform/test/async_map_sample_test.dart @@ -158,7 +158,7 @@ void main() { if (streamType == 'broadcast') { test('multiple listeners all get values', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values.add(1); await Future(() {}); @@ -204,6 +204,6 @@ void main() { test('allows nulls', () async { var stream = Stream.value(null); - await stream.asyncMapSample(expectAsync1((_) async {})).drain(); + await stream.asyncMapSample(expectAsync1((_) async {})).drain(); }); } diff --git a/pkgs/stream_transform/test/async_where_test.dart b/pkgs/stream_transform/test/async_where_test.dart index 3a13a389f..6ea4e76ed 100644 --- a/pkgs/stream_transform/test/async_where_test.dart +++ b/pkgs/stream_transform/test/async_where_test.dart @@ -37,8 +37,8 @@ void main() { test('forwards values to multiple listeners', () async { var values = StreamController.broadcast(); var filtered = values.stream.asyncWhere((e) async => e > 2); - var firstValues = []; - var secondValues = []; + var firstValues = []; + var secondValues = []; filtered ..listen(firstValues.add) ..listen(secondValues.add); @@ -53,7 +53,7 @@ void main() { }); test('closes streams with multiple listeners', () async { - var values = StreamController.broadcast(); + var values = StreamController.broadcast(); var predicate = Completer(); var filtered = values.stream.asyncWhere((_) => predicate.future); var firstDone = false; @@ -73,15 +73,15 @@ void main() { }); test('forwards errors emitted by the test callback', () async { - var errors = []; - var emitted = []; + var errors = []; + var emitted = []; var values = Stream.fromIterable([1, 2, 3, 4]); var filtered = values.asyncWhere((e) async { await Future(() {}); if (e.isEven) throw Exception('$e'); return true; }); - var done = Completer(); + var done = Completer(); filtered.listen(emitted.add, onError: errors.add, onDone: done.complete); await done.future; expect(emitted, [1, 3]); diff --git a/pkgs/stream_transform/test/audit_test.dart b/pkgs/stream_transform/test/audit_test.dart index e2f8133e2..28537db86 100644 --- a/pkgs/stream_transform/test/audit_test.dart +++ b/pkgs/stream_transform/test/audit_test.dart @@ -119,7 +119,7 @@ void main() { values.add(1); async.elapse(const Duration(milliseconds: 3)); values.add(2); - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values.add(3); async.elapse(const Duration(milliseconds: 3)); diff --git a/pkgs/stream_transform/test/buffer_test.dart b/pkgs/stream_transform/test/buffer_test.dart index 1675c287e..830f55539 100644 --- a/pkgs/stream_transform/test/buffer_test.dart +++ b/pkgs/stream_transform/test/buffer_test.dart @@ -228,7 +228,7 @@ void main() { test('emits empty list before values', () async { trigger.add(null); await Future(() {}); - expect(emittedValues, [[]]); + expect(emittedValues, [[]]); }); test('emits empty list after emitting values', () async { @@ -242,7 +242,7 @@ void main() { await Future(() {}); expect(emittedValues, [ [1, 2], - [] + [] ]); }); }); diff --git a/pkgs/stream_transform/test/combine_latest_test.dart b/pkgs/stream_transform/test/combine_latest_test.dart index d2c6003dc..1985c7587 100644 --- a/pkgs/stream_transform/test/combine_latest_test.dart +++ b/pkgs/stream_transform/test/combine_latest_test.dart @@ -127,7 +127,7 @@ void main() { var other = StreamController(); int sum(int a, int b) => throw _NumberedException(3); - var errors = []; + var errors = []; source.stream .combineLatest(other.stream, sum) .listen(null, onError: errors.add); diff --git a/pkgs/stream_transform/test/concurrent_async_map_test.dart b/pkgs/stream_transform/test/concurrent_async_map_test.dart index 3c46a9657..1807f9f8b 100644 --- a/pkgs/stream_transform/test/concurrent_async_map_test.dart +++ b/pkgs/stream_transform/test/concurrent_async_map_test.dart @@ -111,7 +111,7 @@ void main() { if (streamType == 'broadcast') { test('multiple listeners all get values', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); controller.add(1); await Future(() {}); diff --git a/pkgs/stream_transform/test/debounce_test.dart b/pkgs/stream_transform/test/debounce_test.dart index 6b9775f84..19de055c8 100644 --- a/pkgs/stream_transform/test/debounce_test.dart +++ b/pkgs/stream_transform/test/debounce_test.dart @@ -100,7 +100,7 @@ void main() { test('multiple listeners all get values', () { fakeAsync((async) { listen(); - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values ..add(1) @@ -157,7 +157,7 @@ void main() { test('multiple listeners all get values', () { fakeAsync((async) { listen(); - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values ..add(1) @@ -221,7 +221,7 @@ void main() { test('multiple listeners all get values', () { fakeAsync((async) { listen(); - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values ..add(1) @@ -284,7 +284,7 @@ void main() { test('multiple listeners all get values', () { fakeAsync((async) { listen(); - var otherValues = []; + var otherValues = >[]; transformed.listen(otherValues.add); values ..add(1) diff --git a/pkgs/stream_transform/test/followd_by_test.dart b/pkgs/stream_transform/test/followd_by_test.dart index 436d61380..d600d136a 100644 --- a/pkgs/stream_transform/test/followd_by_test.dart +++ b/pkgs/stream_transform/test/followd_by_test.dart @@ -138,13 +138,13 @@ void main() { }); test('forwards values to multiple listeners', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); first.add(1); await first.close(); second.add(2); await Future(() {}); - var thirdValues = []; + var thirdValues = []; transformed.listen(thirdValues.add); second.add(3); await Future(() {}); diff --git a/pkgs/stream_transform/test/merge_test.dart b/pkgs/stream_transform/test/merge_test.dart index 7217945fc..ecbf97f26 100644 --- a/pkgs/stream_transform/test/merge_test.dart +++ b/pkgs/stream_transform/test/merge_test.dart @@ -20,12 +20,12 @@ void main() { test('cancels both sources', () async { var firstCanceled = false; - var first = StreamController() + var first = StreamController() ..onCancel = () { firstCanceled = true; }; var secondCanceled = false; - var second = StreamController() + var second = StreamController() ..onCancel = () { secondCanceled = true; }; @@ -36,8 +36,8 @@ void main() { }); test('completes when both sources complete', () async { - var first = StreamController(); - var second = StreamController(); + var first = StreamController(); + var second = StreamController(); var isDone = false; first.stream.merge(second.stream).listen((_) {}, onDone: () { isDone = true; @@ -49,9 +49,9 @@ void main() { }); test('can cancel and relisten to broadcast stream', () async { - var first = StreamController.broadcast(); - var second = StreamController(); - var emittedValues = []; + var first = StreamController.broadcast(); + var second = StreamController(); + var emittedValues = []; var transformed = first.stream.merge(second.stream); var subscription = transformed.listen(emittedValues.add); first.add(1); @@ -84,17 +84,17 @@ void main() { test('handles mix of broadcast and single-subscription', () async { var firstCanceled = false; - var first = StreamController.broadcast() + var first = StreamController.broadcast() ..onCancel = () { firstCanceled = true; }; var secondBroadcastCanceled = false; - var secondBroadcast = StreamController.broadcast() + var secondBroadcast = StreamController.broadcast() ..onCancel = () { secondBroadcastCanceled = true; }; var secondSingleCanceled = false; - var secondSingle = StreamController() + var secondSingle = StreamController() ..onCancel = () { secondSingleCanceled = true; }; @@ -102,8 +102,8 @@ void main() { var merged = first.stream.mergeAll([secondBroadcast.stream, secondSingle.stream]); - var firstListenerValues = []; - var secondListenerValues = []; + var firstListenerValues = []; + var secondListenerValues = []; var firstSubscription = merged.listen(firstListenerValues.add); var secondSubscription = merged.listen(secondListenerValues.add); diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index 3a126ec04..a0311c5f7 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -18,7 +18,7 @@ void main() { }); test('can create a broadcast stream', () { - var source = StreamController.broadcast(); + var source = StreamController.broadcast(); var transformed = source.stream.scan(null, (_, __) {}); @@ -30,7 +30,7 @@ void main() { int sum(int x, int y) => x + y; - var errors = []; + var errors = []; source.stream.scan(0, sum).listen(null, onError: errors.add); @@ -95,7 +95,7 @@ void main() { Future combine(int x, int y) async => throw StateError('fail'); - var errors = []; + var errors = []; source.stream.scan(0, combine).listen(null, onError: errors.add); diff --git a/pkgs/stream_transform/test/switch_test.dart b/pkgs/stream_transform/test/switch_test.dart index d2f99a8ba..9e70c0811 100644 --- a/pkgs/stream_transform/test/switch_test.dart +++ b/pkgs/stream_transform/test/switch_test.dart @@ -196,7 +196,7 @@ void main() { test('uses map function', () async { var outer = StreamController>(); - var values = []; + var values = []; outer.stream.switchMap(Stream.fromIterable).listen(values.add); outer.add([1, 2, 3]); @@ -207,9 +207,10 @@ void main() { }); test('can create a broadcast stream', () async { - var outer = StreamController.broadcast(); + var outer = StreamController.broadcast(); - var transformed = outer.stream.switchMap((_) => const Stream.empty()); + var transformed = + outer.stream.switchMap((_) => const Stream.empty()); expect(transformed.isBroadcast, true); }); @@ -217,7 +218,7 @@ void main() { test('forwards errors from the convert callback', () async { var errors = []; var source = Stream.fromIterable([1, 2, 3]); - source.switchMap((i) { + source.switchMap((i) { // ignore: only_throw_errors throw 'Error: $i'; }).listen((_) {}, onError: errors.add); diff --git a/pkgs/stream_transform/test/take_until_test.dart b/pkgs/stream_transform/test/take_until_test.dart index 9c73d092b..982b3daac 100644 --- a/pkgs/stream_transform/test/take_until_test.dart +++ b/pkgs/stream_transform/test/take_until_test.dart @@ -80,7 +80,7 @@ void main() { await values.close(); closeTrigger.completeError('sad'); await Future(() {}); - expect(errors, []); + expect(errors, []); }); test('cancels value subscription when trigger fires', () async { @@ -91,7 +91,7 @@ void main() { if (streamType == 'broadcast') { test('multiple listeners all get values', () async { - var otherValues = []; + var otherValues = []; transformed.listen(otherValues.add); values ..add(1) diff --git a/pkgs/stream_transform/test/tap_test.dart b/pkgs/stream_transform/test/tap_test.dart index a42bdc622..f2b43464e 100644 --- a/pkgs/stream_transform/test/tap_test.dart +++ b/pkgs/stream_transform/test/tap_test.dart @@ -9,7 +9,7 @@ import 'package:test/test.dart'; void main() { test('calls function for values', () async { - var valuesSeen = []; + var valuesSeen = []; var stream = Stream.fromIterable([1, 2, 3]); await stream.tap(valuesSeen.add).last; expect(valuesSeen, [1, 2, 3]); @@ -23,7 +23,7 @@ void main() { test('calls function for errors', () async { dynamic error; - var source = StreamController(); + var source = StreamController(); source.stream.tap((_) {}, onError: (e, st) { error = e; }).listen((_) {}, onError: (_) {}); @@ -34,8 +34,9 @@ void main() { test('forwards errors', () async { dynamic error; - var source = StreamController(); - source.stream.tap((_) {}, onError: (e, st) {}).listen((_) {}, onError: (e) { + var source = StreamController(); + source.stream.tap((_) {}, onError: (e, st) {}).listen((_) {}, + onError: (Object e) { error = e; }); source.addError('error'); @@ -45,7 +46,7 @@ void main() { test('calls function on done', () async { var doneCalled = false; - var source = StreamController(); + var source = StreamController(); source.stream.tap((_) {}, onDone: () { doneCalled = true; }).listen((_) {}); @@ -56,7 +57,7 @@ void main() { test('forwards only once with multiple listeners on a broadcast stream', () async { var dataCallCount = 0; - var source = StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.tap((_) { dataCallCount++; }) @@ -71,7 +72,7 @@ void main() { 'forwards errors only once with multiple listeners on a broadcast stream', () async { var errorCallCount = 0; - var source = StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.tap((_) {}, onError: (_, __) { errorCallCount++; }) @@ -85,7 +86,7 @@ void main() { test('calls onDone only once with multiple listeners on a broadcast stream', () async { var doneCallCount = 0; - var source = StreamController.broadcast(); + var source = StreamController.broadcast(); source.stream.tap((_) {}, onDone: () { doneCallCount++; }) @@ -96,9 +97,9 @@ void main() { }); test('forwards values to multiple listeners', () async { - var source = StreamController.broadcast(); - var emittedValues1 = []; - var emittedValues2 = []; + var source = StreamController.broadcast(); + var emittedValues1 = []; + var emittedValues2 = []; source.stream.tap((_) {}) ..listen(emittedValues1.add) ..listen(emittedValues2.add); diff --git a/pkgs/stream_transform/test/where_not_null_test.dart b/pkgs/stream_transform/test/where_not_null_test.dart index c7e4e9b8f..c9af79473 100644 --- a/pkgs/stream_transform/test/where_not_null_test.dart +++ b/pkgs/stream_transform/test/where_not_null_test.dart @@ -23,8 +23,8 @@ void main() { test('forwards values to multiple listeners', () async { var values = StreamController.broadcast(); var filtered = values.stream.whereNotNull(); - var firstValues = []; - var secondValues = []; + var firstValues = []; + var secondValues = []; filtered ..listen(firstValues.add) ..listen(secondValues.add); diff --git a/pkgs/stream_transform/test/where_type_test.dart b/pkgs/stream_transform/test/where_type_test.dart index 1a65dd6ac..4cbea3770 100644 --- a/pkgs/stream_transform/test/where_type_test.dart +++ b/pkgs/stream_transform/test/where_type_test.dart @@ -21,10 +21,10 @@ void main() { }); test('forwards values to multiple listeners', () async { - var values = StreamController.broadcast(); + var values = StreamController.broadcast(); var filtered = values.stream.whereType(); - var firstValues = []; - var secondValues = []; + var firstValues = []; + var secondValues = []; filtered ..listen(firstValues.add) ..listen(secondValues.add); @@ -39,7 +39,7 @@ void main() { }); test('closes streams with multiple listeners', () async { - var values = StreamController.broadcast(); + var values = StreamController.broadcast(); var filtered = values.stream.whereType(); var firstDone = false; var secondDone = false; From 131666ab5709f19d28a3d9153108f871795394ff Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 29 Nov 2023 11:12:53 -0800 Subject: [PATCH 1050/1215] Latest lints, require Dart ^3.1 (dart-lang/stack_trace#146) --- .../.github/workflows/test-package.yml | 2 +- pkgs/stack_trace/CHANGELOG.md | 4 +++ pkgs/stack_trace/analysis_options.yaml | 25 ++---------------- pkgs/stack_trace/example/example.dart | 4 +-- pkgs/stack_trace/pubspec.yaml | 6 ++--- pkgs/stack_trace/test/chain/chain_test.dart | 26 +++++++++---------- pkgs/stack_trace/test/chain/dart2js_test.dart | 9 ++++--- pkgs/stack_trace/test/chain/utils.dart | 8 +++--- pkgs/stack_trace/test/chain/vm_test.dart | 9 ++++--- pkgs/stack_trace/test/trace_test.dart | 4 --- pkgs/stack_trace/test/vm_test.dart | 1 + 11 files changed, 43 insertions(+), 55 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 0155ce90e..030f9a4d3 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.18.0, dev] + sdk: [3.1, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 063cc49b2..2c4c77cd7 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.11.2-wip + +* Require Dart 3.1 or greater + ## 1.11.1 * Make use of `@pragma('vm:awaiter-link')` to make package work better with diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index 48d93f235..ad62f915d 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -1,5 +1,5 @@ -# https://dart.dev/guides/language/analysis-options -include: package:lints/recommended.yaml +# https://dart.dev/tools/analysis#the-analysis-options-file +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: @@ -8,37 +8,16 @@ analyzer: linter: rules: - - always_declare_return_types - - avoid_catching_errors - - avoid_dynamic_calls - avoid_private_typedef_functions - avoid_redundant_argument_values - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - - comment_references - - 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_asserts_in_initializer_lists - - prefer_const_constructors - prefer_const_declarations - - prefer_relative_imports - - prefer_single_quotes - - sort_pub_dependencies - - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unawaited_futures - unnecessary_await_in_return - - unnecessary_lambdas - - unnecessary_parenthesis - - unnecessary_statements - - use_is_even_rather_than_modulo - use_string_buffers - - use_super_parameters diff --git a/pkgs/stack_trace/example/example.dart b/pkgs/stack_trace/example/example.dart index 7d71221ce..d601ca441 100644 --- a/pkgs/stack_trace/example/example.dart +++ b/pkgs/stack_trace/example/example.dart @@ -7,9 +7,9 @@ void main() { } void _scheduleAsync() { - Future.delayed(const Duration(seconds: 1)).then((_) => _runAsync()); + Future.delayed(const Duration(seconds: 1)).then((_) => _runAsync()); } void _runAsync() { - throw 'oh no!'; + throw StateError('oh no!'); } diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 93fd3e591..b3a9d9266 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,14 +1,14 @@ name: stack_trace -version: 1.11.1 +version: 1.11.2-wip description: A package for manipulating stack traces and printing them readably. repository: https://github.com/dart-lang/stack_trace environment: - sdk: ">=2.18.0 <3.0.0" + sdk: ^3.1.0 dependencies: path: ^1.8.0 dev_dependencies: - lints: ^2.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stack_trace/test/chain/chain_test.dart b/pkgs/stack_trace/test/chain/chain_test.dart index aa4256bfc..d5426dda9 100644 --- a/pkgs/stack_trace/test/chain/chain_test.dart +++ b/pkgs/stack_trace/test/chain/chain_test.dart @@ -10,16 +10,16 @@ import 'package:test/test.dart'; import 'utils.dart'; -typedef ChainErrorCallback = void Function(dynamic stack, Chain chain); - void main() { group('Chain.parse()', () { - test('parses a real Chain', () { - return captureFuture(() => inMicrotask(() => throw 'error')) - .then((chain) { - expect( - Chain.parse(chain.toString()).toString(), equals(chain.toString())); - }); + test('parses a real Chain', () async { + // ignore: only_throw_errors + final chain = await captureFuture(() => inMicrotask(() => throw 'error')); + + expect( + Chain.parse(chain.toString()).toString(), + equals(chain.toString()), + ); }); test('parses an empty string', () { @@ -61,7 +61,7 @@ void main() { group('Chain.capture()', () { test('with onError blocks errors', () { Chain.capture(() { - return Future.error('oh no'); + return Future.error('oh no'); }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); expect(chain, isA()); @@ -71,7 +71,7 @@ void main() { test('with no onError blocks errors', () { runZonedGuarded(() { - Chain.capture(() => Future.error('oh no')).then( + Chain.capture(() => Future.error('oh no')).then( expectAsync1((_) {}, count: 0), onError: expectAsync2((_, __) {}, count: 0)); }, expectAsync2((error, chain) { @@ -81,7 +81,7 @@ void main() { }); test("with errorZone: false doesn't block errors", () { - expect(Chain.capture(() => Future.error('oh no'), errorZone: false), + expect(Chain.capture(() => Future.error('oh no'), errorZone: false), throwsA('oh no')); }); @@ -92,13 +92,13 @@ void main() { group('with when: false', () { test("with no onError doesn't block errors", () { - expect(Chain.capture(() => Future.error('oh no'), when: false), + expect(Chain.capture(() => Future.error('oh no'), when: false), throwsA('oh no')); }); test('with onError blocks errors', () { Chain.capture(() { - return Future.error('oh no'); + return Future.error('oh no'); }, onError: expectAsync2((error, chain) { expect(error, equals('oh no')); expect(chain, isA()); diff --git a/pkgs/stack_trace/test/chain/dart2js_test.dart b/pkgs/stack_trace/test/chain/dart2js_test.dart index 584146658..abb842dfc 100644 --- a/pkgs/stack_trace/test/chain/dart2js_test.dart +++ b/pkgs/stack_trace/test/chain/dart2js_test.dart @@ -2,11 +2,14 @@ // 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. +// ignore_for_file: only_throw_errors + // dart2js chain tests are separated out because dart2js stack traces are // inconsistent due to inlining and browser differences. These tests don't // assert anything about the content of the traces, just the number of traces in // a chain. @TestOn('js') +library; import 'dart:async'; @@ -73,7 +76,7 @@ void main() { }); test('multiple times', () { - var completer = Completer(); + var completer = Completer(); var first = true; Chain.capture(() { @@ -138,7 +141,7 @@ void main() { }); test('and relays them to the parent zone', () { - var completer = Completer(); + var completer = Completer(); runZonedGuarded(() { Chain.capture(() { @@ -164,7 +167,7 @@ void main() { }); test('capture() without onError passes exceptions to parent zone', () { - var completer = Completer(); + var completer = Completer(); runZonedGuarded(() { Chain.capture(() => inMicrotask(() => throw 'error')); diff --git a/pkgs/stack_trace/test/chain/utils.dart b/pkgs/stack_trace/test/chain/utils.dart index 2cc64527f..27fb0e684 100644 --- a/pkgs/stack_trace/test/chain/utils.dart +++ b/pkgs/stack_trace/test/chain/utils.dart @@ -47,7 +47,7 @@ void inSyncFuture(void Function() callback) { /// /// If [trace] is passed, it's used as the stack trace for the error. Future completerErrorFuture([StackTrace? trace]) { - var completer = Completer(); + var completer = Completer(); completer.completeError('error', trace); return completer.future; } @@ -56,7 +56,7 @@ Future completerErrorFuture([StackTrace? trace]) { /// /// If [trace] is passed, it's used as the stack trace for the error. Stream controllerErrorStream([StackTrace? trace]) { - var controller = StreamController(); + var controller = StreamController(); controller.addError('error', trace); return controller.stream; } @@ -71,7 +71,9 @@ Future chainForTrace( // [new Future.sync] because those methods don't pass the exception through // the zone specification before propagating it, so there's no chance to // attach a chain to its stack trace. See issue 15105. - Future.value().then((_) => callback()).catchError(completer.completeError); + Future.value() + .then((_) => callback()) + .catchError(completer.completeError); }); return completer.future diff --git a/pkgs/stack_trace/test/chain/vm_test.dart b/pkgs/stack_trace/test/chain/vm_test.dart index 83e01d4f6..5c6c0b7d9 100644 --- a/pkgs/stack_trace/test/chain/vm_test.dart +++ b/pkgs/stack_trace/test/chain/vm_test.dart @@ -2,9 +2,12 @@ // 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. +// ignore_for_file: only_throw_errors + // VM chain tests can rely on stronger guarantees about the contents of the // stack traces than dart2js. @TestOn('dart-vm') +library; import 'dart:async'; @@ -136,7 +139,7 @@ void main() { }); test('multiple times', () { - var completer = Completer(); + var completer = Completer(); var first = true; Chain.capture(() { @@ -231,7 +234,7 @@ void main() { }); test('and relays them to the parent zone', () { - var completer = Completer(); + var completer = Completer(); runZonedGuarded(() { Chain.capture(() { @@ -260,7 +263,7 @@ void main() { }); test('capture() without onError passes exceptions to parent zone', () { - var completer = Completer(); + var completer = Completer(); runZonedGuarded(() { Chain.capture(() => inMicrotask(() => throw 'error')); diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index 15c86aa99..d4bce766e 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -6,10 +6,6 @@ import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; import 'package:test/test.dart'; -Trace getCurrentTrace([int level = 0]) => Trace.current(level); - -Trace nestedGetCurrentTrace(int level) => getCurrentTrace(level); - void main() { // This just shouldn't crash. test('a native stack trace is parseable', Trace.current); diff --git a/pkgs/stack_trace/test/vm_test.dart b/pkgs/stack_trace/test/vm_test.dart index e0dbcff39..70ac0143a 100644 --- a/pkgs/stack_trace/test/vm_test.dart +++ b/pkgs/stack_trace/test/vm_test.dart @@ -7,6 +7,7 @@ /// platform to platform. No similar file exists for dart2js since the specific /// method names there are implementation details. @TestOn('vm') +library; import 'package:path/path.dart' as path; import 'package:stack_trace/stack_trace.dart'; From cfa97eaaba2fafc09a6fe1b7b1b9bf6361583802 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Thu, 30 Nov 2023 11:42:23 +0100 Subject: [PATCH 1051/1215] Remove outdated lints (dart-lang/pubspec_parse#119) --- pkgs/pubspec_parse/analysis_options.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index 7da0e8962..c20999920 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -12,8 +12,6 @@ linter: - avoid_classes_with_only_static_members - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_returning_null - - avoid_returning_null_for_future - avoid_returning_this - avoid_unused_constructor_parameters - avoid_void_async From 8ca0ae06958a703598b5c9d9effc425621c16165 Mon Sep 17 00:00:00 2001 From: Sarah Zakarias Date: Thu, 30 Nov 2023 11:45:09 +0100 Subject: [PATCH 1052/1215] Add support for 'ignored_advisories' field (dart-lang/pubspec_parse#118) --- pkgs/pubspec_parse/CHANGELOG.md | 1 + pkgs/pubspec_parse/lib/src/pubspec.dart | 4 +++ pkgs/pubspec_parse/lib/src/pubspec.g.dart | 3 ++ pkgs/pubspec_parse/test/parse_test.dart | 41 +++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 7444f4f82..87dd5cae8 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.2.4-wip - Require Dart 3.0 +- Added support for `ignored_advisories` field. ## 1.2.3 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index 3eb73cc3f..f6934eef3 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -47,6 +47,9 @@ class Pubspec { /// Optional field to list the topics that this packages belongs to. final List? topics; + /// Optional field to list advisories to be ignored by the client. + final List? ignoredAdvisories; + /// Optional field for specifying included screenshot files. @JsonKey(fromJson: parseScreenshots) final List? screenshots; @@ -110,6 +113,7 @@ class Pubspec { this.issueTracker, this.funding, this.topics, + this.ignoredAdvisories, this.screenshots, this.documentation, this.description, diff --git a/pkgs/pubspec_parse/lib/src/pubspec.g.dart b/pkgs/pubspec_parse/lib/src/pubspec.g.dart index 622999437..fc285718d 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.g.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.g.dart @@ -34,6 +34,8 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( .toList()), topics: $checkedConvert('topics', (v) => (v as List?)?.map((e) => e as String).toList()), + ignoredAdvisories: $checkedConvert('ignored_advisories', + (v) => (v as List?)?.map((e) => e as String).toList()), screenshots: $checkedConvert( 'screenshots', (v) => parseScreenshots(v as List?)), documentation: $checkedConvert('documentation', (v) => v as String?), @@ -55,6 +57,7 @@ Pubspec _$PubspecFromJson(Map json) => $checkedCreate( fieldKeyMap: const { 'publishTo': 'publish_to', 'issueTracker': 'issue_tracker', + 'ignoredAdvisories': 'ignored_advisories', 'devDependencies': 'dev_dependencies', 'dependencyOverrides': 'dependency_overrides' }, diff --git a/pkgs/pubspec_parse/test/parse_test.dart b/pkgs/pubspec_parse/test/parse_test.dart index 31042f1cb..6251f41fb 100644 --- a/pkgs/pubspec_parse/test/parse_test.dart +++ b/pkgs/pubspec_parse/test/parse_test.dart @@ -52,6 +52,7 @@ void main() { 'https://patreon.com/example', ], 'topics': ['widget', 'button'], + 'ignored_advisories': ['111', '222'], 'screenshots': [ {'description': 'my screenshot', 'path': 'path/to/screenshot'}, ], @@ -79,6 +80,9 @@ void main() { expect(value.topics, hasLength(2)); expect(value.topics!.first, 'widget'); expect(value.topics!.last, 'button'); + expect(value.ignoredAdvisories, hasLength(2)); + expect(value.ignoredAdvisories!.first, '111'); + expect(value.ignoredAdvisories!.last, '222'); expect(value.screenshots, hasLength(1)); expect(value.screenshots!.first.description, 'my screenshot'); expect(value.screenshots!.first.path, 'path/to/screenshot'); @@ -425,6 +429,43 @@ line 6, column 13: Unsupported value for "funding". Illegal scheme character at }); }); + group('ignored_advisories', () { + test('not a list', () { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'ignored_advisories': 1, + }, + "Unsupported value for \"ignored_advisories\". type 'int' is not a subtype of type 'List?'", + skipTryPub: true, + ); + }); + + test('not a string', () { + expectParseThrowsContaining( + { + ...defaultPubspec, + 'ignored_advisories': [1], + }, + "Unsupported value for \"ignored_advisories\". type 'int' is not a subtype of type 'String'", + skipTryPub: true, + ); + }); + + test('invalid data - lenient', () async { + final value = await parse( + { + ...defaultPubspec, + 'ignored_advisories': [1], + }, + skipTryPub: true, + lenient: true, + ); + expect(value.name, 'sample'); + expect(value.ignoredAdvisories, isNull); + }); + }); + group('screenshots', () { test('one screenshot', () async { final value = await parse({ From 289718a4844d60ff2db14c7cf3424ef678813ec5 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 30 Nov 2023 18:11:32 -0800 Subject: [PATCH 1053/1215] Update lints, bump min SDK to ^3.1.0 (dart-lang/test_reflective_loader#56) --- .../.github/workflows/build.yaml | 14 +- pkgs/test_reflective_loader/CHANGELOG.md | 4 + .../analysis_options.yaml | 8 +- .../lib/test_reflective_loader.dart | 210 +++++++----------- pkgs/test_reflective_loader/pubspec.yaml | 6 +- .../test/test_reflective_loader_test.dart | 4 +- 6 files changed, 100 insertions(+), 146 deletions(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index a07546bea..9ebdc1f3d 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -18,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [dev, stable] + sdk: [dev, 3.1] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 @@ -26,14 +26,8 @@ jobs: with: sdk: ${{ matrix.sdk }} - - name: pub get - run: dart pub get - + - run: dart pub get - name: dart format run: dart format --output=none --set-exit-if-changed . - - - name: dart analyze - run: dart analyze - - - name: dart test - run: dart test + - run: dart analyze --fatal-infos + - run: dart test diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index e233fef89..5fd4c553e 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.3-wip + +- Require Dart `^3.1.0`. + ## 0.2.2 - Update to package:lints 2.0.0 and move it to a dev dependency. diff --git a/pkgs/test_reflective_loader/analysis_options.yaml b/pkgs/test_reflective_loader/analysis_options.yaml index fc2a9d30e..ea6115827 100644 --- a/pkgs/test_reflective_loader/analysis_options.yaml +++ b/pkgs/test_reflective_loader/analysis_options.yaml @@ -1,11 +1,5 @@ -include: package:lints/recommended.yaml - -analyzer: - errors: - slash_for_doc_comments: ignore +include: package:dart_flutter_team_lints/analysis_options.yaml linter: rules: - - always_declare_return_types - - directives_ordering - public_member_api_docs diff --git a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart index 3881cf1c2..cb69bf3ba 100644 --- a/pkgs/test_reflective_loader/lib/test_reflective_loader.dart +++ b/pkgs/test_reflective_loader/lib/test_reflective_loader.dart @@ -2,47 +2,34 @@ // 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. -library test_reflective_loader; - import 'dart:async'; import 'dart:mirrors'; import 'package:test/test.dart' as test_package; -/** - * A marker annotation used to annotate test methods which are expected to fail - * when asserts are enabled. - */ +/// A marker annotation used to annotate test methods which are expected to fail +/// when asserts are enabled. const Object assertFailingTest = _AssertFailingTest(); -/** - * A marker annotation used to annotate test methods which are expected to fail. - */ +/// A marker annotation used to annotate test methods which are expected to +/// fail. const Object failingTest = FailingTest(); -/** - * A marker annotation used to instruct dart2js to keep reflection information - * for the annotated classes. - */ +/// A marker annotation used to instruct dart2js to keep reflection information +/// for the annotated classes. const Object reflectiveTest = _ReflectiveTest(); -/** - * A marker annotation used to annotate test methods that should be skipped. - */ +/// A marker annotation used to annotate test methods that should be skipped. const Object skippedTest = SkippedTest(); -/** - * A marker annotation used to annotate "solo" groups and tests. - */ +/// A marker annotation used to annotate "solo" groups and tests. const Object soloTest = _SoloTest(); final List<_Group> _currentGroups = <_Group>[]; int _currentSuiteLevel = 0; String _currentSuiteName = ''; -/** - * Is `true` the application is running in the checked mode. - */ +/// Is `true` the application is running in the checked mode. final bool _isCheckedMode = () { try { assert(false); @@ -52,14 +39,12 @@ final bool _isCheckedMode = () { } }(); -/** - * Run the [define] function parameter that calls [defineReflectiveTests] to - * add normal and "solo" tests, and also calls [defineReflectiveSuite] to - * create embedded suites. If the current suite is the top-level one, perform - * check for "solo" groups and tests, and run all or only "solo" items. - */ +/// Run the [define] function parameter that calls [defineReflectiveTests] to +/// add normal and "solo" tests, and also calls [defineReflectiveSuite] to +/// create embedded suites. If the current suite is the top-level one, perform +/// check for "solo" groups and tests, and run all or only "solo" items. void defineReflectiveSuite(void Function() define, {String name = ''}) { - String groupName = _currentSuiteName; + var groupName = _currentSuiteName; _currentSuiteLevel++; try { _currentSuiteName = _combineNames(_currentSuiteName, name); @@ -71,39 +56,37 @@ void defineReflectiveSuite(void Function() define, {String name = ''}) { _addTestsIfTopLevelSuite(); } -/** - * Runs test methods existing in the given [type]. - * - * If there is a "solo" test method in the top-level suite, only "solo" methods - * are run. - * - * If there is a "solo" test type, only its test methods are run. - * - * Otherwise all tests methods of all test types are run. - * - * Each method is run with a new instance of [type]. - * So, [type] should have a default constructor. - * - * If [type] declares method `setUp`, it methods will be invoked before any test - * method invocation. - * - * If [type] declares method `tearDown`, it will be invoked after any test - * method invocation. If method returns [Future] to test some asynchronous - * behavior, then `tearDown` will be invoked in `Future.complete`. - */ +/// Runs test methods existing in the given [type]. +/// +/// If there is a "solo" test method in the top-level suite, only "solo" methods +/// are run. +/// +/// If there is a "solo" test type, only its test methods are run. +/// +/// Otherwise all tests methods of all test types are run. +/// +/// Each method is run with a new instance of [type]. +/// So, [type] should have a default constructor. +/// +/// If [type] declares method `setUp`, it methods will be invoked before any +/// test method invocation. +/// +/// If [type] declares method `tearDown`, it will be invoked after any test +/// method invocation. If method returns [Future] to test some asynchronous +/// behavior, then `tearDown` will be invoked in `Future.complete`. void defineReflectiveTests(Type type) { - ClassMirror classMirror = reflectClass(type); + var classMirror = reflectClass(type); if (!classMirror.metadata.any((InstanceMirror annotation) => annotation.type.reflectedType == _ReflectiveTest)) { - String name = MirrorSystem.getName(classMirror.qualifiedName); + var name = MirrorSystem.getName(classMirror.qualifiedName); throw Exception('Class $name must have annotation "@reflectiveTest" ' 'in order to be run by runReflectiveTests.'); } _Group group; { - bool isSolo = _hasAnnotationInstance(classMirror, soloTest); - String className = MirrorSystem.getName(classMirror.simpleName); + var isSolo = _hasAnnotationInstance(classMirror, soloTest); + var className = MirrorSystem.getName(classMirror.simpleName); group = _Group(isSolo, _combineNames(_currentSuiteName, className)); _currentGroups.add(group); } @@ -115,8 +98,8 @@ void defineReflectiveTests(Type type) { return; } // prepare information about the method - String memberName = MirrorSystem.getName(symbol); - bool isSolo = memberName.startsWith('solo_') || + var memberName = MirrorSystem.getName(symbol); + var isSolo = memberName.startsWith('solo_') || _hasAnnotationInstance(memberMirror, soloTest); // test_ if (memberName.startsWith('test_')) { @@ -162,15 +145,13 @@ void defineReflectiveTests(Type type) { _addTestsIfTopLevelSuite(); } -/** - * If the current suite is the top-level one, add tests to the `test` package. - */ +/// If the current suite is the top-level one, add tests to the `test` package. void _addTestsIfTopLevelSuite() { if (_currentSuiteLevel == 0) { void runTests({required bool allGroups, required bool allTests}) { - for (_Group group in _currentGroups) { + for (var group in _currentGroups) { if (allGroups || group.isSolo) { - for (_Test test in group.tests) { + for (var test in group.tests) { if (allTests || test.isSolo) { test_package.test(test.name, test.function, timeout: test.timeout, skip: test.isSkipped); @@ -191,10 +172,8 @@ void _addTestsIfTopLevelSuite() { } } -/** - * Return the combination of the [base] and [addition] names. - * If any other two is `null`, then the other one is returned. - */ +/// Return the combination of the [base] and [addition] names. +/// If any other two is `null`, then the other one is returned. String _combineNames(String base, String addition) { if (base.isEmpty) { return addition; @@ -206,15 +185,15 @@ String _combineNames(String base, String addition) { } Object? _getAnnotationInstance(DeclarationMirror declaration, Type type) { - for (InstanceMirror annotation in declaration.metadata) { - if (annotation.reflectee.runtimeType == type) { + for (var annotation in declaration.metadata) { + if ((annotation.reflectee as Object).runtimeType == type) { return annotation.reflectee; } } return null; } -bool _hasAnnotationInstance(DeclarationMirror declaration, instance) => +bool _hasAnnotationInstance(DeclarationMirror declaration, Object instance) => declaration.metadata.any((InstanceMirror annotation) => identical(annotation.reflectee, instance)); @@ -233,6 +212,7 @@ Future _invokeSymbolIfExists( InstanceMirror? closure; try { closure = instanceMirror.getField(symbol); + // ignore: avoid_catching_errors } on NoSuchMethodError { // ignore } @@ -243,24 +223,23 @@ Future _invokeSymbolIfExists( return Future.value(invocationResult); } -/** - * Run a test that is expected to fail, and confirm that it fails. - * - * This properly handles the following cases: - * - The test fails by throwing an exception - * - The test returns a future which completes with an error. - * - An exception is thrown to the zone handler from a timer task. - */ +/// Run a test that is expected to fail, and confirm that it fails. +/// +/// This properly handles the following cases: +/// - The test fails by throwing an exception +/// - The test returns a future which completes with an error. +/// - An exception is thrown to the zone handler from a timer task. Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { - bool passed = false; + var passed = false; return runZonedGuarded(() { // ignore: void_checks return Future.sync(() => _runTest(classMirror, symbol)).then((_) { passed = true; test_package.fail('Test passed - expected to fail.'); - }).catchError((e) { + }).catchError((Object e) { // if passed, and we call fail(), rethrow this exception if (passed) { + // ignore: only_throw_errors throw e; } // otherwise, an exception is not a failure for _runFailingTest @@ -268,71 +247,60 @@ Future? _runFailingTest(ClassMirror classMirror, Symbol symbol) { }, (e, st) { // if passed, and we call fail(), rethrow this exception if (passed) { + // ignore: only_throw_errors throw e; } // otherwise, an exception is not a failure for _runFailingTest }); } -Future _runTest(ClassMirror classMirror, Symbol symbol) { - InstanceMirror instanceMirror = classMirror.newInstance(Symbol(''), []); - return _invokeSymbolIfExists(instanceMirror, #setUp) - .then((_) => instanceMirror.invoke(symbol, []).reflectee) - .whenComplete(() => _invokeSymbolIfExists(instanceMirror, #tearDown)); +Future _runTest(ClassMirror classMirror, Symbol symbol) async { + var instanceMirror = classMirror.newInstance(const Symbol(''), []); + try { + await _invokeSymbolIfExists(instanceMirror, #setUp); + await instanceMirror.invoke(symbol, []).reflectee; + } finally { + await _invokeSymbolIfExists(instanceMirror, #tearDown); + } } typedef _TestFunction = dynamic Function(); -/** - * A marker annotation used to annotate test methods which are expected to fail. - */ +/// A marker annotation used to annotate test methods which are expected to +/// fail. class FailingTest { - /** - * Initialize this annotation with the given arguments. - * - * [issue] is a full URI describing the failure and used for tracking. - * [reason] is a free form textual description. - */ + /// Initialize this annotation with the given arguments. + /// + /// [issue] is a full URI describing the failure and used for tracking. + /// [reason] is a free form textual description. const FailingTest({String? issue, String? reason}); } -/** - * A marker annotation used to annotate test methods which are skipped. - */ +/// A marker annotation used to annotate test methods which are skipped. class SkippedTest { - /** - * Initialize this annotation with the given arguments. - * - * [issue] is a full URI describing the failure and used for tracking. - * [reason] is a free form textual description. - */ + /// Initialize this annotation with the given arguments. + /// + /// [issue] is a full URI describing the failure and used for tracking. + /// [reason] is a free form textual description. const SkippedTest({String? issue, String? reason}); } -/** - * A marker annotation used to annotate test methods with additional timeout - * information. - */ +/// A marker annotation used to annotate test methods with additional timeout +/// information. class TestTimeout { final test_package.Timeout _timeout; - /** - * Initialize this annotation with the given timeout. - */ + /// Initialize this annotation with the given timeout. const TestTimeout(test_package.Timeout timeout) : _timeout = timeout; } -/** - * A marker annotation used to annotate test methods which are expected to fail - * when asserts are enabled. - */ +/// A marker annotation used to annotate test methods which are expected to fail +/// when asserts are enabled. class _AssertFailingTest { const _AssertFailingTest(); } -/** - * Information about a type based test group. - */ +/// Information about a type based test group. class _Group { final bool isSolo; final String name; @@ -356,24 +324,18 @@ class _Group { } } -/** - * A marker annotation used to instruct dart2js to keep reflection information - * for the annotated classes. - */ +/// A marker annotation used to instruct dart2js to keep reflection information +/// for the annotated classes. class _ReflectiveTest { const _ReflectiveTest(); } -/** - * A marker annotation used to annotate "solo" groups and tests. - */ +/// A marker annotation used to annotate "solo" groups and tests. class _SoloTest { const _SoloTest(); } -/** - * Information about a test. - */ +/// Information about a test. class _Test { final bool isSolo; final String name; diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index e4de919ee..c30323c7c 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,13 +1,13 @@ name: test_reflective_loader -version: 0.2.2 +version: 0.2.3-wip description: Support for discovering tests and test suites using reflection. repository: https://github.com/dart-lang/test_reflective_loader environment: - sdk: '>=2.12.0 <3.0.0' + sdk: ^3.1.0 dependencies: test: ^1.16.0 dev_dependencies: - lints: ^2.0.0 + dart_flutter_team_lints: ^2.0.0 diff --git a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart index ea7911f7f..fad98a5a1 100644 --- a/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart +++ b/pkgs/test_reflective_loader/test/test_reflective_loader_test.dart @@ -28,7 +28,7 @@ class TestReflectiveLoaderTest { @failingTest void test_fails_throws_sync() { - throw 'foo'; + throw StateError('foo'); } @failingTest @@ -38,7 +38,7 @@ class TestReflectiveLoaderTest { @skippedTest void test_fails_but_skipped() { - throw 'foo'; + throw StateError('foo'); } @skippedTest From bcb8977e840566a37fa4aba96755190e2ce60b5c Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Fri, 1 Dec 2023 16:48:31 +0000 Subject: [PATCH 1054/1215] Fix PollingFileWatcher.ready for files that don't exist (dart-lang/watcher#157) There were a few issues here: - FileWatcher.ready never fired for files that don't exist because of logic inside FileWatcher existing early if the modification time was `null` - The test I recently added trying to catch this was incorrectly passing because the mock timestamp code was set so that files that had not been created would return a 0-mtime whereas in the real implementation they return `null` So this change a) updates the mock to return `null` for uncreated files (to match the real implementation) which breaks a bunch of tests b) fixes those tests by updating FileWatcher._poll() to handle `null` mtime separately from being the first poll. --- pkgs/watcher/CHANGELOG.md | 2 ++ .../watcher/lib/src/file_watcher/polling.dart | 36 ++++++++++++------- pkgs/watcher/lib/src/stat.dart | 2 +- pkgs/watcher/test/utils.dart | 22 ++++++++++-- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 7743fc7a3..7893dafa8 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,5 +1,7 @@ ## 1.1.1-wip +- Ensure `PollingFileWatcher.ready` completes for files that do not exist. + ## 1.1.0 - Require Dart SDK >= 3.0.0 diff --git a/pkgs/watcher/lib/src/file_watcher/polling.dart b/pkgs/watcher/lib/src/file_watcher/polling.dart index 6f1eee4fd..15ff9ab8e 100644 --- a/pkgs/watcher/lib/src/file_watcher/polling.dart +++ b/pkgs/watcher/lib/src/file_watcher/polling.dart @@ -39,8 +39,7 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { /// The previous modification time of the file. /// - /// Used to tell when the file was modified. This is `null` before the file's - /// mtime has first been checked. + /// `null` indicates the file does not (or did not on the last poll) exist. DateTime? _lastModified; _PollingFileWatcher(this.path, Duration pollingDelay) { @@ -50,13 +49,14 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { /// Checks the mtime of the file and whether it's been removed. Future _poll() async { - // We don't mark the file as removed if this is the first poll (indicated by - // [_lastModified] being null). Instead, below we forward the dart:io error - // that comes from trying to read the mtime below. + // We don't mark the file as removed if this is the first poll. Instead, + // below we forward the dart:io error that comes from trying to read the + // mtime below. var pathExists = await File(path).exists(); if (_eventsController.isClosed) return; if (_lastModified != null && !pathExists) { + _flagReady(); _eventsController.add(WatchEvent(ChangeType.REMOVE, path)); unawaited(close()); return; @@ -67,22 +67,34 @@ class _PollingFileWatcher implements FileWatcher, ManuallyClosedWatcher { modified = await modificationTime(path); } on FileSystemException catch (error, stackTrace) { if (!_eventsController.isClosed) { + _flagReady(); _eventsController.addError(error, stackTrace); await close(); } } - if (_eventsController.isClosed) return; - - if (_lastModified == modified) return; + if (_eventsController.isClosed) { + _flagReady(); + return; + } - if (_lastModified == null) { + if (!isReady) { // If this is the first poll, don't emit an event, just set the last mtime // and complete the completer. _lastModified = modified; + _flagReady(); + return; + } + + if (_lastModified == modified) return; + + _lastModified = modified; + _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); + } + + /// Flags this watcher as ready if it has not already been done. + void _flagReady() { + if (!isReady) { _readyCompleter.complete(); - } else { - _lastModified = modified; - _eventsController.add(WatchEvent(ChangeType.MODIFY, path)); } } diff --git a/pkgs/watcher/lib/src/stat.dart b/pkgs/watcher/lib/src/stat.dart index 06e3febf4..fe0f15578 100644 --- a/pkgs/watcher/lib/src/stat.dart +++ b/pkgs/watcher/lib/src/stat.dart @@ -6,7 +6,7 @@ import 'dart:io'; /// A function that takes a file path and returns the last modified time for /// the file at that path. -typedef MockTimeCallback = DateTime Function(String path); +typedef MockTimeCallback = DateTime? Function(String path); MockTimeCallback? _mockTimeCallback; diff --git a/pkgs/watcher/test/utils.dart b/pkgs/watcher/test/utils.dart index 214d66966..7867b9fc2 100644 --- a/pkgs/watcher/test/utils.dart +++ b/pkgs/watcher/test/utils.dart @@ -67,7 +67,7 @@ Future startWatcher({String? path}) async { 'Path is not in the sandbox: $path not in ${d.sandbox}'); var mtime = _mockFileModificationTimes[normalized]; - return DateTime.fromMillisecondsSinceEpoch(mtime ?? 0); + return mtime != null ? DateTime.fromMillisecondsSinceEpoch(mtime) : null; }); // We want to wait until we're ready *after* we subscribe to the watcher's @@ -195,6 +195,11 @@ Future expectRemoveEvent(String path) => Future allowModifyEvent(String path) => _expectOrCollect(mayEmit(isWatchEvent(ChangeType.MODIFY, path))); +/// Track a fake timestamp to be used when writing files. This always increases +/// so that files that are deleted and re-created do not have their timestamp +/// set back to a previously used value. +int _nextTimestamp = 1; + /// Schedules writing a file in the sandbox at [path] with [contents]. /// /// If [contents] is omitted, creates an empty file. If [updateModified] is @@ -216,14 +221,15 @@ void writeFile(String path, {String? contents, bool? updateModified}) { if (updateModified) { path = p.normalize(path); - _mockFileModificationTimes.update(path, (value) => value + 1, - ifAbsent: () => 1); + _mockFileModificationTimes[path] = _nextTimestamp++; } } /// Schedules deleting a file in the sandbox at [path]. void deleteFile(String path) { File(p.join(d.sandbox, path)).deleteSync(); + + _mockFileModificationTimes.remove(path); } /// Schedules renaming a file in the sandbox from [from] to [to]. @@ -245,6 +251,16 @@ void createDir(String path) { /// Schedules renaming a directory in the sandbox from [from] to [to]. void renameDir(String from, String to) { Directory(p.join(d.sandbox, from)).renameSync(p.join(d.sandbox, to)); + + // Migrate timestamps for any files in this folder. + final knownFilePaths = _mockFileModificationTimes.keys.toList(); + for (final filePath in knownFilePaths) { + if (p.isWithin(from, filePath)) { + _mockFileModificationTimes[filePath.replaceAll(from, to)] = + _mockFileModificationTimes[filePath]!; + _mockFileModificationTimes.remove(filePath); + } + } } /// Schedules deleting a directory in the sandbox at [path]. From b30d7f7e8ee72950e0562c42a19a57cbd8ee56bc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Dec 2023 10:30:39 -0800 Subject: [PATCH 1055/1215] Update to latest lints and cleanup (dart-lang/string_scanner#67) --- pkgs/string_scanner/analysis_options.yaml | 6 ------ pkgs/string_scanner/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 0b975913d..813466b66 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -13,27 +13,21 @@ linter: - avoid_classes_with_only_static_members - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_returning_null_for_future - avoid_returning_this - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - - comment_references - join_return_with_assignment - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_relative_imports - - test_types_in_equals - unnecessary_await_in_return - unnecessary_raw_strings - use_if_null_to_convert_nulls_to_bools - use_raw_strings - use_string_buffers - - use_super_parameters diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 40682ecb1..7ceb7d983 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -10,5 +10,5 @@ dependencies: source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 From 4bfe3cb099c34967cec38c7e4252022a8a610878 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 4 Dec 2023 10:30:52 -0800 Subject: [PATCH 1056/1215] drop outdated lints (dart-lang/term_glyph#46) --- pkgs/term_glyph/analysis_options.yaml | 7 ------- pkgs/term_glyph/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index fc4afe346..d16ad8251 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -13,28 +13,21 @@ linter: - avoid_classes_with_only_static_members - avoid_private_typedef_functions - avoid_redundant_argument_values - - avoid_returning_null - - avoid_returning_null_for_future - avoid_returning_this - avoid_unused_constructor_parameters - avoid_void_async - cancel_subscriptions - - comment_references - join_return_with_assignment - literal_only_boolean_expressions - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - package_api_docs - - prefer_const_constructors - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals - - prefer_relative_imports - - test_types_in_equals - unnecessary_await_in_return - unnecessary_breaks - use_if_null_to_convert_nulls_to_bools - use_raw_strings - use_string_buffers - - use_super_parameters diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 5a7702044..76eb5bed1 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -8,6 +8,6 @@ environment: dev_dependencies: csv: ^5.0.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 dart_style: ^2.0.0 test: ^1.16.0 From 0dc94f552da3f473aee3fac93b4943abc6c2145c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 20 Dec 2023 10:00:52 -0800 Subject: [PATCH 1057/1215] blast_repo fixes (dart-lang/watcher#160) no-response --- .../watcher/.github/workflows/no-response.yml | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/pkgs/watcher/.github/workflows/no-response.yml b/pkgs/watcher/.github/workflows/no-response.yml index ac3e456ec..8e5ed57cd 100644 --- a/pkgs/watcher/.github/workflows/no-response.yml +++ b/pkgs/watcher/.github/workflows/no-response.yml @@ -1,12 +1,10 @@ # A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/godofredoc/no-response for docs. +# more information; see https://github.com/actions/stale. name: No Response -# Both `issue_comment` and `scheduled` event types are required. +# Run as a daily cron. on: - issue_comment: - types: [created] schedule: # Every day at 8am - cron: '0 8 * * *' @@ -14,21 +12,26 @@ on: # All permissions not specified are set to 'none'. permissions: issues: write + pull-requests: write jobs: - noResponse: + no-response: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: godofredoc/no-response@0ce2dc0e63e1c7d2b87752ceed091f6d32c9df09 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 with: - responseRequiredLabel: "needs-info" - responseRequiredColor: 4774bc - daysUntilClose: 14 - # Comment to post when closing an Issue for lack of response. - closeComment: > - Without additional information we're not able to resolve this issue, - so it will be closed at this time. You're still free to add more - info and respond to any questions above, though. We'll reopen the - issue if you do. Thanks for your contribution! - token: ${{ github.token }} + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! From 62c7735ea1f3dd7518fa4a7cf2b823dd3b193108 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 08:49:33 +0000 Subject: [PATCH 1058/1215] Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/watcher#161) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0.
Release notes

Sourced from actions/stale's releases.

v9.0.0

Breaking Changes

  1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
  2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

What Else Changed

  1. Performance optimization that removes unnecessary API calls by @​dsame dart-lang/watcher#1033 fixes dart-lang/watcher#792
  2. Logs displaying current github API rate limit by @​dsame dart-lang/watcher#1032 addresses dart-lang/watcher#1029

For more information, please read the action documentation and its section about statefulness

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v8...v9.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=8.0.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/watcher/.github/workflows/no-response.yml b/pkgs/watcher/.github/workflows/no-response.yml index 8e5ed57cd..ab1ac4984 100644 --- a/pkgs/watcher/.github/workflows/no-response.yml +++ b/pkgs/watcher/.github/workflows/no-response.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e with: # Don't automatically mark inactive issues+PRs as stale. days-before-stale: -1 From ed27d9c5005c7d989f3bcff6a7714168fb4a61e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 10:25:09 +0000 Subject: [PATCH 1059/1215] Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/stack_trace#148) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/stale](https://github.com/actions/stale) from 8.0.0 to 9.0.0.
Release notes

Sourced from actions/stale's releases.

v9.0.0

Breaking Changes

  1. Action is now stateful: If the action ends because of operations-per-run then the next run will start from the first unprocessed issue skipping the issues processed during the previous run(s). The state is reset when all the issues are processed. This should be considered for scheduling workflow runs.
  2. Version 9 of this action updated the runtime to Node.js 20. All scripts are now run with Node.js 20 instead of Node.js 16 and are affected by any breaking changes between Node.js 16 and 20.

What Else Changed

  1. Performance optimization that removes unnecessary API calls by @​dsame dart-lang/stack_trace#1033 fixes dart-lang/stack_trace#792
  2. Logs displaying current github API rate limit by @​dsame dart-lang/stack_trace#1032 addresses dart-lang/stack_trace#1029

For more information, please read the action documentation and its section about statefulness

New Contributors

Full Changelog: https://github.com/actions/stale/compare/v8...v9.0.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/stale&package-manager=github_actions&previous-version=8.0.0&new-version=9.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/no-response.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stack_trace/.github/workflows/no-response.yml b/pkgs/stack_trace/.github/workflows/no-response.yml index 8e5ed57cd..ab1ac4984 100644 --- a/pkgs/stack_trace/.github/workflows/no-response.yml +++ b/pkgs/stack_trace/.github/workflows/no-response.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest if: ${{ github.repository_owner == 'dart-lang' }} steps: - - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e with: # Don't automatically mark inactive issues+PRs as stale. days-before-stale: -1 From 5c80b48e619d76c1b6dee6169e21b0badd8067ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 00:36:17 +0000 Subject: [PATCH 1060/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/string_scanner#68) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 4cb7d3a73..4e4e97d8d 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From bded33171a1d7f4fcb13f08acbfd20e4ed865f3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 01:23:56 +0000 Subject: [PATCH 1061/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/timing#40) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/timing#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/timing#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 132c4fc71..f2a55cd3d 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 1cf10a4534934b70ecb55e442288c8471b51f9e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 03:27:16 +0000 Subject: [PATCH 1062/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/stream_channel#99) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 02786315a..41ca6901b 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [2.19.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 95bd915e9e9991dc7e982d12b4238c6cc25010d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 05:25:50 +0000 Subject: [PATCH 1063/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/pubspec_parse#120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 36ed6216e..e2b6fb688 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 13a1499706d215f1404f03ab93645b94c9c0aa2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:17:32 +0000 Subject: [PATCH 1064/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/watcher#162) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/watcher#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/watcher#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index d72e17b92..771d535ae 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 8ac9fdc0dfb7b91fde1b3b2f84fca6e063029a26 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:24:04 +0000 Subject: [PATCH 1065/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/stack_trace#149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 030f9a4d3..0569bf5b7 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From f75e9197b1f1c1758ddb4ebd7ea2f0a7ed697bf1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:35:13 +0000 Subject: [PATCH 1066/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/term_glyph#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available in an environment variable, DART_HOME (dart-lang/term_glyph#43).
  • Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (dart-lang/term_glyph#35).

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 38ced1a4f..84cd3ea5c 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 1db723d5dc439b923ecd87c80b026409d7c62e7c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 07:59:34 -0800 Subject: [PATCH 1067/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/stream_transform#180) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/b64355ae6ca0b5d484f0106a033dd1388965d06d...fedb1266e91cf51be2fdb382869461a434b920a3) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index b23f0fc46..b5e6a5ee7 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 8f06600eee0193c040307267ae36fb81ef6b0f00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:26:15 +0000 Subject: [PATCH 1068/1215] Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/test_reflective_loader#57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.0 to 1.6.2.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

v1.2.0

  • Fixed a path issue impacting git dependencies on Windows.

v1.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.0&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 9ebdc1f3d..8ca97a727 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From c7eef23aa9b3bec0b88418612be76997136775c4 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 16 Feb 2024 16:46:43 -0800 Subject: [PATCH 1069/1215] blast_repo fixes (dart-lang/stream_channel#101) auto-publish, github-actions, no-response --- .../.github/workflows/no-response.yml | 37 +++++++++++++++++++ .../.github/workflows/publish.yaml | 17 +++++++++ 2 files changed, 54 insertions(+) create mode 100644 pkgs/stream_channel/.github/workflows/no-response.yml create mode 100644 pkgs/stream_channel/.github/workflows/publish.yaml diff --git a/pkgs/stream_channel/.github/workflows/no-response.yml b/pkgs/stream_channel/.github/workflows/no-response.yml new file mode 100644 index 000000000..ab1ac4984 --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/stream_channel/.github/workflows/publish.yaml b/pkgs/stream_channel/.github/workflows/publish.yaml new file mode 100644 index 000000000..27157a046 --- /dev/null +++ b/pkgs/stream_channel/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From 45fbe108fd38b1f1134b76ce85ab56b2f96d48e3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 16 Feb 2024 17:47:01 -0800 Subject: [PATCH 1070/1215] Require Dart 3.3, update and fix lints (dart-lang/stream_channel#100) --- .../.github/workflows/test-package.yml | 2 +- pkgs/stream_channel/CHANGELOG.md | 4 ++ pkgs/stream_channel/example/example.dart | 6 +-- pkgs/stream_channel/lib/src/disconnector.dart | 2 +- .../lib/src/guarantee_channel.dart | 2 +- .../lib/src/isolate_channel.dart | 2 +- .../stream_channel/lib/src/multi_channel.dart | 3 +- .../lib/src/stream_channel_completer.dart | 2 +- pkgs/stream_channel/pubspec.yaml | 6 +-- .../test/disconnector_test.dart | 16 +++---- .../test/isolate_channel_test.dart | 8 ++-- .../test/json_document_transformer_test.dart | 2 +- .../test/stream_channel_completer_test.dart | 4 +- .../test/stream_channel_test.dart | 44 +++++++++++++------ .../test/with_close_guarantee_test.dart | 2 +- .../test/with_guarantees_test.dart | 16 +++---- 16 files changed, 71 insertions(+), 50 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 41ca6901b..db6451bcf 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [2.19.0, dev] + sdk: [3.3, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index c78f64f0e..4b8e2b54a 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.1.3-wip + +* Require Dart 3.3 + ## 2.1.2 * Require Dart 2.19 diff --git a/pkgs/stream_channel/example/example.dart b/pkgs/stream_channel/example/example.dart index dd16f6750..b41d8d94a 100644 --- a/pkgs/stream_channel/example/example.dart +++ b/pkgs/stream_channel/example/example.dart @@ -22,7 +22,7 @@ Future main() async { // For example, we can handle standard input as strings: var stringChannel = stdioChannel .transform(StreamChannelTransformer.fromCodec(utf8)) - .transformStream(LineSplitter()); + .transformStream(const LineSplitter()); stringChannel.sink.add('world!\n'); // You can implement StreamChannel by extending StreamChannelMixin, but @@ -84,8 +84,8 @@ Future main() async { // given the corresponding `SendPort`, and then call // `IsolateChannel.connectSend`. var recv = ReceivePort(); - var recvChannel = IsolateChannel.connectReceive(recv); - var sendChannel = IsolateChannel.connectSend(recv.sendPort); + var recvChannel = IsolateChannel.connectReceive(recv); + var sendChannel = IsolateChannel.connectSend(recv.sendPort); // You must manually close `IsolateChannel` sinks, however. await recvChannel.sink.close(); diff --git a/pkgs/stream_channel/lib/src/disconnector.dart b/pkgs/stream_channel/lib/src/disconnector.dart index 61969cbf8..3414e9c77 100644 --- a/pkgs/stream_channel/lib/src/disconnector.dart +++ b/pkgs/stream_channel/lib/src/disconnector.dart @@ -38,7 +38,7 @@ class Disconnector implements StreamChannelTransformer { _sinks.clear(); return Future.wait(futures, eagerError: true); }); - final _disconnectMemo = AsyncMemoizer(); + final _disconnectMemo = AsyncMemoizer>(); @override StreamChannel bind(StreamChannel channel) { diff --git a/pkgs/stream_channel/lib/src/guarantee_channel.dart b/pkgs/stream_channel/lib/src/guarantee_channel.dart index 2aa8b7b97..30ebe2ec6 100644 --- a/pkgs/stream_channel/lib/src/guarantee_channel.dart +++ b/pkgs/stream_channel/lib/src/guarantee_channel.dart @@ -83,7 +83,7 @@ class _GuaranteeSink implements StreamSink { @override Future get done => _doneCompleter.future; - final _doneCompleter = Completer(); + final _doneCompleter = Completer(); /// Whether connection is disconnected. /// diff --git a/pkgs/stream_channel/lib/src/isolate_channel.dart b/pkgs/stream_channel/lib/src/isolate_channel.dart index 3fbd46d23..15c68a41d 100644 --- a/pkgs/stream_channel/lib/src/isolate_channel.dart +++ b/pkgs/stream_channel/lib/src/isolate_channel.dart @@ -51,7 +51,7 @@ class IsolateChannel extends StreamChannelMixin { .transform(StreamSinkTransformer.fromHandlers(handleDone: (sink) { if (!isCompleted) { receivePort.close(); - streamCompleter.setSourceStream(Stream.empty()); + streamCompleter.setSourceStream(const Stream.empty()); sinkCompleter.setDestinationSink(NullStreamSink()); } sink.close(); diff --git a/pkgs/stream_channel/lib/src/multi_channel.dart b/pkgs/stream_channel/lib/src/multi_channel.dart index 82f59c7c9..48942392e 100644 --- a/pkgs/stream_channel/lib/src/multi_channel.dart +++ b/pkgs/stream_channel/lib/src/multi_channel.dart @@ -191,7 +191,8 @@ class _MultiChannel extends StreamChannelMixin // If the inner channel has already closed, create new virtual channels in a // closed state. if (_inner == null) { - return VirtualChannel._(this, inputId, Stream.empty(), NullStreamSink()); + return VirtualChannel._( + this, inputId, const Stream.empty(), NullStreamSink()); } late StreamChannelController controller; diff --git a/pkgs/stream_channel/lib/src/stream_channel_completer.dart b/pkgs/stream_channel/lib/src/stream_channel_completer.dart index 5a824c1f3..9d007eb6c 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_completer.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_completer.dart @@ -34,7 +34,7 @@ class StreamChannelCompleter { /// instead contain just that error. The sink will silently discard all /// events. static StreamChannel fromFuture(Future channelFuture) { - var completer = StreamChannelCompleter(); + var completer = StreamChannelCompleter(); channelFuture.then(completer.setChannel, onError: completer.setError); return completer.channel; } diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0b4f62d4e..0cfd074a5 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,16 +1,16 @@ name: stream_channel -version: 2.1.2 +version: 2.1.3-wip description: >- An abstraction for two-way communication channels based on the Dart Stream class. repository: https://github.com/dart-lang/stream_channel environment: - sdk: '>=2.19.0 <3.0.0' + sdk: ^3.3.0 dependencies: async: ^2.5.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 test: ^1.16.0 diff --git a/pkgs/stream_channel/test/disconnector_test.dart b/pkgs/stream_channel/test/disconnector_test.dart index 28f3fee9a..bbba568ed 100644 --- a/pkgs/stream_channel/test/disconnector_test.dart +++ b/pkgs/stream_channel/test/disconnector_test.dart @@ -14,8 +14,8 @@ void main() { late Disconnector disconnector; late StreamChannel channel; setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); disconnector = Disconnector(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink) @@ -52,7 +52,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -67,7 +67,7 @@ void main() { test('cancels addStream when disconnected', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); expect(channel.sink.addStream(controller.stream), completes); @@ -78,9 +78,9 @@ void main() { }); test('disconnect() returns the close future from the inner sink', () async { - var streamController = StreamController(); - var sinkController = StreamController(); - var disconnector = Disconnector(); + var streamController = StreamController(); + var sinkController = StreamController(); + var disconnector = Disconnector(); var sink = _CloseCompleterSink(sinkController.sink); StreamChannel.withGuarantees(streamController.stream, sink) .transform(disconnector); @@ -140,7 +140,7 @@ void main() { /// returned by [close] using [completer]. class _CloseCompleterSink extends DelegatingStreamSink { /// The completer for the future returned by [close]. - final completer = Completer(); + final completer = Completer(); _CloseCompleterSink(super.inner); diff --git a/pkgs/stream_channel/test/isolate_channel_test.dart b/pkgs/stream_channel/test/isolate_channel_test.dart index 10f1fe53e..3a8b42e9b 100644 --- a/pkgs/stream_channel/test/isolate_channel_test.dart +++ b/pkgs/stream_channel/test/isolate_channel_test.dart @@ -53,7 +53,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -109,7 +109,7 @@ void main() { test('the sink closes as soon as an error is added via addStream', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); @@ -156,7 +156,7 @@ void main() { test('the receiving channel produces an error if it gets the wrong message', () { - var connectedChannel = IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); connectPort.sendPort.send('wrong value'); expect(connectedChannel.stream.toList(), throwsStateError); @@ -165,7 +165,7 @@ void main() { test('the receiving channel closes gracefully without a connection', () async { - var connectedChannel = IsolateChannel.connectReceive(connectPort); + var connectedChannel = IsolateChannel.connectReceive(connectPort); await connectedChannel.sink.close(); await expectLater(connectedChannel.stream.toList(), completion(isEmpty)); await expectLater(connectedChannel.sink.done, completes); diff --git a/pkgs/stream_channel/test/json_document_transformer_test.dart b/pkgs/stream_channel/test/json_document_transformer_test.dart index 48d8f7291..290c4e2c3 100644 --- a/pkgs/stream_channel/test/json_document_transformer_test.dart +++ b/pkgs/stream_channel/test/json_document_transformer_test.dart @@ -41,6 +41,6 @@ void main() { test('synchronously throws if an unencodable object is added', () { var transformed = channel.transform(jsonDocument); expect(() => transformed.sink.add(Object()), - throwsA(TypeMatcher())); + throwsA(const TypeMatcher())); }); } diff --git a/pkgs/stream_channel/test/stream_channel_completer_test.dart b/pkgs/stream_channel/test/stream_channel_completer_test.dart index 22db01a76..c6fddc011 100644 --- a/pkgs/stream_channel/test/stream_channel_completer_test.dart +++ b/pkgs/stream_channel/test/stream_channel_completer_test.dart @@ -14,8 +14,8 @@ void main() { late StreamChannel innerChannel; setUp(() { completer = StreamChannelCompleter(); - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); innerChannel = StreamChannel(streamController.stream, sinkController.sink); }); diff --git a/pkgs/stream_channel/test/stream_channel_test.dart b/pkgs/stream_channel/test/stream_channel_test.dart index 76edbdf91..c44b6ab6f 100644 --- a/pkgs/stream_channel/test/stream_channel_test.dart +++ b/pkgs/stream_channel/test/stream_channel_test.dart @@ -10,21 +10,17 @@ import 'package:stream_channel/stream_channel.dart'; import 'package:test/test.dart'; void main() { - late StreamController streamController; - late StreamController sinkController; - late StreamChannel channel; - setUp(() { - streamController = StreamController(); - sinkController = StreamController(); - channel = StreamChannel(streamController.stream, sinkController.sink); - }); - test("pipe() pipes data from each channel's stream into the other's sink", () { - var otherStreamController = StreamController(); - var otherSinkController = StreamController(); + var otherStreamController = StreamController(); + var otherSinkController = StreamController(); var otherChannel = StreamChannel(otherStreamController.stream, otherSinkController.sink); + + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + channel.pipe(otherChannel); streamController.add(1); @@ -41,6 +37,10 @@ void main() { }); test('transform() transforms the channel', () async { + var streamController = StreamController>(); + var sinkController = StreamController>(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel .cast>() .transform(StreamChannelTransformer.fromCodec(utf8)); @@ -59,6 +59,10 @@ void main() { }); test('transformStream() transforms only the stream', () async { + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel.cast().transformStream(const LineSplitter()); @@ -75,8 +79,12 @@ void main() { }); test('transformSink() transforms only the sink', () async { + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + var transformed = channel.cast().transformSink( - StreamSinkTransformer.fromStreamTransformer(const LineSplitter())); + const StreamSinkTransformer.fromStreamTransformer(LineSplitter())); streamController.add('fbl\nthp'); unawaited(streamController.close()); @@ -91,7 +99,11 @@ void main() { }); test('changeStream() changes the stream', () { - var newController = StreamController(); + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + + var newController = StreamController(); var changed = channel.changeStream((stream) { expect(stream, equals(channel.stream)); return newController.stream; @@ -107,7 +119,11 @@ void main() { }); test('changeSink() changes the sink', () { - var newController = StreamController(); + var streamController = StreamController(); + var sinkController = StreamController(); + var channel = StreamChannel(streamController.stream, sinkController.sink); + + var newController = StreamController(); var changed = channel.changeSink((sink) { expect(sink, equals(channel.sink)); return newController.sink; diff --git a/pkgs/stream_channel/test/with_close_guarantee_test.dart b/pkgs/stream_channel/test/with_close_guarantee_test.dart index a18f09fe1..9c0b72998 100644 --- a/pkgs/stream_channel/test/with_close_guarantee_test.dart +++ b/pkgs/stream_channel/test/with_close_guarantee_test.dart @@ -45,7 +45,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) - .asFuture(), + .asFuture(), completes); await pumpEventQueue(); diff --git a/pkgs/stream_channel/test/with_guarantees_test.dart b/pkgs/stream_channel/test/with_guarantees_test.dart index 849e30491..f026079fb 100644 --- a/pkgs/stream_channel/test/with_guarantees_test.dart +++ b/pkgs/stream_channel/test/with_guarantees_test.dart @@ -12,8 +12,8 @@ void main() { late StreamController sinkController; late StreamChannel channel; setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink); }); @@ -53,7 +53,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.close(); }, count: 2)) - .asFuture(), + .asFuture(), completes); }); @@ -126,7 +126,7 @@ void main() { }); test("events can't be added while a stream is being added", () { - var controller = StreamController(); + var controller = StreamController(); channel.sink.addStream(controller.stream); expect(() => channel.sink.add(1), throwsStateError); @@ -140,8 +140,8 @@ void main() { group('with allowSinkErrors: false', () { setUp(() { - streamController = StreamController(); - sinkController = StreamController(); + streamController = StreamController(); + sinkController = StreamController(); channel = StreamChannel.withGuarantees( streamController.stream, sinkController.sink, allowSinkErrors: false); @@ -166,7 +166,7 @@ void main() { .listen(expectAsync1((event) { if (event == 2) channel.sink.addError('oh no'); }, count: 2)) - .asFuture(), + .asFuture(), completes); }); @@ -180,7 +180,7 @@ void main() { 'adding an error via via addStream causes the stream to emit a done ' 'event', () async { var canceled = false; - var controller = StreamController(onCancel: () { + var controller = StreamController(onCancel: () { canceled = true; }); From 5d1f4fc82155c3e05c7316d991203b93692dbd71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:07:20 +0000 Subject: [PATCH 1071/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/string_scanner#70) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 4e4e97d8d..8f1b1a691 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From ccc92b5952cb3d6f21128439d7c8f2f179d5da4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:24:22 +0000 Subject: [PATCH 1072/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/stream_transform#181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index b5e6a5ee7..18a354d0e 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 176e08016176db0a1a4d25856a3f8334ad0eafff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:28:51 +0000 Subject: [PATCH 1073/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/timing#41) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index f2a55cd3d..990fbd56c 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 81110f1163e86a3cc90e2632d61cf6466ea5c269 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 03:21:07 +0000 Subject: [PATCH 1074/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/stream_channel#102) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index db6451bcf..b7d7d6e06 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From f625a17d724c3b7131d1fc885b9c84e97478e63c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 05:06:46 +0000 Subject: [PATCH 1075/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/pubspec_parse#122) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index e2b6fb688..4604052b0 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 19f39bef6b52c26e087a934698ef1a8f0c3bf809 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 08:30:19 +0000 Subject: [PATCH 1076/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/watcher#163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 771d535ae..ee023e050 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From b8bd35204cc97e7d6c615d009c01d8c5cf35a96b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 10:12:04 +0000 Subject: [PATCH 1077/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/stack_trace#150) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 0569bf5b7..2523e6999 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 6ec3f739f28256404a524151648e303df4b54b62 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 13:09:06 +0000 Subject: [PATCH 1078/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/term_glyph#48) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 84cd3ea5c..3e522b91d 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 14ed328d61b64d6c7de1495d49fe34ce7f3566f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 16:09:14 +0000 Subject: [PATCH 1079/1215] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/test_reflective_loader#58) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2.
Release notes

Sourced from actions/checkout's releases.

v4.1.2

We are investigating the following issue with this release and have rolled-back the v4 tag to point to v4.1.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.1...v4.1.2

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

v3.3.0

v3.2.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 8ca97a727..ef969b173 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 2d58436eefdc13d85fa5f7db0d2f59411274db7b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 10 Apr 2024 13:26:12 -0700 Subject: [PATCH 1080/1215] Bump to latest lints (dart-lang/timing#42) --- pkgs/timing/analysis_options.yaml | 1 + pkgs/timing/pubspec.yaml | 2 +- pkgs/timing/test/timing_test.dart | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/analysis_options.yaml b/pkgs/timing/analysis_options.yaml index d978f811c..396236d68 100644 --- a/pkgs/timing/analysis_options.yaml +++ b/pkgs/timing/analysis_options.yaml @@ -1 +1,2 @@ +# https://dart.dev/tools/analysis#the-analysis-options-file include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index f81c2fc9e..80270ba70 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -13,6 +13,6 @@ dependencies: dev_dependencies: build_runner: ^2.0.0 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 json_serializable: ^6.0.0 test: ^1.0.0 diff --git a/pkgs/timing/test/timing_test.dart b/pkgs/timing/test/timing_test.dart index 610cfceb3..b5836d9d2 100644 --- a/pkgs/timing/test/timing_test.dart +++ b/pkgs/timing/test/timing_test.dart @@ -2,7 +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. -// ignore_for_file: only_throw_errors +// ignore_for_file: only_throw_errors, inference_failure_on_instance_creation import 'dart:async'; From 2b9a8caf8dbe7aa965f07f5e25eae748e07da982 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 00:45:43 +0000 Subject: [PATCH 1081/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/string_scanner#72) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 8f1b1a691..b14a4082a 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 872796e31197bb0244f08cb0cdae0ee755e7482a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 01:16:09 +0000 Subject: [PATCH 1082/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/timing#43) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 990fbd56c..b4460314e 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 85781651607c8db5d6cd78ff7f31b593e87f7e3f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 01:18:04 +0000 Subject: [PATCH 1083/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/stream_transform#183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 18a354d0e..f15336676 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 9992ce8f4de7d2d7f173ea6a2cb891b4d33cd828 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 03:46:43 +0000 Subject: [PATCH 1084/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/stream_channel#103) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index b7d7d6e06..04dbcd2b3 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.3, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From b89f34e4d95593a40474e60b29b628608f42be8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 05:24:07 +0000 Subject: [PATCH 1085/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/pubspec_parse#123) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 4604052b0..5c3041ba7 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 14d8e8ec9db0860169f935f3f049d0b8d9b14a0e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 08:08:52 +0000 Subject: [PATCH 1086/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/watcher#164) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index ee023e050..94a146dd0 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From f13a03331db9163d66f61fbf95100ca8ad26cc4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 10:58:44 +0000 Subject: [PATCH 1087/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/stack_trace#152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 2523e6999..dad1066c3 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 4086768e98e0d1cafa94705e4f2051080ce3fabe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:25:56 +0000 Subject: [PATCH 1088/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/term_glyph#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 3e522b91d..9048acb25 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 41fa1df6414042697310a6bf67a2173fbf91783e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 13:28:42 +0000 Subject: [PATCH 1089/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/term_glyph#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 9048acb25..c5260d0dd 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From c249bfa84648530e902de207f40542bc64198df9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 07:28:28 -0700 Subject: [PATCH 1090/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/timing#44) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/fedb1266e91cf51be2fdb382869461a434b920a3...f0ead981b4d9a35b37f30d36160575d60931ec30) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index b4460314e..2c00371d4 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [3.0.0, dev] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 8a7cdbd56e2dd4d56491aaf5a9149cca894576d6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:17:52 +0000 Subject: [PATCH 1091/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/watcher#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 94a146dd0..7aab282af 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 30351163004ad88c6c6eeb2279ac28d295782fc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:17:55 +0000 Subject: [PATCH 1092/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/pubspec_parse#124) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 5c3041ba7..b43c40ef3 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From c67ff10a7e3e851eb728cc2168ed409a80ceb7b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:21:34 +0000 Subject: [PATCH 1093/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/string_scanner#71) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index b14a4082a..97fdf914e 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 6830fedac32002dbd727f049b351cb30a1b80e4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:23:06 +0000 Subject: [PATCH 1094/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/stream_transform#182) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index f15336676..e08b1d175 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From cfa01d1e3c429e53a079374d18a7eddaf023d032 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:29:38 +0000 Subject: [PATCH 1095/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/stack_trace#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index dad1066c3..2910dbd16 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 00f8ce7c416224d30500d84a88f79dcc815d7712 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 15:32:50 +0000 Subject: [PATCH 1096/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/stream_channel#104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 04dbcd2b3..811bb8040 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 1c91f5b5f52eaad2e404e78f3f22a500694cd28d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:21:20 +0000 Subject: [PATCH 1097/1215] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/test_reflective_loader#60) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4.
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.4

  • Rebuild JS code to include changes from v1.6.3

v1.6.3

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

  • Automatically create OIDC token for pub.dev.
  • Add a reusable workflow for publishing.

v1.3.0

  • The install location of the Dart SDK is now available

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index ef969b173..a733ade3a 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 39b7ebe40e73fd4cd6b00567ee74f369311fa943 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:22:56 +0000 Subject: [PATCH 1098/1215] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/test_reflective_loader#59) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4.
Release notes

Sourced from actions/checkout's releases.

v4.1.4

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.3...v4.1.4

v4.1.3

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.2...v4.1.3

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

v3.5.0

v3.4.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index a733ade3a..97f2c698c 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 135088e411acfe8546eca153c02d7f1c3bb8b386 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Thu, 9 May 2024 13:46:58 -0700 Subject: [PATCH 1099/1215] blast_repo fixes (dart-lang/pubspec_parse#125) dependabot --- pkgs/pubspec_parse/.github/dependabot.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/.github/dependabot.yml b/pkgs/pubspec_parse/.github/dependabot.yml index cf1a70501..cde02ad6a 100644 --- a/pkgs/pubspec_parse/.github/dependabot.yml +++ b/pkgs/pubspec_parse/.github/dependabot.yml @@ -3,9 +3,13 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly labels: - - "autosubmit" + - autosubmit + groups: + github-actions: + patterns: + - "*" From 7c2edadbdc44e080b0d29155b29b8e5606bd6a7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 May 2024 20:51:26 +0000 Subject: [PATCH 1100/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/pubspec_parse#126) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index b43c40ef3..b3f887735 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 2385bc7188f906b1927427d3ad2f7c594b46b4c9 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 10 May 2024 12:42:13 -0700 Subject: [PATCH 1101/1215] blast_repo fixes (dart-lang/timing#45) dependabot --- pkgs/timing/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/timing/.github/dependabot.yml b/pkgs/timing/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/timing/.github/dependabot.yml +++ b/pkgs/timing/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From e2de79737d06377e39820c1b37c4b6ea2fd0635d Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Fri, 10 May 2024 12:43:21 -0700 Subject: [PATCH 1102/1215] blast_repo fixes (dart-lang/test_reflective_loader#61) dependabot --- pkgs/test_reflective_loader/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/test_reflective_loader/.github/dependabot.yml b/pkgs/test_reflective_loader/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/test_reflective_loader/.github/dependabot.yml +++ b/pkgs/test_reflective_loader/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 387f5aed312f5130a039ba9489a364564a29e7f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 20:23:31 +0000 Subject: [PATCH 1103/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/test_reflective_loader#62) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 97f2c698c..338e0b8c5 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 278ea8e16bcb2eb58609213302ce9f4dff7c5bb0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 May 2024 20:23:32 +0000 Subject: [PATCH 1104/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/timing#46) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 2c00371d4..d09036523 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 1f7531bda2e58c53bb4049d13ed2b1bcab4e1964 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:35:39 -0700 Subject: [PATCH 1105/1215] blast_repo fixes (dart-lang/watcher#166) dependabot --- pkgs/watcher/.github/dependabot.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/watcher/.github/dependabot.yaml b/pkgs/watcher/.github/dependabot.yaml index 439e796b4..bf6b38a4d 100644 --- a/pkgs/watcher/.github/dependabot.yaml +++ b/pkgs/watcher/.github/dependabot.yaml @@ -8,3 +8,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 3c7d7b2c757be76efda63a0feeb33cd116d09db2 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:36:06 -0700 Subject: [PATCH 1106/1215] blast_repo fixes (dart-lang/term_glyph#51) dependabot --- pkgs/term_glyph/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/term_glyph/.github/dependabot.yml b/pkgs/term_glyph/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/term_glyph/.github/dependabot.yml +++ b/pkgs/term_glyph/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 9f26b26aa01b63256d2c009d92c56e1bbfc2d764 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:36:14 -0700 Subject: [PATCH 1107/1215] blast_repo fixes (dart-lang/stream_channel#105) dependabot --- pkgs/stream_channel/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/stream_channel/.github/dependabot.yml +++ b/pkgs/stream_channel/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From cc95d8605d58869f25768f7ad0de4643a175c6eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:38:26 +0000 Subject: [PATCH 1108/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/stream_channel#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 811bb8040..aad5df6f4 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From ad36f560ee27fd30f645af4ef0bb426217d3c674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:38:27 +0000 Subject: [PATCH 1109/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/watcher#167) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 7aab282af..eb75dcaa6 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 514bba1ea9b5c1ad1ccb73185cab1c3e0bfab8b4 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:38:31 -0700 Subject: [PATCH 1110/1215] blast_repo fixes (dart-lang/string_scanner#73) dependabot --- pkgs/string_scanner/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/string_scanner/.github/dependabot.yml b/pkgs/string_scanner/.github/dependabot.yml index c84404dc9..a19a66adf 100644 --- a/pkgs/string_scanner/.github/dependabot.yml +++ b/pkgs/string_scanner/.github/dependabot.yml @@ -10,3 +10,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From af9169477a3335eafd2b8e26a9768555ea12553b Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:38:39 -0700 Subject: [PATCH 1111/1215] blast_repo fixes (dart-lang/stack_trace#153) dependabot --- pkgs/stack_trace/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/stack_trace/.github/dependabot.yml b/pkgs/stack_trace/.github/dependabot.yml index fb01db0e6..706926934 100644 --- a/pkgs/stack_trace/.github/dependabot.yml +++ b/pkgs/stack_trace/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 8e0fdcb2c07f842c576f9211c50940a15b4fcb90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:39:15 +0000 Subject: [PATCH 1112/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/term_glyph#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index c5260d0dd..9d2ae2032 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From ff06b0cf970a4d5b5099e4a7add076acf5cb9b8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:40:25 +0000 Subject: [PATCH 1113/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/string_scanner#74) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 97fdf914e..05335028c 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From e6fd46b721785fe96366ad6ebd818b825d066180 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:41:26 +0000 Subject: [PATCH 1114/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/stack_trace#154) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 2910dbd16..e50979b87 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 883a88e6ab1f641c6d5ebdacdcf296664ab65152 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Mon, 13 May 2024 10:42:04 -0700 Subject: [PATCH 1115/1215] blast_repo fixes (dart-lang/stream_transform#184) dependabot --- pkgs/stream_transform/.github/dependabot.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/stream_transform/.github/dependabot.yaml b/pkgs/stream_transform/.github/dependabot.yaml index 439e796b4..bf6b38a4d 100644 --- a/pkgs/stream_transform/.github/dependabot.yaml +++ b/pkgs/stream_transform/.github/dependabot.yaml @@ -8,3 +8,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 5014aafac44d2e8a17be72237d046487a1397c59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 17:45:00 +0000 Subject: [PATCH 1116/1215] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/stream_transform#185) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5
Release notes

Sourced from actions/checkout's releases.

v4.1.5

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.4...v4.1.5

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index e08b1d175..6a81c8a88 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From aa020355b05f196b344ca733ede43a1a6790e2e1 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 28 May 2024 12:35:20 -0700 Subject: [PATCH 1117/1215] blast_repo fixes (dart-lang/pubspec_parse#128) auto-publish --- .../.github/workflows/publish.yaml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 pkgs/pubspec_parse/.github/workflows/publish.yaml diff --git a/pkgs/pubspec_parse/.github/workflows/publish.yaml b/pkgs/pubspec_parse/.github/workflows/publish.yaml new file mode 100644 index 000000000..27157a046 --- /dev/null +++ b/pkgs/pubspec_parse/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ master ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note From 091ed91aa80400e4bfa367202c81f0fefb53c924 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 28 May 2024 14:59:50 -0700 Subject: [PATCH 1118/1215] Add structural equality for dependencies (dart-lang/pubspec_parse#127) * Add structural equality for dependencies * Apply suggestions from code review Co-authored-by: Devon Carew --------- Co-authored-by: Devon Carew --- pkgs/pubspec_parse/CHANGELOG.md | 3 +- pkgs/pubspec_parse/lib/src/dependency.dart | 40 ++++++++++++++++++++++ pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 87dd5cae8..d14b82e40 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,7 +1,8 @@ -## 1.2.4-wip +## 1.3.0 - Require Dart 3.0 - Added support for `ignored_advisories` field. +- Added structural equality for `Dependency` subclasses and `HostedDetails`. ## 1.2.3 diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index 95bbc8ea7..acce59843 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -111,6 +111,13 @@ class SdkDependency extends Dependency { @override String get _info => sdk; + + @override + bool operator ==(Object other) => + other is SdkDependency && other.sdk == sdk && other.version == version; + + @override + int get hashCode => Object.hash(sdk, version); } @JsonSerializable() @@ -136,6 +143,16 @@ class GitDependency extends Dependency { @override String get _info => 'url@$url'; + + @override + bool operator ==(Object other) => + other is GitDependency && + other.url == url && + other.ref == ref && + other.path == path; + + @override + int get hashCode => Object.hash(url, ref, path); } Uri? parseGitUriOrNull(String? value) => @@ -188,6 +205,13 @@ class PathDependency extends Dependency { @override String get _info => 'path@$path'; + + @override + bool operator ==(Object other) => + other is PathDependency && other.path == path; + + @override + int get hashCode => path.hashCode; } @JsonSerializable(disallowUnrecognizedKeys: true) @@ -204,6 +228,15 @@ class HostedDependency extends Dependency { @override String get _info => version.toString(); + + @override + bool operator ==(Object other) => + other is HostedDependency && + other.version == version && + other.hosted == hosted; + + @override + int get hashCode => Object.hash(version, hosted); } @JsonSerializable(disallowUnrecognizedKeys: true) @@ -240,6 +273,13 @@ class HostedDetails { throw ArgumentError.value(data, 'hosted', 'Must be a Map or String.'); } + + @override + bool operator ==(Object other) => + other is HostedDetails && other.name == name && other.url == url; + + @override + int get hashCode => Object.hash(name, url); } VersionConstraint _constraintFromString(String? input) => diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 4f8eabc9a..9ca992dae 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.2.4-wip +version: 1.3.0 description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. From a81f3cececd1cb0d2077c939699aeefc585a75b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 00:20:17 +0000 Subject: [PATCH 1119/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/string_scanner#75) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 05335028c..58a2061ed 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From aefae91e0b44e899144533b83f9ac0de7d9b4763 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:43:20 +0000 Subject: [PATCH 1120/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/timing#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index d09036523..765b2edd1 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 83fd0d658d35a7336997c353889413b9b190e444 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 01:54:03 +0000 Subject: [PATCH 1121/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/stream_transform#186) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 6a81c8a88..c0f34a07f 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 3c38e1fb8e6d286e7da04dcba4fe5f5196da5bd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 03:27:23 +0000 Subject: [PATCH 1122/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/stream_channel#107) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index aad5df6f4..77eb9e176 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 94f1f40aed1fc9baf2fb5f462c53f2ece8ac1459 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 05:38:22 +0000 Subject: [PATCH 1123/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/pubspec_parse#129) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index b3f887735..e55f44e2d 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 26d680b0e55eb18f58c781f373b95e7d0b0b0eb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 08:47:20 +0000 Subject: [PATCH 1124/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/watcher#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index eb75dcaa6..a00813b1b 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 142d4cf089e63759a2ba3b7ce7b447f9bba3ac9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 10:07:09 +0000 Subject: [PATCH 1125/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/stack_trace#155) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index e50979b87..f3dee290b 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 120716000fd9183b83aff7252e7533a017b54295 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 13:05:22 +0000 Subject: [PATCH 1126/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/term_glyph#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 9d2ae2032..f1bac4131 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.0.0, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 8a1643c1e02808afe016fa0fa9de9cea9a88d86b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 16:34:18 +0000 Subject: [PATCH 1127/1215] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/test_reflective_loader#63) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6
Release notes

Sourced from actions/checkout's releases.

v4.1.6

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.1.5...v4.1.6

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

v3.5.2

v3.5.1

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 338e0b8c5..cfad53058 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From df5584740aaa8b5346cd7bdc9ee4a83ad5783d0a Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 4 Jun 2024 09:09:30 -0700 Subject: [PATCH 1128/1215] Latest lints, bump min SDK to 3.2 (dart-lang/pubspec_parse#131) --- .../.github/workflows/test-package.yml | 2 +- pkgs/pubspec_parse/CHANGELOG.md | 4 ++++ pkgs/pubspec_parse/pubspec.yaml | 18 +++++++++--------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index e55f44e2d..da26a738c 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.2, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index d14b82e40..aa99cbb5c 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.3.1-wip + +- Require Dart 3.2 + ## 1.3.0 - Require Dart 3.0 diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 9ca992dae..00cf12ce6 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.3.0 +version: 1.3.1-wip description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. @@ -8,7 +8,7 @@ topics: - dart-pub environment: - sdk: ^3.0.0 + sdk: ^3.2.0 dependencies: checked_yaml: ^2.0.1 @@ -18,14 +18,14 @@ dependencies: yaml: ^3.0.0 dev_dependencies: - build_runner: ^2.0.3 - build_verify: '>=2.0.0 <4.0.0' - dart_flutter_team_lints: ^2.0.0 + build_runner: ^2.2.1 + build_verify: ^3.0.0 + dart_flutter_team_lints: ^3.0.0 json_serializable: ^6.6.0 - path: ^1.5.1 + path: ^1.8.0 # Needed because we are configuring `combining_builder` - source_gen: ^1.0.0 - stack_trace: ^1.9.2 - test: ^1.0.0 + source_gen: ^1.2.3 + stack_trace: ^1.10.0 + test: ^1.21.6 test_descriptor: ^2.0.0 test_process: ^2.0.0 From 28436bf3e199ad6665c72f82dfe810c7817bd734 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Thu, 13 Jun 2024 11:09:45 -0700 Subject: [PATCH 1129/1215] Remove default onData for transformByHandlers (dart-lang/stream_transform#187) Towards dart-lang/stream_transform#111 The default callback is not used in practice outside of tests, but it included a cast to satisfy the type signature which looks worrying for this type of library. Make the callback required and add explicit callbacks (without a cast since the types are consistent) in the tests which used it. --- pkgs/stream_transform/lib/src/from_handlers.dart | 9 ++------- pkgs/stream_transform/test/from_handlers_test.dart | 7 ++++--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/pkgs/stream_transform/lib/src/from_handlers.dart b/pkgs/stream_transform/lib/src/from_handlers.dart index f5c4b847e..1146a13fa 100644 --- a/pkgs/stream_transform/lib/src/from_handlers.dart +++ b/pkgs/stream_transform/lib/src/from_handlers.dart @@ -11,10 +11,9 @@ extension TransformByHandlers on Stream { /// that the handlers are called once per event rather than called for the /// same event for each listener on a broadcast stream. Stream transformByHandlers( - {void Function(S, EventSink)? onData, + {required void Function(S, EventSink) onData, void Function(Object, StackTrace, EventSink)? onError, void Function(EventSink)? onDone}) { - final handleData = onData ?? _defaultHandleData; final handleError = onError ?? _defaultHandleError; final handleDone = onDone ?? _defaultHandleDone; @@ -26,7 +25,7 @@ extension TransformByHandlers on Stream { controller.onListen = () { assert(subscription == null); var valuesDone = false; - subscription = listen((value) => handleData(value, controller), + subscription = listen((value) => onData(value, controller), onError: (Object error, StackTrace stackTrace) { handleError(error, stackTrace, controller); }, onDone: () { @@ -48,10 +47,6 @@ extension TransformByHandlers on Stream { return controller.stream; } - static void _defaultHandleData(S value, EventSink sink) { - sink.add(value as T); - } - static void _defaultHandleError( Object error, StackTrace stackTrace, EventSink sink) { sink.addError(error, stackTrace); diff --git a/pkgs/stream_transform/test/from_handlers_test.dart b/pkgs/stream_transform/test/from_handlers_test.dart index 4e9134f1d..694199c70 100644 --- a/pkgs/stream_transform/test/from_handlers_test.dart +++ b/pkgs/stream_transform/test/from_handlers_test.dart @@ -36,7 +36,8 @@ void main() { group('default from_handlers', () { group('Single subscription stream', () { setUp(() { - setUpForController(StreamController(), (s) => s.transformByHandlers()); + setUpForController(StreamController(), + (s) => s.transformByHandlers(onData: (e, sink) => sink.add(e))); }); test('has correct stream type', () { @@ -75,8 +76,8 @@ void main() { late StreamSubscription subscription2; setUp(() { - setUpForController( - StreamController.broadcast(), (s) => s.transformByHandlers()); + setUpForController(StreamController.broadcast(), + (s) => s.transformByHandlers(onData: (e, sink) => sink.add(e))); emittedValues2 = []; errors2 = []; isDone2 = false; From 7d1c52c29b7c5bff1f6e94b3f6a78a85553828a1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 17 Jun 2024 15:44:24 -0700 Subject: [PATCH 1130/1215] Replace Future.wait with Iterable.wait (dart-lang/stream_transform#188) Towards dart-lang/stream_transform#111 --- pkgs/stream_transform/lib/src/aggregate_sample.dart | 2 +- pkgs/stream_transform/lib/src/async_expand.dart | 2 +- pkgs/stream_transform/lib/src/combine_latest.dart | 4 ++-- pkgs/stream_transform/lib/src/merge.dart | 2 +- pkgs/stream_transform/lib/src/switch.dart | 2 +- pkgs/stream_transform/test/scan_test.dart | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index aa47c1e68..0d53d8a73 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -138,7 +138,7 @@ extension AggregateSample on Stream { // Handle opt-out nulls cancels.removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; - return Future.wait(cancels).then((_) => null); + return cancels.wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/async_expand.dart b/pkgs/stream_transform/lib/src/async_expand.dart index 98d8bb773..e9de12e70 100644 --- a/pkgs/stream_transform/lib/src/async_expand.dart +++ b/pkgs/stream_transform/lib/src/async_expand.dart @@ -81,7 +81,7 @@ extension AsyncExpand on Stream { var cancels = [for (var s in subscriptions) s.cancel()] // Handle opt-out nulls ..removeWhere((Object? f) => f == null); - return Future.wait(cancels).then((_) => null); + return cancels.wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 15c1b683f..fe9e249c5 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -133,7 +133,7 @@ extension CombineLatest on Stream { ..removeWhere((Object? f) => f == null); sourceSubscription = null; otherSubscription = null; - return Future.wait(cancels).then((_) => null); + return cancels.wait.then((_) => null); }; }; return controller.stream; @@ -234,7 +234,7 @@ extension CombineLatest on Stream { // Handle opt-out nulls ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; - return Future.wait(cancels).then((_) => null); + return cancels.wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 2725d5e63..3180c022f 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -94,7 +94,7 @@ extension Merge on Stream { // Handle opt-out nulls ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; - return Future.wait(cancels).then((_) => null); + return cancels.wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index d64fc07da..95abd26a2 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -128,7 +128,7 @@ extension SwitchLatest on Stream> { // Handle opt-out nulls ..removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; - return Future.wait(cancels).then(_ignore); + return cancels.wait.then(_ignore); }; }; return controller.stream; diff --git a/pkgs/stream_transform/test/scan_test.dart b/pkgs/stream_transform/test/scan_test.dart index a0311c5f7..3c749e7a7 100644 --- a/pkgs/stream_transform/test/scan_test.dart +++ b/pkgs/stream_transform/test/scan_test.dart @@ -59,7 +59,7 @@ void main() { const TypeMatcher>(), const TypeMatcher>() ]); - expect(await Future.wait(result), [1, 3]); + expect(await result.wait, [1, 3]); }); test('does not call for subsequent values while waiting', () async { From 630a44133ac3a065743d6667f8bc7b77e5b59436 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Mon, 17 Jun 2024 17:15:42 -0700 Subject: [PATCH 1131/1215] Drop checks for unsound null values (dart-lang/stream_transform#189) Towards dart-lang/stream_transform#111 During the null safety migration it was possible for `StreamSubscription.cancel()` to return `null` in some cases. Now that this package is only used with sound null safe code it isn't possible for these nulls to flow through anymore so it is not necessary to filter for them. --- pkgs/stream_transform/lib/src/aggregate_sample.dart | 2 -- pkgs/stream_transform/lib/src/async_expand.dart | 5 +---- pkgs/stream_transform/lib/src/combine_latest.dart | 10 ++-------- pkgs/stream_transform/lib/src/merge.dart | 6 +----- pkgs/stream_transform/lib/src/switch.dart | 4 +--- 5 files changed, 5 insertions(+), 22 deletions(-) diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index 0d53d8a73..b1040304c 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -135,8 +135,6 @@ extension AggregateSample on Stream { } else { triggerSub!.pause(); } - // Handle opt-out nulls - cancels.removeWhere((Object? f) => f == null); if (cancels.isEmpty) return null; return cancels.wait.then((_) => null); }; diff --git a/pkgs/stream_transform/lib/src/async_expand.dart b/pkgs/stream_transform/lib/src/async_expand.dart index e9de12e70..e0c7672a2 100644 --- a/pkgs/stream_transform/lib/src/async_expand.dart +++ b/pkgs/stream_transform/lib/src/async_expand.dart @@ -78,10 +78,7 @@ extension AsyncExpand on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - var cancels = [for (var s in subscriptions) s.cancel()] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); - return cancels.wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index fe9e249c5..24eca4af3 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -128,9 +128,7 @@ extension CombineLatest on Stream { var cancels = [ sourceSubscription!.cancel(), otherSubscription!.cancel() - ] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); + ]; sourceSubscription = null; otherSubscription = null; return cancels.wait.then((_) => null); @@ -230,11 +228,7 @@ extension CombineLatest on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - var cancels = [for (var s in subscriptions) s.cancel()] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); - if (cancels.isEmpty) return null; - return cancels.wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 3180c022f..9ffeb0ad8 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -90,11 +90,7 @@ extension Merge on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - var cancels = [for (var s in subscriptions) s.cancel()] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); - if (cancels.isEmpty) return null; - return cancels.wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 95abd26a2..2ec3a5441 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -124,9 +124,7 @@ extension SwitchLatest on Stream> { var cancels = [ if (!outerStreamDone) outerSubscription.cancel(), if (sub != null) sub.cancel(), - ] - // Handle opt-out nulls - ..removeWhere((Object? f) => f == null); + ]; if (cancels.isEmpty) return null; return cancels.wait.then(_ignore); }; From 8664c4a5b2a58e5e2fdf36bc531ee0fc27c33af2 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 20 Jun 2024 10:45:40 -0700 Subject: [PATCH 1132/1215] update lints, require Dart 3.1 (dart-lang/string_scanner#76) --- pkgs/string_scanner/.github/workflows/test-package.yml | 2 +- pkgs/string_scanner/CHANGELOG.md | 2 +- pkgs/string_scanner/pubspec.yaml | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 58a2061ed..b65aeefdb 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.1, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index fa7af43f3..386a55b52 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.2.1-wip -* Require Dart 3.0.0 +* Require Dart 3.1.0 ## 1.2.0 diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 7ceb7d983..eea570a4f 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -4,11 +4,11 @@ description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner environment: - sdk: ^3.0.0 + sdk: ^3.1.0 dependencies: source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 - test: ^1.16.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 From 8fb6114848ada20a9654797f619f1d736572fd0c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jun 2024 10:02:59 -0700 Subject: [PATCH 1133/1215] bump lints (dart-lang/term_glyph#54) --- pkgs/term_glyph/.github/workflows/test-package.yml | 2 +- pkgs/term_glyph/CHANGELOG.md | 2 +- pkgs/term_glyph/pubspec.yaml | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index f1bac4131..c744a64da 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.1, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index 657329c98..d25ef1ab5 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.2.2-wip -* Require Dart 3.0 +* Require Dart 3.1 ## 1.2.1 diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 76eb5bed1..e4c998d79 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -4,10 +4,10 @@ description: Useful Unicode glyphs and ASCII substitutes. repository: https://github.com/dart-lang/term_glyph environment: - sdk: ^3.0.0 + sdk: ^3.1.0 dev_dependencies: - csv: ^5.0.0 - dart_flutter_team_lints: ^2.0.0 + csv: ^6.0.0 + dart_flutter_team_lints: ^3.0.0 dart_style: ^2.0.0 - test: ^1.16.0 + test: ^1.16.6 From 5c400a84b384db62e5bfc3d902480079c1b8cafc Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jun 2024 11:15:41 -0700 Subject: [PATCH 1134/1215] bump lints (dart-lang/stream_channel#108) --- pkgs/stream_channel/analysis_options.yaml | 9 --------- pkgs/stream_channel/pubspec.yaml | 4 ++-- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/pkgs/stream_channel/analysis_options.yaml b/pkgs/stream_channel/analysis_options.yaml index 8e5d4a792..44cda4da2 100644 --- a/pkgs/stream_channel/analysis_options.yaml +++ b/pkgs/stream_channel/analysis_options.yaml @@ -3,12 +3,3 @@ include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true - -linter: - rules: - - comment_references - - always_declare_return_types - - omit_local_variable_types - - prefer_single_quotes - - unawaited_futures - - use_super_parameters diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 0cfd074a5..652472170 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -12,5 +12,5 @@ dependencies: async: ^2.5.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 - test: ^1.16.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 From 63af0323a62b9b54e167c91fe90cd2f8f161a99c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 24 Jun 2024 18:38:31 -0700 Subject: [PATCH 1135/1215] update lints (dart-lang/watcher#169) --- pkgs/watcher/.github/workflows/test-package.yml | 2 +- pkgs/watcher/CHANGELOG.md | 1 + pkgs/watcher/pubspec.yaml | 7 +++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index a00813b1b..4d2eef4c2 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -46,7 +46,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] - sdk: [3.0.0, dev] + sdk: [3.1, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 7893dafa8..8f4d289d3 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.1.1-wip - Ensure `PollingFileWatcher.ready` completes for files that do not exist. +- Require Dart SDK `^3.1.0` ## 1.1.0 diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 431e99b13..108be66df 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -6,7 +6,7 @@ description: >- repository: https://github.com/dart-lang/watcher environment: - sdk: ^3.0.0 + sdk: ^3.1.0 dependencies: async: ^2.5.0 @@ -14,7 +14,6 @@ dependencies: dev_dependencies: benchmark_harness: ^2.0.0 - dart_flutter_team_lints: ^2.1.0 - test: ^1.16.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 test_descriptor: ^2.0.0 - From a6d268e720e87128b09274e8a65116011d1a0f44 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 26 Jun 2024 11:49:05 -0700 Subject: [PATCH 1136/1215] Update lints and min SDK (dart-lang/timing#48) --- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- pkgs/timing/CHANGELOG.md | 2 +- pkgs/timing/pubspec.yaml | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 765b2edd1..fe53ec0bc 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -20,7 +20,7 @@ jobs: strategy: fail-fast: false matrix: - sdk: [3.0.0, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 @@ -44,7 +44,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.0.0, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index 0c38a7661..f173a3faa 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,6 +1,6 @@ ## 1.0.2-wip -- Require Dart `3.0`. +- Require Dart `3.4`. ## 1.0.1 diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 80270ba70..0be8e50c2 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -6,13 +6,13 @@ description: >- repository: https://github.com/dart-lang/timing environment: - sdk: ^3.0.0 + sdk: ^3.4.0 dependencies: - json_annotation: ^4.3.0 + json_annotation: ^4.9.0 dev_dependencies: - build_runner: ^2.0.0 - dart_flutter_team_lints: ^2.0.0 + build_runner: ^2.0.6 + dart_flutter_team_lints: ^3.0.0 json_serializable: ^6.0.0 - test: ^1.0.0 + test: ^1.17.10 From fa4c6940b98bc27f2a69127915e47ca3656601b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 00:54:09 +0000 Subject: [PATCH 1137/1215] Bump the github-actions group with 2 updates (dart-lang/string_scanner#77) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/string_scanner#118: dart-lang/setup-dartdart-lang/string_scanner#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/string_scanner#118: dart-lang/setup-dartdart-lang/string_scanner#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index b65aeefdb..9fc02d97c 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 8a644154cb068e912ca979d505964ccb57d8ce6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 01:32:10 +0000 Subject: [PATCH 1138/1215] Bump the github-actions group with 2 updates (dart-lang/timing#49) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/timing#118: dart-lang/setup-dartdart-lang/timing#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/timing#118: dart-lang/setup-dartdart-lang/timing#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index fe53ec0bc..a6d3a64d7 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [3.4, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -46,8 +46,8 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 0d0621e48c8fbde35768966af36209a061bc6599 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 01:37:35 +0000 Subject: [PATCH 1139/1215] Bump the github-actions group with 2 updates (dart-lang/stream_transform#191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/stream_transform#118: dart-lang/setup-dartdart-lang/stream_transform#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/stream_transform#118: dart-lang/setup-dartdart-lang/stream_transform#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index c0f34a07f..9e664b10b 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,8 +50,8 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 2d967e90eeb44a54405ec3c4cd51d4f563cb460e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 03:33:11 +0000 Subject: [PATCH 1140/1215] Bump the github-actions group with 2 updates (dart-lang/stream_channel#109) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 77eb9e176..9d9f1cc08 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From c363290cc2104ad71d1567a8bf48918861b0fd31 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 05:05:17 +0000 Subject: [PATCH 1141/1215] Bump the github-actions group with 2 updates (dart-lang/pubspec_parse#133) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/pubspec_parse#118: dart-lang/setup-dartdart-lang/pubspec_parse#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/pubspec_parse#118: dart-lang/setup-dartdart-lang/pubspec_parse#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index da26a738c..1bd25f969 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -48,8 +48,8 @@ jobs: os: [ubuntu-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From d494a03f8806447c33e234b6a6efb770ad02bf67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:14:05 +0000 Subject: [PATCH 1142/1215] Bump the github-actions group with 2 updates (dart-lang/watcher#170) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/watcher#118: dart-lang/setup-dartdart-lang/watcher#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/watcher#118: dart-lang/setup-dartdart-lang/watcher#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 4d2eef4c2..37e75dbc8 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -48,8 +48,8 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 9d500a73eaf7c8caac36473dc5018009891fee79 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:58:18 +0000 Subject: [PATCH 1143/1215] Bump the github-actions group with 2 updates (dart-lang/stack_trace#156) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/stack_trace#118: dart-lang/setup-dartdart-lang/stack_trace#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/stack_trace#118: dart-lang/setup-dartdart-lang/stack_trace#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index f3dee290b..25edb675d 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 7e9844312f2dcb1b1d795f3c30f027320aa81bea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:57:05 +0000 Subject: [PATCH 1144/1215] Bump the github-actions group with 2 updates (dart-lang/term_glyph#55) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/term_glyph#118: dart-lang/setup-dartdart-lang/term_glyph#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/term_glyph#118: dart-lang/setup-dartdart-lang/term_glyph#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index c744a64da..d1828e76b 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,8 +22,8 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,8 +49,8 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From 93d51e16ca5060760bf3714941dfedaabdb620c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:21:57 +0000 Subject: [PATCH 1145/1215] Bump the github-actions group with 2 updates (dart-lang/test_reflective_loader#64) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7
Release notes

Sourced from actions/checkout's releases.

v4.1.7

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.6...v4.1.7

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

v3.5.3

... (truncated)

Commits

Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.6.5

dart-lang/test_reflective_loader#118: dart-lang/setup-dartdart-lang/test_reflective_loader#118

Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.6.5

dart-lang/test_reflective_loader#118: dart-lang/setup-dartdart-lang/test_reflective_loader#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

  • Re-wrote the implementation of the action into Dart.
  • Auto-detect the platform architecture (x64, ia32, arm, arm64).
  • Improved the caching and download resilience of the sdk.
  • Added a new action output: dart-version - the installed version of the sdk.

v1.4.0

... (truncated)

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index cfad53058..f863fb20e 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,8 +21,8 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 096e2ddc3a71c399ed09cc364933ad866ee65dba Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 8 Jul 2024 10:41:11 -0700 Subject: [PATCH 1146/1215] update lints (dart-lang/stack_trace#157) --- pkgs/stack_trace/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index b3a9d9266..2438909e2 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -10,5 +10,5 @@ dependencies: path: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 - test: ^1.16.0 + dart_flutter_team_lints: ^3.0.0 + test: ^1.16.6 From a8412336926a28d0604eb311b41bd609852f5ea3 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Tue, 9 Jul 2024 16:35:39 -0700 Subject: [PATCH 1147/1215] Add a `SpanScanner.spanFromPosition()` method (dart-lang/string_scanner#78) Tracking raw ints can be more efficient than tracking `LineScannerState` objects, and allows users to do small manual manipulations on the resulting positions. --- pkgs/string_scanner/CHANGELOG.md | 5 ++++- .../lib/src/relative_span_scanner.dart | 12 +++++++++++ pkgs/string_scanner/lib/src/span_scanner.dart | 11 ++++++++++ pkgs/string_scanner/pubspec.yaml | 2 +- .../test/span_scanner_test.dart | 20 +++++++++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index 386a55b52..a4c17b6bd 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,7 +1,10 @@ -## 1.2.1-wip +## 1.3.0 * Require Dart 3.1.0 +* Add a `SpanScanner.spanFromPosition()` method which takes raw code units + rather than `SpanScanner.spanFrom()`'s `LineScannerState`s. + ## 1.2.0 * Require Dart 2.18.0 diff --git a/pkgs/string_scanner/lib/src/relative_span_scanner.dart b/pkgs/string_scanner/lib/src/relative_span_scanner.dart index 150d5071e..cd9af0e03 100644 --- a/pkgs/string_scanner/lib/src/relative_span_scanner.dart +++ b/pkgs/string_scanner/lib/src/relative_span_scanner.dart @@ -78,6 +78,18 @@ class RelativeSpanScanner extends StringScanner implements SpanScanner { _startLocation.offset + endPosition); } + @override + FileSpan spanFromPosition(int startPosition, [int? endPosition]) { + RangeError.checkValidRange( + startPosition, + endPosition, + _sourceFile.length - _startLocation.offset, + 'startPosition', + 'endPosition'); + return _sourceFile.span(_startLocation.offset + startPosition, + _startLocation.offset + (endPosition ?? position)); + } + @override bool matches(Pattern pattern) { if (!super.matches(pattern)) { diff --git a/pkgs/string_scanner/lib/src/span_scanner.dart b/pkgs/string_scanner/lib/src/span_scanner.dart index 413a43331..509cf6004 100644 --- a/pkgs/string_scanner/lib/src/span_scanner.dart +++ b/pkgs/string_scanner/lib/src/span_scanner.dart @@ -91,6 +91,17 @@ class SpanScanner extends StringScanner implements LineScanner { return _sourceFile.span(startState.position, endPosition); } + /// Creates a [FileSpan] representing the source range between [startPosition] + /// and [endPosition], or the current position if [endPosition] is null. + /// + /// Each position should be a code unit offset into the string being scanned, + /// with the same conventions as [StringScanner.position]. + /// + /// Throws a [RangeError] if [startPosition] or [endPosition] aren't within + /// this source file. + FileSpan spanFromPosition(int startPosition, [int? endPosition]) => + _sourceFile.span(startPosition, endPosition ?? position); + @override bool matches(Pattern pattern) { if (!super.matches(pattern)) { diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index eea570a4f..b8585385c 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.2.1-wip +version: 1.3.0 description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner diff --git a/pkgs/string_scanner/test/span_scanner_test.dart b/pkgs/string_scanner/test/span_scanner_test.dart index 0e20c36a5..93d9c477c 100644 --- a/pkgs/string_scanner/test/span_scanner_test.dart +++ b/pkgs/string_scanner/test/span_scanner_test.dart @@ -75,6 +75,16 @@ void main() { expect(span.text, equals('o\nbar\nba')); }); + test('.spanFromPosition() returns a span from a previous state', () { + scanner.scan('fo'); + final start = scanner.position; + scanner.scan('o\nba'); + scanner.scan('r\nba'); + + final span = scanner.spanFromPosition(start + 2, start + 5); + expect(span.text, equals('bar')); + }); + test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); @@ -139,6 +149,16 @@ void testForImplementation( expect(span.text, equals('o\nbar\nba')); }); + test('.spanFromPosition() returns a span from a previous state', () { + scanner.scan('fo'); + final start = scanner.position; + scanner.scan('o\nba'); + scanner.scan('r\nba'); + + final span = scanner.spanFromPosition(start + 2, start + 5); + expect(span.text, equals('bar')); + }); + test('.emptySpan returns an empty span at the current location', () { scanner.scan('foo\nba'); From c49c4109c774ec67fd1cb8828e6b2953d914a700 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 29 Jul 2024 11:27:21 -0700 Subject: [PATCH 1148/1215] Fix some trivial doc comment lints (dart-lang/stream_channel#110) --- pkgs/stream_channel/lib/src/stream_channel_controller.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/stream_channel/lib/src/stream_channel_controller.dart b/pkgs/stream_channel/lib/src/stream_channel_controller.dart index 5c788667d..25d5239b2 100644 --- a/pkgs/stream_channel/lib/src/stream_channel_controller.dart +++ b/pkgs/stream_channel/lib/src/stream_channel_controller.dart @@ -2,6 +2,9 @@ // 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. +/// @docImport 'isolate_channel.dart'; +library; + import 'dart:async'; import '../stream_channel.dart'; @@ -11,7 +14,7 @@ import '../stream_channel.dart'; /// This exposes two connected [StreamChannel]s, [local] and [foreign]. The /// user's code should use [local] to emit and receive events. Then [foreign] /// can be returned for others to use. For example, here's a simplified version -/// of the implementation of [new IsolateChannel]: +/// of the implementation of [IsolateChannel.new]: /// /// ```dart /// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) { From 145be47b64c3c59f1e2340e2370d0c5e8537aa09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Tue, 17 Sep 2024 11:58:58 +0200 Subject: [PATCH 1149/1215] Fix analysis issues (dart-lang/stack_trace#160) --- pkgs/stack_trace/lib/src/frame.dart | 5 ++++- pkgs/stack_trace/lib/src/trace.dart | 9 ++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 88670a1c7..7cd95168b 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -218,9 +218,12 @@ class Frame { /// Parses a Firefox 'eval' or 'function' stack frame. /// - /// for example: + /// For example: + /// + /// ``` /// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 /// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 + /// ``` factory Frame._parseFirefoxEval(String frame) => _catchFormatException(frame, () { final match = _firefoxEvalLocation.firstMatch(frame); diff --git a/pkgs/stack_trace/lib/src/trace.dart b/pkgs/stack_trace/lib/src/trace.dart index 2e4427d4b..b8c62f5cf 100644 --- a/pkgs/stack_trace/lib/src/trace.dart +++ b/pkgs/stack_trace/lib/src/trace.dart @@ -31,9 +31,12 @@ final _v8TraceLine = RegExp(r' ?at '); /// /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/stack /// -/// These stack traces looks like: -/// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 -/// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 +/// These stack traces look like: +/// +/// ```` +/// anonymous/<@https://example.com/stuff.js line 693 > Function:3:40 +/// anonymous/<@https://example.com/stuff.js line 693 > eval:3:40 +/// ```` final _firefoxEvalTrace = RegExp(r'@\S+ line \d+ >.* (Function|eval):\d+:\d+'); /// A RegExp to match Firefox and Safari's stack traces. From 875fad0c96c5fe34cd8d4680c3a1aa41efc56f49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 19 Sep 2024 10:42:38 +0200 Subject: [PATCH 1150/1215] Add support for parsing Wasm stack frames of Chrome (V8), Firefox, Safari (dart-lang/stack_trace#159) Instead of updating existing regexes to handle new formats, this adds new regexes for Wasm frames. Parser functions are updated to try to parse the frame with Wasm regexes. Column numbers can be used by the `source_map_stack_trace` package to map Wasm frames to source locations. Tests added for parsing all combinations of: - Frames with and without function names - In Chrome, Firefox, Safari formats --- pkgs/stack_trace/CHANGELOG.md | 1 + pkgs/stack_trace/lib/src/frame.dart | 234 +++++++++++++++++++------- pkgs/stack_trace/test/frame_test.dart | 79 +++++++++ pkgs/stack_trace/test/trace_test.dart | 124 ++++++++++++++ 4 files changed, 377 insertions(+), 61 deletions(-) diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 2c4c77cd7..029f155cb 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.11.2-wip * Require Dart 3.1 or greater +* Added support for parsing Wasm frames of Chrome (V8), Firefox, Safari. ## 1.11.1 diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index 7cd95168b..bd0a582bf 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -17,12 +17,39 @@ final _vmFrame = RegExp(r'^#\d+\s+(\S.*) \((.+?)((?::\d+){0,2})\)$'); // at VW.call$0 (eval as fn // (https://example.com/stuff.dart.js:560:28), efn:3:28) // at https://example.com/stuff.dart.js:560:28 -final _v8Frame = +final _v8JsFrame = RegExp(r'^\s*at (?:(\S.*?)(?: \[as [^\]]+\])? \((.*)\)|(.*))$'); // https://example.com/stuff.dart.js:560:28 // https://example.com/stuff.dart.js:560 -final _v8UrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?$|native$'); +// +// Group 1: URI, required +// Group 2: line number, required +// Group 3: column number, optional +final _v8JsUrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?$|native$'); + +// With names: +// +// at Error.f (wasm://wasm/0006d966:wasm-function[119]:0xbb13) +// at g (wasm://wasm/0006d966:wasm-function[796]:0x143b4) +// +// Without names: +// +// at wasm://wasm/0005168a:wasm-function[119]:0xbb13 +// at wasm://wasm/0005168a:wasm-function[796]:0x143b4 +// +// Matches named groups: +// +// - "member": optional, `Error.f` in the first example, NA in the second. +// - "uri": `wasm://wasm/0006d966`. +// - "index": `119`. +// - "offset": (hex number) `bb13`. +// +// To avoid having multiple groups for the same part of the frame, this regex +// matches unmatched parentheses after the member name. +final _v8WasmFrame = RegExp(r'^\s*at (?:(?.+) )?' + r'(?:\(?(?:(?wasm:\S+):wasm-function\[(?\d+)\]' + r'\:0x(?[0-9a-fA-F]+))\)?)$'); // eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28 // eval as function (https://example.com/stuff.dart.js:560:28) @@ -41,7 +68,7 @@ final _firefoxEvalLocation = // .VW.call$0/name<@https://example.com/stuff.dart.js:560 // .VW.call$0@https://example.com/stuff.dart.js:560:36 // https://example.com/stuff.dart.js:560 -final _firefoxSafariFrame = RegExp(r'^' +final _firefoxSafariJSFrame = RegExp(r'^' r'(?:' // Member description. Not present in some Safari frames. r'([^@(/]*)' // The actual name of the member. r'(?:\(.*\))?' // Arguments to the member, sometimes captured by Firefox. @@ -56,6 +83,58 @@ final _firefoxSafariFrame = RegExp(r'^' // empty in Safari if it's unknown. r'$'); +// With names: +// +// g@http://localhost:8080/test.wasm:wasm-function[796]:0x143b4 +// f@http://localhost:8080/test.wasm:wasm-function[795]:0x143a8 +// main@http://localhost:8080/test.wasm:wasm-function[792]:0x14390 +// +// Without names: +// +// @http://localhost:8080/test.wasm:wasm-function[796]:0x143b4 +// @http://localhost:8080/test.wasm:wasm-function[795]:0x143a8 +// @http://localhost:8080/test.wasm:wasm-function[792]:0x14390 +// +// JSShell in the command line uses a different format, which this regex also +// parses. +// +// With names: +// +// main@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[792]:0x14378 +// +// Without names: +// +// @/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[792]:0x14378 +// +// Matches named groups: +// +// - "member": Function name, may be empty: `g`. +// - "uri": `http://localhost:8080/test.wasm`. +// - "index": `796`. +// - "offset": (in hex) `143b4`. +final _firefoxWasmFrame = + RegExp(r'^(?.*?)@(?:(?\S+).*?:wasm-function' + r'\[(?\d+)\]:0x(?[0-9a-fA-F]+))$'); + +// With names: +// +// (Note: Lines below are literal text, e.g. is not a placeholder, it's a +// part of the stack frame.) +// +// .wasm-function[g]@[wasm code] +// .wasm-function[f]@[wasm code] +// .wasm-function[main]@[wasm code] +// +// Without names: +// +// .wasm-function[796]@[wasm code] +// .wasm-function[795]@[wasm code] +// .wasm-function[792]@[wasm code] +// +// Matches named group "member": `g` or `796`. +final _safariWasmFrame = + RegExp(r'^.*?wasm-function\[(?.*)\]@\[wasm code\]$'); + // foo/bar.dart 10:11 Foo._bar // foo/bar.dart 10:11 (anonymous function).dart.fn // https://dart.dev/foo/bar.dart Foo._bar @@ -163,48 +242,62 @@ class Frame { /// Parses a string representation of a Chrome/V8 stack frame. factory Frame.parseV8(String frame) => _catchFormatException(frame, () { - var match = _v8Frame.firstMatch(frame); - if (match == null) return UnparsedFrame(frame); + // Try to match a Wasm frame first: the Wasm frame regex won't match a + // JS frame but the JS frame regex may match a Wasm frame. + var match = _v8WasmFrame.firstMatch(frame); + if (match != null) { + final member = match.namedGroup('member'); + final uri = _uriOrPathToUri(match.namedGroup('uri')!); + final functionIndex = match.namedGroup('index')!; + final functionOffset = + int.parse(match.namedGroup('offset')!, radix: 16); + return Frame(uri, 1, functionOffset + 1, member ?? functionIndex); + } - // v8 location strings can be arbitrarily-nested, since it adds a layer - // of nesting for each eval performed on that line. - Frame parseLocation(String location, String member) { - var evalMatch = _v8EvalLocation.firstMatch(location); - while (evalMatch != null) { - location = evalMatch[1]!; - evalMatch = _v8EvalLocation.firstMatch(location); + match = _v8JsFrame.firstMatch(frame); + if (match != null) { + // v8 location strings can be arbitrarily-nested, since it adds a + // layer of nesting for each eval performed on that line. + Frame parseJsLocation(String location, String member) { + var evalMatch = _v8EvalLocation.firstMatch(location); + while (evalMatch != null) { + location = evalMatch[1]!; + evalMatch = _v8EvalLocation.firstMatch(location); + } + + if (location == 'native') { + return Frame(Uri.parse('native'), null, null, member); + } + + var urlMatch = _v8JsUrlLocation.firstMatch(location); + if (urlMatch == null) return UnparsedFrame(frame); + + final uri = _uriOrPathToUri(urlMatch[1]!); + final line = int.parse(urlMatch[2]!); + final columnMatch = urlMatch[3]; + final column = columnMatch != null ? int.parse(columnMatch) : null; + return Frame(uri, line, column, member); } - if (location == 'native') { - return Frame(Uri.parse('native'), null, null, member); + // V8 stack frames can be in two forms. + if (match[2] != null) { + // The first form looks like " at FUNCTION (LOCATION)". V8 proper + // lists anonymous functions within eval as "", while + // IE10 lists them as "Anonymous function". + return parseJsLocation( + match[2]!, + match[1]! + .replaceAll('', '') + .replaceAll('Anonymous function', '') + .replaceAll('(anonymous function)', '')); + } else { + // The second form looks like " at LOCATION", and is used for + // anonymous functions. + return parseJsLocation(match[3]!, ''); } - - var urlMatch = _v8UrlLocation.firstMatch(location); - if (urlMatch == null) return UnparsedFrame(frame); - - final uri = _uriOrPathToUri(urlMatch[1]!); - final line = int.parse(urlMatch[2]!); - final columnMatch = urlMatch[3]; - final column = columnMatch != null ? int.parse(columnMatch) : null; - return Frame(uri, line, column, member); } - // V8 stack frames can be in two forms. - if (match[2] != null) { - // The first form looks like " at FUNCTION (LOCATION)". V8 proper - // lists anonymous functions within eval as "", while IE10 - // lists them as "Anonymous function". - return parseLocation( - match[2]!, - match[1]! - .replaceAll('', '') - .replaceAll('Anonymous function', '') - .replaceAll('(anonymous function)', '')); - } else { - // The second form looks like " at LOCATION", and is used for - // anonymous functions. - return parseLocation(match[3]!, ''); - } + return UnparsedFrame(frame); }); /// Parses a string representation of a JavaScriptCore stack trace. @@ -237,35 +330,54 @@ class Frame { return Frame(uri, line, null, member); }); - /// Parses a string representation of a Firefox stack frame. + /// Parses a string representation of a Firefox or Safari stack frame. factory Frame.parseFirefox(String frame) => _catchFormatException(frame, () { - var match = _firefoxSafariFrame.firstMatch(frame); - if (match == null) return UnparsedFrame(frame); + var match = _firefoxSafariJSFrame.firstMatch(frame); + if (match != null) { + if (match[3]!.contains(' line ')) { + return Frame._parseFirefoxEval(frame); + } - if (match[3]!.contains(' line ')) { - return Frame._parseFirefoxEval(frame); - } + // Normally this is a URI, but in a jsshell trace it can be a path. + var uri = _uriOrPathToUri(match[3]!); - // Normally this is a URI, but in a jsshell trace it can be a path. - var uri = _uriOrPathToUri(match[3]!); + var member = match[1]; + if (member != null) { + member += + List.filled('/'.allMatches(match[2]!).length, '.').join(); + if (member == '') member = ''; - var member = match[1]; - if (member != null) { - member += - List.filled('/'.allMatches(match[2]!).length, '.').join(); - if (member == '') member = ''; + // Some Firefox members have initial dots. We remove them for + // consistency with other platforms. + member = member.replaceFirst(_initialDot, ''); + } else { + member = ''; + } - // Some Firefox members have initial dots. We remove them for - // consistency with other platforms. - member = member.replaceFirst(_initialDot, ''); - } else { - member = ''; + var line = match[4] == '' ? null : int.parse(match[4]!); + var column = + match[5] == null || match[5] == '' ? null : int.parse(match[5]!); + return Frame(uri, line, column, member); } - var line = match[4] == '' ? null : int.parse(match[4]!); - var column = - match[5] == null || match[5] == '' ? null : int.parse(match[5]!); - return Frame(uri, line, column, member); + match = _firefoxWasmFrame.firstMatch(frame); + if (match != null) { + final member = match.namedGroup('member')!; + final uri = _uriOrPathToUri(match.namedGroup('uri')!); + final functionIndex = match.namedGroup('index')!; + final functionOffset = + int.parse(match.namedGroup('offset')!, radix: 16); + return Frame(uri, 1, functionOffset + 1, + member.isNotEmpty ? member : functionIndex); + } + + match = _safariWasmFrame.firstMatch(frame); + if (match != null) { + final member = match.namedGroup('member')!; + return Frame(Uri(path: 'wasm code'), null, null, member); + } + + return UnparsedFrame(frame); }); /// Parses a string representation of a Safari 6.0 stack frame. diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index 6e8df727f..e62e8437c 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -632,6 +632,85 @@ baz@https://pub.dev/buz.js:56355:55 equals('$relative 5:10 in Foo')); }); }); + + test('parses a V8 Wasm frame with a name', () { + var frame = Frame.parseV8(' at Error._throwWithCurrentStackTrace ' + '(wasm://wasm/0006d966:wasm-function[119]:0xbb13)'); + expect(frame.uri, Uri.parse('wasm://wasm/0006d966')); + expect(frame.line, 1); + expect(frame.column, 0xbb13 + 1); + expect(frame.member, 'Error._throwWithCurrentStackTrace'); + }); + + test('parses a V8 Wasm frame with a name with spaces', () { + var frame = Frame.parseV8(' at main tear-off trampoline ' + '(wasm://wasm/0017fbea:wasm-function[863]:0x23cc8)'); + expect(frame.uri, Uri.parse('wasm://wasm/0017fbea')); + expect(frame.line, 1); + expect(frame.column, 0x23cc8 + 1); + expect(frame.member, 'main tear-off trampoline'); + }); + + test('parses a V8 Wasm frame without a name', () { + var frame = + Frame.parseV8(' at wasm://wasm/0006d966:wasm-function[119]:0xbb13'); + expect(frame.uri, Uri.parse('wasm://wasm/0006d966')); + expect(frame.line, 1); + expect(frame.column, 0xbb13 + 1); + expect(frame.member, '119'); + }); + + test('parses a Firefox Wasm frame with a name', () { + var frame = Frame.parseFirefox( + 'g@http://localhost:8080/test.wasm:wasm-function[796]:0x143b4'); + expect(frame.uri, Uri.parse('http://localhost:8080/test.wasm')); + expect(frame.line, 1); + expect(frame.column, 0x143b4 + 1); + expect(frame.member, 'g'); + }); + + test('parses a Firefox Wasm frame with a name with spaces', () { + var frame = Frame.parseFirefox( + 'main tear-off trampoline@http://localhost:8080/test.wasm:wasm-function[794]:0x14387'); + expect(frame.uri, Uri.parse('http://localhost:8080/test.wasm')); + expect(frame.line, 1); + expect(frame.column, 0x14387 + 1); + expect(frame.member, 'main tear-off trampoline'); + }); + + test('parses a Firefox Wasm frame without a name', () { + var frame = Frame.parseFirefox( + '@http://localhost:8080/test.wasm:wasm-function[796]:0x143b4'); + expect(frame.uri, Uri.parse('http://localhost:8080/test.wasm')); + expect(frame.line, 1); + expect(frame.column, 0x143b4 + 1); + expect(frame.member, '796'); + }); + + test('parses a Safari Wasm frame with a name', () { + var frame = Frame.parseSafari('.wasm-function[g]@[wasm code]'); + expect(frame.uri, Uri.parse('wasm code')); + expect(frame.line, null); + expect(frame.column, null); + expect(frame.member, 'g'); + }); + + test('parses a Safari Wasm frame with a name', () { + var frame = Frame.parseSafari( + '.wasm-function[main tear-off trampoline]@[wasm code]'); + expect(frame.uri, Uri.parse('wasm code')); + expect(frame.line, null); + expect(frame.column, null); + expect(frame.member, 'main tear-off trampoline'); + }); + + test('parses a Safari Wasm frame without a name', () { + var frame = Frame.parseSafari('.wasm-function[796]@[wasm code]'); + expect(frame.uri, Uri.parse('wasm code')); + expect(frame.line, null); + expect(frame.column, null); + expect(frame.member, '796'); + }); } void expectIsUnparsed(Frame Function(String) constructor, String text) { diff --git a/pkgs/stack_trace/test/trace_test.dart b/pkgs/stack_trace/test/trace_test.dart index d4bce766e..e09de9555 100644 --- a/pkgs/stack_trace/test/trace_test.dart +++ b/pkgs/stack_trace/test/trace_test.dart @@ -296,6 +296,130 @@ void main() { expect(trace.frames[0].uri, equals(Uri.parse('file:///pull.dart'))); expect(trace.frames[1].uri, equals(Uri.parse('dart:the/future.dart'))); }); + + test('parses a V8 stack frace with Wasm frames correctly', () { + var trace = Trace.parse( + '\tat Error._throwWithCurrentStackTrace (wasm://wasm/0006d892:wasm-function[119]:0xbaf8)\n' + '\tat main (wasm://wasm/0006d892:wasm-function[792]:0x14378)\n' + '\tat main tear-off trampoline (wasm://wasm/0006d892:wasm-function[794]:0x14387)\n' + '\tat _invokeMain (wasm://wasm/0006d892:wasm-function[70]:0xa56c)\n' + '\tat InstantiatedApp.invokeMain (/home/user/test.mjs:361:37)\n' + '\tat main (/home/user/run_wasm.js:416:21)\n' + '\tat async action (/home/user/run_wasm.js:353:38)\n' + '\tat async eventLoop (/home/user/run_wasm.js:329:9)'); + + expect(trace.frames.length, 8); + + for (final frame in trace.frames) { + expect(frame is UnparsedFrame, false); + } + + expect(trace.frames[0].uri, Uri.parse('wasm://wasm/0006d892')); + expect(trace.frames[0].line, 1); + expect(trace.frames[0].column, 0xbaf8 + 1); + expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); + + expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); + expect(trace.frames[4].line, 361); + expect(trace.frames[4].column, 37); + expect(trace.frames[4].member, 'InstantiatedApp.invokeMain'); + + expect(trace.frames[5].uri, Uri.parse('file:///home/user/run_wasm.js')); + expect(trace.frames[5].line, 416); + expect(trace.frames[5].column, 21); + expect(trace.frames[5].member, 'main'); + }); + + test('parses Firefox stack frace with Wasm frames correctly', () { + var trace = Trace.parse( + 'Error._throwWithCurrentStackTrace@http://localhost:8080/test.wasm:wasm-function[119]:0xbaf8\n' + 'main@http://localhost:8080/test.wasm:wasm-function[792]:0x14378\n' + 'main tear-off trampoline@http://localhost:8080/test.wasm:wasm-function[794]:0x14387\n' + '_invokeMain@http://localhost:8080/test.wasm:wasm-function[70]:0xa56c\n' + 'invoke@http://localhost:8080/test.mjs:48:26'); + + expect(trace.frames.length, 5); + + for (final frame in trace.frames) { + expect(frame is UnparsedFrame, false); + } + + expect(trace.frames[0].uri, Uri.parse('http://localhost:8080/test.wasm')); + expect(trace.frames[0].line, 1); + expect(trace.frames[0].column, 0xbaf8 + 1); + expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); + + expect(trace.frames[4].uri, Uri.parse('http://localhost:8080/test.mjs')); + expect(trace.frames[4].line, 48); + expect(trace.frames[4].column, 26); + expect(trace.frames[4].member, 'invoke'); + }); + + test('parses JSShell stack frace with Wasm frames correctly', () { + var trace = Trace.parse( + 'Error._throwWithCurrentStackTrace@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[119]:0xbaf8\n' + 'main@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[792]:0x14378\n' + 'main tear-off trampoline@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[794]:0x14387\n' + '_invokeMain@/home/user/test.mjs line 29 > WebAssembly.compile:wasm-function[70]:0xa56c\n' + 'invokeMain@/home/user/test.mjs:361:37\n' + 'main@/home/user/run_wasm.js:416:21\n' + 'async*action@/home/user/run_wasm.js:353:44\n' + 'eventLoop@/home/user/run_wasm.js:329:15\n' + 'self.dartMainRunner@/home/user/run_wasm.js:354:14\n' + '@/home/user/run_wasm.js:419:15'); + + expect(trace.frames.length, 10); + + for (final frame in trace.frames) { + expect(frame is UnparsedFrame, false); + } + + expect(trace.frames[0].uri, Uri.parse('file:///home/user/test.mjs')); + expect(trace.frames[0].line, 1); + expect(trace.frames[0].column, 0xbaf8 + 1); + expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); + + expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); + expect(trace.frames[4].line, 361); + expect(trace.frames[4].column, 37); + expect(trace.frames[4].member, 'invokeMain'); + + expect(trace.frames[9].uri, Uri.parse('file:///home/user/run_wasm.js')); + expect(trace.frames[9].line, 419); + expect(trace.frames[9].column, 15); + expect(trace.frames[9].member, ''); + }); + + test('parses Safari stack frace with Wasm frames correctly', () { + var trace = Trace.parse( + '.wasm-function[Error._throwWithCurrentStackTrace]@[wasm code]\n' + '.wasm-function[main]@[wasm code]\n' + '.wasm-function[main tear-off trampoline]@[wasm code]\n' + '.wasm-function[_invokeMain]@[wasm code]\n' + 'invokeMain@/home/user/test.mjs:361:48\n' + '@/home/user/run_wasm.js:416:31'); + + expect(trace.frames.length, 6); + + for (final frame in trace.frames) { + expect(frame is UnparsedFrame, false); + } + + expect(trace.frames[0].uri, Uri.parse('wasm code')); + expect(trace.frames[0].line, null); + expect(trace.frames[0].column, null); + expect(trace.frames[0].member, 'Error._throwWithCurrentStackTrace'); + + expect(trace.frames[4].uri, Uri.parse('file:///home/user/test.mjs')); + expect(trace.frames[4].line, 361); + expect(trace.frames[4].column, 48); + expect(trace.frames[4].member, 'invokeMain'); + + expect(trace.frames[5].uri, Uri.parse('file:///home/user/run_wasm.js')); + expect(trace.frames[5].line, 416); + expect(trace.frames[5].column, 31); + expect(trace.frames[5].member, ''); + }); }); test('.toString() nicely formats the stack trace', () { From 63dbf2f82b2c4fb9ee5d358ea0218c9737e1e8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 19 Sep 2024 12:06:02 +0200 Subject: [PATCH 1151/1215] Relax URI matching in V8 Wasm frame regex (dart-lang/stack_trace#161) Handle URIs other than `wasm://`. Fixes dart-lang/stack_trace#131. --- pkgs/stack_trace/lib/src/frame.dart | 2 +- pkgs/stack_trace/test/frame_test.dart | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/pkgs/stack_trace/lib/src/frame.dart b/pkgs/stack_trace/lib/src/frame.dart index bd0a582bf..d4043b780 100644 --- a/pkgs/stack_trace/lib/src/frame.dart +++ b/pkgs/stack_trace/lib/src/frame.dart @@ -48,7 +48,7 @@ final _v8JsUrlLocation = RegExp(r'^(.*?):(\d+)(?::(\d+))?$|native$'); // To avoid having multiple groups for the same part of the frame, this regex // matches unmatched parentheses after the member name. final _v8WasmFrame = RegExp(r'^\s*at (?:(?.+) )?' - r'(?:\(?(?:(?wasm:\S+):wasm-function\[(?\d+)\]' + r'(?:\(?(?:(?\S+):wasm-function\[(?\d+)\]' r'\:0x(?[0-9a-fA-F]+))\)?)$'); // eval as function (https://example.com/stuff.dart.js:560:28), efn:3:28 diff --git a/pkgs/stack_trace/test/frame_test.dart b/pkgs/stack_trace/test/frame_test.dart index e62e8437c..a5dfc2064 100644 --- a/pkgs/stack_trace/test/frame_test.dart +++ b/pkgs/stack_trace/test/frame_test.dart @@ -651,6 +651,15 @@ baz@https://pub.dev/buz.js:56355:55 expect(frame.member, 'main tear-off trampoline'); }); + test('parses a V8 Wasm frame with a name with colons and parens', () { + var frame = Frame.parseV8(' at a::b::c() ' + '(https://a.b.com/x/y/z.wasm:wasm-function[66334]:0x12c28ad)'); + expect(frame.uri, Uri.parse('https://a.b.com/x/y/z.wasm')); + expect(frame.line, 1); + expect(frame.column, 0x12c28ad + 1); + expect(frame.member, 'a::b::c()'); + }); + test('parses a V8 Wasm frame without a name', () { var frame = Frame.parseV8(' at wasm://wasm/0006d966:wasm-function[119]:0xbb13'); From 3cbb2ca181d8c2bef80edd82d288db50e7089b85 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 27 Sep 2024 10:13:38 -0700 Subject: [PATCH 1152/1215] Require dart 3.4, prepare for release v1.12.0 (dart-lang/stack_trace#162) Doing a minor release since features were added --- pkgs/stack_trace/.github/workflows/test-package.yml | 2 +- pkgs/stack_trace/CHANGELOG.md | 4 ++-- pkgs/stack_trace/lib/src/stack_zone_specification.dart | 2 +- pkgs/stack_trace/pubspec.yaml | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 25edb675d..bbdb9d2fd 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -47,7 +47,7 @@ jobs: matrix: # Add macos-latest and/or windows-latest if relevant for this package. os: [ubuntu-latest] - sdk: [3.1, dev] + sdk: [3.4, dev] steps: - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 029f155cb..56aa7f642 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,7 +1,7 @@ -## 1.11.2-wip +## 1.12.0 -* Require Dart 3.1 or greater * Added support for parsing Wasm frames of Chrome (V8), Firefox, Safari. +* Require Dart 3.4 or greater ## 1.11.1 diff --git a/pkgs/stack_trace/lib/src/stack_zone_specification.dart b/pkgs/stack_trace/lib/src/stack_zone_specification.dart index 7309ce0ea..901a5ee8b 100644 --- a/pkgs/stack_trace/lib/src/stack_zone_specification.dart +++ b/pkgs/stack_trace/lib/src/stack_zone_specification.dart @@ -158,7 +158,7 @@ class StackZoneSpecification { try { // TODO(rnystrom): Is the null-assertion correct here? It is nullable in // Zone. Should we check for that here? - self.parent!.runBinary(_onError!, error, stackChain); + self.parent!.runBinary(_onError, error, stackChain); } on Object catch (newError, newStackTrace) { if (identical(newError, error)) { parent.handleUncaughtError(zone, error, stackChain); diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 2438909e2..a06cd6f1c 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,10 +1,10 @@ name: stack_trace -version: 1.11.2-wip +version: 1.12.0 description: A package for manipulating stack traces and printing them readably. repository: https://github.com/dart-lang/stack_trace environment: - sdk: ^3.1.0 + sdk: ^3.4.0 dependencies: path: ^1.8.0 From 0d71bece47e6a0ccfc1db28112764c38c9f5106b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:22:01 +0000 Subject: [PATCH 1153/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/string_scanner#79) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 9fc02d97c..91f097e22 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From d1ebf855b77347340fbc88c834a0825c92e67675 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 01:02:51 +0000 Subject: [PATCH 1154/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/timing#51) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index a6d3a64d7..c4e9ff0e6 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 28e800633dd1550e45944a3445db3239920bc1f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 01:31:17 +0000 Subject: [PATCH 1155/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/stream_transform#192) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 9e664b10b..41d421aba 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From b820aeba0e772c04d0dc6c188f2814ce20996b08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 03:17:00 +0000 Subject: [PATCH 1156/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/stream_channel#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 9d9f1cc08..30feba18c 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From b9c5b3b4affba1bd6cb2e5c6c72b03eb1744f162 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 05:50:53 +0000 Subject: [PATCH 1157/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/pubspec_parse#135) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 1bd25f969..756cf5c84 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From d27c72f64c137209643458ec6cc5a41f4330c800 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:11:01 +0000 Subject: [PATCH 1158/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/watcher#171) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 37e75dbc8..de0b6e9b0 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From abe36a3018078b76bc6bfa5d3768e3d8d4eba617 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:21:00 +0000 Subject: [PATCH 1159/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/stack_trace#163) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index bbdb9d2fd..9bc3f553c 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From fa98761393e41cde49826989a9ec5ed2cbb404d9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 13:07:05 +0000 Subject: [PATCH 1160/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/term_glyph#56) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index d1828e76b..aedb2c1e0 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 762063c0916a7b3279e804fd85a1f0a631df5f5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:42:56 +0000 Subject: [PATCH 1161/1215] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/test_reflective_loader#65) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0
Release notes

Sourced from actions/checkout's releases.

v4.2.0

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.1.7...v4.2.0

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

v4.0.0

v3.6.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index f863fb20e..c95f0c729 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 5916da269c0eaaba43064fce2c233ce57691f874 Mon Sep 17 00:00:00 2001 From: Danny Tuppeny Date: Wed, 9 Oct 2024 20:46:54 +0100 Subject: [PATCH 1162/1215] Avoid treating /r as newline on it (dart-lang/string_scanner#81) Fixes https://github.com/dart-lang/string_scanner/issues/80 This fixes an error when scanning a zero-length match when between a CR and LF. * Fix typo * comment nits * Fix some bugs when setting position if the current position is between \r\n --------- Co-authored-by: Nate Bosch --- pkgs/string_scanner/CHANGELOG.md | 8 + pkgs/string_scanner/lib/src/line_scanner.dart | 70 ++++- pkgs/string_scanner/pubspec.yaml | 2 +- .../test/line_scanner_test.dart | 243 ++++++++++++++++-- 4 files changed, 292 insertions(+), 31 deletions(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index a4c17b6bd..ee75f7338 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,11 @@ +## 1.4.0 + +* Fix `LineScanner`'s handling of `\r\n`'s to preventing errors scanning + zero-length matches when between CR and LF. CR is treated as a new line only + if not immediately followed by a LF. +* Fix `LineScanner`'s updating of `column` when setting `position` if the + current position is not `0`. + ## 1.3.0 * Require Dart 3.1.0 diff --git a/pkgs/string_scanner/lib/src/line_scanner.dart b/pkgs/string_scanner/lib/src/line_scanner.dart index 2903c4039..b18d61057 100644 --- a/pkgs/string_scanner/lib/src/line_scanner.dart +++ b/pkgs/string_scanner/lib/src/line_scanner.dart @@ -8,8 +8,9 @@ import 'utils.dart'; // Note that much of this code is duplicated in eager_span_scanner.dart. -/// A regular expression matching newlines across platforms. -final _newlineRegExp = RegExp(r'\r\n?|\n'); +/// A regular expression matching newlines. A newline is either a `\n`, a `\r\n` +/// or a `\r` that is not immediately followed by a `\n`. +final _newlineRegExp = RegExp(r'\n|\r\n|\r(?!\n)'); /// A subclass of [StringScanner] that tracks line and column information. class LineScanner extends StringScanner { @@ -48,27 +49,57 @@ class LineScanner extends StringScanner { @override set position(int newPosition) { + if (newPosition == position) { + return; + } + final oldPosition = position; super.position = newPosition; - if (newPosition > oldPosition) { - final newlines = _newlinesIn(string.substring(oldPosition, newPosition)); + if (newPosition == 0) { + _line = 0; + _column = 0; + } else if (newPosition > oldPosition) { + final newlines = _newlinesIn(string.substring(oldPosition, newPosition), + endPosition: newPosition); _line += newlines.length; if (newlines.isEmpty) { _column += newPosition - oldPosition; } else { - _column = newPosition - newlines.last.end; + // The regex got a substring, so we need to account for where it started + // in the string. + final offsetOfLastNewline = oldPosition + newlines.last.end; + _column = newPosition - offsetOfLastNewline; } - } else { - final newlines = _newlinesIn(string.substring(newPosition, oldPosition)); - if (_betweenCRLF) newlines.removeLast(); + } else if (newPosition < oldPosition) { + final newlines = _newlinesIn(string.substring(newPosition, oldPosition), + endPosition: oldPosition); _line -= newlines.length; if (newlines.isEmpty) { _column -= oldPosition - newPosition; } else { - _column = - newPosition - string.lastIndexOf(_newlineRegExp, newPosition) - 1; + // To compute the new column, we need to locate the last newline before + // the new position. When searching, we must exclude the CR if we're + // between a CRLF because it's not considered a newline. + final crOffset = _betweenCRLF ? -1 : 0; + // Additionally, if we use newPosition as the end of the search and the + // character at that position itself (the next character) is a newline + // we should not use it, so also offset to account for that. + const currentCharOffset = -1; + final lastNewline = string.lastIndexOf( + _newlineRegExp, newPosition + currentCharOffset + crOffset); + + // Now we need to know the offset after the newline. This is the index + // above plus the length of the newline (eg. if we found `\r\n`) we need + // to add two. However if no newline was found, that index is 0. + final offsetAfterLastNewline = lastNewline == -1 + ? 0 + : string[lastNewline] == '\r' && string[lastNewline + 1] == '\n' + ? lastNewline + 2 + : lastNewline + 1; + + _column = newPosition - offsetAfterLastNewline; } } } @@ -103,7 +134,7 @@ class LineScanner extends StringScanner { bool scan(Pattern pattern) { if (!super.scan(pattern)) return false; - final newlines = _newlinesIn(lastMatch![0]!); + final newlines = _newlinesIn(lastMatch![0]!, endPosition: position); _line += newlines.length; if (newlines.isEmpty) { _column += lastMatch![0]!.length; @@ -115,10 +146,21 @@ class LineScanner extends StringScanner { } /// Returns a list of [Match]es describing all the newlines in [text], which - /// is assumed to end at [position]. - List _newlinesIn(String text) { + /// ends at [endPosition]. + /// + /// If [text] ends with `\r`, it will only be treated as a newline if the next + /// character at [position] is not a `\n`. + List _newlinesIn(String text, {required int endPosition}) { final newlines = _newlineRegExp.allMatches(text).toList(); - if (_betweenCRLF) newlines.removeLast(); + // If the last character is a `\r` it will have been treated as a newline, + // but this is only valid if the next character is not a `\n`. + if (endPosition < string.length && + text.endsWith('\r') && + string[endPosition] == '\n') { + // newlines should never be empty here, because if `text` ends with `\r` + // it would have matched `\r(?!\n)` in the newline regex. + newlines.removeLast(); + } return newlines; } } diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index b8585385c..a8295e9c2 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.3.0 +version: 1.4.0 description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/string_scanner diff --git a/pkgs/string_scanner/test/line_scanner_test.dart b/pkgs/string_scanner/test/line_scanner_test.dart index d31d313a3..1af5c3666 100644 --- a/pkgs/string_scanner/test/line_scanner_test.dart +++ b/pkgs/string_scanner/test/line_scanner_test.dart @@ -19,25 +19,24 @@ void main() { group('scan()', () { test('consuming no newlines increases the column but not the line', () { - scanner.scan('foo'); + scanner.expect('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); }); - test('consuming a newline resets the column and increases the line', () { + test('consuming a LF resets the column and increases the line', () { scanner.expect('foo\nba'); expect(scanner.line, equals(1)); expect(scanner.column, equals(2)); }); - test('consuming multiple newlines resets the column and increases the line', - () { + test('consuming multiple LFs resets the column and increases the line', () { scanner.expect('foo\nbar\r\nb'); expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); - test("consuming halfway through a CR LF doesn't count as a line", () { + test('consuming a CR LF increases the line only after the LF', () { scanner.expect('foo\nbar\r'); expect(scanner.line, equals(1)); expect(scanner.column, equals(4)); @@ -46,6 +45,41 @@ void main() { expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); + + test('consuming a CR not followed by LF increases the line', () { + scanner = LineScanner('foo\nbar\rbaz'); + scanner.expect('foo\nbar\r'); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + + scanner.expect('b'); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test('consuming a CR at the end increases the line', () { + scanner = LineScanner('foo\nbar\r'); + scanner.expect('foo\nbar\r'); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + expect(scanner.isDone, isTrue); + }); + + test('consuming a mix of CR, LF, CR+LF increases the line', () { + scanner = LineScanner('0\n1\r2\r\n3'); + scanner.expect('0\n1\r2\r\n3'); + expect(scanner.line, equals(3)); + expect(scanner.column, equals(1)); + }); + + test('scanning a zero length match between CR LF does not fail', () { + scanner.expect('foo\nbar\r'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + scanner.expect(RegExp('(?!x)')); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + }); }); group('readChar()', () { @@ -56,7 +90,7 @@ void main() { expect(scanner.column, equals(1)); }); - test('consuming a newline resets the column and increases the line', () { + test('consuming a LF resets the column and increases the line', () { scanner.expect('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); @@ -66,19 +100,52 @@ void main() { expect(scanner.column, equals(0)); }); - test("consuming halfway through a CR LF doesn't count as a line", () { + test('consuming a CR LF increases the line only after the LF', () { + scanner = LineScanner('foo\r\nbar'); + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.readChar(); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(4)); + + scanner.readChar(); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test('consuming a CR not followed by a LF increases the line', () { + scanner = LineScanner('foo\nbar\rbaz'); scanner.expect('foo\nbar'); expect(scanner.line, equals(1)); expect(scanner.column, equals(3)); scanner.readChar(); + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); + + test('consuming a CR at the end increases the line', () { + scanner = LineScanner('foo\nbar\r'); + scanner.expect('foo\nbar'); expect(scanner.line, equals(1)); - expect(scanner.column, equals(4)); + expect(scanner.column, equals(3)); scanner.readChar(); expect(scanner.line, equals(2)); expect(scanner.column, equals(0)); }); + + test('consuming a mix of CR, LF, CR+LF increases the line', () { + scanner = LineScanner('0\n1\r2\r\n3'); + for (var i = 0; i < scanner.string.length; i++) { + scanner.readChar(); + } + + expect(scanner.line, equals(3)); + expect(scanner.column, equals(1)); + }); }); group('readCodePoint()', () { @@ -122,7 +189,7 @@ void main() { expect(scanner.column, equals(1)); }); - test('consuming a newline resets the column and increases the line', () { + test('consuming a LF resets the column and increases the line', () { scanner.expect('foo'); expect(scanner.line, equals(0)); expect(scanner.column, equals(3)); @@ -132,7 +199,7 @@ void main() { expect(scanner.column, equals(0)); }); - test("consuming halfway through a CR LF doesn't count as a line", () { + test('consuming a CR LF increases the line only after the LF', () { scanner.expect('foo\nbar'); expect(scanner.line, equals(1)); expect(scanner.column, equals(3)); @@ -145,6 +212,38 @@ void main() { expect(scanner.line, equals(2)); expect(scanner.column, equals(0)); }); + + test('consuming a CR not followed by LF increases the line', () { + scanner = LineScanner('foo\rbar'); + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.scanChar($cr); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test('consuming a CR at the end increases the line', () { + scanner = LineScanner('foo\r'); + scanner.expect('foo'); + expect(scanner.line, equals(0)); + expect(scanner.column, equals(3)); + + scanner.scanChar($cr); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(0)); + }); + + test('consuming a mix of CR, LF, CR+LF increases the line', () { + scanner = LineScanner('0\n1\r2\r\n3'); + for (var i = 0; i < scanner.string.length; i++) { + scanner.scanChar(scanner.string[i].codeUnits.single); + } + + expect(scanner.line, equals(3)); + expect(scanner.column, equals(1)); + }); }); group('before a surrogate pair', () { @@ -201,27 +300,102 @@ void main() { }); group('position=', () { - test('forward through newlines sets the line and column', () { - scanner.position = 10; // "foo\nbar\r\nb" + test('forward through LFs sets the line and column', () { + scanner = LineScanner('foo\nbar\nbaz'); + scanner.position = 9; // "foo\nbar\nb" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test('forward from non-zero character through LFs sets the line and column', + () { + scanner = LineScanner('foo\nbar\nbaz'); + scanner.expect('fo'); + scanner.position = 9; // "foo\nbar\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); }); + test('forward through CR LFs sets the line and column', () { + scanner = LineScanner('foo\r\nbar\r\nbaz'); + scanner.position = 11; // "foo\r\nbar\r\nb" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test('forward through CR not followed by LFs sets the line and column', () { + scanner = LineScanner('foo\rbar\rbaz'); + scanner.position = 9; // "foo\rbar\rb" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(1)); + }); + + test('forward through CR at end sets the line and column', () { + scanner = LineScanner('foo\rbar\r'); + scanner.position = 8; // "foo\rbar\r" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); + + test('forward through a mix of CR, LF, CR+LF sets the line and column', () { + scanner = LineScanner('0\n1\r2\r\n3'); + scanner.position = scanner.string.length; + + expect(scanner.line, equals(3)); + expect(scanner.column, equals(1)); + }); + test('forward through no newlines sets the column', () { scanner.position = 2; // "fo" expect(scanner.line, equals(0)); expect(scanner.column, equals(2)); }); - test('backward through newlines sets the line and column', () { - scanner.scan('foo\nbar\r\nbaz'); + test('backward through LFs sets the line and column', () { + scanner = LineScanner('foo\nbar\nbaz'); + scanner.expect('foo\nbar\nbaz'); + scanner.position = 2; // "fo" + expect(scanner.line, equals(0)); + expect(scanner.column, equals(2)); + }); + + test('backward through CR LFs sets the line and column', () { + scanner = LineScanner('foo\r\nbar\r\nbaz'); + scanner.expect('foo\r\nbar\r\nbaz'); scanner.position = 2; // "fo" expect(scanner.line, equals(0)); expect(scanner.column, equals(2)); }); + test('backward through CR not followed by LFs sets the line and column', + () { + scanner = LineScanner('foo\rbar\rbaz'); + scanner.expect('foo\rbar\rbaz'); + scanner.position = 2; // "fo" + expect(scanner.line, equals(0)); + expect(scanner.column, equals(2)); + }); + + test('backward through CR at end sets the line and column', () { + scanner = LineScanner('foo\rbar\r'); + scanner.expect('foo\rbar\r'); + scanner.position = 2; // "fo" + expect(scanner.line, equals(0)); + expect(scanner.column, equals(2)); + }); + + test('backward through a mix of CR, LF, CR+LF sets the line and column', + () { + scanner = LineScanner('0\n1\r2\r\n3'); + scanner.expect(scanner.string); + + scanner.position = 1; + expect(scanner.line, equals(0)); + expect(scanner.column, equals(1)); + }); + test('backward through no newlines sets the column', () { - scanner.scan('foo\nbar\r\nbaz'); + scanner.expect('foo\nbar\r\nbaz'); scanner.position = 10; // "foo\nbar\r\nb" expect(scanner.line, equals(2)); expect(scanner.column, equals(1)); @@ -232,10 +406,47 @@ void main() { expect(scanner.line, equals(1)); expect(scanner.column, equals(4)); }); + + test('forward from halfway through a CR LF counts as a line', () { + scanner.expect('foo\nbar\r'); + scanner.position = 11; // "foo\nbar\r\nba" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(2)); + }); + + test('backward to between CR LF', () { + scanner.expect('foo\nbar\r\nbaz'); + scanner.position = 8; // "foo\nbar\r" + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + }); + + test('backward from between CR LF', () { + scanner.expect('foo\nbar\r'); + expect(scanner.line, equals(1)); + expect(scanner.column, equals(4)); + scanner.position = 5; // "foo\nb" + expect(scanner.line, equals(1)); + expect(scanner.column, equals(1)); + }); + + test('backward to after CR LF', () { + scanner.expect('foo\nbar\r\nbaz'); + scanner.position = 9; // "foo\nbar\r\n" + expect(scanner.line, equals(2)); + expect(scanner.column, equals(0)); + }); + + test('backward to before CR LF', () { + scanner.expect('foo\nbar\r\nbaz'); + scanner.position = 7; // "foo\nbar" + expect(scanner.line, equals(1)); + expect(scanner.column, equals(3)); + }); }); test('state= restores the line, column, and position', () { - scanner.scan('foo\nb'); + scanner.expect('foo\nb'); final state = scanner.state; scanner.scan('ar\nba'); From bc01cd9f5ff0c2e231b169d833fb08140988226c Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Fri, 18 Oct 2024 17:19:17 -0700 Subject: [PATCH 1163/1215] Add a shared ignoreArgument callback (dart-lang/stream_transform#190) Add a `common_callbacks.dart` library with a single top level function `ignoreArgument` which takes a single `dynamic` argument and does nothing. Replace all `(_) => null` function literals, as well as a few library-private functions with unnecessarily specific signatures, with the shared definition. As suggested in dart-lang/stream_transform#188 --- pkgs/stream_transform/lib/src/aggregate_sample.dart | 4 +++- pkgs/stream_transform/lib/src/async_expand.dart | 5 ++++- pkgs/stream_transform/lib/src/async_map.dart | 4 ++-- pkgs/stream_transform/lib/src/combine_latest.dart | 8 ++++++-- pkgs/stream_transform/lib/src/common_callbacks.dart | 5 +++++ pkgs/stream_transform/lib/src/merge.dart | 6 +++++- pkgs/stream_transform/lib/src/rate_limit.dart | 4 ++-- pkgs/stream_transform/lib/src/switch.dart | 6 ++---- 8 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 pkgs/stream_transform/lib/src/common_callbacks.dart diff --git a/pkgs/stream_transform/lib/src/aggregate_sample.dart b/pkgs/stream_transform/lib/src/aggregate_sample.dart index b1040304c..f2ff8ed3b 100644 --- a/pkgs/stream_transform/lib/src/aggregate_sample.dart +++ b/pkgs/stream_transform/lib/src/aggregate_sample.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'common_callbacks.dart'; + extension AggregateSample on Stream { /// Computes a value based on sequences of events, then emits that value when /// [trigger] emits an event. @@ -136,7 +138,7 @@ extension AggregateSample on Stream { triggerSub!.pause(); } if (cancels.isEmpty) return null; - return cancels.wait.then((_) => null); + return cancels.wait.then(ignoreArgument); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/async_expand.dart b/pkgs/stream_transform/lib/src/async_expand.dart index e0c7672a2..28d2f4076 100644 --- a/pkgs/stream_transform/lib/src/async_expand.dart +++ b/pkgs/stream_transform/lib/src/async_expand.dart @@ -4,6 +4,7 @@ import 'dart:async'; +import 'common_callbacks.dart'; import 'switch.dart'; /// Alternatives to [asyncExpand]. @@ -78,7 +79,9 @@ extension AsyncExpand on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()] + .wait + .then(ignoreArgument); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/async_map.dart b/pkgs/stream_transform/lib/src/async_map.dart index 81a176fba..094df9c94 100644 --- a/pkgs/stream_transform/lib/src/async_map.dart +++ b/pkgs/stream_transform/lib/src/async_map.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'aggregate_sample.dart'; +import 'common_callbacks.dart'; import 'from_handlers.dart'; import 'rate_limit.dart'; @@ -72,7 +73,7 @@ extension AsyncMap on Stream { trigger: workFinished.stream, aggregate: _dropPrevious, longPoll: true, - onEmpty: _ignore) + onEmpty: ignoreArgument) ._asyncMapThen(convert, workFinished.add); } @@ -133,4 +134,3 @@ extension AsyncMap on Stream { } T _dropPrevious(T event, _) => event; -void _ignore(Sink sink) {} diff --git a/pkgs/stream_transform/lib/src/combine_latest.dart b/pkgs/stream_transform/lib/src/combine_latest.dart index 24eca4af3..f02a19e55 100644 --- a/pkgs/stream_transform/lib/src/combine_latest.dart +++ b/pkgs/stream_transform/lib/src/combine_latest.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'common_callbacks.dart'; + /// Utilities to combine events from multiple streams through a callback or into /// a list. extension CombineLatest on Stream { @@ -131,7 +133,7 @@ extension CombineLatest on Stream { ]; sourceSubscription = null; otherSubscription = null; - return cancels.wait.then((_) => null); + return cancels.wait.then(ignoreArgument); }; }; return controller.stream; @@ -228,7 +230,9 @@ extension CombineLatest on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()] + .wait + .then(ignoreArgument); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/common_callbacks.dart b/pkgs/stream_transform/lib/src/common_callbacks.dart new file mode 100644 index 000000000..c239220c2 --- /dev/null +++ b/pkgs/stream_transform/lib/src/common_callbacks.dart @@ -0,0 +1,5 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// 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. + +void ignoreArgument(_) {} diff --git a/pkgs/stream_transform/lib/src/merge.dart b/pkgs/stream_transform/lib/src/merge.dart index 9ffeb0ad8..3bfe06c7e 100644 --- a/pkgs/stream_transform/lib/src/merge.dart +++ b/pkgs/stream_transform/lib/src/merge.dart @@ -4,6 +4,8 @@ import 'dart:async'; +import 'common_callbacks.dart'; + /// Utilities to interleave events from multiple streams. extension Merge on Stream { /// Merges values and errors from this stream and [other] in any order as they @@ -90,7 +92,9 @@ extension Merge on Stream { } controller.onCancel = () { if (subscriptions.isEmpty) return null; - return [for (var s in subscriptions) s.cancel()].wait.then((_) => null); + return [for (var s in subscriptions) s.cancel()] + .wait + .then(ignoreArgument); }; }; return controller.stream; diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 347919bde..9be0be627 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'aggregate_sample.dart'; +import 'common_callbacks.dart'; import 'from_handlers.dart'; /// Utilities to rate limit events. @@ -305,7 +306,7 @@ extension RateLimit on Stream { trigger: trigger, aggregate: _dropPrevious, longPoll: longPoll, - onEmpty: _ignore); + onEmpty: ignoreArgument); /// Aggregates values until this source stream does not emit for [duration], /// then emits the aggregated values. @@ -353,4 +354,3 @@ extension RateLimit on Stream { T _dropPrevious(T element, _) => element; List _collect(T event, List? soFar) => (soFar ?? [])..add(event); void _empty(Sink> sink) => sink.add([]); -void _ignore(Sink sink) {} diff --git a/pkgs/stream_transform/lib/src/switch.dart b/pkgs/stream_transform/lib/src/switch.dart index 2ec3a5441..546036e7c 100644 --- a/pkgs/stream_transform/lib/src/switch.dart +++ b/pkgs/stream_transform/lib/src/switch.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'async_expand.dart'; +import 'common_callbacks.dart'; /// A utility to take events from the most recent sub stream returned by a /// callback. @@ -126,12 +127,9 @@ extension SwitchLatest on Stream> { if (sub != null) sub.cancel(), ]; if (cancels.isEmpty) return null; - return cancels.wait.then(_ignore); + return cancels.wait.then(ignoreArgument); }; }; return controller.stream; } } - -/// Helper function to ignore future callback -void _ignore(_, [__]) {} From 3a870590e910f76b4bf29dca55f2a39309ae7fa6 Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Tue, 22 Oct 2024 13:25:44 -0400 Subject: [PATCH 1164/1215] fix "throttle" docs typo (dart-lang/stream_transform#193) --- pkgs/stream_transform/lib/src/rate_limit.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/stream_transform/lib/src/rate_limit.dart b/pkgs/stream_transform/lib/src/rate_limit.dart index 9be0be627..299c23049 100644 --- a/pkgs/stream_transform/lib/src/rate_limit.dart +++ b/pkgs/stream_transform/lib/src/rate_limit.dart @@ -105,7 +105,7 @@ extension RateLimit on Stream { /// /// For example: /// - /// source.throtte(Duration(seconds: 6)); + /// source.throttle(Duration(seconds: 6)); /// /// source: 1-2-3---4-5-6---7-8-| /// result: 1-------4-------7---| From 770c3713a27b82578cb8472d186c19a20851e89b Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 28 Oct 2024 14:51:08 -0700 Subject: [PATCH 1165/1215] blast_repo fixes (dart-lang/pubspec_parse#138) drop-lint --- pkgs/pubspec_parse/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/pubspec_parse/analysis_options.yaml b/pkgs/pubspec_parse/analysis_options.yaml index c20999920..93eeebff2 100644 --- a/pkgs/pubspec_parse/analysis_options.yaml +++ b/pkgs/pubspec_parse/analysis_options.yaml @@ -22,7 +22,6 @@ linter: - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals From f876f9de3273080a639a0dbfc2bdab2f7a74dbde Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 28 Oct 2024 19:07:20 -0700 Subject: [PATCH 1166/1215] blast_repo fixes (dart-lang/string_scanner#83) drop-lint --- pkgs/string_scanner/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/string_scanner/analysis_options.yaml b/pkgs/string_scanner/analysis_options.yaml index 813466b66..59f763a4d 100644 --- a/pkgs/string_scanner/analysis_options.yaml +++ b/pkgs/string_scanner/analysis_options.yaml @@ -22,7 +22,6 @@ linter: - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals From b6e51c4bba285c9fed3002f84540ddc8949db591 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 28 Oct 2024 19:07:45 -0700 Subject: [PATCH 1167/1215] blast_repo fixes (dart-lang/stack_trace#164) drop-lint --- pkgs/stack_trace/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/stack_trace/analysis_options.yaml b/pkgs/stack_trace/analysis_options.yaml index ad62f915d..4eb82ceca 100644 --- a/pkgs/stack_trace/analysis_options.yaml +++ b/pkgs/stack_trace/analysis_options.yaml @@ -17,7 +17,6 @@ linter: - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - unnecessary_await_in_return - use_string_buffers From 28028c8afd6b79f99f1b10c5e3659d7a573f6783 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Tue, 29 Oct 2024 11:07:01 -0700 Subject: [PATCH 1168/1215] blast_repo fixes (dart-lang/term_glyph#57) drop-lint --- pkgs/term_glyph/analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/term_glyph/analysis_options.yaml b/pkgs/term_glyph/analysis_options.yaml index d16ad8251..6d74ee93f 100644 --- a/pkgs/term_glyph/analysis_options.yaml +++ b/pkgs/term_glyph/analysis_options.yaml @@ -22,7 +22,6 @@ linter: - missing_whitespace_between_adjacent_strings - no_adjacent_strings_in_list - no_runtimeType_toString - - package_api_docs - prefer_const_declarations - prefer_expression_function_bodies - prefer_final_locals From 8c0f5652e576489d1521f824ccd9393e46fd5773 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:27:17 +0000 Subject: [PATCH 1169/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/string_scanner#84) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index 91f097e22..a5149a239 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 00223b431fd6aa3bc70c5b7e587a3d082c402a94 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 01:34:08 +0000 Subject: [PATCH 1170/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/stream_transform#194) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index 41d421aba..cd9122165 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -50,7 +50,7 @@ jobs: # Bump SDK for Legacy tests when changing min SDK. sdk: [3.1, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 07afd97ba833e9fa5eeb0e117152192e2211a037 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 01:48:21 +0000 Subject: [PATCH 1171/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/timing#52) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index c4e9ff0e6..47d31d68a 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -46,7 +46,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From ae5aad43d700aa1689580603c55697ff864ca85b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 03:59:06 +0000 Subject: [PATCH 1172/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/stream_channel#112) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index 30feba18c..e667e382e 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.3, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From fba7c1f6d2c17ac83c32be11a5bb58b8cab6626c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 05:11:08 +0000 Subject: [PATCH 1173/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/pubspec_parse#139) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 756cf5c84..16fb962ec 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 94fff3004900737da61f91831462a69e0f06a63d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 08:07:19 +0000 Subject: [PATCH 1174/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/watcher#172) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index de0b6e9b0..13d140e76 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -48,7 +48,7 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From f618c004d7ff03836efec845a85a1ad0e21dbc5e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:16:49 +0000 Subject: [PATCH 1175/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/stack_trace#165) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index 9bc3f553c..abebeee9f 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.4, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 3f2fadb2af1d2ae7c1dd6324b347e58145f829e1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 13:55:19 +0000 Subject: [PATCH 1176/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/term_glyph#58) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index aedb2c1e0..08951cc08 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -22,7 +22,7 @@ jobs: matrix: sdk: [dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} @@ -49,7 +49,7 @@ jobs: os: [ubuntu-latest] sdk: [3.1, dev] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From 1729eee40d78eb4ad868b7b958a16e8b63a0f8ba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:47:02 +0000 Subject: [PATCH 1177/1215] Bump actions/checkout from 4.2.0 to 4.2.2 in the github-actions group (dart-lang/test_reflective_loader#66) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.2.0 to 4.2.2
Release notes

Sourced from actions/checkout's releases.

v4.2.2

What's Changed

Full Changelog: https://github.com/actions/checkout/compare/v4.2.1...v4.2.2

v4.2.1

What's Changed

New Contributors

Full Changelog: https://github.com/actions/checkout/compare/v4.2.0...v4.2.1

Changelog

Sourced from actions/checkout's changelog.

Changelog

v4.2.2

v4.2.1

v4.2.0

v4.1.7

v4.1.6

v4.1.5

v4.1.4

v4.1.3

v4.1.2

v4.1.1

v4.1.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.2.0&new-version=4.2.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index c95f0c729..59675a863 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -21,7 +21,7 @@ jobs: sdk: [dev, 3.1] steps: - - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From bc0d37022765730f8eb3f4677b8e60db9126c49e Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 19 Nov 2024 18:52:20 +0100 Subject: [PATCH 1178/1215] chore: Remove deprecated package_api_docs rule (dart-lang/pubspec_parse#141) * chore: Remove deprecated package_api_docs rule * chore: Add changelog entry --- pkgs/pubspec_parse/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index aa99cbb5c..91613ccf6 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.3.1-wip - Require Dart 3.2 +- Remove deprecated package_api_docs rule ## 1.3.0 From b47d77a4aad6d79346a57cc1dab9bd52792a0fd7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:11:17 +0000 Subject: [PATCH 1179/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/string_scanner#85) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/string_scanner#118: dart-lang/setup-dartdart-lang/string_scanner#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/string_scanner/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/string_scanner/.github/workflows/test-package.yml b/pkgs/string_scanner/.github/workflows/test-package.yml index a5149a239..c60f71070 100644 --- a/pkgs/string_scanner/.github/workflows/test-package.yml +++ b/pkgs/string_scanner/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From d83abd979f609f11403a069919174e01fde7d11d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 01:23:21 +0000 Subject: [PATCH 1180/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/stream_transform#195) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/stream_transform#118: dart-lang/setup-dartdart-lang/stream_transform#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_transform/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/pkgs/stream_transform/.github/workflows/test-package.yml index cd9122165..6f545fb1b 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/pkgs/stream_transform/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -51,7 +51,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 088950c4eb1c3451a95dd84396de081b08810b1b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 01:33:27 +0000 Subject: [PATCH 1181/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/timing#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/timing#118: dart-lang/setup-dartdart-lang/timing#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/timing/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml index 47d31d68a..416123a22 100644 --- a/pkgs/timing/.github/workflows/test-package.yml +++ b/pkgs/timing/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -47,7 +47,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 7808a8850caae1362e3f583eb81b34fbcb707a8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 03:37:21 +0000 Subject: [PATCH 1182/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/stream_channel#113) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/stream_channel#118: dart-lang/setup-dartdart-lang/stream_channel#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stream_channel/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/pkgs/stream_channel/.github/workflows/test-package.yml index e667e382e..c70b745e2 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/pkgs/stream_channel/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.3, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From c3fa9594c431be80054059a2f4bcaf832b410f71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 05:17:22 +0000 Subject: [PATCH 1183/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/pubspec_parse#142) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/pubspec_parse#118: dart-lang/setup-dartdart-lang/pubspec_parse#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/pubspec_parse/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/pkgs/pubspec_parse/.github/workflows/test-package.yml index 16fb962ec..922d6c28e 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/pkgs/pubspec_parse/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.2, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 0086feae01eacc2745287971fa93bb1f60115e0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 08:17:18 +0000 Subject: [PATCH 1184/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/watcher#173) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/watcher#118: dart-lang/setup-dartdart-lang/watcher#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/watcher/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/pkgs/watcher/.github/workflows/test-package.yml index 13d140e76..b501c983a 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/pkgs/watcher/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -49,7 +49,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From db041d1c2a78ed81ab3f18d0127c27e2af83ea8b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 10:38:05 +0000 Subject: [PATCH 1185/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/stack_trace#168) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/stack_trace#118: dart-lang/setup-dartdart-lang/stack_trace#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/stack_trace/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/pkgs/stack_trace/.github/workflows/test-package.yml index abebeee9f..01fb647a3 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/pkgs/stack_trace/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.4, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From da99c5c9fb37c524894582d862a25c2245623384 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 13:31:33 +0000 Subject: [PATCH 1186/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/term_glyph#59) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/term_glyph#118: dart-lang/setup-dartdart-lang/term_glyph#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/term_glyph/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/pkgs/term_glyph/.github/workflows/test-package.yml index 08951cc08..15b3b623e 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/pkgs/term_glyph/.github/workflows/test-package.yml @@ -23,7 +23,7 @@ jobs: sdk: [dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install @@ -50,7 +50,7 @@ jobs: sdk: [3.1, dev] steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} - id: install From 5d042243ab6b868db9cf5619dc6c37d992f6c60f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Dec 2024 16:45:10 +0000 Subject: [PATCH 1187/1215] Bump dart-lang/setup-dart in the github-actions group (dart-lang/test_reflective_loader#67) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `dart-lang/setup-dart` from 1.6.5 to 1.7.0
Release notes

Sourced from dart-lang/setup-dart's releases.

v1.7.0

What's Changed

  • Install a Flutter SDK in the publish workflow allowing for publication of flutter packages.
Changelog

Sourced from dart-lang/setup-dart's changelog.

v1.7.0

v1.6.5

dart-lang/test_reflective_loader#118: dart-lang/setup-dartdart-lang/test_reflective_loader#118

v1.6.4

  • Rebuild JS code.

v1.6.3

v1.6.2

v1.6.1

  • Updated the google storage url for main channel releases.

v1.6.0

  • Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. 3.2).

v1.5.1

  • No longer test the setup-dart action on pre-2.12 SDKs.
  • Upgrade JS interop code to use extension types (the new name for inline classes).
  • The upcoming rename of the be channel to main is now supported with forward compatibility that switches when the rename happens.

v1.5.0

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.5&new-version=1.7.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
--- pkgs/test_reflective_loader/.github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/pkgs/test_reflective_loader/.github/workflows/build.yaml index 59675a863..2c15d9546 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/pkgs/test_reflective_loader/.github/workflows/build.yaml @@ -22,7 +22,7 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} From 96a8d204fc89513ced4e2cd78b145efbc95fe749 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 16:50:30 +0100 Subject: [PATCH 1188/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/stack_trace.md | 5 +++++ pkgs/stack_trace/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/stack_trace.md diff --git a/.github/ISSUE_TEMPLATE/stack_trace.md b/.github/ISSUE_TEMPLATE/stack_trace.md new file mode 100644 index 000000000..417362b3f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/stack_trace.md @@ -0,0 +1,5 @@ +--- +name: "package:stack_trace" +about: "Create a bug or file a feature request against package:stack_trace." +labels: "package:stack_trace" +--- \ No newline at end of file diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index a06cd6f1c..7e76f0bbf 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,7 +1,7 @@ name: stack_trace version: 1.12.0 description: A package for manipulating stack traces and printing them readably. -repository: https://github.com/dart-lang/stack_trace +repository: https://github.com/dart-lang/tools/tree/main/pkgs/stack_trace environment: sdk: ^3.4.0 From 055862b5037b403560e1bb2c81c1bc6c0cc951e3 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 16:58:51 +0100 Subject: [PATCH 1189/1215] merge fixes --- .github/labeler.yml | 4 ++ .../workflows/stack_trace.yaml | 17 +++++++-- README.md | 1 + pkgs/stack_trace/.github/dependabot.yml | 15 -------- .../.github/workflows/no-response.yml | 37 ------------------- pkgs/stack_trace/CHANGELOG.md | 4 ++ pkgs/stack_trace/README.md | 2 +- pkgs/stack_trace/pubspec.yaml | 2 +- 8 files changed, 25 insertions(+), 57 deletions(-) rename pkgs/stack_trace/.github/workflows/test-package.yml => .github/workflows/stack_trace.yaml (85%) delete mode 100644 pkgs/stack_trace/.github/dependabot.yml delete mode 100644 pkgs/stack_trace/.github/workflows/no-response.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index eca80bbc2..9bca16c4f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -84,6 +84,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' +'package:stack_trace': + - changed-files: + - any-glob-to-any-file: 'pkgs/stack_trace/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/pkgs/stack_trace/.github/workflows/test-package.yml b/.github/workflows/stack_trace.yaml similarity index 85% rename from pkgs/stack_trace/.github/workflows/test-package.yml rename to .github/workflows/stack_trace.yaml index 01fb647a3..7435967a8 100644 --- a/pkgs/stack_trace/.github/workflows/test-package.yml +++ b/.github/workflows/stack_trace.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:stack_trace on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stack_trace.yaml' + - 'pkgs/stack_trace/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stack_trace.yaml' + - 'pkgs/stack_trace/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/stack_trace/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 50517c36e..e7d1e9eda 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ don't naturally belong to other topic monorepos (like | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | +| [stack_trace](pkgs/stack_trace/) | A package for manipulating stack traces and printing them readably. | [![package issues](https://img.shields.io/badge/package:stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Astack_trace) | [![pub package](https://img.shields.io/pub/v/stack_trace.svg)](https://pub.dev/packages/stack_trace) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/stack_trace/.github/dependabot.yml b/pkgs/stack_trace/.github/dependabot.yml deleted file mode 100644 index 706926934..000000000 --- a/pkgs/stack_trace/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates - -version: 2 -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/stack_trace/.github/workflows/no-response.yml b/pkgs/stack_trace/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/stack_trace/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/stack_trace/CHANGELOG.md b/pkgs/stack_trace/CHANGELOG.md index 56aa7f642..e92cf9cea 100644 --- a/pkgs/stack_trace/CHANGELOG.md +++ b/pkgs/stack_trace/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.12.1 + +* Move to `dart-lang/tools` monorepo. + ## 1.12.0 * Added support for parsing Wasm frames of Chrome (V8), Firefox, Safari. diff --git a/pkgs/stack_trace/README.md b/pkgs/stack_trace/README.md index 83bae61d1..b10a55638 100644 --- a/pkgs/stack_trace/README.md +++ b/pkgs/stack_trace/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/stack_trace/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stack_trace/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/stack_trace.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/stack_trace.yaml) [![pub package](https://img.shields.io/pub/v/stack_trace.svg)](https://pub.dev/packages/stack_trace) [![package publisher](https://img.shields.io/pub/publisher/stack_trace.svg)](https://pub.dev/packages/stack_trace/publisher) diff --git a/pkgs/stack_trace/pubspec.yaml b/pkgs/stack_trace/pubspec.yaml index 7e76f0bbf..4f387b1c4 100644 --- a/pkgs/stack_trace/pubspec.yaml +++ b/pkgs/stack_trace/pubspec.yaml @@ -1,5 +1,5 @@ name: stack_trace -version: 1.12.0 +version: 1.12.1 description: A package for manipulating stack traces and printing them readably. repository: https://github.com/dart-lang/tools/tree/main/pkgs/stack_trace From 8021ff098cefbb3dec93e77a675c5db241c7bf76 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 17:01:55 +0100 Subject: [PATCH 1190/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/stream_channel.md | 5 ++++ pkgs/stream_channel/CONTRIBUTING.md | 33 ------------------------ pkgs/stream_channel/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/stream_channel.md delete mode 100644 pkgs/stream_channel/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/stream_channel.md b/.github/ISSUE_TEMPLATE/stream_channel.md new file mode 100644 index 000000000..76b599497 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/stream_channel.md @@ -0,0 +1,5 @@ +--- +name: "package:stream_channel" +about: "Create a bug or file a feature request against package:stream_channel." +labels: "package:stream_channel" +--- \ No newline at end of file diff --git a/pkgs/stream_channel/CONTRIBUTING.md b/pkgs/stream_channel/CONTRIBUTING.md deleted file mode 100644 index 6f5e0ea67..000000000 --- a/pkgs/stream_channel/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file - // 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index 652472170..c1b8e1f19 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -3,7 +3,7 @@ version: 2.1.3-wip description: >- An abstraction for two-way communication channels based on the Dart Stream class. -repository: https://github.com/dart-lang/stream_channel +repository: https://github.com/dart-lang/tools/tree/main/pkgs/stream_channel environment: sdk: ^3.3.0 From e66e313089cd413db345a3ab57db09da45bf2128 Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 10 Dec 2024 17:04:34 +0100 Subject: [PATCH 1191/1215] merge fixes --- .github/labeler.yml | 4 ++ .../workflows/stream_channel.yaml | 16 ++++++-- README.md | 1 + pkgs/stream_channel/.github/dependabot.yml | 15 -------- .../.github/workflows/no-response.yml | 37 ------------------- .../.github/workflows/publish.yaml | 17 --------- pkgs/stream_channel/CHANGELOG.md | 3 +- pkgs/stream_channel/README.md | 2 +- pkgs/stream_channel/pubspec.yaml | 2 +- 9 files changed, 22 insertions(+), 75 deletions(-) rename pkgs/stream_channel/.github/workflows/test-package.yml => .github/workflows/stream_channel.yaml (85%) delete mode 100644 pkgs/stream_channel/.github/dependabot.yml delete mode 100644 pkgs/stream_channel/.github/workflows/no-response.yml delete mode 100644 pkgs/stream_channel/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index eca80bbc2..ea9baeba9 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -84,6 +84,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' +'package:stream_channel': + - changed-files: + - any-glob-to-any-file: 'pkgs/stream_channel/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/pkgs/stream_channel/.github/workflows/test-package.yml b/.github/workflows/stream_channel.yaml similarity index 85% rename from pkgs/stream_channel/.github/workflows/test-package.yml rename to .github/workflows/stream_channel.yaml index c70b745e2..c39424dc5 100644 --- a/pkgs/stream_channel/.github/workflows/test-package.yml +++ b/.github/workflows/stream_channel.yaml @@ -1,17 +1,27 @@ -name: Dart CI +name: package:stream_channel on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_channel.yaml' + - 'pkgs/stream_channel/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_channel.yaml' + - 'pkgs/stream_channel/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github +defaults: + run: + working-directory: pkgs/stream_channel/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 50517c36e..495f0ea36 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ don't naturally belong to other topic monorepos (like | [mime](pkgs/mime/) | Utilities for handling media (MIME) types, including determining a type from a file extension and file contents. | [![package issues](https://img.shields.io/badge/package:mime-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Amime) | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticating with a remote service via OAuth2 on behalf of a user, and making authorized HTTP requests with the user's OAuth2 credentials. | [![package issues](https://img.shields.io/badge/package:oauth2-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aoauth2) | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | +| [stream_channel](pkgs/stream_channel/) | An abstraction for two-way communication channels based on the Dart Stream class. | [![package issues](https://img.shields.io/badge/package:stream_channel-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Astream_channel) | [![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/stream_channel/.github/dependabot.yml b/pkgs/stream_channel/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/stream_channel/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/stream_channel/.github/workflows/no-response.yml b/pkgs/stream_channel/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/stream_channel/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/stream_channel/.github/workflows/publish.yaml b/pkgs/stream_channel/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046..000000000 --- a/pkgs/stream_channel/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/stream_channel/CHANGELOG.md b/pkgs/stream_channel/CHANGELOG.md index 4b8e2b54a..30f7d32bc 100644 --- a/pkgs/stream_channel/CHANGELOG.md +++ b/pkgs/stream_channel/CHANGELOG.md @@ -1,6 +1,7 @@ -## 2.1.3-wip +## 2.1.3 * Require Dart 3.3 +* Move to `dart-lang/tools` monorepo. ## 2.1.2 diff --git a/pkgs/stream_channel/README.md b/pkgs/stream_channel/README.md index ae1ea219d..3677ccf5e 100644 --- a/pkgs/stream_channel/README.md +++ b/pkgs/stream_channel/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_channel/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/stream_channel.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/stream_channel.yaml) [![pub package](https://img.shields.io/pub/v/stream_channel.svg)](https://pub.dev/packages/stream_channel) [![package publisher](https://img.shields.io/pub/publisher/stream_channel.svg)](https://pub.dev/packages/stream_channel/publisher) diff --git a/pkgs/stream_channel/pubspec.yaml b/pkgs/stream_channel/pubspec.yaml index c1b8e1f19..eec8c1ba5 100644 --- a/pkgs/stream_channel/pubspec.yaml +++ b/pkgs/stream_channel/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_channel -version: 2.1.3-wip +version: 2.1.3 description: >- An abstraction for two-way communication channels based on the Dart Stream class. From a7ddf356ad32bd36742108d300e12484772e3fb3 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Tue, 10 Dec 2024 19:12:35 +0100 Subject: [PATCH 1192/1215] fix: Pubspec.environment can never be null (dart-lang/pubspec_parse#137) * fix: Pubspec.environment can never be null * chore: Add changelog entry * fix: _environmentMap to return empty map when input is null --- pkgs/pubspec_parse/CHANGELOG.md | 1 + pkgs/pubspec_parse/lib/src/pubspec.dart | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 91613ccf6..2768cdebd 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ ## 1.3.1-wip - Require Dart 3.2 +- Set `Pubspec.environment` to non-nullable. - Remove deprecated package_api_docs rule ## 1.3.0 diff --git a/pkgs/pubspec_parse/lib/src/pubspec.dart b/pkgs/pubspec_parse/lib/src/pubspec.dart index f6934eef3..1317a2309 100644 --- a/pkgs/pubspec_parse/lib/src/pubspec.dart +++ b/pkgs/pubspec_parse/lib/src/pubspec.dart @@ -74,7 +74,7 @@ class Pubspec { final String? documentation; @JsonKey(fromJson: _environmentMap) - final Map? environment; + final Map environment; @JsonKey(fromJson: parseDeps) final Map dependencies; @@ -186,7 +186,7 @@ class Pubspec { Version? _versionFromString(String? input) => input == null ? null : Version.parse(input); -Map? _environmentMap(Map? source) => +Map _environmentMap(Map? source) => source?.map((k, value) { final key = k as String; if (key == 'dart') { @@ -222,4 +222,5 @@ Map? _environmentMap(Map? source) => } return MapEntry(key, constraint); - }); + }) ?? + {}; From 9ee62d4e1d4c0ebdd5572964652cbe5985e33c67 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:01:50 +0100 Subject: [PATCH 1193/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/stream_transform.md | 5 +++++ pkgs/stream_transform/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/stream_transform.md diff --git a/.github/ISSUE_TEMPLATE/stream_transform.md b/.github/ISSUE_TEMPLATE/stream_transform.md new file mode 100644 index 000000000..475bd837f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/stream_transform.md @@ -0,0 +1,5 @@ +--- +name: "package:stream_transform" +about: "Create a bug or file a feature request against package:stream_transform." +labels: "package:stream_transform" +--- \ No newline at end of file diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 9cd6584c1..1ad7013b7 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,7 +1,7 @@ name: stream_transform version: 2.1.1-wip description: A collection of utilities to transform and manipulate streams. -repository: https://github.com/dart-lang/stream_transform +repository: https://github.com/dart-lang/tools/tree/main/pkgs/stream_transform environment: sdk: ^3.1.0 From 19a4b38d5eb8f7d265f399971101bddab0963e8a Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:05:22 +0100 Subject: [PATCH 1194/1215] Moving fixes --- .github/labeler.yml | 4 ++++ .github/workflows/clock.yaml | 4 ++-- .../workflows/stream_transform.yaml | 17 ++++++++++++++--- README.md | 1 + pkgs/stream_transform/.github/dependabot.yaml | 14 -------------- pkgs/stream_transform/CHANGELOG.md | 3 ++- pkgs/stream_transform/README.md | 4 ++-- pkgs/stream_transform/pubspec.yaml | 2 +- 8 files changed, 26 insertions(+), 23 deletions(-) rename pkgs/stream_transform/.github/workflows/test-package.yml => .github/workflows/stream_transform.yaml (84%) delete mode 100644 pkgs/stream_transform/.github/dependabot.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..ea34541fc 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -108,6 +108,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/sse/**' +'package:stream_transform': + - changed-files: + - any-glob-to-any-file: 'pkgs/stream_transform/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/.github/workflows/clock.yaml b/.github/workflows/clock.yaml index aef089513..a09a6010c 100644 --- a/.github/workflows/clock.yaml +++ b/.github/workflows/clock.yaml @@ -5,12 +5,12 @@ on: push: branches: [ main ] paths: - - '.github/workflows/clock.yml' + - '.github/workflows/clock.yaml' - 'pkgs/clock/**' pull_request: branches: [ main ] paths: - - '.github/workflows/clock.yml' + - '.github/workflows/clock.yaml' - 'pkgs/clock/**' schedule: - cron: "0 0 * * 0" diff --git a/pkgs/stream_transform/.github/workflows/test-package.yml b/.github/workflows/stream_transform.yaml similarity index 84% rename from pkgs/stream_transform/.github/workflows/test-package.yml rename to .github/workflows/stream_transform.yaml index 6f545fb1b..a36a77660 100644 --- a/pkgs/stream_transform/.github/workflows/test-package.yml +++ b/.github/workflows/stream_transform.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:stream_transform on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_transform.yaml' + - 'pkgs/stream_transform/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/stream_transform.yaml' + - 'pkgs/stream_transform/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/stream_transform/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 79d1dde21..7b351f678 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ don't naturally belong to other topic monorepos (like | [source_maps](pkgs/source_maps/) | A library to programmatically manipulate source map files. | [![package issues](https://img.shields.io/badge/package:source_maps-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_maps) | [![pub package](https://img.shields.io/pub/v/source_maps.svg)](https://pub.dev/packages/source_maps) | | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | +| [stream_transform](pkgs/stream_transform/) | A collection of utilities to transform and manipulate streams. | [![package issues](https://img.shields.io/badge/package:stream_transform-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Astream_transform) | [![pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/stream_transform/.github/dependabot.yaml b/pkgs/stream_transform/.github/dependabot.yaml deleted file mode 100644 index bf6b38a4d..000000000 --- a/pkgs/stream_transform/.github/dependabot.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Dependabot configuration file. -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/stream_transform/CHANGELOG.md b/pkgs/stream_transform/CHANGELOG.md index c1e2c0ea1..a71b2fb1c 100644 --- a/pkgs/stream_transform/CHANGELOG.md +++ b/pkgs/stream_transform/CHANGELOG.md @@ -1,9 +1,10 @@ -## 2.1.1-wip +## 2.1.1 - Require Dart 3.1 or greater - Forward errors from the `trigger` future through to the result stream in `takeUntil`. Previously an error would have not closed the stream, and instead raised as an unhandled async error. +- Move to `dart-lang/tools` monorepo. ## 2.1.0 diff --git a/pkgs/stream_transform/README.md b/pkgs/stream_transform/README.md index 68d84d9a5..e7049bdc5 100644 --- a/pkgs/stream_transform/README.md +++ b/pkgs/stream_transform/README.md @@ -1,5 +1,5 @@ -[![Dart CI](https://github.com/dart-lang/stream_transform/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/stream_transform/actions/workflows/test-package.yml) -[![Pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/stream_transform.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/stream_transform.yaml) +[![pub package](https://img.shields.io/pub/v/stream_transform.svg)](https://pub.dev/packages/stream_transform) [![package publisher](https://img.shields.io/pub/publisher/stream_transform.svg)](https://pub.dev/packages/stream_transform/publisher) Extension methods on `Stream` adding common transform operators. diff --git a/pkgs/stream_transform/pubspec.yaml b/pkgs/stream_transform/pubspec.yaml index 1ad7013b7..1e2298abe 100644 --- a/pkgs/stream_transform/pubspec.yaml +++ b/pkgs/stream_transform/pubspec.yaml @@ -1,5 +1,5 @@ name: stream_transform -version: 2.1.1-wip +version: 2.1.1 description: A collection of utilities to transform and manipulate streams. repository: https://github.com/dart-lang/tools/tree/main/pkgs/stream_transform From 696b3f2dc4963097e40a0e95042d0f4394e04167 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:08:00 +0100 Subject: [PATCH 1195/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/string_scanner.md | 5 +++++ pkgs/string_scanner/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/string_scanner.md diff --git a/.github/ISSUE_TEMPLATE/string_scanner.md b/.github/ISSUE_TEMPLATE/string_scanner.md new file mode 100644 index 000000000..ad89f1b5b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/string_scanner.md @@ -0,0 +1,5 @@ +--- +name: "package:string_scanner" +about: "Create a bug or file a feature request against package:string_scanner." +labels: "package:string_scanner" +--- \ No newline at end of file diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index a8295e9c2..0930cda49 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,7 +1,7 @@ name: string_scanner version: 1.4.0 description: A class for parsing strings using a sequence of patterns. -repository: https://github.com/dart-lang/string_scanner +repository: https://github.com/dart-lang/tools/tree/main/pkgs/string_scanner environment: sdk: ^3.1.0 From ce1f43e32c730a0dfa771e4547a18da7522375f5 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:17:24 +0100 Subject: [PATCH 1196/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/term_glyph.md | 5 +++++ pkgs/term_glyph/CONTRIBUTING.md | 33 ---------------------------- pkgs/term_glyph/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/term_glyph.md delete mode 100644 pkgs/term_glyph/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/term_glyph.md b/.github/ISSUE_TEMPLATE/term_glyph.md new file mode 100644 index 000000000..b6a47669c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/term_glyph.md @@ -0,0 +1,5 @@ +--- +name: "package:term_glyph" +about: "Create a bug or file a feature request against package:term_glyph." +labels: "package:term_glyph" +--- \ No newline at end of file diff --git a/pkgs/term_glyph/CONTRIBUTING.md b/pkgs/term_glyph/CONTRIBUTING.md deleted file mode 100644 index 6f5e0ea67..000000000 --- a/pkgs/term_glyph/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file - // 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index e4c998d79..2fb408774 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,7 +1,7 @@ name: term_glyph version: 1.2.2-wip description: Useful Unicode glyphs and ASCII substitutes. -repository: https://github.com/dart-lang/term_glyph +repository: https://github.com/dart-lang/tools/tree/main/pkgs/term_glyph environment: sdk: ^3.1.0 From 1d99aaacbf709a2284c6eee3583d0fafcfec21da Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:22:30 +0100 Subject: [PATCH 1197/1215] Moving fixes --- .github/labeler.yml | 4 ++++ .../workflows/term_glyph.yaml | 17 ++++++++++++++--- README.md | 1 + pkgs/term_glyph/.github/dependabot.yml | 15 --------------- pkgs/term_glyph/CHANGELOG.md | 3 ++- pkgs/term_glyph/README.md | 2 +- pkgs/term_glyph/pubspec.yaml | 2 +- 7 files changed, 23 insertions(+), 21 deletions(-) rename pkgs/term_glyph/.github/workflows/test-package.yml => .github/workflows/term_glyph.yaml (85%) delete mode 100644 pkgs/term_glyph/.github/dependabot.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..4c93a3929 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -108,6 +108,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/sse/**' +'package:term_glyph': + - changed-files: + - any-glob-to-any-file: 'pkgs/term_glyph/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/pkgs/term_glyph/.github/workflows/test-package.yml b/.github/workflows/term_glyph.yaml similarity index 85% rename from pkgs/term_glyph/.github/workflows/test-package.yml rename to .github/workflows/term_glyph.yaml index 15b3b623e..5b3b3209b 100644 --- a/pkgs/term_glyph/.github/workflows/test-package.yml +++ b/.github/workflows/term_glyph.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:term_glyph on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/term_glyph.yaml' + - 'pkgs/term_glyph/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/term_glyph.yaml' + - 'pkgs/term_glyph/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/term_glyph/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 79d1dde21..fc9fa4b41 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ don't naturally belong to other topic monorepos (like | [source_maps](pkgs/source_maps/) | A library to programmatically manipulate source map files. | [![package issues](https://img.shields.io/badge/package:source_maps-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_maps) | [![pub package](https://img.shields.io/pub/v/source_maps.svg)](https://pub.dev/packages/source_maps) | | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | +| [term_glyph](pkgs/term_glyph/) | Useful Unicode glyphs and ASCII substitutes. | [![package issues](https://img.shields.io/badge/package:term_glyph-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aterm_glyph) | [![pub package](https://img.shields.io/pub/v/term_glyph.svg)](https://pub.dev/packages/term_glyph) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/term_glyph/.github/dependabot.yml b/pkgs/term_glyph/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/term_glyph/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/term_glyph/CHANGELOG.md b/pkgs/term_glyph/CHANGELOG.md index d25ef1ab5..b7359cfb7 100644 --- a/pkgs/term_glyph/CHANGELOG.md +++ b/pkgs/term_glyph/CHANGELOG.md @@ -1,6 +1,7 @@ -## 1.2.2-wip +## 1.2.2 * Require Dart 3.1 +* Move to `dart-lang/tools` monorepo. ## 1.2.1 diff --git a/pkgs/term_glyph/README.md b/pkgs/term_glyph/README.md index 3a75d0606..75039aaeb 100644 --- a/pkgs/term_glyph/README.md +++ b/pkgs/term_glyph/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/term_glyph/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/term_glyph/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/term_glyph.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/term_glyph.yaml) [![pub package](https://img.shields.io/pub/v/term_glyph.svg)](https://pub.dev/packages/term_glyph) [![package publisher](https://img.shields.io/pub/publisher/term_glyph.svg)](https://pub.dev/packages/term_glyph/publisher) diff --git a/pkgs/term_glyph/pubspec.yaml b/pkgs/term_glyph/pubspec.yaml index 2fb408774..c429307b9 100644 --- a/pkgs/term_glyph/pubspec.yaml +++ b/pkgs/term_glyph/pubspec.yaml @@ -1,5 +1,5 @@ name: term_glyph -version: 1.2.2-wip +version: 1.2.2 description: Useful Unicode glyphs and ASCII substitutes. repository: https://github.com/dart-lang/tools/tree/main/pkgs/term_glyph From 3586c28fefc9b5c186303c9851427689a2f9101b Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:33:29 +0100 Subject: [PATCH 1198/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/timing.md | 5 +++++ pkgs/timing/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/timing.md diff --git a/.github/ISSUE_TEMPLATE/timing.md b/.github/ISSUE_TEMPLATE/timing.md new file mode 100644 index 000000000..38a001578 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/timing.md @@ -0,0 +1,5 @@ +--- +name: "package:timing" +about: "Create a bug or file a feature request against package:timing." +labels: "package:timing" +--- \ No newline at end of file diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 0be8e50c2..5601f8e66 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.0.2-wip description: >- A simple package for tracking the performance of synchronous and asynchronous actions. -repository: https://github.com/dart-lang/timing +repository: https://github.com/dart-lang/tools/tree/main/pkgs/timing environment: sdk: ^3.4.0 From 3b69cad818f8df9b6444fbe1b145027e8e1cc4dc Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:36:02 +0100 Subject: [PATCH 1199/1215] Moving fixes --- .github/labeler.yml | 4 ++ README.md | 1 + pkgs/timing/.github/dependabot.yml | 15 ----- pkgs/timing/.github/workflows/publish.yaml | 14 ----- .../timing/.github/workflows/test-package.yml | 56 ------------------- pkgs/timing/CHANGELOG.md | 3 +- pkgs/timing/README.md | 2 +- pkgs/timing/pubspec.yaml | 2 +- 8 files changed, 9 insertions(+), 88 deletions(-) delete mode 100644 pkgs/timing/.github/dependabot.yml delete mode 100644 pkgs/timing/.github/workflows/publish.yaml delete mode 100644 pkgs/timing/.github/workflows/test-package.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..35bba8f7a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -108,6 +108,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/sse/**' +'package:timing': + - changed-files: + - any-glob-to-any-file: 'pkgs/timing/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/README.md b/README.md index 79d1dde21..013ac0929 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ don't naturally belong to other topic monorepos (like | [source_maps](pkgs/source_maps/) | A library to programmatically manipulate source map files. | [![package issues](https://img.shields.io/badge/package:source_maps-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_maps) | [![pub package](https://img.shields.io/pub/v/source_maps.svg)](https://pub.dev/packages/source_maps) | | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | +| [timing](pkgs/timing/) | A simple package for tracking the performance of synchronous and asynchronous actions. | [![package issues](https://img.shields.io/badge/package:timing-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Atiming) | [![pub package](https://img.shields.io/pub/v/timing.svg)](https://pub.dev/packages/timing) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/timing/.github/dependabot.yml b/pkgs/timing/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/timing/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/timing/.github/workflows/publish.yaml b/pkgs/timing/.github/workflows/publish.yaml deleted file mode 100644 index fcb7ccb89..000000000 --- a/pkgs/timing/.github/workflows/publish.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+*' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main diff --git a/pkgs/timing/.github/workflows/test-package.yml b/pkgs/timing/.github/workflows/test-package.yml deleted file mode 100644 index 416123a22..000000000 --- a/pkgs/timing/.github/workflows/test-package.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Dart CI - -on: - # Run on PRs and pushes to the default branch. - push: - branches: [ master ] - pull_request: - branches: [ master ] - schedule: - - cron: "0 0 * * 0" - -env: - PUB_ENVIRONMENT: bot.github - -jobs: - # Check code formatting and static analysis on a single OS (linux) - # against Dart dev. - analyze: - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - sdk: [3.4, dev] - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 - with: - sdk: ${{ matrix.sdk }} - - id: install - run: dart pub get - - run: dart format --output=none --set-exit-if-changed . - if: always() && steps.install.outcome == 'success' - - run: dart analyze --fatal-infos - if: always() && steps.install.outcome == 'success' - - # Run tests on a matrix consisting of two dimensions: - # 1. OS: ubuntu-latest, (macos-latest, windows-latest) - # 2. release channel: dev, 2.2.0 - test: - needs: analyze - runs-on: ${{ matrix.os }} - strategy: - fail-fast: false - matrix: - # Add macos-latest and/or windows-latest if relevant for this package. - os: [ubuntu-latest] - sdk: [3.4, dev] - steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 - - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 - with: - sdk: ${{ matrix.sdk }} - - id: install - run: dart pub get - - run: dart test --platform vm - if: always() && steps.install.outcome == 'success' diff --git a/pkgs/timing/CHANGELOG.md b/pkgs/timing/CHANGELOG.md index f173a3faa..8cdb8eadc 100644 --- a/pkgs/timing/CHANGELOG.md +++ b/pkgs/timing/CHANGELOG.md @@ -1,6 +1,7 @@ -## 1.0.2-wip +## 1.0.2 - Require Dart `3.4`. +- Move to `dart-lang/tools` monorepo. ## 1.0.1 diff --git a/pkgs/timing/README.md b/pkgs/timing/README.md index ad7481abc..9dab7cc51 100644 --- a/pkgs/timing/README.md +++ b/pkgs/timing/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/timing/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/timing/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/timing.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/timing.yaml) [![pub package](https://img.shields.io/pub/v/timing.svg)](https://pub.dev/packages/timing) [![package publisher](https://img.shields.io/pub/publisher/timing.svg)](https://pub.dev/packages/timing/publisher) diff --git a/pkgs/timing/pubspec.yaml b/pkgs/timing/pubspec.yaml index 5601f8e66..891a8af3d 100644 --- a/pkgs/timing/pubspec.yaml +++ b/pkgs/timing/pubspec.yaml @@ -1,5 +1,5 @@ name: timing -version: 1.0.2-wip +version: 1.0.2 description: >- A simple package for tracking the performance of synchronous and asynchronous actions. From c9dedca2ca42cd623438ceabf46fe8a6b65dd213 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:36:51 +0100 Subject: [PATCH 1200/1215] Add ci --- .github/workflows/timing.yaml | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 .github/workflows/timing.yaml diff --git a/.github/workflows/timing.yaml b/.github/workflows/timing.yaml new file mode 100644 index 000000000..df77b137e --- /dev/null +++ b/.github/workflows/timing.yaml @@ -0,0 +1,67 @@ +name: package:timing + +on: + # Run on PRs and pushes to the default branch. + push: + branches: [ main ] + paths: + - '.github/workflows/timing.yaml' + - 'pkgs/timing/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/timing.yaml' + - 'pkgs/timing/**' + schedule: + - cron: "0 0 * * 0" + +env: + PUB_ENVIRONMENT: bot.github + + +defaults: + run: + working-directory: pkgs/timing/ + +jobs: + # Check code formatting and static analysis on a single OS (linux) + # against Dart dev. + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sdk: [3.4, dev] + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 + with: + sdk: ${{ matrix.sdk }} + - id: install + run: dart pub get + - run: dart format --output=none --set-exit-if-changed . + if: always() && steps.install.outcome == 'success' + - run: dart analyze --fatal-infos + if: always() && steps.install.outcome == 'success' + + # Run tests on a matrix consisting of two dimensions: + # 1. OS: ubuntu-latest, (macos-latest, windows-latest) + # 2. release channel: dev, 2.2.0 + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + # Add macos-latest and/or windows-latest if relevant for this package. + os: [ubuntu-latest] + sdk: [3.4, dev] + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 + - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 + with: + sdk: ${{ matrix.sdk }} + - id: install + run: dart pub get + - run: dart test --platform vm + if: always() && steps.install.outcome == 'success' From 1d67e12aaab1e3a5ce4e1185577e2f32994e0cc0 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:39:04 +0100 Subject: [PATCH 1201/1215] Add issue template and other fixes --- .../ISSUE_TEMPLATE/test_reflective_loader.md | 5 +++ pkgs/test_reflective_loader/CONTRIBUTING.md | 33 ------------------- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 34 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/test_reflective_loader.md delete mode 100644 pkgs/test_reflective_loader/CONTRIBUTING.md diff --git a/.github/ISSUE_TEMPLATE/test_reflective_loader.md b/.github/ISSUE_TEMPLATE/test_reflective_loader.md new file mode 100644 index 000000000..bde03feb7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/test_reflective_loader.md @@ -0,0 +1,5 @@ +--- +name: "package:test_reflective_loader" +about: "Create a bug or file a feature request against package:test_reflective_loader." +labels: "package:test_reflective_loader" +--- \ No newline at end of file diff --git a/pkgs/test_reflective_loader/CONTRIBUTING.md b/pkgs/test_reflective_loader/CONTRIBUTING.md deleted file mode 100644 index 6f5e0ea67..000000000 --- a/pkgs/test_reflective_loader/CONTRIBUTING.md +++ /dev/null @@ -1,33 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at -the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. - -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. - -### File headers -All files in the project must start with the following header. - - // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file - // 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. - -### The small print -Contributions made by corporations are covered by a different agreement than the -one above, the -[Software Grant and Corporate Contributor License Agreement](https://developers.google.com/open-source/cla/corporate). diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index c30323c7c..dfb3cd06d 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,7 +1,7 @@ name: test_reflective_loader version: 0.2.3-wip description: Support for discovering tests and test suites using reflection. -repository: https://github.com/dart-lang/test_reflective_loader +repository: https://github.com/dart-lang/tools/tree/main/pkgs/test_reflective_loader environment: sdk: ^3.1.0 From 59d823edad641ec8dcde9e2f15c36826af0d9ccf Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:42:35 +0100 Subject: [PATCH 1202/1215] Moving fixes --- .github/labeler.yml | 4 ++++ .../workflows/test_reflective_loader.yaml | 22 ++++++++++++++----- README.md | 1 + .../.github/dependabot.yml | 15 ------------- pkgs/test_reflective_loader/CHANGELOG.md | 3 ++- pkgs/test_reflective_loader/README.md | 5 +++-- pkgs/test_reflective_loader/pubspec.yaml | 2 +- 7 files changed, 27 insertions(+), 25 deletions(-) rename pkgs/test_reflective_loader/.github/workflows/build.yaml => .github/workflows/test_reflective_loader.yaml (57%) delete mode 100644 pkgs/test_reflective_loader/.github/dependabot.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..16a5ce833 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -108,6 +108,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/sse/**' +'package:test_reflective_loader': + - changed-files: + - any-glob-to-any-file: 'pkgs/test_reflective_loader/**' + 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' diff --git a/pkgs/test_reflective_loader/.github/workflows/build.yaml b/.github/workflows/test_reflective_loader.yaml similarity index 57% rename from pkgs/test_reflective_loader/.github/workflows/build.yaml rename to .github/workflows/test_reflective_loader.yaml index 2c15d9546..975c97049 100644 --- a/pkgs/test_reflective_loader/.github/workflows/build.yaml +++ b/.github/workflows/test_reflective_loader.yaml @@ -1,17 +1,27 @@ -name: Dart +name: package:test_reflective_loader on: - pull_request: + # Run on PRs and pushes to the default branch. push: - branches: - - master + branches: [ main ] + paths: + - '.github/workflows/test_reflective_loader.yaml' + - 'pkgs/test_reflective_loader/**' + pull_request: + branches: [ main ] + paths: + - '.github/workflows/test_reflective_loader.yaml' + - 'pkgs/test_reflective_loader/**' schedule: - # “At 00:00 (UTC) on Sunday.” - - cron: '0 0 * * 0' + - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github +defaults: + run: + working-directory: pkgs/test_reflective_loader/ + jobs: build: runs-on: ubuntu-latest diff --git a/README.md b/README.md index 79d1dde21..74be5a926 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ don't naturally belong to other topic monorepos (like | [source_maps](pkgs/source_maps/) | A library to programmatically manipulate source map files. | [![package issues](https://img.shields.io/badge/package:source_maps-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_maps) | [![pub package](https://img.shields.io/pub/v/source_maps.svg)](https://pub.dev/packages/source_maps) | | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | +| [test_reflective_loader](pkgs/test_reflective_loader/) | Support for discovering tests and test suites using reflection. | [![package issues](https://img.shields.io/badge/package:test_reflective_loader-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Atest_reflective_loader) | [![pub package](https://img.shields.io/pub/v/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | ## Publishing automation diff --git a/pkgs/test_reflective_loader/.github/dependabot.yml b/pkgs/test_reflective_loader/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/test_reflective_loader/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/test_reflective_loader/CHANGELOG.md b/pkgs/test_reflective_loader/CHANGELOG.md index 5fd4c553e..803eb0e0c 100644 --- a/pkgs/test_reflective_loader/CHANGELOG.md +++ b/pkgs/test_reflective_loader/CHANGELOG.md @@ -1,6 +1,7 @@ -## 0.2.3-wip +## 0.2.3 - Require Dart `^3.1.0`. +- Move to `dart-lang/tools` monorepo. ## 0.2.2 diff --git a/pkgs/test_reflective_loader/README.md b/pkgs/test_reflective_loader/README.md index f7d07dbe3..9b5a83d4e 100644 --- a/pkgs/test_reflective_loader/README.md +++ b/pkgs/test_reflective_loader/README.md @@ -1,5 +1,6 @@ -[![Build Status](https://github.com/dart-lang/test_reflective_loader/workflows/Dart/badge.svg)](https://github.com/dart-lang/test_reflective_loader/actions) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/test_reflective_loader.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/test_reflective_loader.yaml) [![pub package](https://img.shields.io/pub/v/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader) +[![package publisher](https://img.shields.io/pub/publisher/test_reflective_loader.svg)](https://pub.dev/packages/test_reflective_loader/publisher) Support for discovering tests and test suites using reflection. @@ -24,4 +25,4 @@ executed after the returned `Future` completes. Please file feature requests and bugs at the [issue tracker][tracker]. -[tracker]: https://github.com/dart-lang/test_reflective_loader/issues +[tracker]: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Atest_reflective_loader diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index dfb3cd06d..953ece944 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -1,5 +1,5 @@ name: test_reflective_loader -version: 0.2.3-wip +version: 0.2.3 description: Support for discovering tests and test suites using reflection. repository: https://github.com/dart-lang/tools/tree/main/pkgs/test_reflective_loader From 8a6a8185dcc9b4c01030d6189f8eab977f4af274 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:45:37 +0100 Subject: [PATCH 1203/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/watcher.md | 5 +++++ pkgs/watcher/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/watcher.md diff --git a/.github/ISSUE_TEMPLATE/watcher.md b/.github/ISSUE_TEMPLATE/watcher.md new file mode 100644 index 000000000..2578819b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/watcher.md @@ -0,0 +1,5 @@ +--- +name: "package:watcher" +about: "Create a bug or file a feature request against package:watcher." +labels: "package:watcher" +--- \ No newline at end of file diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index 108be66df..f96a74a2c 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.1.1-wip description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. -repository: https://github.com/dart-lang/watcher +repository: https://github.com/dart-lang/tools/tree/main/pkgs/watcher environment: sdk: ^3.1.0 From 40494e78dd4322b23a89b9a7a25d5a9b9f7347b3 Mon Sep 17 00:00:00 2001 From: Moritz Date: Wed, 11 Dec 2024 14:50:07 +0100 Subject: [PATCH 1204/1215] Moving fixes --- .github/labeler.yml | 4 ++ .../workflows/watcher.yaml | 17 +++++++-- README.md | 1 + pkgs/watcher/.github/dependabot.yaml | 14 ------- .../watcher/.github/workflows/no-response.yml | 37 ------------------- pkgs/watcher/.github/workflows/publish.yaml | 14 ------- pkgs/watcher/CHANGELOG.md | 3 +- pkgs/watcher/README.md | 2 +- pkgs/watcher/pubspec.yaml | 2 +- 9 files changed, 23 insertions(+), 71 deletions(-) rename pkgs/watcher/.github/workflows/test-package.yml => .github/workflows/watcher.yaml (85%) delete mode 100644 pkgs/watcher/.github/dependabot.yaml delete mode 100644 pkgs/watcher/.github/workflows/no-response.yml delete mode 100644 pkgs/watcher/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index 1cc4b2058..f69c1bc27 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -111,3 +111,7 @@ 'package:unified_analytics': - changed-files: - any-glob-to-any-file: 'pkgs/unified_analytics/**' + +'package:watcher': + - changed-files: + - any-glob-to-any-file: 'pkgs/watcher/**' diff --git a/pkgs/watcher/.github/workflows/test-package.yml b/.github/workflows/watcher.yaml similarity index 85% rename from pkgs/watcher/.github/workflows/test-package.yml rename to .github/workflows/watcher.yaml index b501c983a..a04483c4d 100644 --- a/pkgs/watcher/.github/workflows/test-package.yml +++ b/.github/workflows/watcher.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:watcher on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/watcher.yaml' + - 'pkgs/watcher/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/watcher.yaml' + - 'pkgs/watcher/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/watcher/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index 79d1dde21..11ff12977 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ don't naturally belong to other topic monorepos (like | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | | [sse](pkgs/sse/) | Provides client and server functionality for setting up bi-directional communication through Server Sent Events (SSE) and corresponding POST requests. | [![package issues](https://img.shields.io/badge/package:sse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asse) | [![pub package](https://img.shields.io/pub/v/sse.svg)](https://pub.dev/packages/sse) | | [unified_analytics](pkgs/unified_analytics/) | A package for logging analytics for all Dart and Flutter related tooling to Google Analytics. | [![package issues](https://img.shields.io/badge/package:unified_analytics-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Aunified_analytics) | [![pub package](https://img.shields.io/pub/v/unified_analytics.svg)](https://pub.dev/packages/unified_analytics) | +| [watcher](pkgs/watcher/) | Monitor directories and send notifications when the contents change. | [![package issues](https://img.shields.io/badge/package:watcher-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Awatcher) | [![pub package](https://img.shields.io/pub/v/watcher.svg)](https://pub.dev/packages/watcher) | ## Publishing automation diff --git a/pkgs/watcher/.github/dependabot.yaml b/pkgs/watcher/.github/dependabot.yaml deleted file mode 100644 index bf6b38a4d..000000000 --- a/pkgs/watcher/.github/dependabot.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# Dependabot configuration file. -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/watcher/.github/workflows/no-response.yml b/pkgs/watcher/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/watcher/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/watcher/.github/workflows/publish.yaml b/pkgs/watcher/.github/workflows/publish.yaml deleted file mode 100644 index 2239b63d3..000000000 --- a/pkgs/watcher/.github/workflows/publish.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main diff --git a/pkgs/watcher/CHANGELOG.md b/pkgs/watcher/CHANGELOG.md index 8f4d289d3..ef3a7e2d3 100644 --- a/pkgs/watcher/CHANGELOG.md +++ b/pkgs/watcher/CHANGELOG.md @@ -1,7 +1,8 @@ -## 1.1.1-wip +## 1.1.1 - Ensure `PollingFileWatcher.ready` completes for files that do not exist. - Require Dart SDK `^3.1.0` +- Move to `dart-lang/tools` monorepo. ## 1.1.0 diff --git a/pkgs/watcher/README.md b/pkgs/watcher/README.md index 677ca35b2..83a0324b4 100644 --- a/pkgs/watcher/README.md +++ b/pkgs/watcher/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/watcher/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/watcher/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/watcher.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/watcher.yaml) [![pub package](https://img.shields.io/pub/v/watcher.svg)](https://pub.dev/packages/watcher) [![package publisher](https://img.shields.io/pub/publisher/watcher.svg)](https://pub.dev/packages/watcher/publisher) diff --git a/pkgs/watcher/pubspec.yaml b/pkgs/watcher/pubspec.yaml index f96a74a2c..7781bd445 100644 --- a/pkgs/watcher/pubspec.yaml +++ b/pkgs/watcher/pubspec.yaml @@ -1,5 +1,5 @@ name: watcher -version: 1.1.1-wip +version: 1.1.1 description: >- A file system watcher. It monitors changes to contents of directories and sends notifications when files have been added, removed, or modified. From a0c9f10e0b767de9eea199c4aa1b0f02da58a6c4 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Wed, 11 Dec 2024 16:33:23 +0100 Subject: [PATCH 1205/1215] refactor!: Seal the Dependency class (dart-lang/pubspec_parse#140) * fix: Don't use runtimeType for toString --- pkgs/pubspec_parse/CHANGELOG.md | 3 +- pkgs/pubspec_parse/lib/src/dependency.dart | 43 +++++++++------------- pkgs/pubspec_parse/pubspec.yaml | 2 +- 3 files changed, 20 insertions(+), 28 deletions(-) diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 2768cdebd..251d4cc47 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,6 +1,7 @@ -## 1.3.1-wip +## 1.4.0-wip - Require Dart 3.2 +- Seal the `Dependency` class. - Set `Pubspec.environment` to non-nullable. - Remove deprecated package_api_docs rule diff --git a/pkgs/pubspec_parse/lib/src/dependency.dart b/pkgs/pubspec_parse/lib/src/dependency.dart index acce59843..24c65eac1 100644 --- a/pkgs/pubspec_parse/lib/src/dependency.dart +++ b/pkgs/pubspec_parse/lib/src/dependency.dart @@ -90,14 +90,7 @@ Dependency? _fromJson(Object? data, String name) { return null; } -abstract class Dependency { - Dependency._(); - - String get _info; - - @override - String toString() => '$runtimeType: $_info'; -} +sealed class Dependency {} @JsonSerializable() class SdkDependency extends Dependency { @@ -106,11 +99,7 @@ class SdkDependency extends Dependency { final VersionConstraint version; SdkDependency(this.sdk, {VersionConstraint? version}) - : version = version ?? VersionConstraint.any, - super._(); - - @override - String get _info => sdk; + : version = version ?? VersionConstraint.any; @override bool operator ==(Object other) => @@ -118,6 +107,9 @@ class SdkDependency extends Dependency { @override int get hashCode => Object.hash(sdk, version); + + @override + String toString() => 'SdkDependency: $sdk'; } @JsonSerializable() @@ -127,7 +119,7 @@ class GitDependency extends Dependency { final String? ref; final String? path; - GitDependency(this.url, {this.ref, this.path}) : super._(); + GitDependency(this.url, {this.ref, this.path}); factory GitDependency.fromData(Object? data) { if (data is String) { @@ -141,9 +133,6 @@ class GitDependency extends Dependency { throw ArgumentError.value(data, 'git', 'Must be a String or a Map.'); } - @override - String get _info => 'url@$url'; - @override bool operator ==(Object other) => other is GitDependency && @@ -153,6 +142,9 @@ class GitDependency extends Dependency { @override int get hashCode => Object.hash(url, ref, path); + + @override + String toString() => 'GitDependency: url@$url'; } Uri? parseGitUriOrNull(String? value) => @@ -194,7 +186,7 @@ Uri? _tryParseScpUri(String value) { class PathDependency extends Dependency { final String path; - PathDependency(this.path) : super._(); + PathDependency(this.path); factory PathDependency.fromData(Object? data) { if (data is String) { @@ -203,15 +195,15 @@ class PathDependency extends Dependency { throw ArgumentError.value(data, 'path', 'Must be a String.'); } - @override - String get _info => 'path@$path'; - @override bool operator ==(Object other) => other is PathDependency && other.path == path; @override int get hashCode => path.hashCode; + + @override + String toString() => 'PathDependency: path@$path'; } @JsonSerializable(disallowUnrecognizedKeys: true) @@ -223,11 +215,7 @@ class HostedDependency extends Dependency { final HostedDetails? hosted; HostedDependency({VersionConstraint? version, this.hosted}) - : version = version ?? VersionConstraint.any, - super._(); - - @override - String get _info => version.toString(); + : version = version ?? VersionConstraint.any; @override bool operator ==(Object other) => @@ -237,6 +225,9 @@ class HostedDependency extends Dependency { @override int get hashCode => Object.hash(version, hosted); + + @override + String toString() => 'HostedDependency: $version'; } @JsonSerializable(disallowUnrecognizedKeys: true) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 00cf12ce6..bcdaa31ff 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.3.1-wip +version: 1.4.0-wip description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. From ea2419fdc3610cbc90a9525c5208fd5f100de3e3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 11 Dec 2024 14:23:51 -0600 Subject: [PATCH 1206/1215] Move to latest dart_flutter_team_lints (#1667) --- pkgs/source_maps/CHANGELOG.md | 2 ++ pkgs/source_maps/lib/builder.dart | 2 +- pkgs/source_maps/lib/parser.dart | 2 +- pkgs/source_maps/lib/printer.dart | 2 +- pkgs/source_maps/lib/refactor.dart | 2 +- pkgs/source_maps/lib/source_maps.dart | 2 +- pkgs/source_maps/lib/src/utils.dart | 2 +- pkgs/source_maps/lib/src/vlq.dart | 2 +- pkgs/source_maps/pubspec.yaml | 4 ++-- pkgs/source_maps/test/common.dart | 2 +- pkgs/source_maps/test/utils_test.dart | 2 +- 11 files changed, 13 insertions(+), 11 deletions(-) diff --git a/pkgs/source_maps/CHANGELOG.md b/pkgs/source_maps/CHANGELOG.md index ae7711e57..b06ac72ea 100644 --- a/pkgs/source_maps/CHANGELOG.md +++ b/pkgs/source_maps/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.10.14-wip + ## 0.10.13 * Require Dart 3.3 diff --git a/pkgs/source_maps/lib/builder.dart b/pkgs/source_maps/lib/builder.dart index 54ba7433f..9043c6326 100644 --- a/pkgs/source_maps/lib/builder.dart +++ b/pkgs/source_maps/lib/builder.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Contains a builder object useful for creating source maps programatically. -library source_maps.builder; +library; // TODO(sigmund): add a builder for multi-section mappings. diff --git a/pkgs/source_maps/lib/parser.dart b/pkgs/source_maps/lib/parser.dart index b699ac728..590dfc682 100644 --- a/pkgs/source_maps/lib/parser.dart +++ b/pkgs/source_maps/lib/parser.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Contains the top-level function to parse source maps version 3. -library source_maps.parser; +library; import 'dart:convert'; diff --git a/pkgs/source_maps/lib/printer.dart b/pkgs/source_maps/lib/printer.dart index 17733cdd3..32523d62f 100644 --- a/pkgs/source_maps/lib/printer.dart +++ b/pkgs/source_maps/lib/printer.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Contains a code printer that generates code by recording the source maps. -library source_maps.printer; +library; import 'package:source_span/source_span.dart'; diff --git a/pkgs/source_maps/lib/refactor.dart b/pkgs/source_maps/lib/refactor.dart index 98e0c9345..a518a0ce4 100644 --- a/pkgs/source_maps/lib/refactor.dart +++ b/pkgs/source_maps/lib/refactor.dart @@ -6,7 +6,7 @@ /// /// [TextEditTransaction] supports making a series of changes to a text buffer. /// [guessIndent] helps to guess the appropriate indentiation for the new code. -library source_maps.refactor; +library; import 'package:source_span/source_span.dart'; diff --git a/pkgs/source_maps/lib/source_maps.dart b/pkgs/source_maps/lib/source_maps.dart index 58f805a3a..244dee7a9 100644 --- a/pkgs/source_maps/lib/source_maps.dart +++ b/pkgs/source_maps/lib/source_maps.dart @@ -24,7 +24,7 @@ /// var mapping = parse(json); /// mapping.spanFor(outputSpan1.line, outputSpan1.column) /// ``` -library source_maps; +library; import 'package:source_span/source_span.dart'; diff --git a/pkgs/source_maps/lib/src/utils.dart b/pkgs/source_maps/lib/src/utils.dart index f70531e95..ba04fbb0f 100644 --- a/pkgs/source_maps/lib/src/utils.dart +++ b/pkgs/source_maps/lib/src/utils.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Utilities that shouldn't be in this package. -library source_maps.utils; +library; /// Find the first entry in a sorted [list] that matches a monotonic predicate. /// Given a result `n`, that all items before `n` will not match, `n` matches, diff --git a/pkgs/source_maps/lib/src/vlq.dart b/pkgs/source_maps/lib/src/vlq.dart index 61b476839..3b0562d82 100644 --- a/pkgs/source_maps/lib/src/vlq.dart +++ b/pkgs/source_maps/lib/src/vlq.dart @@ -10,7 +10,7 @@ /// represented by using the least significant bit of the value as the sign bit. /// /// For more details see the source map [version 3 documentation](https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?usp=sharing). -library source_maps.src.vlq; +library; import 'dart:math'; diff --git a/pkgs/source_maps/pubspec.yaml b/pkgs/source_maps/pubspec.yaml index 8518fa756..32cbf4fb7 100644 --- a/pkgs/source_maps/pubspec.yaml +++ b/pkgs/source_maps/pubspec.yaml @@ -1,5 +1,5 @@ name: source_maps -version: 0.10.13 +version: 0.10.14-wip description: A library to programmatically manipulate source map files. repository: https://github.com/dart-lang/tools/tree/main/pkgs/source_maps @@ -10,6 +10,6 @@ dependencies: source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 term_glyph: ^1.2.0 test: ^1.16.0 diff --git a/pkgs/source_maps/test/common.dart b/pkgs/source_maps/test/common.dart index f6139de47..e225ff5a4 100644 --- a/pkgs/source_maps/test/common.dart +++ b/pkgs/source_maps/test/common.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Common input/output used by builder, parser and end2end tests -library test.common; +library; import 'package:source_maps/source_maps.dart'; import 'package:source_span/source_span.dart'; diff --git a/pkgs/source_maps/test/utils_test.dart b/pkgs/source_maps/test/utils_test.dart index 4abdce298..2516d1e47 100644 --- a/pkgs/source_maps/test/utils_test.dart +++ b/pkgs/source_maps/test/utils_test.dart @@ -3,7 +3,7 @@ // BSD-style license that can be found in the LICENSE file. /// Tests for the binary search utility algorithm. -library test.utils_test; +library; import 'package:source_maps/src/utils.dart'; import 'package:test/test.dart'; From 42effa673a1dd3b66454fdbb6919993a4f556a7c Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 11 Dec 2024 19:54:26 -0600 Subject: [PATCH 1207/1215] Migrate many custom matchers to TypeMatcher (#1668) --- pkgs/file/pubspec.yaml | 4 + pkgs/file_testing/CHANGELOG.md | 5 + pkgs/file_testing/analysis_options.yaml | 7 +- .../lib/src/testing/core_matchers.dart | 109 +++--------------- pkgs/file_testing/pubspec.yaml | 6 +- 5 files changed, 30 insertions(+), 101 deletions(-) diff --git a/pkgs/file/pubspec.yaml b/pkgs/file/pubspec.yaml index 5de5d37c1..0dc81cd22 100644 --- a/pkgs/file/pubspec.yaml +++ b/pkgs/file/pubspec.yaml @@ -15,3 +15,7 @@ dev_dependencies: file_testing: ^3.0.0 lints: ^2.0.1 test: ^1.23.1 + +dependency_overrides: + file_testing: + path: ../file_testing diff --git a/pkgs/file_testing/CHANGELOG.md b/pkgs/file_testing/CHANGELOG.md index 0af779d87..17039ee16 100644 --- a/pkgs/file_testing/CHANGELOG.md +++ b/pkgs/file_testing/CHANGELOG.md @@ -1,3 +1,8 @@ +## 3.1.0-wip + +* Changed the type of several matchers to `TypeMatcher` which allows cascading + their usage with `.having` and similar. + ## 3.0.2 * Require Dart 3.1. diff --git a/pkgs/file_testing/analysis_options.yaml b/pkgs/file_testing/analysis_options.yaml index 8fbd2e443..d978f811c 100644 --- a/pkgs/file_testing/analysis_options.yaml +++ b/pkgs/file_testing/analysis_options.yaml @@ -1,6 +1 @@ -include: package:lints/recommended.yaml - -analyzer: - errors: - # Allow having TODOs in the code - todo: ignore +include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/pkgs/file_testing/lib/src/testing/core_matchers.dart b/pkgs/file_testing/lib/src/testing/core_matchers.dart index f58539f19..801209e89 100644 --- a/pkgs/file_testing/lib/src/testing/core_matchers.dart +++ b/pkgs/file_testing/lib/src/testing/core_matchers.dart @@ -2,6 +2,8 @@ // 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. +// ignore_for_file: comment_references + import 'dart:io'; import 'package:test/test.dart'; @@ -9,26 +11,27 @@ import 'package:test/test.dart'; import 'internal.dart'; /// Matcher that successfully matches against any instance of [Directory]. -const Matcher isDirectory = TypeMatcher(); +const isDirectory = TypeMatcher(); /// Matcher that successfully matches against any instance of [File]. -const Matcher isFile = TypeMatcher(); +const isFile = TypeMatcher(); /// Matcher that successfully matches against any instance of [Link]. -const Matcher isLink = TypeMatcher(); +const isLink = TypeMatcher(); /// Matcher that successfully matches against any instance of /// [FileSystemEntity]. -const Matcher isFileSystemEntity = TypeMatcher(); +const isFileSystemEntity = TypeMatcher(); /// Matcher that successfully matches against any instance of [FileStat]. -const Matcher isFileStat = TypeMatcher(); +const isFileStat = TypeMatcher(); /// Returns a [Matcher] that matches [path] against an entity's path. /// /// [path] may be a String, a predicate function, or a [Matcher]. If it is /// a String, it will be wrapped in an equality matcher. -Matcher hasPath(dynamic path) => _HasPath(path); +TypeMatcher hasPath(dynamic path) => + isFileSystemEntity.having((e) => e.path, 'path', path); /// Returns a [Matcher] that successfully matches against an instance of /// [FileSystemException]. @@ -39,7 +42,8 @@ Matcher hasPath(dynamic path) => _HasPath(path); /// [osErrorCode] may be an `int`, a predicate function, or a [Matcher]. If it /// is an `int`, it will be wrapped in an equality matcher. Matcher isFileSystemException([dynamic osErrorCode]) => - _FileSystemException(osErrorCode); + const TypeMatcher().having((e) => e.osError?.errorCode, + 'osError.errorCode', _fileExceptionWrapMatcher(osErrorCode)); /// Returns a matcher that successfully matches against a future or function /// that throws a [FileSystemException]. @@ -67,89 +71,10 @@ void expectFileSystemException(dynamic osErrorCode, void Function() callback) { /// Matcher that successfully matches against a [FileSystemEntity] that /// exists ([FileSystemEntity.existsSync] returns true). -const Matcher exists = _Exists(); - -class _FileSystemException extends Matcher { - _FileSystemException(dynamic osErrorCode) - : _matcher = _wrapMatcher(osErrorCode); - - final Matcher? _matcher; - - static Matcher? _wrapMatcher(dynamic osErrorCode) { - if (osErrorCode == null) { - return null; - } - return ignoreOsErrorCodes ? anything : wrapMatcher(osErrorCode); - } - - @override - bool matches(dynamic item, Map matchState) { - if (item is FileSystemException) { - return _matcher == null || - _matcher!.matches(item.osError?.errorCode, matchState); - } - return false; - } - - @override - Description describe(Description desc) { - if (_matcher == null) { - return desc.add('FileSystemException'); - } else { - desc.add('FileSystemException with osError.errorCode: '); - return _matcher!.describe(desc); - } - } -} - -class _HasPath extends Matcher { - _HasPath(dynamic path) : _matcher = wrapMatcher(path); - - final Matcher _matcher; +final TypeMatcher exists = + isFileSystemEntity.having((e) => e.existsSync(), 'existsSync', true); - @override - bool matches(dynamic item, Map matchState) => - _matcher.matches(item.path, matchState); - - @override - Description describe(Description desc) { - desc.add('has path: '); - return _matcher.describe(desc); - } - - @override - Description describeMismatch( - dynamic item, - Description desc, - Map matchState, - bool verbose, - ) { - desc.add('has path: \'${item.path}\'').add('\n Which: '); - final Description pathDesc = StringDescription(); - _matcher.describeMismatch(item.path, pathDesc, matchState, verbose); - desc.add(pathDesc.toString()); - return desc; - } -} - -class _Exists extends Matcher { - const _Exists(); - - @override - bool matches(dynamic item, Map matchState) => - item is FileSystemEntity && item.existsSync(); - - @override - Description describe(Description description) => - description.add('a file system entity that exists'); - - @override - Description describeMismatch( - dynamic item, - Description description, - Map matchState, - bool verbose, - ) { - return description.add('does not exist'); - } -} +Matcher? _fileExceptionWrapMatcher(dynamic osErrorCode) => + (osErrorCode == null || ignoreOsErrorCodes) + ? anything + : wrapMatcher(osErrorCode); diff --git a/pkgs/file_testing/pubspec.yaml b/pkgs/file_testing/pubspec.yaml index 691efa0e6..895826a39 100644 --- a/pkgs/file_testing/pubspec.yaml +++ b/pkgs/file_testing/pubspec.yaml @@ -1,5 +1,5 @@ name: file_testing -version: 3.0.2 +version: 3.1.0-wip description: Testing utilities for package:file. repository: https://github.com/dart-lang/tools/tree/main/pkgs/file_testing issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Afile_testing @@ -10,5 +10,5 @@ environment: dependencies: test: ^1.23.1 -dev_dependencies: - lints: ^5.0.0 +dev_dependencies: + dart_flutter_team_lints: ^3.0.0 From 9ab106daaf3821164c7bf01424ac302e3fef29a3 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Wed, 11 Dec 2024 21:27:35 -0600 Subject: [PATCH 1208/1215] file: enable and fix latest team lints (#1669) --- pkgs/file/CHANGELOG.md | 2 + pkgs/file/analysis_options.yaml | 7 +- pkgs/file/example/main.dart | 4 +- pkgs/file/lib/chroot.dart | 2 + pkgs/file/lib/file.dart | 2 + pkgs/file/lib/local.dart | 2 + pkgs/file/lib/memory.dart | 2 + pkgs/file/lib/src/backends/chroot.dart | 10 +- .../src/backends/chroot/chroot_directory.dart | 46 +- .../lib/src/backends/chroot/chroot_file.dart | 10 +- .../backends/chroot/chroot_file_system.dart | 22 +- .../chroot/chroot_file_system_entity.dart | 10 +- .../lib/src/backends/chroot/chroot_link.dart | 6 +- .../chroot/chroot_random_access_file.dart | 2 +- .../src/backends/local/local_directory.dart | 10 +- .../lib/src/backends/local/local_file.dart | 8 +- .../src/backends/local/local_file_system.dart | 4 +- .../local/local_file_system_entity.dart | 6 +- .../lib/src/backends/local/local_link.dart | 8 +- pkgs/file/lib/src/backends/memory/clock.dart | 2 + pkgs/file/lib/src/backends/memory/common.dart | 2 +- .../src/backends/memory/memory_directory.dart | 37 +- .../lib/src/backends/memory/memory_file.dart | 46 +- .../src/backends/memory/memory_file_stat.dart | 8 +- .../backends/memory/memory_file_system.dart | 25 +- .../memory/memory_file_system_entity.dart | 24 +- .../lib/src/backends/memory/memory_link.dart | 15 +- .../memory/memory_random_access_file.dart | 23 +- pkgs/file/lib/src/backends/memory/node.dart | 27 +- .../lib/src/backends/memory/operations.dart | 30 +- pkgs/file/lib/src/backends/memory/style.dart | 3 +- pkgs/file/lib/src/backends/memory/utils.dart | 15 +- .../src/forwarding/forwarding_directory.dart | 5 +- .../lib/src/forwarding/forwarding_file.dart | 5 +- .../forwarding/forwarding_file_system.dart | 5 +- .../forwarding_file_system_entity.dart | 5 +- .../lib/src/forwarding/forwarding_link.dart | 5 +- .../forwarding_random_access_file.dart | 7 +- pkgs/file/lib/src/interface.dart | 2 - pkgs/file/lib/src/interface/error_codes.dart | 2 +- pkgs/file/lib/src/interface/file_system.dart | 20 +- pkgs/file/lib/src/io.dart | 2 + pkgs/file/pubspec.yaml | 4 +- pkgs/file/test/chroot_test.dart | 10 +- pkgs/file/test/common_tests.dart | 459 +++++++++--------- pkgs/file/test/local_test.dart | 8 +- pkgs/file/test/memory_operations_test.dart | 57 ++- pkgs/file/test/memory_test.dart | 19 +- pkgs/file/test/utils.dart | 4 +- pkgs/file/test/utils_test.dart | 26 +- 50 files changed, 534 insertions(+), 531 deletions(-) diff --git a/pkgs/file/CHANGELOG.md b/pkgs/file/CHANGELOG.md index 50c96c49d..3a3969cad 100644 --- a/pkgs/file/CHANGELOG.md +++ b/pkgs/file/CHANGELOG.md @@ -1,3 +1,5 @@ +## 7.0.2-wip + ## 7.0.1 * Update the pubspec repository field to reflect the new package repository. diff --git a/pkgs/file/analysis_options.yaml b/pkgs/file/analysis_options.yaml index 8fbd2e443..d978f811c 100644 --- a/pkgs/file/analysis_options.yaml +++ b/pkgs/file/analysis_options.yaml @@ -1,6 +1 @@ -include: package:lints/recommended.yaml - -analyzer: - errors: - # Allow having TODOs in the code - todo: ignore +include: package:dart_flutter_team_lints/analysis_options.yaml diff --git a/pkgs/file/example/main.dart b/pkgs/file/example/main.dart index 7ca0bc73f..b03b363f0 100644 --- a/pkgs/file/example/main.dart +++ b/pkgs/file/example/main.dart @@ -7,8 +7,8 @@ import 'package:file/memory.dart'; Future main() async { final FileSystem fs = MemoryFileSystem(); - final Directory tmp = await fs.systemTempDirectory.createTemp('example_'); - final File outputFile = tmp.childFile('output'); + final tmp = await fs.systemTempDirectory.createTemp('example_'); + final outputFile = tmp.childFile('output'); await outputFile.writeAsString('Hello world!'); print(outputFile.readAsStringSync()); } diff --git a/pkgs/file/lib/chroot.dart b/pkgs/file/lib/chroot.dart index 56d2bd5d7..6992ad0b4 100644 --- a/pkgs/file/lib/chroot.dart +++ b/pkgs/file/lib/chroot.dart @@ -3,4 +3,6 @@ // BSD-style license that can be found in the LICENSE file. /// A file system that provides a view into _another_ `FileSystem` via a path. +library; + export 'src/backends/chroot.dart'; diff --git a/pkgs/file/lib/file.dart b/pkgs/file/lib/file.dart index cdde9fedd..c2e97b2ee 100644 --- a/pkgs/file/lib/file.dart +++ b/pkgs/file/lib/file.dart @@ -4,5 +4,7 @@ /// Core interfaces containing the abstract `FileSystem` interface definition /// and all associated types used by `FileSystem`. +library; + export 'src/forwarding.dart'; export 'src/interface.dart'; diff --git a/pkgs/file/lib/local.dart b/pkgs/file/lib/local.dart index 74f506e36..5b1e3cd9d 100644 --- a/pkgs/file/lib/local.dart +++ b/pkgs/file/lib/local.dart @@ -4,4 +4,6 @@ /// A local file system implementation. This relies on the use of `dart:io` /// and is thus not suitable for use in the browser. +library; + export 'src/backends/local.dart'; diff --git a/pkgs/file/lib/memory.dart b/pkgs/file/lib/memory.dart index c5705eff9..690b65fa5 100644 --- a/pkgs/file/lib/memory.dart +++ b/pkgs/file/lib/memory.dart @@ -4,5 +4,7 @@ /// An implementation of `FileSystem` that exists entirely in memory with an /// internal representation loosely based on the Filesystem Hierarchy Standard. +library; + export 'src/backends/memory.dart'; export 'src/backends/memory/operations.dart'; diff --git a/pkgs/file/lib/src/backends/chroot.dart b/pkgs/file/lib/src/backends/chroot.dart index 6082e808c..402dbec5b 100644 --- a/pkgs/file/lib/src/backends/chroot.dart +++ b/pkgs/file/lib/src/backends/chroot.dart @@ -2,16 +2,16 @@ // 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. -library file.src.backends.chroot; - import 'dart:convert'; import 'dart:typed_data'; -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; import 'package:path/path.dart' as p; +import '../common.dart' as common; +import '../forwarding.dart'; +import '../interface.dart'; +import '../io.dart' as io; + part 'chroot/chroot_directory.dart'; part 'chroot/chroot_file.dart'; part 'chroot/chroot_file_system.dart'; diff --git a/pkgs/file/lib/src/backends/chroot/chroot_directory.dart b/pkgs/file/lib/src/backends/chroot/chroot_directory.dart index 8fec7b198..e09419384 100644 --- a/pkgs/file/lib/src/backends/chroot/chroot_directory.dart +++ b/pkgs/file/lib/src/backends/chroot/chroot_directory.dart @@ -2,18 +2,18 @@ // 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. -part of file.src.backends.chroot; +part of '../chroot.dart'; class _ChrootDirectory extends _ChrootFileSystemEntity with ForwardingDirectory, common.DirectoryAddOnsMixin { - _ChrootDirectory(ChrootFileSystem fs, String path) : super(fs, path); + _ChrootDirectory(super.fs, super.path); factory _ChrootDirectory.wrapped( ChrootFileSystem fs, Directory delegate, { bool relative = false, }) { - String localPath = fs._local(delegate.path, relative: relative); + var localPath = fs._local(delegate.path, relative: relative); return _ChrootDirectory(fs, localPath); } @@ -32,7 +32,7 @@ class _ChrootDirectory extends _ChrootFileSystemEntity if (await fileSystem.type(path) != expectedType) { throw common.notADirectory(path); } - FileSystemEntityType type = await fileSystem.type(newPath); + var type = await fileSystem.type(newPath); if (type != FileSystemEntityType.notFound) { if (type != expectedType) { throw common.notADirectory(newPath); @@ -44,7 +44,7 @@ class _ChrootDirectory extends _ChrootFileSystemEntity throw common.directoryNotEmpty(newPath); } } - String target = await fileSystem.link(path).target(); + var target = await fileSystem.link(path).target(); await fileSystem.link(path).delete(); await fileSystem.link(newPath).create(target); return fileSystem.directory(newPath); @@ -60,7 +60,7 @@ class _ChrootDirectory extends _ChrootFileSystemEntity if (fileSystem.typeSync(path) != expectedType) { throw common.notADirectory(path); } - FileSystemEntityType type = fileSystem.typeSync(newPath); + var type = fileSystem.typeSync(newPath); if (type != FileSystemEntityType.notFound) { if (type != expectedType) { throw common.notADirectory(newPath); @@ -72,7 +72,7 @@ class _ChrootDirectory extends _ChrootFileSystemEntity throw common.directoryNotEmpty(newPath); } } - String target = fileSystem.link(path).targetSync(); + var target = fileSystem.link(path).targetSync(); fileSystem.link(path).deleteSync(); fileSystem.link(newPath).createSync(target); return fileSystem.directory(newPath); @@ -97,17 +97,15 @@ class _ChrootDirectory extends _ChrootFileSystemEntity @override Future create({bool recursive = false}) async { if (_isLink) { - switch (await fileSystem.type(path)) { - case FileSystemEntityType.notFound: - throw common.noSuchFileOrDirectory(path); - case FileSystemEntityType.file: - throw common.fileExists(path); - case FileSystemEntityType.directory: + return switch (await fileSystem.type(path)) { + FileSystemEntityType.notFound => + throw common.noSuchFileOrDirectory(path), + FileSystemEntityType.file => throw common.fileExists(path), + FileSystemEntityType.directory => // Nothing to do. - return this; - default: - throw AssertionError(); - } + this, + _ => throw AssertionError() + }; } else { return wrap(await delegate.create(recursive: recursive)); } @@ -137,8 +135,8 @@ class _ChrootDirectory extends _ChrootFileSystemEntity bool recursive = false, bool followLinks = true, }) { - Directory delegate = this.delegate as Directory; - String dirname = delegate.path; + var delegate = this.delegate as Directory; + var dirname = delegate.path; return delegate .list(recursive: recursive, followLinks: followLinks) .map((io.FileSystemEntity entity) => _denormalize(entity, dirname)); @@ -149,8 +147,8 @@ class _ChrootDirectory extends _ChrootFileSystemEntity bool recursive = false, bool followLinks = true, }) { - Directory delegate = this.delegate as Directory; - String dirname = delegate.path; + var delegate = this.delegate as Directory; + var dirname = delegate.path; return delegate .listSync(recursive: recursive, followLinks: followLinks) .map((io.FileSystemEntity entity) => _denormalize(entity, dirname)) @@ -158,9 +156,9 @@ class _ChrootDirectory extends _ChrootFileSystemEntity } FileSystemEntity _denormalize(io.FileSystemEntity entity, String dirname) { - p.Context ctx = fileSystem.path; - String relativePart = ctx.relative(entity.path, from: dirname); - String entityPath = ctx.join(path, relativePart); + var ctx = fileSystem.path; + var relativePart = ctx.relative(entity.path, from: dirname); + var entityPath = ctx.join(path, relativePart); if (entity is io.File) { return _ChrootFile(fileSystem, entityPath); } else if (entity is io.Directory) { diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file.dart b/pkgs/file/lib/src/backends/chroot/chroot_file.dart index 4b67bc1f6..d6c29fcff 100644 --- a/pkgs/file/lib/src/backends/chroot/chroot_file.dart +++ b/pkgs/file/lib/src/backends/chroot/chroot_file.dart @@ -2,20 +2,20 @@ // 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. -part of file.src.backends.chroot; +part of '../chroot.dart'; typedef _SetupCallback = dynamic Function(); class _ChrootFile extends _ChrootFileSystemEntity with ForwardingFile { - _ChrootFile(ChrootFileSystem fs, String path) : super(fs, path); + _ChrootFile(super.fs, super.path); factory _ChrootFile.wrapped( ChrootFileSystem fs, io.File delegate, { bool relative = false, }) { - String localPath = fs._local(delegate.path, relative: relative); + var localPath = fs._local(delegate.path, relative: relative); return _ChrootFile(fs, localPath); } @@ -126,7 +126,7 @@ class _ChrootFile extends _ChrootFileSystemEntity @override Future create({bool recursive = false, bool exclusive = false}) async { - String path = fileSystem._resolve( + var path = fileSystem._resolve( this.path, followLinks: false, notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow, @@ -158,7 +158,7 @@ class _ChrootFile extends _ChrootFileSystemEntity @override void createSync({bool recursive = false, bool exclusive = false}) { - String path = fileSystem._resolve( + var path = fileSystem._resolve( this.path, followLinks: false, notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow, diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart b/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart index 6889c987b..503821fb4 100644 --- a/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart +++ b/pkgs/file/lib/src/backends/chroot/chroot_file_system.dart @@ -2,7 +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. -part of file.src.backends.chroot; +part of '../chroot.dart'; const String _thisDir = '.'; const String _parentDir = '..'; @@ -107,7 +107,7 @@ class ChrootFileSystem extends FileSystem { } value = _resolve(value, notFound: _NotFoundBehavior.throwError); - String realPath = _real(value, resolve: false); + var realPath = _real(value, resolve: false); switch (delegate.typeSync(realPath, followLinks: false)) { case FileSystemEntityType.directory: break; @@ -117,7 +117,7 @@ class ChrootFileSystem extends FileSystem { throw common.notADirectory(path as String); } assert(() { - p.Context ctx = delegate.path; + var ctx = delegate.path; return ctx.isAbsolute(value) && value == ctx.canonicalize(value); }()); _cwd = value; @@ -201,7 +201,7 @@ class ChrootFileSystem extends FileSystem { throw _ChrootJailException(); } // TODO(tvolkert): See if _context.relative() works here - String result = realPath.substring(root.length); + var result = realPath.substring(root.length); if (result.isEmpty) { result = _localRoot; } @@ -263,8 +263,8 @@ class ChrootFileSystem extends FileSystem { throw common.noSuchFileOrDirectory(path); } - p.Context ctx = this.path; - String root = _localRoot; + var ctx = this.path; + var root = _localRoot; List parts, ledger; if (ctx.isAbsolute(path)) { parts = ctx.split(path).sublist(1); @@ -277,9 +277,9 @@ class ChrootFileSystem extends FileSystem { } String getCurrentPath() => root + ctx.joinAll(ledger); - Set breadcrumbs = {}; + var breadcrumbs = {}; while (parts.isNotEmpty) { - String segment = parts.removeAt(0); + var segment = parts.removeAt(0); if (segment == _thisDir) { continue; } else if (segment == _parentDir) { @@ -290,8 +290,8 @@ class ChrootFileSystem extends FileSystem { } ledger.add(segment); - String currentPath = getCurrentPath(); - String realPath = _real(currentPath, resolve: false); + var currentPath = getCurrentPath(); + var realPath = _real(currentPath, resolve: false); switch (delegate.typeSync(realPath, followLinks: false)) { case FileSystemEntityType.directory: @@ -333,7 +333,7 @@ class ChrootFileSystem extends FileSystem { if (!breadcrumbs.add(currentPath)) { throw common.tooManyLevelsOfSymbolicLinks(path); } - String target = delegate.link(realPath).targetSync(); + var target = delegate.link(realPath).targetSync(); if (ctx.isAbsolute(target)) { ledger.clear(); parts.insertAll(0, ctx.split(target).sublist(1)); diff --git a/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart b/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart index 8e859ace8..18e37cd02 100644 --- a/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart +++ b/pkgs/file/lib/src/backends/chroot/chroot_file_system_entity.dart @@ -2,7 +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. -part of file.src.backends.chroot; +part of '../chroot.dart'; abstract class _ChrootFileSystemEntity extends ForwardingFileSystemEntity { @@ -103,7 +103,7 @@ abstract class _ChrootFileSystemEntity delete({bool recursive = false}) async { - String path = fileSystem._resolve(this.path, + var path = fileSystem._resolve(this.path, followLinks: false, notFound: _NotFoundBehavior.throwError); String real(String path) => fileSystem._real(path, resolve: false); @@ -114,7 +114,7 @@ abstract class _ChrootFileSystemEntity fileSystem._real(path, resolve: false); @@ -143,7 +143,7 @@ abstract class _ChrootFileSystemEntity with ForwardingLink { - _ChrootLink(ChrootFileSystem fs, String path) : super(fs, path); + _ChrootLink(super.fs, super.path); factory _ChrootLink.wrapped( ChrootFileSystem fs, io.Link delegate, { bool relative = false, }) { - String localPath = fs._local(delegate.path, relative: relative); + var localPath = fs._local(delegate.path, relative: relative); return _ChrootLink(fs, localPath); } diff --git a/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart b/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart index 4105ac807..10bbd7035 100644 --- a/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart +++ b/pkgs/file/lib/src/backends/chroot/chroot_random_access_file.dart @@ -2,7 +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. -part of file.src.backends.chroot; +part of '../chroot.dart'; class _ChrootRandomAccessFile with ForwardingRandomAccessFile { _ChrootRandomAccessFile(this.path, this.delegate); diff --git a/pkgs/file/lib/src/backends/local/local_directory.dart b/pkgs/file/lib/src/backends/local/local_directory.dart index e23e68fe0..3e1db6140 100644 --- a/pkgs/file/lib/src/backends/local/local_directory.dart +++ b/pkgs/file/lib/src/backends/local/local_directory.dart @@ -2,10 +2,10 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; - +import '../../common.dart' as common; +import '../../forwarding.dart'; +import '../../interface.dart'; +import '../../io.dart' as io; import 'local_file_system_entity.dart'; /// [Directory] implementation that forwards all calls to `dart:io`. @@ -13,7 +13,7 @@ class LocalDirectory extends LocalFileSystemEntity with ForwardingDirectory, common.DirectoryAddOnsMixin { /// Instantiates a new [LocalDirectory] tied to the specified file system /// and delegating to the specified [delegate]. - LocalDirectory(FileSystem fs, io.Directory delegate) : super(fs, delegate); + LocalDirectory(super.fs, super.delegate); @override String toString() => "LocalDirectory: '$path'"; diff --git a/pkgs/file/lib/src/backends/local/local_file.dart b/pkgs/file/lib/src/backends/local/local_file.dart index 36293ba51..a4bc10627 100644 --- a/pkgs/file/lib/src/backends/local/local_file.dart +++ b/pkgs/file/lib/src/backends/local/local_file.dart @@ -2,9 +2,9 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/io.dart' as io; - +import '../../forwarding.dart'; +import '../../interface.dart'; +import '../../io.dart' as io; import 'local_file_system_entity.dart'; /// [File] implementation that forwards all calls to `dart:io`. @@ -12,7 +12,7 @@ class LocalFile extends LocalFileSystemEntity with ForwardingFile { /// Instantiates a new [LocalFile] tied to the specified file system /// and delegating to the specified [delegate]. - LocalFile(FileSystem fs, io.File delegate) : super(fs, delegate); + LocalFile(super.fs, super.delegate); @override String toString() => "LocalFile: '$path'"; diff --git a/pkgs/file/lib/src/backends/local/local_file_system.dart b/pkgs/file/lib/src/backends/local/local_file_system.dart index 635998e10..7541c370f 100644 --- a/pkgs/file/lib/src/backends/local/local_file_system.dart +++ b/pkgs/file/lib/src/backends/local/local_file_system.dart @@ -2,10 +2,10 @@ // 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. -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; import 'package:path/path.dart' as p; +import '../../interface.dart'; +import '../../io.dart' as io; import 'local_directory.dart'; import 'local_file.dart'; import 'local_link.dart'; diff --git a/pkgs/file/lib/src/backends/local/local_file_system_entity.dart b/pkgs/file/lib/src/backends/local/local_file_system_entity.dart index ca4617b01..d0da55975 100644 --- a/pkgs/file/lib/src/backends/local/local_file_system_entity.dart +++ b/pkgs/file/lib/src/backends/local/local_file_system_entity.dart @@ -2,9 +2,9 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/io.dart' as io; - +import '../../forwarding.dart'; +import '../../interface.dart'; +import '../../io.dart' as io; import 'local_directory.dart'; import 'local_file.dart'; import 'local_link.dart'; diff --git a/pkgs/file/lib/src/backends/local/local_link.dart b/pkgs/file/lib/src/backends/local/local_link.dart index fc67d5e88..2ce479165 100644 --- a/pkgs/file/lib/src/backends/local/local_link.dart +++ b/pkgs/file/lib/src/backends/local/local_link.dart @@ -2,9 +2,9 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/io.dart' as io; - +import '../../forwarding.dart'; +import '../../interface.dart'; +import '../../io.dart' as io; import 'local_file_system_entity.dart'; /// [Link] implementation that forwards all calls to `dart:io`. @@ -12,7 +12,7 @@ class LocalLink extends LocalFileSystemEntity with ForwardingLink { /// Instantiates a new [LocalLink] tied to the specified file system /// and delegating to the specified [delegate]. - LocalLink(FileSystem fs, io.Link delegate) : super(fs, delegate); + LocalLink(super.fs, super.delegate); @override String toString() => "LocalLink: '$path'"; diff --git a/pkgs/file/lib/src/backends/memory/clock.dart b/pkgs/file/lib/src/backends/memory/clock.dart index 98d5434f9..57c1b72cd 100644 --- a/pkgs/file/lib/src/backends/memory/clock.dart +++ b/pkgs/file/lib/src/backends/memory/clock.dart @@ -2,6 +2,8 @@ // 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. +// ignore_for_file: comment_references + /// Interface describing clocks used by the [MemoryFileSystem]. /// /// The [MemoryFileSystem] uses a clock to determine the modification times of diff --git a/pkgs/file/lib/src/backends/memory/common.dart b/pkgs/file/lib/src/backends/memory/common.dart index 80e3c3851..eb4ca43d7 100644 --- a/pkgs/file/lib/src/backends/memory/common.dart +++ b/pkgs/file/lib/src/backends/memory/common.dart @@ -2,7 +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. -import 'package:file/src/common.dart' as common; +import '../../common.dart' as common; /// Generates a path to use in error messages. typedef PathGenerator = dynamic Function(); diff --git a/pkgs/file/lib/src/backends/memory/memory_directory.dart b/pkgs/file/lib/src/backends/memory/memory_directory.dart index 95fe54247..e73b96706 100644 --- a/pkgs/file/lib/src/backends/memory/memory_directory.dart +++ b/pkgs/file/lib/src/backends/memory/memory_directory.dart @@ -2,11 +2,11 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; import 'package:meta/meta.dart'; +import '../../common.dart' as common; +import '../../interface.dart'; +import '../../io.dart' as io; import 'common.dart'; import 'memory_file.dart'; import 'memory_file_system_entity.dart'; @@ -25,8 +25,7 @@ class MemoryDirectory extends MemoryFileSystemEntity with common.DirectoryAddOnsMixin implements Directory { /// Instantiates a new [MemoryDirectory]. - MemoryDirectory(NodeBasedFileSystem fileSystem, String path) - : super(fileSystem, path); + MemoryDirectory(super.fileSystem, super.path); @override io.FileSystemEntityType get expectedType => io.FileSystemEntityType.directory; @@ -52,7 +51,7 @@ class MemoryDirectory extends MemoryFileSystemEntity @override void createSync({bool recursive = false}) { fileSystem.opHandle(path, FileSystemOp.create); - Node? node = internalCreateSync( + var node = internalCreateSync( followTailLink: true, visitLinks: true, createChild: (DirectoryNode parent, bool isFinalSegment) { @@ -75,19 +74,19 @@ class MemoryDirectory extends MemoryFileSystemEntity @override Directory createTempSync([String? prefix]) { prefix = '${prefix ?? ''}rand'; - String fullPath = fileSystem.path.join(path, prefix); - String dirname = fileSystem.path.dirname(fullPath); - String basename = fileSystem.path.basename(fullPath); - DirectoryNode? node = fileSystem.findNode(dirname) as DirectoryNode?; + var fullPath = fileSystem.path.join(path, prefix); + var dirname = fileSystem.path.dirname(fullPath); + var basename = fileSystem.path.basename(fullPath); + var node = fileSystem.findNode(dirname) as DirectoryNode?; checkExists(node, () => dirname); utils.checkIsDir(node!, () => dirname); - int tempCounter = _systemTempCounter[fileSystem] ?? 0; + var tempCounter = _systemTempCounter[fileSystem] ?? 0; String name() => '$basename$tempCounter'; while (node.children.containsKey(name())) { tempCounter++; } _systemTempCounter[fileSystem] = tempCounter; - DirectoryNode tempDir = DirectoryNode(node); + var tempDir = DirectoryNode(node); node.children[name()] = tempDir; return MemoryDirectory(fileSystem, fileSystem.path.join(dirname, name())) ..createSync(); @@ -128,9 +127,9 @@ class MemoryDirectory extends MemoryFileSystemEntity bool recursive = false, bool followLinks = true, }) { - DirectoryNode node = backing as DirectoryNode; - List listing = []; - List<_PendingListTask> tasks = <_PendingListTask>[ + var node = backing as DirectoryNode; + var listing = []; + var tasks = <_PendingListTask>[ _PendingListTask( node, path.endsWith(fileSystem.path.separator) @@ -140,14 +139,14 @@ class MemoryDirectory extends MemoryFileSystemEntity ), ]; while (tasks.isNotEmpty) { - _PendingListTask task = tasks.removeLast(); + var task = tasks.removeLast(); task.dir.children.forEach((String name, Node child) { - Set breadcrumbs = Set.from(task.breadcrumbs); - String childPath = fileSystem.path.join(task.path, name); + var breadcrumbs = Set.from(task.breadcrumbs); + var childPath = fileSystem.path.join(task.path, name); while (followLinks && utils.isLink(child) && breadcrumbs.add(child as LinkNode)) { - Node? referent = child.referentOrNull; + var referent = child.referentOrNull; if (referent != null) { child = referent; } diff --git a/pkgs/file/lib/src/backends/memory/memory_file.dart b/pkgs/file/lib/src/backends/memory/memory_file.dart index ba4faab37..1a8f5f972 100644 --- a/pkgs/file/lib/src/backends/memory/memory_file.dart +++ b/pkgs/file/lib/src/backends/memory/memory_file.dart @@ -7,26 +7,25 @@ import 'dart:convert'; import 'dart:math' as math show min; import 'dart:typed_data'; -import 'package:file/file.dart'; -import 'package:file/src/backends/memory/operations.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; import 'package:meta/meta.dart'; +import '../../common.dart' as common; +import '../../interface.dart'; +import '../../io.dart' as io; import 'common.dart'; import 'memory_file_system_entity.dart'; import 'memory_random_access_file.dart'; import 'node.dart'; +import 'operations.dart'; import 'utils.dart' as utils; /// Internal implementation of [File]. class MemoryFile extends MemoryFileSystemEntity implements File { /// Instantiates a new [MemoryFile]. - const MemoryFile(NodeBasedFileSystem fileSystem, String path) - : super(fileSystem, path); + const MemoryFile(super.fileSystem, super.path); FileNode get _resolvedBackingOrCreate { - Node? node = backingOrNull; + var node = backingOrNull; if (node == null) { node = _doCreate(); } else { @@ -61,7 +60,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { } Node? _doCreate({bool recursive = false}) { - Node? node = internalCreateSync( + var node = internalCreateSync( followTailLink: true, createChild: (DirectoryNode parent, bool isFinalSegment) { if (isFinalSegment) { @@ -88,7 +87,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { newPath, followTailLink: true, checkType: (Node node) { - FileSystemEntityType actualType = node.stat.type; + var actualType = node.stat.type; if (actualType != expectedType) { throw actualType == FileSystemEntityType.notFound ? common.noSuchFileOrDirectory(path) @@ -103,7 +102,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { @override File copySync(String newPath) { fileSystem.opHandle(path, FileSystemOp.copy); - FileNode sourceNode = resolvedBacking as FileNode; + var sourceNode = resolvedBacking as FileNode; fileSystem.findNode( newPath, segmentVisitor: ( @@ -116,7 +115,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { if (currentSegment == finalSegment) { if (child != null) { if (utils.isLink(child)) { - List ledger = []; + var ledger = []; child = utils.resolveLinks(child as LinkNode, () => newPath, ledger: ledger); checkExists(child, () => newPath); @@ -127,7 +126,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { utils.checkType(expectedType, child.type, () => newPath); parent.children.remove(childName); } - FileNode newNode = FileNode(parent); + var newNode = FileNode(parent); newNode.copyFrom(sourceNode); parent.children[childName] = newNode; } @@ -158,7 +157,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { @override void setLastAccessedSync(DateTime time) { - FileNode node = resolvedBacking as FileNode; + var node = resolvedBacking as FileNode; node.accessed = time.millisecondsSinceEpoch; } @@ -174,7 +173,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { @override void setLastModifiedSync(DateTime time) { - FileNode node = resolvedBacking as FileNode; + var node = resolvedBacking as FileNode; node.modified = time.millisecondsSinceEpoch; } @@ -199,8 +198,8 @@ class MemoryFile extends MemoryFileSystemEntity implements File { Stream> openRead([int? start, int? end]) { fileSystem.opHandle(path, FileSystemOp.open); try { - FileNode node = resolvedBacking as FileNode; - Uint8List content = node.content; + var node = resolvedBacking as FileNode; + var content = node.content; if (start != null) { content = end == null ? content.sublist(start) @@ -253,13 +252,13 @@ class MemoryFile extends MemoryFileSystemEntity implements File { @override List readAsLinesSync({Encoding encoding = utf8}) { - String str = readAsStringSync(encoding: encoding); + var str = readAsStringSync(encoding: encoding); if (str.isEmpty) { return []; } - final List lines = str.split('\n'); + final lines = str.split('\n'); if (str.endsWith('\n')) { // A final newline should not create an additional line. lines.removeLast(); @@ -287,7 +286,7 @@ class MemoryFile extends MemoryFileSystemEntity implements File { if (!utils.isWriteMode(mode)) { throw common.badFileDescriptor(path); } - FileNode node = _resolvedBackingOrCreate; + var node = _resolvedBackingOrCreate; _truncateIfNecessary(node, mode); fileSystem.opHandle(path, FileSystemOp.write); node.write(bytes); @@ -349,7 +348,7 @@ class _FileSink implements io.IOSink { deferredException = e; } - Future future = Future.microtask(() { + var future = Future.microtask(() { if (deferredException != null) { throw deferredException; } @@ -387,7 +386,7 @@ class _FileSink implements io.IOSink { @override void writeAll(Iterable objects, [String separator = '']) { - bool firstIter = true; + var firstIter = true; for (dynamic obj in objects) { if (!firstIter) { write(separator); @@ -418,7 +417,7 @@ class _FileSink implements io.IOSink { _streamCompleter = Completer(); stream.listen( - (List data) => _addData(data), + _addData, cancelOnError: true, onError: (Object error, StackTrace stackTrace) { _streamCompleter!.completeError(error, stackTrace); @@ -445,8 +444,7 @@ class _FileSink implements io.IOSink { _isClosed = true; _pendingWrites.then( (_) => _completer.complete(), - onError: (Object error, StackTrace stackTrace) => - _completer.completeError(error, stackTrace), + onError: _completer.completeError, ); } return _completer.future; diff --git a/pkgs/file/lib/src/backends/memory/memory_file_stat.dart b/pkgs/file/lib/src/backends/memory/memory_file_stat.dart index 94f86d155..ce6bedac1 100644 --- a/pkgs/file/lib/src/backends/memory/memory_file_stat.dart +++ b/pkgs/file/lib/src/backends/memory/memory_file_stat.dart @@ -2,7 +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. -import 'package:file/src/io.dart' as io; +import '../../io.dart' as io; /// Internal implementation of [io.FileStat]. class MemoryFileStat implements io.FileStat { @@ -47,8 +47,8 @@ class MemoryFileStat implements io.FileStat { @override String modeString() { - int permissions = mode & 0xFFF; - List codes = const [ + var permissions = mode & 0xFFF; + var codes = const [ '---', '--x', '-w-', @@ -58,7 +58,7 @@ class MemoryFileStat implements io.FileStat { 'rw-', 'rwx', ]; - List result = []; + var result = []; result ..add(codes[(permissions >> 6) & 0x7]) ..add(codes[(permissions >> 3) & 0x7]) diff --git a/pkgs/file/lib/src/backends/memory/memory_file_system.dart b/pkgs/file/lib/src/backends/memory/memory_file_system.dart index f3cdaeede..dd359f049 100644 --- a/pkgs/file/lib/src/backends/memory/memory_file_system.dart +++ b/pkgs/file/lib/src/backends/memory/memory_file_system.dart @@ -2,11 +2,10 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/backends/memory/operations.dart'; -import 'package:file/src/io.dart' as io; import 'package:path/path.dart' as p; +import '../../interface.dart'; +import '../../io.dart' as io; import 'clock.dart'; import 'common.dart'; import 'memory_directory.dart'; @@ -14,6 +13,7 @@ import 'memory_file.dart'; import 'memory_file_stat.dart'; import 'memory_link.dart'; import 'node.dart'; +import 'operations.dart'; import 'style.dart'; import 'utils.dart' as utils; @@ -91,7 +91,7 @@ class _MemoryFileSystem extends FileSystem p.Context _context; @override - final Function(String context, FileSystemOp operation) opHandle; + final void Function(String context, FileSystemOp operation) opHandle; @override final Clock clock; @@ -141,7 +141,7 @@ class _MemoryFileSystem extends FileSystem } value = directory(value).resolveSymbolicLinksSync(); - Node? node = findNode(value); + var node = findNode(value); checkExists(node, () => value); utils.checkIsDir(node!, () => value); assert(_context.isAbsolute(value)); @@ -166,9 +166,9 @@ class _MemoryFileSystem extends FileSystem @override bool identicalSync(String path1, String path2) { - Node? node1 = findNode(path1); + var node1 = findNode(path1); checkExists(node1, () => path1); - Node? node2 = findNode(path2); + var node2 = findNode(path2); checkExists(node2, () => path2); return node1 != null && node1 == node2; } @@ -220,14 +220,13 @@ class _MemoryFileSystem extends FileSystem reference ??= _current; } - List parts = path.split(style.separator) - ..removeWhere(utils.isEmpty); - DirectoryNode? directory = reference?.directory; + var parts = path.split(style.separator)..removeWhere(utils.isEmpty); + var directory = reference?.directory; Node? child = directory; - int finalSegment = parts.length - 1; - for (int i = 0; i <= finalSegment; i++) { - String basename = parts[i]; + var finalSegment = parts.length - 1; + for (var i = 0; i <= finalSegment; i++) { + var basename = parts[i]; assert(basename.isNotEmpty); switch (basename) { diff --git a/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart b/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart index ad987d71a..1990abcd0 100644 --- a/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart +++ b/pkgs/file/lib/src/backends/memory/memory_file_system_entity.dart @@ -2,11 +2,11 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; import 'package:meta/meta.dart'; +import '../../common.dart' as common; +import '../../interface.dart'; +import '../../io.dart' as io; import 'common.dart'; import 'memory_directory.dart'; import 'node.dart'; @@ -60,7 +60,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { /// The type of the node is not guaranteed to match [expectedType]. @protected Node get backing { - Node? node = fileSystem.findNode(path); + var node = fileSystem.findNode(path); checkExists(node, () => path); return node!; } @@ -71,7 +71,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { /// doesn't match, this will throw a [io.FileSystemException]. @protected Node get resolvedBacking { - Node node = backing; + var node = backing; node = utils.isLink(node) ? utils.resolveLinks(node as LinkNode, () => path) : node; @@ -107,14 +107,14 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { if (path.isEmpty) { throw common.noSuchFileOrDirectory(path); } - List ledger = []; + var ledger = []; if (isAbsolute) { ledger.add(fileSystem.style.drive); } - Node? node = fileSystem.findNode(path, + var node = fileSystem.findNode(path, pathWithSymlinks: ledger, followTailLink: true); checkExists(node, () => path); - String resolved = ledger.join(fileSystem.path.separator); + var resolved = ledger.join(fileSystem.path.separator); if (resolved == fileSystem.style.drive) { resolved = fileSystem.style.root; } else if (!fileSystem.path.isAbsolute(resolved)) { @@ -151,7 +151,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { @override FileSystemEntity get absolute { - String absolutePath = path; + var absolutePath = path; if (!fileSystem.path.isAbsolute(absolutePath)) { absolutePath = fileSystem.path.join(fileSystem.cwd, absolutePath); } @@ -242,7 +242,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { bool followTailLink = false, utils.TypeChecker? checkType, }) { - Node node = backing; + var node = backing; (checkType ?? defaultCheckType)(node); fileSystem.findNode( newPath, @@ -256,7 +256,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { if (currentSegment == finalSegment) { if (child != null) { if (followTailLink) { - FileSystemEntityType childType = child.stat.type; + var childType = child.stat.type; if (childType != FileSystemEntityType.notFound) { utils.checkType(expectedType, child.stat.type, () => newPath); } @@ -289,7 +289,7 @@ abstract class MemoryFileSystemEntity implements FileSystemEntity { utils.TypeChecker? checkType, }) { fileSystem.opHandle(path, FileSystemOp.delete); - Node node = backing; + var node = backing; if (!recursive) { if (node is DirectoryNode && node.children.isNotEmpty) { throw common.directoryNotEmpty(path); diff --git a/pkgs/file/lib/src/backends/memory/memory_link.dart b/pkgs/file/lib/src/backends/memory/memory_link.dart index 7d5afb42f..a599fe8f1 100644 --- a/pkgs/file/lib/src/backends/memory/memory_link.dart +++ b/pkgs/file/lib/src/backends/memory/memory_link.dart @@ -2,11 +2,11 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; import 'package:meta/meta.dart'; +import '../../common.dart' as common; +import '../../interface.dart'; +import '../../io.dart' as io; import 'memory_file_system_entity.dart'; import 'node.dart'; import 'operations.dart'; @@ -15,8 +15,7 @@ import 'utils.dart' as utils; /// Internal implementation of [Link]. class MemoryLink extends MemoryFileSystemEntity implements Link { /// Instantiates a new [MemoryLink]. - const MemoryLink(NodeBasedFileSystem fileSystem, String path) - : super(fileSystem, path); + const MemoryLink(super.fileSystem, super.path); @override io.FileSystemEntityType get expectedType => io.FileSystemEntityType.link; @@ -50,7 +49,7 @@ class MemoryLink extends MemoryFileSystemEntity implements Link { @override void createSync(String target, {bool recursive = false}) { - bool preexisting = true; + var preexisting = true; fileSystem.opHandle(path, FileSystemOp.create); internalCreateSync( createChild: (DirectoryNode parent, bool isFinalSegment) { @@ -76,7 +75,7 @@ class MemoryLink extends MemoryFileSystemEntity implements Link { @override void updateSync(String target) { - Node node = backing; + var node = backing; utils.checkType(expectedType, node.type, () => path); (node as LinkNode).target = target; } @@ -93,7 +92,7 @@ class MemoryLink extends MemoryFileSystemEntity implements Link { @override String targetSync() { - Node node = backing; + var node = backing; if (node.type != expectedType) { // Note: this may change; https://github.com/dart-lang/sdk/issues/28204 throw common.noSuchFileOrDirectory(path); diff --git a/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart b/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart index d4fe73d18..190f0a137 100644 --- a/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart +++ b/pkgs/file/lib/src/backends/memory/memory_random_access_file.dart @@ -6,10 +6,11 @@ import 'dart:convert'; import 'dart:math' as math show min; import 'dart:typed_data'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; - +import '../../common.dart' as common; +import '../../io.dart' as io; +import '../memory.dart' show MemoryFileSystem; import 'memory_file.dart'; +import 'memory_file_system.dart' show MemoryFileSystem; import 'node.dart'; import 'utils.dart' as utils; @@ -106,8 +107,8 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { /// Wraps a synchronous function to make it appear asynchronous. /// /// [_asyncOperationPending], [_checkAsync], and [_asyncWrapper] are used to - /// mimic [RandomAccessFile]'s enforcement that only one asynchronous - /// operation is pending for a [RandomAccessFile] instance. Since + /// mimic [io.RandomAccessFile]'s enforcement that only one asynchronous + /// operation is pending for a [io.RandomAccessFile] instance. Since /// [MemoryFileSystem]-based classes are likely to be used in tests, fidelity /// is important to catch errors that might occur in production. /// @@ -211,7 +212,7 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { _checkReadable('read'); // TODO(jamesderlin): Check for integer overflow. final int end = math.min(_position + bytes, lengthSync()); - final Uint8List copy = _node.content.sublist(_position, end); + final copy = _node.content.sublist(_position, end); _position = end; return copy; } @@ -243,7 +244,7 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { end = RangeError.checkValidRange(start, end, buffer.length); - final int length = lengthSync(); + final length = lengthSync(); int i; for (i = start; i < end && _position < length; i += 1, _position += 1) { buffer[i] = _node.content[_position]; @@ -288,7 +289,7 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { 'truncate failed', path, common.invalidArgument(path).osError); } - final int oldLength = lengthSync(); + final oldLength = lengthSync(); if (length < oldLength) { _node.truncate(length); @@ -329,7 +330,7 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { // [Uint8List] will truncate values to 8-bits automatically, so we don't // need to check [value]. - int length = lengthSync(); + var length = lengthSync(); if (_position >= length) { // If [_position] is out of bounds, [RandomAccessFile] zero-fills the // file. @@ -363,8 +364,8 @@ class MemoryRandomAccessFile implements io.RandomAccessFile { end = RangeError.checkValidRange(start, end, buffer.length); - final int writeByteCount = end - start; - final int endPosition = _position + writeByteCount; + final writeByteCount = end - start; + final endPosition = _position + writeByteCount; if (endPosition > lengthSync()) { truncateSync(endPosition); diff --git a/pkgs/file/lib/src/backends/memory/node.dart b/pkgs/file/lib/src/backends/memory/node.dart index ae4d3f75d..eea72b58c 100644 --- a/pkgs/file/lib/src/backends/memory/node.dart +++ b/pkgs/file/lib/src/backends/memory/node.dart @@ -4,13 +4,12 @@ import 'dart:typed_data'; -import 'package:file/file.dart'; -import 'package:file/src/backends/memory/operations.dart'; -import 'package:file/src/io.dart' as io; - +import '../../interface.dart'; +import '../../io.dart' as io; import 'clock.dart'; import 'common.dart'; import 'memory_file_stat.dart'; +import 'operations.dart'; import 'style.dart'; /// Visitor callback for use with [NodeBasedFileSystem.findNode]. @@ -115,7 +114,7 @@ abstract class Node { /// Reparents this node to live in the specified directory. set parent(DirectoryNode parent) { - DirectoryNode ancestor = parent; + var ancestor = parent; while (!ancestor.isRoot) { if (ancestor == this) { throw const io.FileSystemException( @@ -149,8 +148,8 @@ abstract class Node { /// you call [stat] on them). abstract class RealNode extends Node { /// Constructs a new [RealNode] as a child of the specified [parent]. - RealNode(DirectoryNode? parent) : super(parent) { - int now = clock.now.millisecondsSinceEpoch; + RealNode(super.parent) { + var now = clock.now.millisecondsSinceEpoch; changed = now; modified = now; accessed = now; @@ -195,7 +194,7 @@ abstract class RealNode extends Node { /// Class that represents the backing for an in-memory directory. class DirectoryNode extends RealNode { /// Constructs a new [DirectoryNode] as a child of the specified [parent]. - DirectoryNode(DirectoryNode? parent) : super(parent); + DirectoryNode(super.parent); /// Child nodes, indexed by their basename. final Map children = {}; @@ -237,7 +236,7 @@ class RootNode extends DirectoryNode { /// Class that represents the backing for an in-memory regular file. class FileNode extends RealNode { /// Constructs a new [FileNode] as a child of the specified [parent]. - FileNode(DirectoryNode parent) : super(parent); + FileNode(DirectoryNode super.parent); /// File contents in bytes. Uint8List get content => _content; @@ -251,7 +250,7 @@ class FileNode extends RealNode { /// Appends the specified bytes to the end of this node's [content]. void write(List bytes) { - Uint8List existing = _content; + var existing = _content; _content = Uint8List(existing.length + bytes.length); _content.setRange(0, existing.length, existing); _content.setRange(existing.length, _content.length, bytes); @@ -286,9 +285,7 @@ class FileNode extends RealNode { class LinkNode extends Node { /// Constructs a new [LinkNode] as a child of the specified [parent] and /// linking to the specified [target] path. - LinkNode(DirectoryNode parent, this.target) - : assert(target.isNotEmpty), - super(parent); + LinkNode(DirectoryNode super.parent, this.target) : assert(target.isNotEmpty); /// The path to which this link points. String target; @@ -309,7 +306,7 @@ class LinkNode extends Node { Node? Function(DirectoryNode parent, String childName, Node? child)? tailVisitor, }) { - Node? referent = fs.findNode( + var referent = fs.findNode( target, reference: this, segmentVisitor: ( @@ -349,7 +346,7 @@ class LinkNode extends Node { } _reentrant = true; try { - Node? node = referentOrNull; + var node = referentOrNull; return node == null ? MemoryFileStat.notFound : node.stat; } finally { _reentrant = false; diff --git a/pkgs/file/lib/src/backends/memory/operations.dart b/pkgs/file/lib/src/backends/memory/operations.dart index 9fc7462fc..57d118b11 100644 --- a/pkgs/file/lib/src/backends/memory/operations.dart +++ b/pkgs/file/lib/src/backends/memory/operations.dart @@ -2,6 +2,8 @@ // 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. +// ignore_for_file: comment_references + /// A file system operation used by the [MemoryFileSytem] to allow /// tests to insert errors for certain operations. /// @@ -64,23 +66,15 @@ class FileSystemOp { @override String toString() { - switch (_value) { - case 0: - return 'FileSystemOp.read'; - case 1: - return 'FileSystemOp.write'; - case 2: - return 'FileSystemOp.delete'; - case 3: - return 'FileSystemOp.create'; - case 4: - return 'FileSystemOp.open'; - case 5: - return 'FileSystemOp.copy'; - case 6: - return 'FileSystemOp.exists'; - default: - throw StateError('Invalid FileSytemOp type: $this'); - } + return switch (_value) { + 0 => 'FileSystemOp.read', + 1 => 'FileSystemOp.write', + 2 => 'FileSystemOp.delete', + 3 => 'FileSystemOp.create', + 4 => 'FileSystemOp.open', + 5 => 'FileSystemOp.copy', + 6 => 'FileSystemOp.exists', + _ => throw StateError('Invalid FileSytemOp type: $this') + }; } } diff --git a/pkgs/file/lib/src/backends/memory/style.dart b/pkgs/file/lib/src/backends/memory/style.dart index 701c9d05e..f4bd33fb7 100644 --- a/pkgs/file/lib/src/backends/memory/style.dart +++ b/pkgs/file/lib/src/backends/memory/style.dart @@ -2,9 +2,10 @@ // 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. -import 'package:file/file.dart'; import 'package:path/path.dart' as p; +import '../../interface.dart'; + /// Class that represents the path style that a memory file system should /// adopt. /// diff --git a/pkgs/file/lib/src/backends/memory/utils.dart b/pkgs/file/lib/src/backends/memory/utils.dart index eec998038..aa24cfb57 100644 --- a/pkgs/file/lib/src/backends/memory/utils.dart +++ b/pkgs/file/lib/src/backends/memory/utils.dart @@ -2,20 +2,19 @@ // 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. -import 'package:file/file.dart'; -import 'package:file/src/common.dart' as common; -import 'package:file/src/io.dart' as io; - +import '../../common.dart' as common; +import '../../interface.dart'; +import '../../io.dart' as io; import 'common.dart'; import 'node.dart'; -/// Checks if `node.type` returns [io.FileSystemEntityType.FILE]. +/// Checks if `node.type` returns [io.FileSystemEntityType.file]. bool isFile(Node? node) => node?.type == io.FileSystemEntityType.file; -/// Checks if `node.type` returns [io.FileSystemEntityType.DIRECTORY]. +/// Checks if `node.type` returns [io.FileSystemEntityType.directory]. bool isDirectory(Node? node) => node?.type == io.FileSystemEntityType.directory; -/// Checks if `node.type` returns [io.FileSystemEntityType.LINK]. +/// Checks if `node.type` returns [io.FileSystemEntityType.link]. bool isLink(Node? node) => node?.type == io.FileSystemEntityType.link; /// Validator function that is expected to throw a [FileSystemException] if @@ -86,7 +85,7 @@ Node resolveLinks( tailVisitor, }) { // Record a breadcrumb trail to guard against symlink loops. - Set breadcrumbs = {}; + var breadcrumbs = {}; Node node = link; while (isLink(node)) { diff --git a/pkgs/file/lib/src/forwarding/forwarding_directory.dart b/pkgs/file/lib/src/forwarding/forwarding_directory.dart index dba0c8ed6..ad1c548c1 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_directory.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_directory.dart @@ -2,8 +2,9 @@ // 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. -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; +import '../forwarding.dart'; +import '../interface.dart'; +import '../io.dart' as io; /// A directory that forwards all methods and properties to a delegate. mixin ForwardingDirectory diff --git a/pkgs/file/lib/src/forwarding/forwarding_file.dart b/pkgs/file/lib/src/forwarding/forwarding_file.dart index 49c211db7..d6cfe3bb7 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_file.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_file.dart @@ -5,8 +5,9 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; +import '../forwarding.dart'; +import '../interface.dart'; +import '../io.dart' as io; /// A file that forwards all methods and properties to a delegate. mixin ForwardingFile diff --git a/pkgs/file/lib/src/forwarding/forwarding_file_system.dart b/pkgs/file/lib/src/forwarding/forwarding_file_system.dart index d864db94c..885fdb618 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_file_system.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_file_system.dart @@ -2,11 +2,12 @@ // 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. -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; +import '../interface.dart'; +import '../io.dart' as io; + /// A file system that forwards all methods and properties to a delegate. abstract class ForwardingFileSystem extends FileSystem { /// Creates a new [ForwardingFileSystem] that forwards all methods and diff --git a/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart b/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart index 3c41b39b4..1c0628ee4 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_file_system_entity.dart @@ -2,10 +2,11 @@ // 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. -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; import 'package:meta/meta.dart'; +import '../interface.dart'; +import '../io.dart' as io; + /// A file system entity that forwards all methods and properties to a delegate. abstract class ForwardingFileSystemEntity implements FileSystemEntity { diff --git a/pkgs/file/lib/src/forwarding/forwarding_link.dart b/pkgs/file/lib/src/forwarding/forwarding_link.dart index 7a60ecbfe..915e710cf 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_link.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_link.dart @@ -2,8 +2,9 @@ // 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. -import 'package:file/src/io.dart' as io; -import 'package:file/file.dart'; +import '../forwarding.dart'; +import '../interface.dart'; +import '../io.dart' as io; /// A link that forwards all methods and properties to a delegate. mixin ForwardingLink diff --git a/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart b/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart index 9dd407930..3847b91f4 100644 --- a/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart +++ b/pkgs/file/lib/src/forwarding/forwarding_random_access_file.dart @@ -5,11 +5,12 @@ import 'dart:convert'; import 'dart:typed_data'; -import 'package:file/src/io.dart' as io; import 'package:meta/meta.dart'; -/// A [RandomAccessFile] implementation that forwards all methods and properties -/// to a delegate. +import '../io.dart' as io; + +/// A [io.RandomAccessFile] implementation that forwards all methods and +/// properties to a delegate. mixin ForwardingRandomAccessFile implements io.RandomAccessFile { /// The entity to which this entity will forward all methods and properties. @protected diff --git a/pkgs/file/lib/src/interface.dart b/pkgs/file/lib/src/interface.dart index 4662e3515..d9b7ed592 100644 --- a/pkgs/file/lib/src/interface.dart +++ b/pkgs/file/lib/src/interface.dart @@ -2,8 +2,6 @@ // 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. -library file.src.interface; - export 'interface/directory.dart'; export 'interface/error_codes.dart'; export 'interface/file.dart'; diff --git a/pkgs/file/lib/src/interface/error_codes.dart b/pkgs/file/lib/src/interface/error_codes.dart index 8943538cb..4836b5658 100644 --- a/pkgs/file/lib/src/interface/error_codes.dart +++ b/pkgs/file/lib/src/interface/error_codes.dart @@ -168,7 +168,7 @@ class ErrorCodes { static int get EXDEV => _platform((_Codes codes) => codes.exdev); static int _platform(int Function(_Codes codes) getCode) { - _Codes codes = (_platforms[operatingSystem] ?? _platforms['linux'])!; + var codes = (_platforms[operatingSystem] ?? _platforms['linux'])!; return getCode(codes); } } diff --git a/pkgs/file/lib/src/interface/file_system.dart b/pkgs/file/lib/src/interface/file_system.dart index ecc01a801..2d4e4aa3b 100644 --- a/pkgs/file/lib/src/interface/file_system.dart +++ b/pkgs/file/lib/src/interface/file_system.dart @@ -6,7 +6,6 @@ import 'package:meta/meta.dart'; import 'package:path/path.dart' as p; import '../io.dart' as io; - import 'directory.dart'; import 'file.dart'; import 'file_system_entity.dart'; @@ -99,9 +98,9 @@ abstract class FileSystem { bool get isWatchSupported; /// Finds the type of file system object that a [path] points to. Returns - /// a Future that completes with the result. + /// a `Future` that completes with the result. /// - /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// [io.FileSystemEntityType.link] will only be returned if [followLinks] is /// `false`, and [path] points to a link /// /// If the [path] does not point to a file system object or an error occurs @@ -111,37 +110,38 @@ abstract class FileSystem { /// Syncronously finds the type of file system object that a [path] points /// to. Returns a [io.FileSystemEntityType]. /// - /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is + /// [io.FileSystemEntityType.link] will only be returned if [followLinks] is /// `false`, and [path] points to a link /// /// If the [path] does not point to a file system object or an error occurs /// then [io.FileSystemEntityType.notFound] is returned. io.FileSystemEntityType typeSync(String path, {bool followLinks = true}); - /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.FILE]. + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.file]. Future isFile(String path) async => await type(path) == io.FileSystemEntityType.file; /// Synchronously checks if [`type(path)`](type) returns - /// [io.FileSystemEntityType.FILE]. + /// [io.FileSystemEntityType.file]. bool isFileSync(String path) => typeSync(path) == io.FileSystemEntityType.file; - /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.DIRECTORY]. + /// Checks if [`type(path)`](type) returns + /// [io.FileSystemEntityType.directory]. Future isDirectory(String path) async => await type(path) == io.FileSystemEntityType.directory; /// Synchronously checks if [`type(path)`](type) returns - /// [io.FileSystemEntityType.DIRECTORY]. + /// [io.FileSystemEntityType.directory]. bool isDirectorySync(String path) => typeSync(path) == io.FileSystemEntityType.directory; - /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.LINK]. + /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.link]. Future isLink(String path) async => await type(path, followLinks: false) == io.FileSystemEntityType.link; /// Synchronously checks if [`type(path)`](type) returns - /// [io.FileSystemEntityType.LINK]. + /// [io.FileSystemEntityType.link]. bool isLinkSync(String path) => typeSync(path, followLinks: false) == io.FileSystemEntityType.link; diff --git a/pkgs/file/lib/src/io.dart b/pkgs/file/lib/src/io.dart index 9d57e7869..28c1d6dfa 100644 --- a/pkgs/file/lib/src/io.dart +++ b/pkgs/file/lib/src/io.dart @@ -8,6 +8,8 @@ /// the `file` package. The `file` package re-exports these interfaces (or in /// some cases, implementations of these interfaces by the same name), so this /// file need not be exposes publicly and exists for internal use only. +library; + export 'dart:io' show Directory, diff --git a/pkgs/file/pubspec.yaml b/pkgs/file/pubspec.yaml index 0dc81cd22..0ad65b0d6 100644 --- a/pkgs/file/pubspec.yaml +++ b/pkgs/file/pubspec.yaml @@ -1,5 +1,5 @@ name: file -version: 7.0.1 +version: 7.0.2-wip description: A pluggable, mockable file system abstraction for Dart. repository: https://github.com/dart-lang/tools/tree/main/pkgs/file issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Afile @@ -12,8 +12,8 @@ dependencies: path: ^1.8.3 dev_dependencies: + dart_flutter_team_lints: ^3.0.0 file_testing: ^3.0.0 - lints: ^2.0.1 test: ^1.23.1 dependency_overrides: diff --git a/pkgs/file/test/chroot_test.dart b/pkgs/file/test/chroot_test.dart index 6c34ff200..cf23f4755 100644 --- a/pkgs/file/test/chroot_test.dart +++ b/pkgs/file/test/chroot_test.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') +library; + import 'dart:io' as io; import 'package:file/chroot.dart'; @@ -17,14 +19,15 @@ import 'common_tests.dart'; void main() { group('ChrootFileSystem', () { ChrootFileSystem createMemoryBackedChrootFileSystem() { - MemoryFileSystem fs = MemoryFileSystem(); + var fs = MemoryFileSystem(); fs.directory('/tmp').createSync(); return ChrootFileSystem(fs, '/tmp'); } // TODO(jamesderlin): Make ChrootFile.openSync return a delegating // RandomAccessFile that uses the chroot'd path. - List skipCommon = [ + var skipCommon = [ + // ignore: lines_longer_than_80_chars 'File > open > .* > RandomAccessFile > read > openReadHandleDoesNotChange', 'File > open > .* > RandomAccessFile > openWriteHandleDoesNotChange', ]; @@ -137,6 +140,7 @@ void main() { test('referencesRootEntityForJailbreakPath', () { mem.file('/foo').createSync(); dynamic f = fs.file('../foo'); + // ignore: avoid_dynamic_calls expect(f.delegate.path, '/tmp/foo'); }); }); @@ -151,7 +155,7 @@ void main() { group('copy', () { test('copiesToRootDirectoryIfDestinationIsJailbreakPath', () { - File f = fs.file('/foo')..createSync(); + var f = fs.file('/foo')..createSync(); f.copySync('../bar'); expect(mem.file('/bar'), isNot(exists)); expect(mem.file('/tmp/bar'), exists); diff --git a/pkgs/file/test/common_tests.dart b/pkgs/file/test/common_tests.dart index 6028c7715..491d4f985 100644 --- a/pkgs/file/test/common_tests.dart +++ b/pkgs/file/test/common_tests.dart @@ -3,6 +3,8 @@ // BSD-style license that can be found in the LICENSE file. @TestOn('vm') +library; + import 'dart:async'; import 'dart:convert'; import 'dart:io' as io; @@ -10,8 +12,8 @@ import 'dart:io' as io; import 'package:file/file.dart'; import 'package:file_testing/file_testing.dart'; import 'package:path/path.dart' as p; -import 'package:test/test.dart'; import 'package:test/test.dart' as testpkg show group, setUp, tearDown, test; +import 'package:test/test.dart'; import 'utils.dart'; @@ -54,7 +56,7 @@ void runCommonTests( List skip = const [], FileSystemGenerator? replay, }) { - RootPathGenerator? rootfn = root; + var rootfn = root; group('common', () { late FileSystemGenerator createFs; @@ -62,7 +64,7 @@ void runCommonTests( late List tearDowns; late FileSystem fs; late String root; - List stack = []; + var stack = []; void skipIfNecessary(String description, void Function() callback) { stack.add(description); @@ -105,7 +107,7 @@ void runCommonTests( testpkg.setUp(() async { await Future.forEach(setUps, (SetUpTearDown setUp) => setUp()); await body(); - for (SetUpTearDown tearDown in tearDowns) { + for (var tearDown in tearDowns) { await tearDown(); } createFs = replay; @@ -115,7 +117,7 @@ void runCommonTests( testpkg.test(description, body, skip: skip); testpkg.tearDown(() async { - for (SetUpTearDown tearDown in tearDowns) { + for (var tearDown in tearDowns) { await tearDown(); } }); @@ -126,13 +128,13 @@ void runCommonTests( /// Returns [path] prefixed by the [root] namespace. /// This is only intended for absolute paths. String ns(String path) { - p.Context posix = p.Context(style: p.Style.posix); - List parts = posix.split(path); + var posix = p.Context(style: p.Style.posix); + var parts = posix.split(path); parts[0] = root; path = fs.path.joinAll(parts); - String rootPrefix = fs.path.rootPrefix(path); + var rootPrefix = fs.path.rootPrefix(path); assert(rootPrefix.isNotEmpty); - String result = root == rootPrefix + var result = root == rootPrefix ? path : (path == rootPrefix ? root @@ -160,7 +162,7 @@ void runCommonTests( test('succeedsWithUriArgument', () { fs.directory(ns('/foo')).createSync(); - Uri uri = fs.path.toUri(ns('/foo')); + var uri = fs.path.toUri(ns('/foo')); expect(fs.directory(uri), exists); }); @@ -173,11 +175,11 @@ void runCommonTests( }); // Fails due to - // https://github.com/google/file.dart/issues/112 + // https://github.com/dart-lang/tools/issues/632 test('considersBothSlashesEquivalent', () { fs.directory(r'foo\bar_dir').createSync(recursive: true); expect(fs.directory(r'foo/bar_dir'), exists); - }, skip: 'Fails due to https://github.com/google/file.dart/issues/112'); + }, skip: 'Fails due to https://github.com/dart-lang/tools/issues/632'); }); group('file', () { @@ -191,7 +193,7 @@ void runCommonTests( test('succeedsWithUriArgument', () { fs.file(ns('/foo')).createSync(); - Uri uri = fs.path.toUri(ns('/foo')); + var uri = fs.path.toUri(ns('/foo')); expect(fs.file(uri), exists); }); @@ -204,11 +206,11 @@ void runCommonTests( }); // Fails due to - // https://github.com/google/file.dart/issues/112 + // https://github.com/dart-lang/tools/issues/632 test('considersBothSlashesEquivalent', () { fs.file(r'foo\bar_file').createSync(recursive: true); expect(fs.file(r'foo/bar_file'), exists); - }, skip: 'Fails due to https://github.com/google/file.dart/issues/112'); + }, skip: 'Fails due to https://github.com/dart-lang/tools/issues/632'); }); group('link', () { @@ -223,7 +225,7 @@ void runCommonTests( test('succeedsWithUriArgument', () { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - Uri uri = fs.path.toUri(ns('/bar')); + var uri = fs.path.toUri(ns('/bar')); expect(fs.link(uri), exists); }); @@ -248,7 +250,7 @@ void runCommonTests( group('systemTempDirectory', () { test('existsAsDirectory', () { - Directory tmp = fs.systemTempDirectory; + var tmp = fs.systemTempDirectory; expect(tmp, isDirectory); expect(tmp, exists); }); @@ -318,7 +320,7 @@ void runCommonTests( test('staysAtRootIfSetToParentOfRoot', () { fs.currentDirectory = List.filled(20, '..').join(fs.path.separator); - String cwd = fs.currentDirectory.path; + var cwd = fs.currentDirectory.path; expect(cwd, fs.path.rootPrefix(cwd)); }); @@ -371,36 +373,36 @@ void runCommonTests( group('stat', () { test('isNotFoundForEmptyPath', () { - FileStat stat = fs.statSync(''); + var stat = fs.statSync(''); expect(stat.type, FileSystemEntityType.notFound); }); test('isNotFoundForPathToNonExistentEntityAtTail', () { - FileStat stat = fs.statSync(ns('/foo')); + var stat = fs.statSync(ns('/foo')); expect(stat.type, FileSystemEntityType.notFound); }); test('isNotFoundForPathToNonExistentEntityInTraversal', () { - FileStat stat = fs.statSync(ns('/foo/bar')); + var stat = fs.statSync(ns('/foo/bar')); expect(stat.type, FileSystemEntityType.notFound); }); test('isDirectoryForDirectory', () { fs.directory(ns('/foo')).createSync(); - FileStat stat = fs.statSync(ns('/foo')); + var stat = fs.statSync(ns('/foo')); expect(stat.type, FileSystemEntityType.directory); }); test('isFileForFile', () { fs.file(ns('/foo')).createSync(); - FileStat stat = fs.statSync(ns('/foo')); + var stat = fs.statSync(ns('/foo')); expect(stat.type, FileSystemEntityType.file); }); test('isFileForLinkToFile', () { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - FileStat stat = fs.statSync(ns('/bar')); + var stat = fs.statSync(ns('/bar')); expect(stat.type, FileSystemEntityType.file); }); @@ -408,7 +410,7 @@ void runCommonTests( fs.link(ns('/foo')).createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/baz')); fs.link(ns('/baz')).createSync(ns('/foo')); - FileStat stat = fs.statSync(ns('/foo')); + var stat = fs.statSync(ns('/foo')); expect(stat.type, FileSystemEntityType.notFound); }); }); @@ -454,18 +456,18 @@ void runCommonTests( group('type', () { test('isFileForFile', () { fs.file(ns('/foo')).createSync(); - FileSystemEntityType type = fs.typeSync(ns('/foo')); + var type = fs.typeSync(ns('/foo')); expect(type, FileSystemEntityType.file); }); test('isDirectoryForDirectory', () { fs.directory(ns('/foo')).createSync(); - FileSystemEntityType type = fs.typeSync(ns('/foo')); + var type = fs.typeSync(ns('/foo')); expect(type, FileSystemEntityType.directory); }); test('isDirectoryForAncestorOfRoot', () { - FileSystemEntityType type = fs + var type = fs .typeSync(List.filled(20, '..').join(fs.path.separator)); expect(type, FileSystemEntityType.directory); }); @@ -473,15 +475,14 @@ void runCommonTests( test('isFileForLinkToFileAndFollowLinksTrue', () { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - FileSystemEntityType type = fs.typeSync(ns('/bar')); + var type = fs.typeSync(ns('/bar')); expect(type, FileSystemEntityType.file); }); test('isLinkForLinkToFileAndFollowLinksFalse', () { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - FileSystemEntityType type = - fs.typeSync(ns('/bar'), followLinks: false); + var type = fs.typeSync(ns('/bar'), followLinks: false); expect(type, FileSystemEntityType.link); }); @@ -489,17 +490,17 @@ void runCommonTests( fs.link(ns('/foo')).createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/baz')); fs.link(ns('/baz')).createSync(ns('/foo')); - FileSystemEntityType type = fs.typeSync(ns('/foo')); + var type = fs.typeSync(ns('/foo')); expect(type, FileSystemEntityType.notFound); }); test('isNotFoundForNoEntityAtTail', () { - FileSystemEntityType type = fs.typeSync(ns('/foo')); + var type = fs.typeSync(ns('/foo')); expect(type, FileSystemEntityType.notFound); }); test('isNotFoundForNoDirectoryInTraversal', () { - FileSystemEntityType type = fs.typeSync(ns('/foo/bar/baz')); + var type = fs.typeSync(ns('/foo/bar/baz')); expect(type, FileSystemEntityType.notFound); }); }); @@ -676,8 +677,8 @@ void runCommonTests( }); test('succeedsIfDestinationDoesntExist', () { - Directory src = fs.directory(ns('/foo'))..createSync(); - Directory dest = src.renameSync(ns('/bar')); + var src = fs.directory(ns('/foo'))..createSync(); + var dest = src.renameSync(ns('/bar')); expect(dest.path, ns('/bar')); expect(dest, exists); }); @@ -686,8 +687,8 @@ void runCommonTests( 'succeedsIfDestinationIsEmptyDirectory', () { fs.directory(ns('/bar')).createSync(); - Directory src = fs.directory(ns('/foo'))..createSync(); - Directory dest = src.renameSync(ns('/bar')); + var src = fs.directory(ns('/foo'))..createSync(); + var dest = src.renameSync(ns('/bar')); expect(src, isNot(exists)); expect(dest, exists); }, @@ -697,14 +698,14 @@ void runCommonTests( test('throwsIfDestinationIsFile', () { fs.file(ns('/bar')).createSync(); - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.ENOTDIR, () { src.renameSync(ns('/bar')); }); }); test('throwsIfDestinationParentFolderDoesntExist', () { - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.ENOENT, () { src.renameSync(ns('/bar/baz')); }); @@ -712,7 +713,7 @@ void runCommonTests( test('throwsIfDestinationIsNonEmptyDirectory', () { fs.file(ns('/bar/baz')).createSync(recursive: true); - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); // The error will be 'Directory not empty' on OS X, but it will be // 'File exists' on Linux. expectFileSystemException( @@ -749,7 +750,7 @@ void runCommonTests( }); test('throwsIfDestinationIsLinkToNotFound', () { - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/baz')); expectFileSystemException(ErrorCodes.ENOTDIR, () { src.renameSync(ns('/bar')); @@ -757,7 +758,7 @@ void runCommonTests( }); test('throwsIfDestinationIsLinkToEmptyDirectory', () { - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); fs.link(ns('/baz')).createSync(ns('/bar')); expectFileSystemException(ErrorCodes.ENOTDIR, () { @@ -766,7 +767,7 @@ void runCommonTests( }); test('succeedsIfDestinationIsInDifferentDirectory', () { - Directory src = fs.directory(ns('/foo'))..createSync(); + var src = fs.directory(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); src.renameSync(ns('/bar/baz')); expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); @@ -790,24 +791,24 @@ void runCommonTests( group('delete', () { test('returnsCovariantType', () async { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); expect(await dir.delete(), isDirectory); }); test('succeedsIfEmptyDirectoryExistsAndRecursiveFalse', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); dir.deleteSync(); expect(dir, isNot(exists)); }); test('succeedsIfEmptyDirectoryExistsAndRecursiveTrue', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); dir.deleteSync(recursive: true); expect(dir, isNot(exists)); }); test('throwsIfNonEmptyDirectoryExistsAndRecursiveFalse', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); fs.file(ns('/foo/bar')).createSync(); expectFileSystemException(ErrorCodes.ENOTEMPTY, () { dir.deleteSync(); @@ -815,7 +816,7 @@ void runCommonTests( }); test('succeedsIfNonEmptyDirectoryExistsAndRecursiveTrue', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); fs.file(ns('/foo/bar')).createSync(); dir.deleteSync(recursive: true); expect(fs.directory(ns('/foo')), isNot(exists)); @@ -997,7 +998,7 @@ void runCommonTests( test('handlesParentAndThisFolderReferences', () { fs.directory(ns('/foo/bar/baz')).createSync(recursive: true); fs.link(ns('/foo/bar/baz/qux')).createSync(fs.path.join('..', '..')); - String resolved = fs + var resolved = fs .directory(ns('/foo/./bar/baz/../baz/qux/bar')) .resolveSymbolicLinksSync(); expect(resolved, ns('/foo/bar')); @@ -1015,7 +1016,7 @@ void runCommonTests( .createSync(fs.path.join('..', '..', 'qux'), recursive: true); fs.link(ns('/qux')).createSync('quux'); fs.link(ns('/quux/quuz')).createSync(ns('/foo'), recursive: true); - String resolved = fs + var resolved = fs .directory(ns('/foo//bar/./baz/quuz/bar/..///bar/baz/')) .resolveSymbolicLinksSync(); expect(resolved, ns('/quux')); @@ -1069,29 +1070,29 @@ void runCommonTests( test('resolvesNameCollisions', () { fs.directory(ns('/foo/bar')).createSync(recursive: true); - Directory tmp = fs.directory(ns('/foo')).createTempSync('bar'); + var tmp = fs.directory(ns('/foo')).createTempSync('bar'); expect(tmp.path, allOf(isNot(ns('/foo/bar')), startsWith(ns('/foo/bar')))); }); test('succeedsWithoutPrefix', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); expect(dir.createTempSync().path, startsWith(ns('/foo/'))); }); test('succeedsWithPrefix', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); expect(dir.createTempSync('bar').path, startsWith(ns('/foo/bar'))); }); test('succeedsWithNestedPathPrefixThatExists', () { fs.directory(ns('/foo/bar')).createSync(recursive: true); - Directory tmp = fs.directory(ns('/foo')).createTempSync('bar/baz'); + var tmp = fs.directory(ns('/foo')).createTempSync('bar/baz'); expect(tmp.path, startsWith(ns('/foo/bar/baz'))); }); test('throwsWithNestedPathPrefixThatDoesntExist', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.ENOENT, () { dir.createTempSync('bar/baz'); }); @@ -1123,7 +1124,7 @@ void runCommonTests( }); test('returnsEmptyListForEmptyDirectory', () { - Directory empty = fs.directory(ns('/bar'))..createSync(); + var empty = fs.directory(ns('/bar'))..createSync(); expect(empty.listSync(), isEmpty); }); @@ -1134,7 +1135,7 @@ void runCommonTests( }); test('returnsLinkObjectsIfFollowLinksFalse', () { - List list = dir.listSync(followLinks: false); + var list = dir.listSync(followLinks: false); expect(list, hasLength(3)); expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar'))))); expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz'))))); @@ -1142,7 +1143,7 @@ void runCommonTests( }); test('followsLinksIfFollowLinksTrue', () { - List list = dir.listSync(); + var list = dir.listSync(); expect(list, hasLength(3)); expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar'))))); expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz'))))); @@ -1189,8 +1190,7 @@ void runCommonTests( test('childEntriesNotNormalized', () { dir = fs.directory(ns('/bar/baz'))..createSync(recursive: true); fs.file(ns('/bar/baz/qux')).createSync(); - List list = - fs.directory(ns('/bar//../bar/./baz')).listSync(); + var list = fs.directory(ns('/bar//../bar/./baz')).listSync(); expect(list, hasLength(1)); expect(list[0], allOf(isFile, hasPath(ns('/bar//../bar/./baz/qux')))); }); @@ -1198,9 +1198,8 @@ void runCommonTests( test('symlinksToNotFoundAlwaysReturnedAsLinks', () { dir = fs.directory(ns('/bar'))..createSync(); fs.link(ns('/bar/baz')).createSync('qux'); - for (bool followLinks in const [true, false]) { - List list = - dir.listSync(followLinks: followLinks); + for (var followLinks in const [true, false]) { + var list = dir.listSync(followLinks: followLinks); expect(list, hasLength(1)); expect(list[0], allOf(isLink, hasPath(ns('/bar/baz')))); } @@ -1208,7 +1207,7 @@ void runCommonTests( }); test('childEntities', () { - Directory dir = fs.directory(ns('/foo'))..createSync(); + var dir = fs.directory(ns('/foo'))..createSync(); dir.childDirectory('bar').createSync(); dir.childFile('baz').createSync(); dir.childLink('qux').createSync('bar'); @@ -1321,22 +1320,22 @@ void runCommonTests( }); test('succeedsIfDestinationDoesntExistAtTail', () { - File src = fs.file(ns('/foo'))..createSync(); - File dest = src.renameSync(ns('/bar')); + var src = fs.file(ns('/foo'))..createSync(); + var dest = src.renameSync(ns('/bar')); expect(fs.file(ns('/foo')), isNot(exists)); expect(fs.file(ns('/bar')), exists); expect(dest.path, ns('/bar')); }); test('throwsIfDestinationDoesntExistViaTraversal', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.ENOENT, () { f.renameSync(ns('/bar/baz')); }); }); test('succeedsIfDestinationExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.file(ns('/bar')).createSync(); f.renameSync(ns('/bar')); expect(fs.file(ns('/foo')), isNot(exists)); @@ -1344,7 +1343,7 @@ void runCommonTests( }); test('throwsIfDestinationExistsAsDirectory', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); expectFileSystemException(ErrorCodes.EISDIR, () { f.renameSync(ns('/bar')); @@ -1352,7 +1351,7 @@ void runCommonTests( }); test('succeedsIfDestinationExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.file(ns('/bar')).createSync(); fs.link(ns('/baz')).createSync(ns('/bar')); f.renameSync(ns('/baz')); @@ -1364,7 +1363,7 @@ void runCommonTests( }); test('throwsIfDestinationExistsAsLinkToDirectory', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); fs.link(ns('/baz')).createSync(ns('/bar')); expectFileSystemException(ErrorCodes.EISDIR, () { @@ -1373,7 +1372,7 @@ void runCommonTests( }); test('succeedsIfDestinationExistsAsLinkToNotFound', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/baz')); f.renameSync(ns('/bar')); expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); @@ -1429,7 +1428,7 @@ void runCommonTests( }); test('succeedsIfDestinationDoesntExistAtTail', () { - File f = fs.file(ns('/foo')) + var f = fs.file(ns('/foo')) ..createSync() ..writeAsStringSync('foo'); f.copySync(ns('/bar')); @@ -1439,14 +1438,14 @@ void runCommonTests( }); test('throwsIfDestinationDoesntExistViaTraversal', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.ENOENT, () { f.copySync(ns('/bar/baz')); }); }); test('succeedsIfDestinationExistsAsFile', () { - File f = fs.file(ns('/foo')) + var f = fs.file(ns('/foo')) ..createSync() ..writeAsStringSync('foo'); fs.file(ns('/bar')) @@ -1460,7 +1459,7 @@ void runCommonTests( }); test('throwsIfDestinationExistsAsDirectory', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); expectFileSystemException(ErrorCodes.EISDIR, () { f.copySync(ns('/bar')); @@ -1468,7 +1467,7 @@ void runCommonTests( }); test('succeedsIfDestinationExistsAsLinkToFile', () { - File f = fs.file(ns('/foo')) + var f = fs.file(ns('/foo')) ..createSync() ..writeAsStringSync('foo'); fs.file(ns('/bar')) @@ -1487,7 +1486,7 @@ void runCommonTests( }, skip: io.Platform.isWindows /* No links on Windows */); test('throwsIfDestinationExistsAsLinkToDirectory', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.directory(ns('/bar')).createSync(); fs.link(ns('/baz')).createSync(ns('/bar')); expectFileSystemException(ErrorCodes.EISDIR, () { @@ -1525,7 +1524,7 @@ void runCommonTests( }); test('succeedsIfDestinationIsInDifferentDirectoryThanSource', () { - File f = fs.file(ns('/foo/bar')) + var f = fs.file(ns('/foo/bar')) ..createSync(recursive: true) ..writeAsStringSync('foo'); fs.directory(ns('/baz')).createSync(); @@ -1587,12 +1586,12 @@ void runCommonTests( }); test('returnsZeroForNewlyCreatedFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expect(f.lengthSync(), 0); }); test('writeNBytesReturnsLengthN', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([1, 2, 3, 4], flush: true); expect(f.lengthSync(), 4); }); @@ -1616,10 +1615,10 @@ void runCommonTests( group('lastAccessed', () { test('isNowForNewlyCreatedFile', () { - DateTime before = downstairs(); - File f = fs.file(ns('/foo'))..createSync(); - DateTime after = ceil(); - DateTime accessed = f.lastAccessedSync(); + var before = downstairs(); + var f = fs.file(ns('/foo'))..createSync(); + var after = ceil(); + var accessed = f.lastAccessedSync(); expect(accessed, isSameOrAfter(before)); expect(accessed, isSameOrBefore(after)); }); @@ -1638,18 +1637,18 @@ void runCommonTests( }); test('succeedsIfExistsAsLinkToFile', () { - DateTime before = downstairs(); + var before = downstairs(); fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - DateTime after = ceil(); - DateTime accessed = fs.file(ns('/bar')).lastAccessedSync(); + var after = ceil(); + var accessed = fs.file(ns('/bar')).lastAccessedSync(); expect(accessed, isSameOrAfter(before)); expect(accessed, isSameOrBefore(after)); }); }); group('setLastAccessed', () { - final DateTime time = DateTime(1999); + final time = DateTime(1999); test('throwsIfDoesntExist', () { expectFileSystemException(ErrorCodes.ENOENT, () { @@ -1665,13 +1664,13 @@ void runCommonTests( }); test('succeedsIfExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.setLastAccessedSync(time); expect(fs.file(ns('/foo')).lastAccessedSync(), time); }); test('succeedsIfExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); f.setLastAccessedSync(time); expect(fs.file(ns('/bar')).lastAccessedSync(), time); @@ -1680,10 +1679,10 @@ void runCommonTests( group('lastModified', () { test('isNowForNewlyCreatedFile', () { - DateTime before = downstairs(); - File f = fs.file(ns('/foo'))..createSync(); - DateTime after = ceil(); - DateTime modified = f.lastModifiedSync(); + var before = downstairs(); + var f = fs.file(ns('/foo'))..createSync(); + var after = ceil(); + var modified = f.lastModifiedSync(); expect(modified, isSameOrAfter(before)); expect(modified, isSameOrBefore(after)); }); @@ -1702,18 +1701,18 @@ void runCommonTests( }); test('succeedsIfExistsAsLinkToFile', () { - DateTime before = downstairs(); + var before = downstairs(); fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - DateTime after = ceil(); - DateTime modified = fs.file(ns('/bar')).lastModifiedSync(); + var after = ceil(); + var modified = fs.file(ns('/bar')).lastModifiedSync(); expect(modified, isSameOrAfter(before)); expect(modified, isSameOrBefore(after)); }); }); group('setLastModified', () { - final DateTime time = DateTime(1999); + final time = DateTime(1999); test('throwsIfDoesntExist', () { expectFileSystemException(ErrorCodes.ENOENT, () { @@ -1729,13 +1728,13 @@ void runCommonTests( }); test('succeedsIfExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.setLastModifiedSync(time); expect(fs.file(ns('/foo')).lastModifiedSync(), time); }); test('succeedsIfExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); f.setLastModifiedSync(time); expect(fs.file(ns('/bar')).lastModifiedSync(), time); @@ -1752,7 +1751,7 @@ void runCommonTests( }); } else { test('createsFileIfDoesntExistAtTail', () { - RandomAccessFile raf = fs.file(ns('/bar')).openSync(mode: mode); + var raf = fs.file(ns('/bar')).openSync(mode: mode); raf.closeSync(); expect(fs.file(ns('/bar')), exists); }); @@ -1877,39 +1876,39 @@ void runCommonTests( }); test('readIntoWithBufferLargerThanContent', () { - List buffer = List.filled(1024, 0); - int numRead = raf.readIntoSync(buffer); + var buffer = List.filled(1024, 0); + var numRead = raf.readIntoSync(buffer); expect(numRead, 21); expect(utf8.decode(buffer.sublist(0, 21)), 'pre-existing content\n'); }); test('readIntoWithBufferSmallerThanContent', () { - List buffer = List.filled(10, 0); - int numRead = raf.readIntoSync(buffer); + var buffer = List.filled(10, 0); + var numRead = raf.readIntoSync(buffer); expect(numRead, 10); expect(utf8.decode(buffer), 'pre-existi'); }); test('readIntoWithStart', () { - List buffer = List.filled(10, 0); - int numRead = raf.readIntoSync(buffer, 2); + var buffer = List.filled(10, 0); + var numRead = raf.readIntoSync(buffer, 2); expect(numRead, 8); expect(utf8.decode(buffer.sublist(2)), 'pre-exis'); }); test('readIntoWithStartAndEnd', () { - List buffer = List.filled(10, 0); - int numRead = raf.readIntoSync(buffer, 2, 5); + var buffer = List.filled(10, 0); + var numRead = raf.readIntoSync(buffer, 2, 5); expect(numRead, 3); expect(utf8.decode(buffer.sublist(2, 5)), 'pre'); }); test('openReadHandleDoesNotChange', () { - final String initial = utf8.decode(raf.readSync(4)); + final initial = utf8.decode(raf.readSync(4)); expect(initial, 'pre-'); - final File newFile = f.renameSync(ns('/bar')); - String rest = utf8.decode(raf.readSync(1024)); + final newFile = f.renameSync(ns('/bar')); + var rest = utf8.decode(raf.readSync(1024)); expect(rest, 'existing content\n'); assert(newFile.path != f.path); @@ -1942,13 +1941,13 @@ void runCommonTests( }); } else { test('lengthGrowsAsDataIsWritten', () { - int lengthBefore = f.lengthSync(); + var lengthBefore = f.lengthSync(); raf.writeByteSync(0xFACE); expect(raf.lengthSync(), lengthBefore + 1); }); test('flush', () { - int lengthBefore = f.lengthSync(); + var lengthBefore = f.lengthSync(); raf.writeByteSync(0xFACE); raf.flushSync(); expect(f.lengthSync(), lengthBefore + 1); @@ -2009,10 +2008,10 @@ void runCommonTests( test('openWriteHandleDoesNotChange', () { raf.writeStringSync('Hello '); - final File newFile = f.renameSync(ns('/bar')); + final newFile = f.renameSync(ns('/bar')); raf.writeStringSync('world'); - final String contents = newFile.readAsStringSync(); + final contents = newFile.readAsStringSync(); if (mode == FileMode.write || mode == FileMode.writeOnly) { expect(contents, 'Hello world'); } else { @@ -2067,7 +2066,7 @@ void runCommonTests( }); } else { test('growsAfterWrite', () { - int positionBefore = raf.positionSync(); + var positionBefore = raf.positionSync(); raf.writeStringSync('Hello world'); expect(raf.positionSync(), positionBefore + 11); }); @@ -2165,42 +2164,42 @@ void runCommonTests( group('openRead', () { test('throwsIfDoesntExist', () { - Stream> stream = fs.file(ns('/foo')).openRead(); + var stream = fs.file(ns('/foo')).openRead(); expect(stream.drain(), throwsFileSystemException(ErrorCodes.ENOENT)); }); test('succeedsIfExistsAsFile', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world', flush: true); - Stream> stream = f.openRead(); - List> data = await stream.toList(); + var stream = f.openRead(); + var data = await stream.toList(); expect(data, hasLength(1)); expect(utf8.decode(data[0]), 'Hello world'); }); test('throwsIfExistsAsDirectory', () { fs.directory(ns('/foo')).createSync(); - Stream> stream = fs.file(ns('/foo')).openRead(); + var stream = fs.file(ns('/foo')).openRead(); expect(stream.drain(), throwsFileSystemException(ErrorCodes.EISDIR)); }); test('succeedsIfExistsAsLinkToFile', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); f.writeAsStringSync('Hello world', flush: true); - Stream> stream = fs.file(ns('/bar')).openRead(); - List> data = await stream.toList(); + var stream = fs.file(ns('/bar')).openRead(); + var data = await stream.toList(); expect(data, hasLength(1)); expect(utf8.decode(data[0]), 'Hello world'); }); test('respectsStartAndEndParameters', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world', flush: true); - Stream> stream = f.openRead(2); - List> data = await stream.toList(); + var stream = f.openRead(2); + var data = await stream.toList(); expect(data, hasLength(1)); expect(utf8.decode(data[0]), 'llo world'); stream = f.openRead(2, 5); @@ -2210,24 +2209,24 @@ void runCommonTests( }); test('throwsIfStartParameterIsNegative', () async { - File f = fs.file(ns('/foo'))..createSync(); - Stream> stream = f.openRead(-2); + var f = fs.file(ns('/foo'))..createSync(); + var stream = f.openRead(-2); expect(stream.drain(), throwsRangeError); }); test('stopsAtEndOfFileIfEndParameterIsPastEndOfFile', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world', flush: true); - Stream> stream = f.openRead(2, 1024); - List> data = await stream.toList(); + var stream = f.openRead(2, 1024); + var data = await stream.toList(); expect(data, hasLength(1)); expect(utf8.decode(data[0]), 'llo world'); }); test('providesSingleSubscriptionStream', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world', flush: true); - Stream> stream = f.openRead(); + var stream = f.openRead(); expect(stream.isBroadcast, isFalse); await stream.drain(); }); @@ -2237,20 +2236,20 @@ void runCommonTests( // split across multiple chunks in the [Stream]. However, there // doesn't seem to be a good way to determine the chunk size used by // [io.File]. - final List data = List.generate( + final data = List.generate( 1024 * 256, (int index) => index & 0xFF, growable: false, ); - final File f = fs.file(ns('/foo'))..createSync(); + final f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync(data, flush: true); - final Stream> stream = f.openRead(); + final stream = f.openRead(); File? newFile; List? initialChunk; - final List remainingChunks = []; + final remainingChunks = []; await for (List chunk in stream) { if (initialChunk == null) { @@ -2276,7 +2275,7 @@ void runCommonTests( test('openReadCompatibleWithUtf8Decoder', () async { const content = 'Hello world!'; - File file = fs.file(ns('/foo')) + var file = fs.file(ns('/foo')) ..createSync() ..writeAsStringSync(content); expect( @@ -2315,8 +2314,8 @@ void runCommonTests( }); test('succeedsIfExistsAsEmptyFile', () async { - File f = fs.file(ns('/foo'))..createSync(); - IOSink sink = f.openWrite(); + var f = fs.file(ns('/foo'))..createSync(); + var sink = f.openWrite(); sink.write('Hello world'); await sink.flush(); await sink.close(); @@ -2326,7 +2325,7 @@ void runCommonTests( test('succeedsIfExistsAsLinkToFile', () async { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - IOSink sink = fs.file(ns('/bar')).openWrite(); + var sink = fs.file(ns('/bar')).openWrite(); sink.write('Hello world'); await sink.flush(); await sink.close(); @@ -2334,9 +2333,9 @@ void runCommonTests( }); test('overwritesContentInWriteMode', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello'); - IOSink sink = f.openWrite(); + var sink = f.openWrite(); sink.write('Goodbye'); await sink.flush(); await sink.close(); @@ -2344,9 +2343,9 @@ void runCommonTests( }); test('appendsContentInAppendMode', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello'); - IOSink sink = f.openWrite(mode: FileMode.append); + var sink = f.openWrite(mode: FileMode.append); sink.write('Goodbye'); await sink.flush(); await sink.close(); @@ -2354,12 +2353,12 @@ void runCommonTests( }); test('openWriteHandleDoesNotChange', () async { - File f = fs.file(ns('/foo'))..createSync(); - IOSink sink = f.openWrite(); + var f = fs.file(ns('/foo'))..createSync(); + var sink = f.openWrite(); sink.write('Hello'); await sink.flush(); - final File newFile = f.renameSync(ns('/bar')); + final newFile = f.renameSync(ns('/bar')); sink.write('Goodbye'); await sink.flush(); await sink.close(); @@ -2377,7 +2376,7 @@ void runCommonTests( late bool isSinkClosed; Future closeSink() { - Future future = sink.close(); + var future = sink.close(); isSinkClosed = true; return future; } @@ -2448,13 +2447,13 @@ void runCommonTests( test('ignoresCloseAfterAlreadyClosed', () async { sink.write('Hello world'); - Future f1 = closeSink(); - Future f2 = closeSink(); + var f1 = closeSink(); + var f2 = closeSink(); await Future.wait(>[f1, f2]); }); test('returnsAccurateDoneFuture', () async { - bool done = false; + var done = false; // ignore: unawaited_futures sink.done.then((dynamic _) => done = true); expect(done, isFalse); @@ -2469,7 +2468,7 @@ void runCommonTests( late bool isControllerClosed; Future closeController() { - Future future = controller.close(); + var future = controller.close(); isControllerClosed = true; return future; } @@ -2543,7 +2542,7 @@ void runCommonTests( }); test('succeedsIfExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([1, 2, 3, 4]); expect(f.readAsBytesSync(), [1, 2, 3, 4]); }); @@ -2556,12 +2555,12 @@ void runCommonTests( }); test('returnsEmptyListForZeroByteFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expect(f.readAsBytesSync(), isEmpty); }); test('returns a copy, not a view, of the file content', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([1, 2, 3, 4]); List result = f.readAsBytesSync(); expect(result, [1, 2, 3, 4]); @@ -2593,7 +2592,7 @@ void runCommonTests( }); test('succeedsIfExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world'); expect(f.readAsStringSync(), 'Hello world'); }); @@ -2606,14 +2605,14 @@ void runCommonTests( }); test('returnsEmptyStringForZeroByteFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expect(f.readAsStringSync(), isEmpty); }); }); group('readAsLines', () { - const String testString = 'Hello world\nHow are you?\nI am fine'; - final List expectedLines = [ + const testString = 'Hello world\nHow are you?\nI am fine'; + final expectedLines = [ 'Hello world', 'How are you?', 'I am fine', @@ -2641,25 +2640,25 @@ void runCommonTests( }); test('succeedsIfExistsAsFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync(testString); expect(f.readAsLinesSync(), expectedLines); }); test('succeedsIfExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); f.writeAsStringSync(testString); expect(f.readAsLinesSync(), expectedLines); }); test('returnsEmptyListForZeroByteFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expect(f.readAsLinesSync(), isEmpty); }); test('isTrailingNewlineAgnostic', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('$testString\n'); expect(f.readAsLinesSync(), expectedLines); @@ -2677,7 +2676,7 @@ void runCommonTests( }); test('createsFileIfDoesntExist', () { - File f = fs.file(ns('/foo')); + var f = fs.file(ns('/foo')); expect(f, isNot(exists)); f.writeAsBytesSync([1, 2, 3, 4]); expect(f, exists); @@ -2699,21 +2698,21 @@ void runCommonTests( }); test('succeedsIfExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); fs.file(ns('/bar')).writeAsBytesSync([1, 2, 3, 4]); expect(f.readAsBytesSync(), [1, 2, 3, 4]); }); test('throwsIfFileModeRead', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.EBADF, () { f.writeAsBytesSync([1], mode: FileMode.read); }); }); test('overwritesContentIfFileModeWrite', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([1, 2]); expect(f.readAsBytesSync(), [1, 2]); f.writeAsBytesSync([3, 4]); @@ -2721,7 +2720,7 @@ void runCommonTests( }); test('appendsContentIfFileModeAppend', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([1, 2], mode: FileMode.append); expect(f.readAsBytesSync(), [1, 2]); f.writeAsBytesSync([3, 4], mode: FileMode.append); @@ -2729,17 +2728,17 @@ void runCommonTests( }); test('acceptsEmptyBytesList', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsBytesSync([]); expect(f.readAsBytesSync(), []); }); test('updatesLastModifiedTime', () async { - File f = fs.file(ns('/foo'))..createSync(); - DateTime before = f.statSync().modified; + var f = fs.file(ns('/foo'))..createSync(); + var before = f.statSync().modified; await Future.delayed(const Duration(seconds: 2)); f.writeAsBytesSync([1, 2, 3]); - DateTime after = f.statSync().modified; + var after = f.statSync().modified; expect(after, isAfter(before)); }); }); @@ -2750,7 +2749,7 @@ void runCommonTests( }); test('createsFileIfDoesntExist', () { - File f = fs.file(ns('/foo')); + var f = fs.file(ns('/foo')); expect(f, isNot(exists)); f.writeAsStringSync('Hello world'); expect(f, exists); @@ -2772,21 +2771,21 @@ void runCommonTests( }); test('succeedsIfExistsAsLinkToFile', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); fs.file(ns('/bar')).writeAsStringSync('Hello world'); expect(f.readAsStringSync(), 'Hello world'); }); test('throwsIfFileModeRead', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expectFileSystemException(ErrorCodes.EBADF, () { f.writeAsStringSync('Hello world', mode: FileMode.read); }); }); test('overwritesContentIfFileModeWrite', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello world'); expect(f.readAsStringSync(), 'Hello world'); f.writeAsStringSync('Goodbye cruel world'); @@ -2794,7 +2793,7 @@ void runCommonTests( }); test('appendsContentIfFileModeAppend', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync('Hello', mode: FileMode.append); expect(f.readAsStringSync(), 'Hello'); f.writeAsStringSync('Goodbye', mode: FileMode.append); @@ -2802,7 +2801,7 @@ void runCommonTests( }); test('acceptsEmptyString', () { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); f.writeAsStringSync(''); expect(f.readAsStringSync(), isEmpty); }); @@ -2847,38 +2846,38 @@ void runCommonTests( group('stat', () { test('isNotFoundIfDoesntExistAtTail', () { - FileStat stat = fs.file(ns('/foo')).statSync(); + var stat = fs.file(ns('/foo')).statSync(); expect(stat.type, FileSystemEntityType.notFound); }); test('isNotFoundIfDoesntExistViaTraversal', () { - FileStat stat = fs.file(ns('/foo/bar')).statSync(); + var stat = fs.file(ns('/foo/bar')).statSync(); expect(stat.type, FileSystemEntityType.notFound); }); test('isDirectoryIfExistsAsDirectory', () { fs.directory(ns('/foo')).createSync(); - FileStat stat = fs.file(ns('/foo')).statSync(); + var stat = fs.file(ns('/foo')).statSync(); expect(stat.type, FileSystemEntityType.directory); }); test('isFileIfExistsAsFile', () { fs.file(ns('/foo')).createSync(); - FileStat stat = fs.file(ns('/foo')).statSync(); + var stat = fs.file(ns('/foo')).statSync(); expect(stat.type, FileSystemEntityType.file); }); test('isFileIfExistsAsLinkToFile', () { fs.file(ns('/foo')).createSync(); fs.link(ns('/bar')).createSync(ns('/foo')); - FileStat stat = fs.file(ns('/bar')).statSync(); + var stat = fs.file(ns('/bar')).statSync(); expect(stat.type, FileSystemEntityType.file); }); }); group('delete', () { test('returnsCovariantType', () async { - File f = fs.file(ns('/foo'))..createSync(); + var f = fs.file(ns('/foo'))..createSync(); expect(await f.delete(), isFile); }); @@ -2953,14 +2952,14 @@ void runCommonTests( group('uri', () { test('whenTargetIsDirectory', () { fs.directory(ns('/foo')).createSync(); - Link l = fs.link(ns('/bar'))..createSync(ns('/foo')); + var l = fs.link(ns('/bar'))..createSync(ns('/foo')); expect(l.uri, fs.path.toUri(ns('/bar'))); expect(fs.link('bar').uri.toString(), 'bar'); }); test('whenTargetIsFile', () { fs.file(ns('/foo')).createSync(); - Link l = fs.link(ns('/bar'))..createSync(ns('/foo')); + var l = fs.link(ns('/bar'))..createSync(ns('/foo')); expect(l.uri, fs.path.toUri(ns('/bar'))); expect(fs.link('bar').uri.toString(), 'bar'); }); @@ -2991,24 +2990,24 @@ void runCommonTests( }); test('isTrueIfTargetIsNotFound', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(l, exists); }); test('isTrueIfTargetIsFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); expect(l, exists); }); test('isTrueIfTargetIsDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); expect(l, exists); }); test('isTrueIfTargetIsLinkLoop', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/foo')); expect(l, exists); }); @@ -3038,29 +3037,29 @@ void runCommonTests( }); test('isNotFoundIfTargetNotFoundAtTail', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(l.statSync().type, FileSystemEntityType.notFound); }); test('isNotFoundIfTargetNotFoundViaTraversal', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar/baz')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar/baz')); expect(l.statSync().type, FileSystemEntityType.notFound); }); test('isNotFoundIfTargetIsLinkLoop', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/foo')); expect(l.statSync().type, FileSystemEntityType.notFound); }); test('isFileIfTargetIsFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); expect(l.statSync().type, FileSystemEntityType.file); }); test('isDirectoryIfTargetIsDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); expect(l.statSync().type, FileSystemEntityType.directory); }); @@ -3068,7 +3067,7 @@ void runCommonTests( group('delete', () { test('returnsCovariantType', () async { - Link link = fs.link(ns('/foo'))..createSync(ns('/bar')); + var link = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(await link.delete(), isLink); }); @@ -3118,7 +3117,7 @@ void runCommonTests( }); test('unlinksIfTargetIsFileAndRecursiveFalse', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); l.deleteSync(); expect(fs.typeSync(ns('/foo'), followLinks: false), @@ -3128,7 +3127,7 @@ void runCommonTests( }); test('unlinksIfTargetIsFileAndRecursiveTrue', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); l.deleteSync(recursive: true); expect(fs.typeSync(ns('/foo'), followLinks: false), @@ -3138,7 +3137,7 @@ void runCommonTests( }); test('unlinksIfTargetIsDirectoryAndRecursiveFalse', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); l.deleteSync(); expect(fs.typeSync(ns('/foo'), followLinks: false), @@ -3148,7 +3147,7 @@ void runCommonTests( }); test('unlinksIfTargetIsDirectoryAndRecursiveTrue', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); l.deleteSync(recursive: true); expect(fs.typeSync(ns('/foo'), followLinks: false), @@ -3158,7 +3157,7 @@ void runCommonTests( }); test('unlinksIfTargetIsLinkLoop', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/foo')); l.deleteSync(); expect(fs.typeSync(ns('/foo'), followLinks: false), @@ -3178,7 +3177,7 @@ void runCommonTests( }); test('ignoresLinkTarget', () { - Link l = fs.link(ns('/foo/bar')) + var l = fs.link(ns('/foo/bar')) ..createSync(ns('/baz/qux'), recursive: true); expect(l.parent.path, ns('/foo')); }); @@ -3190,7 +3189,7 @@ void runCommonTests( }); test('succeedsIfLinkDoesntExistAtTail', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.link); expect(l.targetSync(), ns('/bar')); @@ -3203,7 +3202,7 @@ void runCommonTests( }); test('succeedsIfLinkDoesntExistViaTraversalAndRecursiveTrue', () { - Link l = fs.link(ns('/foo/bar'))..createSync('baz', recursive: true); + var l = fs.link(ns('/foo/bar'))..createSync('baz', recursive: true); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.directory); expect(fs.typeSync(ns('/foo/bar'), followLinks: false), @@ -3242,7 +3241,7 @@ void runCommonTests( group('update', () { test('returnsCovariantType', () async { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(await l.update(ns('/baz')), isLink); }); @@ -3336,24 +3335,24 @@ void runCommonTests( }); test('succeedsIfTargetIsNotFound', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expect(l.targetSync(), ns('/bar')); }); test('succeedsIfTargetIsFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); expect(l.targetSync(), ns('/bar')); }); test('succeedsIfTargetIsDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); expect(l.targetSync(), ns('/bar')); }); test('succeedsIfTargetIsLinkLoop', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/foo')); expect(l.targetSync(), ns('/bar')); }); @@ -3393,9 +3392,9 @@ void runCommonTests( }); test('succeedsIfSourceIsLinkToFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/bar')).createSync(); - Link renamed = l.renameSync(ns('/baz')); + var renamed = l.renameSync(ns('/baz')); expect(renamed.path, ns('/baz')); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.notFound); @@ -3407,8 +3406,8 @@ void runCommonTests( }); test('succeedsIfSourceIsLinkToNotFound', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); - Link renamed = l.renameSync(ns('/baz')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var renamed = l.renameSync(ns('/baz')); expect(renamed.path, ns('/baz')); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.notFound); @@ -3418,9 +3417,9 @@ void runCommonTests( }); test('succeedsIfSourceIsLinkToDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/bar')).createSync(); - Link renamed = l.renameSync(ns('/baz')); + var renamed = l.renameSync(ns('/baz')); expect(renamed.path, ns('/baz')); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.notFound); @@ -3432,9 +3431,9 @@ void runCommonTests( }); test('succeedsIfSourceIsLinkLoop', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/bar')).createSync(ns('/foo')); - Link renamed = l.renameSync(ns('/baz')); + var renamed = l.renameSync(ns('/baz')); expect(renamed.path, ns('/baz')); expect(fs.typeSync(ns('/foo'), followLinks: false), FileSystemEntityType.notFound); @@ -3446,22 +3445,22 @@ void runCommonTests( }); test('succeedsIfDestinationDoesntExistAtTail', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); - Link renamed = l.renameSync(ns('/baz')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var renamed = l.renameSync(ns('/baz')); expect(renamed.path, ns('/baz')); expect(fs.link(ns('/foo')), isNot(exists)); expect(fs.link(ns('/baz')), exists); }); test('throwsIfDestinationDoesntExistViaTraversal', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); expectFileSystemException(ErrorCodes.ENOENT, () { l.renameSync(ns('/baz/qux')); }); }); test('throwsIfDestinationExistsAsFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/baz')).createSync(); expectFileSystemException(ErrorCodes.EINVAL, () { l.renameSync(ns('/baz')); @@ -3469,7 +3468,7 @@ void runCommonTests( }); test('throwsIfDestinationExistsAsDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/baz')).createSync(); expectFileSystemException(ErrorCodes.EINVAL, () { l.renameSync(ns('/baz')); @@ -3477,7 +3476,7 @@ void runCommonTests( }); test('succeedsIfDestinationExistsAsLinkToFile', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.file(ns('/baz')).createSync(); fs.link(ns('/qux')).createSync(ns('/baz')); l.renameSync(ns('/qux')); @@ -3490,7 +3489,7 @@ void runCommonTests( }); test('throwsIfDestinationExistsAsLinkToDirectory', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.directory(ns('/baz')).createSync(); fs.link(ns('/qux')).createSync(ns('/baz')); l.renameSync(ns('/qux')); @@ -3503,7 +3502,7 @@ void runCommonTests( }); test('succeedsIfDestinationExistsAsLinkToNotFound', () { - Link l = fs.link(ns('/foo'))..createSync(ns('/bar')); + var l = fs.link(ns('/foo'))..createSync(ns('/bar')); fs.link(ns('/baz')).createSync(ns('/qux')); l.renameSync(ns('/baz')); expect(fs.typeSync(ns('/foo')), FileSystemEntityType.notFound); diff --git a/pkgs/file/test/local_test.dart b/pkgs/file/test/local_test.dart index e1618d230..b794ccd7b 100644 --- a/pkgs/file/test/local_test.dart +++ b/pkgs/file/test/local_test.dart @@ -2,7 +2,11 @@ // 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. +// ignore_for_file: lines_longer_than_80_chars + @TestOn('vm') +library; + import 'dart:io' as io; import 'package:file/local.dart'; @@ -33,7 +37,7 @@ void main() { setUpAll(() { if (io.Platform.isWindows) { // TODO(tvolkert): Remove once all more serious test failures are fixed - // https://github.com/google/file.dart/issues/56 + // https://github.com/dart-lang/tools/issues/618 ignoreOsErrorCodes = true; } }); @@ -42,7 +46,7 @@ void main() { ignoreOsErrorCodes = false; }); - Map> skipOnPlatform = >{ + var skipOnPlatform = >{ 'windows': [ 'FileSystem > currentDirectory > throwsIfHasNonExistentPathInComplexChain', 'FileSystem > currentDirectory > resolvesLinksIfEncountered', diff --git a/pkgs/file/test/memory_operations_test.dart b/pkgs/file/test/memory_operations_test.dart index 5e27843b5..916707c62 100644 --- a/pkgs/file/test/memory_operations_test.dart +++ b/pkgs/file/test/memory_operations_test.dart @@ -2,22 +2,21 @@ // 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. -import 'package:file/file.dart'; import 'package:file/memory.dart'; import 'package:test/test.dart'; void main() { test('Read operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.read) { contexts.add(context); operations.add(operation); } }); - final File file = fs.file('test')..createSync(); + final file = fs.file('test')..createSync(); await file.readAsBytes(); file.readAsBytesSync(); @@ -34,16 +33,16 @@ void main() { }); test('Write operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.write) { contexts.add(context); operations.add(operation); } }); - final File file = fs.file('test')..createSync(); + final file = fs.file('test')..createSync(); await file.writeAsBytes([]); file.writeAsBytesSync([]); @@ -60,18 +59,18 @@ void main() { }); test('Delete operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.delete) { contexts.add(context); operations.add(operation); } }); - final File file = fs.file('test')..createSync(); - final Directory directory = fs.directory('testDir')..createSync(); - final Link link = fs.link('testLink')..createSync('foo'); + final file = fs.file('test')..createSync(); + final directory = fs.directory('testDir')..createSync(); + final link = fs.link('testLink')..createSync('foo'); await file.delete(); file.createSync(); @@ -98,9 +97,9 @@ void main() { }); test('Create operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.create) { contexts.add(context); @@ -139,16 +138,16 @@ void main() { }); test('Open operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.open) { contexts.add(context); operations.add(operation); } }); - final File file = fs.file('test')..createSync(); + final file = fs.file('test')..createSync(); await file.open(); file.openSync(); @@ -165,16 +164,16 @@ void main() { }); test('Copy operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.copy) { contexts.add(context); operations.add(operation); } }); - final File file = fs.file('test')..createSync(); + final file = fs.file('test')..createSync(); await file.copy('A'); file.copySync('B'); @@ -187,9 +186,9 @@ void main() { }); test('Exists operations invoke opHandle', () async { - List contexts = []; - List operations = []; - MemoryFileSystem fs = MemoryFileSystem.test( + var contexts = []; + var operations = []; + var fs = MemoryFileSystem.test( opHandle: (String context, FileSystemOp operation) { if (operation == FileSystemOp.exists) { contexts.add(context); diff --git a/pkgs/file/test/memory_test.dart b/pkgs/file/test/memory_test.dart index f3b324e6c..ce8675f2e 100644 --- a/pkgs/file/test/memory_test.dart +++ b/pkgs/file/test/memory_test.dart @@ -66,8 +66,7 @@ void main() { }); test('MemoryFileSystem.test', () { - final MemoryFileSystem fs = - MemoryFileSystem.test(); // creates root directory + final fs = MemoryFileSystem.test(); // creates root directory fs.file('/test1.txt').createSync(); // creates file fs.file('/test2.txt').createSync(); // creates file expect(fs.directory('/').statSync().modified, DateTime(2000, 1, 1, 0, 1)); @@ -95,10 +94,10 @@ void main() { }); test('MemoryFile.openSync returns a MemoryRandomAccessFile', () async { - final MemoryFileSystem fs = MemoryFileSystem.test(); + final fs = MemoryFileSystem.test(); final io.File file = fs.file('/test1')..createSync(); - io.RandomAccessFile raf = file.openSync(); + var raf = file.openSync(); try { expect(raf, isA()); } finally { @@ -114,7 +113,7 @@ void main() { }); test('MemoryFileSystem.systemTempDirectory test', () { - final MemoryFileSystem fs = MemoryFileSystem.test(); + final fs = MemoryFileSystem.test(); final io.Directory fooA = fs.systemTempDirectory.createTempSync('foo'); final io.Directory fooB = fs.systemTempDirectory.createTempSync('foo'); @@ -122,7 +121,7 @@ void main() { expect(fooA.path, '/.tmp_rand0/foorand0'); expect(fooB.path, '/.tmp_rand0/foorand1'); - final MemoryFileSystem secondFs = MemoryFileSystem.test(); + final secondFs = MemoryFileSystem.test(); final io.Directory fooAA = secondFs.systemTempDirectory.createTempSync('foo'); @@ -136,16 +135,16 @@ void main() { test('Failed UTF8 decoding in MemoryFileSystem throws a FileSystemException', () { - final MemoryFileSystem fileSystem = MemoryFileSystem.test(); - final File file = fileSystem.file('foo') + final fileSystem = MemoryFileSystem.test(); + final file = fileSystem.file('foo') ..writeAsBytesSync([0xFFFE]); // Invalid UTF8 expect(file.readAsStringSync, throwsA(isA())); }); test('Creating a temporary directory actually creates the directory', () { - final MemoryFileSystem fileSystem = MemoryFileSystem.test(); - final Directory tempDir = fileSystem.currentDirectory.createTempSync('foo'); + final fileSystem = MemoryFileSystem.test(); + final tempDir = fileSystem.currentDirectory.createTempSync('foo'); expect(tempDir.existsSync(), true); }); diff --git a/pkgs/file/test/utils.dart b/pkgs/file/test/utils.dart index 231312fbe..797ec9de5 100644 --- a/pkgs/file/test/utils.dart +++ b/pkgs/file/test/utils.dart @@ -25,7 +25,7 @@ DateTime floor([DateTime? time]) { /// If [time] is not specified, it will default to the current time. DateTime ceil([DateTime? time]) { time ??= DateTime.now(); - int microseconds = (1000 * time.millisecond) + time.microsecond; + var microseconds = (1000 * time.millisecond) + time.microsecond; return (microseconds == 0) ? time // Add just enough milliseconds and microseconds to reach the next second. @@ -78,7 +78,7 @@ abstract class _CompareDateTime extends Matcher { bool verbose, ) { if (item is DateTime) { - Duration diff = item.difference(_time).abs(); + var diff = item.difference(_time).abs(); return description.add('is $mismatchAdjective $_time by $diff'); } else { return description.add('is not a DateTime'); diff --git a/pkgs/file/test/utils_test.dart b/pkgs/file/test/utils_test.dart index 75293bf3c..23788e983 100644 --- a/pkgs/file/test/utils_test.dart +++ b/pkgs/file/test/utils_test.dart @@ -8,9 +8,9 @@ import 'utils.dart'; void main() { test('floorAndCeilProduceExactSecondDateTime', () { - DateTime time = DateTime.fromMicrosecondsSinceEpoch(1001); - DateTime lower = floor(time); - DateTime upper = ceil(time); + var time = DateTime.fromMicrosecondsSinceEpoch(1001); + var lower = floor(time); + var upper = ceil(time); expect(lower.millisecond, 0); expect(upper.millisecond, 0); expect(lower.microsecond, 0); @@ -18,26 +18,26 @@ void main() { }); test('floorAndCeilWorkWithNow', () { - DateTime time = DateTime.now(); - int lower = time.difference(floor(time)).inMicroseconds; - int upper = ceil(time).difference(time).inMicroseconds; + var time = DateTime.now(); + var lower = time.difference(floor(time)).inMicroseconds; + var upper = ceil(time).difference(time).inMicroseconds; expect(lower, lessThan(1000000)); expect(upper, lessThanOrEqualTo(1000000)); }); test('floorAndCeilWorkWithExactSecondDateTime', () { - DateTime time = DateTime.parse('1999-12-31 23:59:59'); - DateTime lower = floor(time); - DateTime upper = ceil(time); + var time = DateTime.parse('1999-12-31 23:59:59'); + var lower = floor(time); + var upper = ceil(time); expect(lower, time); expect(upper, time); }); test('floorAndCeilWorkWithInexactSecondDateTime', () { - DateTime time = DateTime.parse('1999-12-31 23:59:59.500'); - DateTime lower = floor(time); - DateTime upper = ceil(time); - Duration difference = upper.difference(lower); + var time = DateTime.parse('1999-12-31 23:59:59.500'); + var lower = floor(time); + var upper = ceil(time); + var difference = upper.difference(lower); expect(difference.inMicroseconds, 1000000); }); } From 71c9cc10e7d74bd0d408c2c669f5861a3bc9871f Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Fri, 13 Dec 2024 19:33:07 -0600 Subject: [PATCH 1209/1215] Bump dart_flutter_team lints to latest across packages (#1679) --- .github/workflows/bazel_worker.yaml | 2 + pkgs/bazel_worker/benchmark/benchmark.dart | 19 +- .../e2e_test/bin/async_worker_in_isolate.dart | 5 +- .../e2e_test/lib/async_worker.dart | 5 +- .../lib/forwards_to_isolate_async_worker.dart | 6 +- pkgs/bazel_worker/e2e_test/pubspec.yaml | 2 +- pkgs/bazel_worker/e2e_test/test/e2e_test.dart | 18 +- pkgs/bazel_worker/example/client.dart | 12 +- .../lib/src/async_message_grouper.dart | 17 +- pkgs/bazel_worker/lib/src/driver/driver.dart | 104 ++++++----- .../lib/src/driver/driver_connection.dart | 11 +- pkgs/bazel_worker/lib/src/utils.dart | 5 +- .../lib/src/worker/async_worker_loop.dart | 20 +- .../lib/src/worker/sync_worker_loop.dart | 19 +- .../lib/src/worker/worker_connection.dart | 20 +- pkgs/bazel_worker/lib/testing.dart | 21 ++- pkgs/bazel_worker/test/driver_test.dart | 174 +++++++++++------- .../test/message_grouper_test.dart | 93 ++++------ pkgs/bazel_worker/test/worker_loop_test.dart | 67 ++++--- pkgs/clock/analysis_options.yaml | 1 - pkgs/coverage/analysis_options.yaml | 5 - pkgs/test_reflective_loader/pubspec.yaml | 2 +- 22 files changed, 360 insertions(+), 268 deletions(-) diff --git a/.github/workflows/bazel_worker.yaml b/.github/workflows/bazel_worker.yaml index 0eb06dad7..29c0a0d07 100644 --- a/.github/workflows/bazel_worker.yaml +++ b/.github/workflows/bazel_worker.yaml @@ -36,6 +36,8 @@ jobs: - uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 with: sdk: ${{ matrix.sdk }} + - run: dart pub get - run: "dart format --output=none --set-exit-if-changed ." + if: ${{ matrix.sdk == dev }} - name: Test run: ./tool/travis.sh diff --git a/pkgs/bazel_worker/benchmark/benchmark.dart b/pkgs/bazel_worker/benchmark/benchmark.dart index 035e2b848..0a0312203 100644 --- a/pkgs/bazel_worker/benchmark/benchmark.dart +++ b/pkgs/bazel_worker/benchmark/benchmark.dart @@ -12,10 +12,7 @@ Future main() async { var path = 'blaze-bin/some/path/to/a/file/that/is/an/input/$i'; workRequest ..arguments.add('--input=$path') - ..inputs.add(Input( - path: '', - digest: List.filled(70, 0x11), - )); + ..inputs.add(Input(path: '', digest: List.filled(70, 0x11))); } // Serialize it. @@ -24,14 +21,20 @@ Future main() async { print('Request has $length requestBytes.'); // Add the length in front base 128 encoded as in the worker protocol. - requestBytes = - Uint8List.fromList(requestBytes.toList()..insertAll(0, _varInt(length))); + requestBytes = Uint8List.fromList( + requestBytes.toList()..insertAll(0, _varInt(length)), + ); // Split into 10000 byte chunks. var lists = []; for (var i = 0; i < requestBytes.length; i += 10000) { - lists.add(Uint8List.sublistView( - requestBytes, i, min(i + 10000, requestBytes.length))); + lists.add( + Uint8List.sublistView( + requestBytes, + i, + min(i + 10000, requestBytes.length), + ), + ); } // Time `AsyncMessageGrouper` and deserialization. diff --git a/pkgs/bazel_worker/e2e_test/bin/async_worker_in_isolate.dart b/pkgs/bazel_worker/e2e_test/bin/async_worker_in_isolate.dart index a94875d57..285b03d2a 100644 --- a/pkgs/bazel_worker/e2e_test/bin/async_worker_in_isolate.dart +++ b/pkgs/bazel_worker/e2e_test/bin/async_worker_in_isolate.dart @@ -17,7 +17,10 @@ import 'package:e2e_test/forwards_to_isolate_async_worker.dart'; Future main(List args, [SendPort? message]) async { var receivePort = ReceivePort(); await Isolate.spawnUri( - Uri.file('async_worker.dart'), [], receivePort.sendPort); + Uri.file('async_worker.dart'), + [], + receivePort.sendPort, + ); var worker = await ForwardsToIsolateAsyncWorker.create(receivePort); await worker.run(); diff --git a/pkgs/bazel_worker/e2e_test/lib/async_worker.dart b/pkgs/bazel_worker/e2e_test/lib/async_worker.dart index d48d87c8d..55f517134 100644 --- a/pkgs/bazel_worker/e2e_test/lib/async_worker.dart +++ b/pkgs/bazel_worker/e2e_test/lib/async_worker.dart @@ -16,9 +16,6 @@ class ExampleAsyncWorker extends AsyncWorkerLoop { @override Future performRequest(WorkRequest request) async { - return WorkResponse( - exitCode: 0, - output: request.arguments.join('\n'), - ); + return WorkResponse(exitCode: 0, output: request.arguments.join('\n')); } } diff --git a/pkgs/bazel_worker/e2e_test/lib/forwards_to_isolate_async_worker.dart b/pkgs/bazel_worker/e2e_test/lib/forwards_to_isolate_async_worker.dart index bb937b220..a4845cf9e 100644 --- a/pkgs/bazel_worker/e2e_test/lib/forwards_to_isolate_async_worker.dart +++ b/pkgs/bazel_worker/e2e_test/lib/forwards_to_isolate_async_worker.dart @@ -13,9 +13,11 @@ class ForwardsToIsolateAsyncWorker extends AsyncWorkerLoop { final IsolateDriverConnection _isolateDriverConnection; static Future create( - ReceivePort receivePort) async { + ReceivePort receivePort, + ) async { return ForwardsToIsolateAsyncWorker( - await IsolateDriverConnection.create(receivePort)); + await IsolateDriverConnection.create(receivePort), + ); } ForwardsToIsolateAsyncWorker(this._isolateDriverConnection); diff --git a/pkgs/bazel_worker/e2e_test/pubspec.yaml b/pkgs/bazel_worker/e2e_test/pubspec.yaml index 56f00cd4c..7eaa89a16 100644 --- a/pkgs/bazel_worker/e2e_test/pubspec.yaml +++ b/pkgs/bazel_worker/e2e_test/pubspec.yaml @@ -10,6 +10,6 @@ dependencies: dev_dependencies: cli_util: ^0.4.2 - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^3.0.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/bazel_worker/e2e_test/test/e2e_test.dart b/pkgs/bazel_worker/e2e_test/test/e2e_test.dart index caa813a46..6b79b5edb 100644 --- a/pkgs/bazel_worker/e2e_test/test/e2e_test.dart +++ b/pkgs/bazel_worker/e2e_test/test/e2e_test.dart @@ -12,14 +12,18 @@ import 'package:test/test.dart'; void main() { var dart = p.join(sdkPath, 'bin', 'dart'); - runE2eTestForWorker('sync worker', - () => Process.start(dart, [p.join('bin', 'sync_worker.dart')])); - runE2eTestForWorker('async worker', - () => Process.start(dart, [p.join('bin', 'async_worker.dart')])); runE2eTestForWorker( - 'async worker in isolate', - () => - Process.start(dart, [p.join('bin', 'async_worker_in_isolate.dart')])); + 'sync worker', + () => Process.start(dart, [p.join('bin', 'sync_worker.dart')]), + ); + runE2eTestForWorker( + 'async worker', + () => Process.start(dart, [p.join('bin', 'async_worker.dart')]), + ); + runE2eTestForWorker( + 'async worker in isolate', + () => Process.start(dart, [p.join('bin', 'async_worker_in_isolate.dart')]), + ); } void runE2eTestForWorker(String groupName, SpawnWorker spawnWorker) { diff --git a/pkgs/bazel_worker/example/client.dart b/pkgs/bazel_worker/example/client.dart index 7147fcbf0..326bb180b 100644 --- a/pkgs/bazel_worker/example/client.dart +++ b/pkgs/bazel_worker/example/client.dart @@ -5,10 +5,14 @@ import 'package:bazel_worker/driver.dart'; void main() async { var scratchSpace = await Directory.systemTemp.createTemp(); var driver = BazelWorkerDriver( - () => Process.start(Platform.resolvedExecutable, - [Platform.script.resolve('worker.dart').toFilePath()], - workingDirectory: scratchSpace.path), - maxWorkers: 4); + () => Process.start( + Platform.resolvedExecutable, + [ + Platform.script.resolve('worker.dart').toFilePath(), + ], + workingDirectory: scratchSpace.path), + maxWorkers: 4, + ); var response = await driver.doWork(WorkRequest(arguments: ['foo'])); if (response.exitCode != EXIT_CODE_OK) { print('Worker request failed'); diff --git a/pkgs/bazel_worker/lib/src/async_message_grouper.dart b/pkgs/bazel_worker/lib/src/async_message_grouper.dart index e1f0deaef..8fc47780a 100644 --- a/pkgs/bazel_worker/lib/src/async_message_grouper.dart +++ b/pkgs/bazel_worker/lib/src/async_message_grouper.dart @@ -86,13 +86,18 @@ class AsyncMessageGrouper implements MessageGrouper { // Copy as much as possible from the input buffer. Limit is the // smaller of the remaining length to fill in the message and the // remaining length in the buffer. - var lengthToCopy = min(_message.length - _messagePos, - _inputBuffer.length - _inputBufferPos); + var lengthToCopy = min( + _message.length - _messagePos, + _inputBuffer.length - _inputBufferPos, + ); _message.setRange( - _messagePos, - _messagePos + lengthToCopy, - _inputBuffer.sublist( - _inputBufferPos, _inputBufferPos + lengthToCopy)); + _messagePos, + _messagePos + lengthToCopy, + _inputBuffer.sublist( + _inputBufferPos, + _inputBufferPos + lengthToCopy, + ), + ); _messagePos += lengthToCopy; _inputBufferPos += lengthToCopy; diff --git a/pkgs/bazel_worker/lib/src/driver/driver.dart b/pkgs/bazel_worker/lib/src/driver/driver.dart index 4a780208a..06cf0feb1 100644 --- a/pkgs/bazel_worker/lib/src/driver/driver.dart +++ b/pkgs/bazel_worker/lib/src/driver/driver.dart @@ -44,9 +44,12 @@ class BazelWorkerDriver { /// Factory method that spawns a worker process. final SpawnWorker _spawnWorker; - BazelWorkerDriver(this._spawnWorker, - {int? maxIdleWorkers, int? maxWorkers, int? maxRetries}) - : _maxIdleWorkers = maxIdleWorkers ?? 4, + BazelWorkerDriver( + this._spawnWorker, { + int? maxIdleWorkers, + int? maxWorkers, + int? maxRetries, + }) : _maxIdleWorkers = maxIdleWorkers ?? 4, _maxWorkers = maxWorkers ?? 4, _maxRetries = maxRetries ?? 4; @@ -56,8 +59,10 @@ class BazelWorkerDriver { /// [request] has been actually sent to the worker. This allows the caller /// to determine when actual work is being done versus just waiting for an /// available worker. - Future doWork(WorkRequest request, - {void Function(Future)? trackWork}) { + Future doWork( + WorkRequest request, { + void Function(Future)? trackWork, + }) { var attempt = _WorkAttempt(request, trackWork: trackWork); _workQueue.add(attempt); _runWorkQueue(); @@ -69,9 +74,11 @@ class BazelWorkerDriver { for (var worker in _readyWorkers.toList()) { _killWorker(worker); } - await Future.wait(_spawningWorkers.map((worker) async { - _killWorker(await worker); - })); + await Future.wait( + _spawningWorkers.map((worker) async { + _killWorker(await worker); + }), + ); } /// Runs as many items in [_workQueue] as possible given the number of @@ -88,8 +95,10 @@ class BazelWorkerDriver { if (_workQueue.isEmpty) return; if (_numWorkers == _maxWorkers && _idleWorkers.isEmpty) return; if (_numWorkers > _maxWorkers) { - throw StateError('Internal error, created to many workers. Please ' - 'file a bug at https://github.com/dart-lang/bazel_worker/issues/new'); + throw StateError( + 'Internal error, created to many workers. Please ' + 'file a bug at https://github.com/dart-lang/bazel_worker/issues/new', + ); } // At this point we definitely want to run a task, we just need to decide @@ -137,48 +146,51 @@ class BazelWorkerDriver { void _runWorker(Process worker, _WorkAttempt attempt) { var rescheduled = false; - runZonedGuarded(() async { - var connection = _workerConnections[worker]!; + runZonedGuarded( + () async { + var connection = _workerConnections[worker]!; - connection.writeRequest(attempt.request); - var responseFuture = connection.readResponse(); - if (attempt.trackWork != null) { - attempt.trackWork!(responseFuture); - } - var response = await responseFuture; - - // It is possible for us to complete with an error response due to an - // unhandled async error before we get here. - if (!attempt.responseCompleter.isCompleted) { - if (response.exitCode == EXIT_CODE_BROKEN_PIPE) { + connection.writeRequest(attempt.request); + var responseFuture = connection.readResponse(); + if (attempt.trackWork != null) { + attempt.trackWork!(responseFuture); + } + var response = await responseFuture; + + // It is possible for us to complete with an error response due to an + // unhandled async error before we get here. + if (!attempt.responseCompleter.isCompleted) { + if (response.exitCode == EXIT_CODE_BROKEN_PIPE) { + rescheduled = _tryReschedule(attempt); + if (rescheduled) return; + stderr.writeln('Failed to run request ${attempt.request}'); + response = WorkResponse( + exitCode: EXIT_CODE_ERROR, + output: + 'Invalid response from worker, this probably means it wrote ' + 'invalid output or died.', + ); + } + attempt.responseCompleter.complete(response); + _cleanUp(worker); + } + }, + (e, s) { + // Note that we don't need to do additional cleanup here on failures. If + // the worker dies that is already handled in a generic fashion, we just + // need to make sure we complete with a valid response. + if (!attempt.responseCompleter.isCompleted) { rescheduled = _tryReschedule(attempt); if (rescheduled) return; - stderr.writeln('Failed to run request ${attempt.request}'); - response = WorkResponse( + var response = WorkResponse( exitCode: EXIT_CODE_ERROR, - output: - 'Invalid response from worker, this probably means it wrote ' - 'invalid output or died.', + output: 'Error running worker:\n$e\n$s', ); + attempt.responseCompleter.complete(response); + _cleanUp(worker); } - attempt.responseCompleter.complete(response); - _cleanUp(worker); - } - }, (e, s) { - // Note that we don't need to do additional cleanup here on failures. If - // the worker dies that is already handled in a generic fashion, we just - // need to make sure we complete with a valid response. - if (!attempt.responseCompleter.isCompleted) { - rescheduled = _tryReschedule(attempt); - if (rescheduled) return; - var response = WorkResponse( - exitCode: EXIT_CODE_ERROR, - output: 'Error running worker:\n$e\n$s', - ); - attempt.responseCompleter.complete(response); - _cleanUp(worker); - } - }); + }, + ); } /// Performs post-work cleanup for [worker]. diff --git a/pkgs/bazel_worker/lib/src/driver/driver_connection.dart b/pkgs/bazel_worker/lib/src/driver/driver_connection.dart index b419debbc..80d5c98cf 100644 --- a/pkgs/bazel_worker/lib/src/driver/driver_connection.dart +++ b/pkgs/bazel_worker/lib/src/driver/driver_connection.dart @@ -34,13 +34,16 @@ class StdDriverConnection implements DriverConnection { Future get done => _messageGrouper.done; - StdDriverConnection( - {Stream>? inputStream, StreamSink>? outputStream}) - : _messageGrouper = AsyncMessageGrouper(inputStream ?? stdin), + StdDriverConnection({ + Stream>? inputStream, + StreamSink>? outputStream, + }) : _messageGrouper = AsyncMessageGrouper(inputStream ?? stdin), _outputStream = outputStream ?? stdout; factory StdDriverConnection.forWorker(Process worker) => StdDriverConnection( - inputStream: worker.stdout, outputStream: worker.stdin); + inputStream: worker.stdout, + outputStream: worker.stdin, + ); /// Note: This will attempts to recover from invalid proto messages by parsing /// them as strings. This is a common error case for workers (they print a diff --git a/pkgs/bazel_worker/lib/src/utils.dart b/pkgs/bazel_worker/lib/src/utils.dart index 609b4356a..f67bbac1e 100644 --- a/pkgs/bazel_worker/lib/src/utils.dart +++ b/pkgs/bazel_worker/lib/src/utils.dart @@ -13,8 +13,9 @@ List protoToDelimitedBuffer(GeneratedMessage message) { var delimiterBuffer = CodedBufferWriter(); delimiterBuffer.writeInt32NoTag(messageBuffer.lengthInBytes); - var result = - Uint8List(messageBuffer.lengthInBytes + delimiterBuffer.lengthInBytes); + var result = Uint8List( + messageBuffer.lengthInBytes + delimiterBuffer.lengthInBytes, + ); delimiterBuffer.writeTo(result); messageBuffer.writeTo(result, delimiterBuffer.lengthInBytes); diff --git a/pkgs/bazel_worker/lib/src/worker/async_worker_loop.dart b/pkgs/bazel_worker/lib/src/worker/async_worker_loop.dart index 5182b5598..a95d09a1f 100644 --- a/pkgs/bazel_worker/lib/src/worker/async_worker_loop.dart +++ b/pkgs/bazel_worker/lib/src/worker/async_worker_loop.dart @@ -32,20 +32,20 @@ abstract class AsyncWorkerLoop implements WorkerLoop { var request = await connection.readRequest(); if (request == null) break; var printMessages = StringBuffer(); - response = await runZoned(() => performRequest(request), - zoneSpecification: - ZoneSpecification(print: (self, parent, zone, message) { - printMessages.writeln(); - printMessages.write(message); - })); + response = await runZoned( + () => performRequest(request), + zoneSpecification: ZoneSpecification( + print: (self, parent, zone, message) { + printMessages.writeln(); + printMessages.write(message); + }, + ), + ); if (printMessages.isNotEmpty) { response.output = '${response.output}$printMessages'; } } catch (e, s) { - response = WorkResponse( - exitCode: EXIT_CODE_ERROR, - output: '$e\n$s', - ); + response = WorkResponse(exitCode: EXIT_CODE_ERROR, output: '$e\n$s'); } connection.writeResponse(response); diff --git a/pkgs/bazel_worker/lib/src/worker/sync_worker_loop.dart b/pkgs/bazel_worker/lib/src/worker/sync_worker_loop.dart index a8571058c..51da684ab 100644 --- a/pkgs/bazel_worker/lib/src/worker/sync_worker_loop.dart +++ b/pkgs/bazel_worker/lib/src/worker/sync_worker_loop.dart @@ -30,19 +30,20 @@ abstract class SyncWorkerLoop implements WorkerLoop { var request = connection.readRequest(); if (request == null) break; var printMessages = StringBuffer(); - response = runZoned(() => performRequest(request), zoneSpecification: - ZoneSpecification(print: (self, parent, zone, message) { - printMessages.writeln(); - printMessages.write(message); - })); + response = runZoned( + () => performRequest(request), + zoneSpecification: ZoneSpecification( + print: (self, parent, zone, message) { + printMessages.writeln(); + printMessages.write(message); + }, + ), + ); if (printMessages.isNotEmpty) { response.output = '${response.output}$printMessages'; } } catch (e, s) { - response = WorkResponse( - exitCode: EXIT_CODE_ERROR, - output: '$e\n$s', - ); + response = WorkResponse(exitCode: EXIT_CODE_ERROR, output: '$e\n$s'); } connection.writeResponse(response); diff --git a/pkgs/bazel_worker/lib/src/worker/worker_connection.dart b/pkgs/bazel_worker/lib/src/worker/worker_connection.dart index b395316a3..fd5508e4a 100644 --- a/pkgs/bazel_worker/lib/src/worker/worker_connection.dart +++ b/pkgs/bazel_worker/lib/src/worker/worker_connection.dart @@ -29,13 +29,16 @@ abstract class AsyncWorkerConnection implements WorkerConnection { /// Creates a [StdAsyncWorkerConnection] with the specified [inputStream] /// and [outputStream], unless [sendPort] is specified, in which case /// creates a [SendPortAsyncWorkerConnection]. - factory AsyncWorkerConnection( - {Stream>? inputStream, - StreamSink>? outputStream, - SendPort? sendPort}) => + factory AsyncWorkerConnection({ + Stream>? inputStream, + StreamSink>? outputStream, + SendPort? sendPort, + }) => sendPort == null ? StdAsyncWorkerConnection( - inputStream: inputStream, outputStream: outputStream) + inputStream: inputStream, + outputStream: outputStream, + ) : SendPortAsyncWorkerConnection(sendPort); @override @@ -53,9 +56,10 @@ class StdAsyncWorkerConnection implements AsyncWorkerConnection { final AsyncMessageGrouper _messageGrouper; final StreamSink> _outputStream; - StdAsyncWorkerConnection( - {Stream>? inputStream, StreamSink>? outputStream}) - : _messageGrouper = AsyncMessageGrouper(inputStream ?? stdin), + StdAsyncWorkerConnection({ + Stream>? inputStream, + StreamSink>? outputStream, + }) : _messageGrouper = AsyncMessageGrouper(inputStream ?? stdin), _outputStream = outputStream ?? stdout; @override diff --git a/pkgs/bazel_worker/lib/testing.dart b/pkgs/bazel_worker/lib/testing.dart index 3ae4c1f4d..7aefabbd8 100644 --- a/pkgs/bazel_worker/lib/testing.dart +++ b/pkgs/bazel_worker/lib/testing.dart @@ -72,10 +72,18 @@ class TestStdinAsync implements TestStdin { } @override - StreamSubscription listen(void Function(Uint8List bytes)? onData, - {Function? onError, void Function()? onDone, bool? cancelOnError}) { - return _controller.stream.listen(onData, - onError: onError, onDone: onDone, cancelOnError: cancelOnError); + StreamSubscription listen( + void Function(Uint8List bytes)? onData, { + Function? onError, + void Function()? onDone, + bool? cancelOnError, + }) { + return _controller.stream.listen( + onData, + onError: onError, + onDone: onDone, + cancelOnError: cancelOnError, + ); } @override @@ -165,8 +173,9 @@ class TestAsyncWorkerConnection extends StdAsyncWorkerConnection final List responses = []; TestAsyncWorkerConnection( - Stream> inputStream, StreamSink> outputStream) - : super(inputStream: inputStream, outputStream: outputStream); + Stream> inputStream, + StreamSink> outputStream, + ) : super(inputStream: inputStream, outputStream: outputStream); @override void writeResponse(WorkResponse response) { diff --git a/pkgs/bazel_worker/test/driver_test.dart b/pkgs/bazel_worker/test/driver_test.dart index c3978304e..c3db55c66 100644 --- a/pkgs/bazel_worker/test/driver_test.dart +++ b/pkgs/bazel_worker/test/driver_test.dart @@ -23,27 +23,37 @@ void main() { await _doRequests(count: 1); }); - test('can run multiple batches of requests through multiple workers', - () async { - var maxWorkers = 4; - var maxIdleWorkers = 2; - driver = BazelWorkerDriver(MockWorker.spawn, - maxWorkers: maxWorkers, maxIdleWorkers: maxIdleWorkers); - for (var i = 0; i < 10; i++) { - await _doRequests(driver: driver); - expect(MockWorker.liveWorkers.length, maxIdleWorkers); - // No workers should be killed while there is ongoing work, but they - // should be cleaned up once there isn't any more work to do. - expect(MockWorker.deadWorkers.length, - (maxWorkers - maxIdleWorkers) * (i + 1)); - } - }); + test( + 'can run multiple batches of requests through multiple workers', + () async { + var maxWorkers = 4; + var maxIdleWorkers = 2; + driver = BazelWorkerDriver( + MockWorker.spawn, + maxWorkers: maxWorkers, + maxIdleWorkers: maxIdleWorkers, + ); + for (var i = 0; i < 10; i++) { + await _doRequests(driver: driver); + expect(MockWorker.liveWorkers.length, maxIdleWorkers); + // No workers should be killed while there is ongoing work, but they + // should be cleaned up once there isn't any more work to do. + expect( + MockWorker.deadWorkers.length, + (maxWorkers - maxIdleWorkers) * (i + 1), + ); + } + }, + ); test('can run multiple requests through one worker', () async { var maxWorkers = 1; var maxIdleWorkers = 1; - driver = BazelWorkerDriver(MockWorker.spawn, - maxWorkers: maxWorkers, maxIdleWorkers: maxIdleWorkers); + driver = BazelWorkerDriver( + MockWorker.spawn, + maxWorkers: maxWorkers, + maxIdleWorkers: maxIdleWorkers, + ); for (var i = 0; i < 10; i++) { await _doRequests(driver: driver); expect(MockWorker.liveWorkers.length, 1); @@ -52,8 +62,11 @@ void main() { }); test('can run one request through multiple workers', () async { - driver = - BazelWorkerDriver(MockWorker.spawn, maxWorkers: 4, maxIdleWorkers: 4); + driver = BazelWorkerDriver( + MockWorker.spawn, + maxWorkers: 4, + maxIdleWorkers: 4, + ); for (var i = 0; i < 10; i++) { await _doRequests(driver: driver, count: 1); expect(MockWorker.liveWorkers.length, 1); @@ -63,8 +76,11 @@ void main() { test('can run with maxIdleWorkers == 0', () async { var maxWorkers = 4; - driver = BazelWorkerDriver(MockWorker.spawn, - maxWorkers: maxWorkers, maxIdleWorkers: 0); + driver = BazelWorkerDriver( + MockWorker.spawn, + maxWorkers: maxWorkers, + maxIdleWorkers: 0, + ); for (var i = 0; i < 10; i++) { await _doRequests(driver: driver); expect(MockWorker.liveWorkers.length, 0); @@ -77,14 +93,15 @@ void main() { driver = BazelWorkerDriver(MockWorker.spawn, maxWorkers: maxWorkers); var tracking = []; await _doRequests( - driver: driver, - count: 10, - trackWork: (Future response) { - // We should never be tracking more than `maxWorkers` jobs at a time. - expect(tracking.length, lessThan(maxWorkers)); - tracking.add(response); - response.then((_) => tracking.remove(response)); - }); + driver: driver, + count: 10, + trackWork: (Future response) { + // We should never be tracking more than `maxWorkers` jobs at a time. + expect(tracking.length, lessThan(maxWorkers)); + tracking.add(response); + response.then((_) => tracking.remove(response)); + }, + ); }); group('failing workers', () { @@ -93,27 +110,39 @@ void main() { void createDriver({int maxRetries = 2, int numBadWorkers = 2}) { var numSpawned = 0; driver = BazelWorkerDriver( - () async => MockWorker(workerLoopFactory: (MockWorker worker) { - var connection = StdAsyncWorkerConnection( - inputStream: worker._stdinController.stream, - outputStream: worker._stdoutController.sink); - if (numSpawned < numBadWorkers) { - numSpawned++; - return ThrowingMockWorkerLoop( - worker, MockWorker.responseQueue, connection); - } else { - return MockWorkerLoop(MockWorker.responseQueue, - connection: connection); - } - }), - maxRetries: maxRetries); + () async => MockWorker( + workerLoopFactory: (MockWorker worker) { + var connection = StdAsyncWorkerConnection( + inputStream: worker._stdinController.stream, + outputStream: worker._stdoutController.sink, + ); + if (numSpawned < numBadWorkers) { + numSpawned++; + return ThrowingMockWorkerLoop( + worker, + MockWorker.responseQueue, + connection, + ); + } else { + return MockWorkerLoop( + MockWorker.responseQueue, + connection: connection, + ); + } + }, + ), + maxRetries: maxRetries, + ); } test('should retry up to maxRetries times', () async { createDriver(); var expectedResponse = WorkResponse(); - MockWorker.responseQueue.addAll( - [disconnectedResponse, disconnectedResponse, expectedResponse]); + MockWorker.responseQueue.addAll([ + disconnectedResponse, + disconnectedResponse, + expectedResponse, + ]); var actualResponse = await driver!.doWork(WorkRequest()); // The first 2 null responses are thrown away, and we should get the // third one. @@ -125,23 +154,29 @@ void main() { test('should fail if it exceeds maxRetries failures', () async { createDriver(maxRetries: 2, numBadWorkers: 3); - MockWorker.responseQueue.addAll( - [disconnectedResponse, disconnectedResponse, WorkResponse()]); + MockWorker.responseQueue.addAll([ + disconnectedResponse, + disconnectedResponse, + WorkResponse(), + ]); var actualResponse = await driver!.doWork(WorkRequest()); // Should actually get a bad response. expect(actualResponse.exitCode, 15); expect( - actualResponse.output, - 'Invalid response from worker, this probably means it wrote ' - 'invalid output or died.'); + actualResponse.output, + 'Invalid response from worker, this probably means it wrote ' + 'invalid output or died.', + ); expect(MockWorker.deadWorkers.length, 3); }); }); test('handles spawnWorker failures', () async { - driver = BazelWorkerDriver(() async => throw StateError('oh no!'), - maxRetries: 0); + driver = BazelWorkerDriver( + () async => throw StateError('oh no!'), + maxRetries: 0, + ); expect(driver!.doWork(WorkRequest()), throwsA(isA())); }); @@ -156,10 +191,11 @@ void main() { /// Runs [count] of fake work requests through [driver], and asserts that they /// all completed. -Future _doRequests( - {BazelWorkerDriver? driver, - int count = 100, - void Function(Future)? trackWork}) async { +Future _doRequests({ + BazelWorkerDriver? driver, + int count = 100, + void Function(Future)? trackWork, +}) async { // If we create a driver, we need to make sure and terminate it. var terminateDriver = driver == null; driver ??= BazelWorkerDriver(MockWorker.spawn); @@ -167,7 +203,8 @@ Future _doRequests( var responses = List.generate(count, (_) => WorkResponse()); MockWorker.responseQueue.addAll(responses); var actualResponses = await Future.wait( - requests.map((request) => driver!.doWork(request, trackWork: trackWork))); + requests.map((request) => driver!.doWork(request, trackWork: trackWork)), + ); expect(actualResponses, unorderedEquals(responses)); if (terminateDriver) await driver.terminateWorkers(); } @@ -191,9 +228,11 @@ class MockWorkerLoop extends AsyncWorkerLoop { class ThrowingMockWorkerLoop extends MockWorkerLoop { final MockWorker _mockWorker; - ThrowingMockWorkerLoop(this._mockWorker, Queue responseQueue, - AsyncWorkerConnection connection) - : super(responseQueue, connection: connection); + ThrowingMockWorkerLoop( + this._mockWorker, + Queue responseQueue, + AsyncWorkerConnection connection, + ) : super(responseQueue, connection: connection); /// Run the worker loop. The returned [Future] doesn't complete until /// [connection#readRequest] returns `null`. @@ -234,10 +273,13 @@ class MockWorker implements Process { liveWorkers.add(this); var workerLoop = workerLoopFactory != null ? workerLoopFactory(this) - : MockWorkerLoop(responseQueue, + : MockWorkerLoop( + responseQueue, connection: StdAsyncWorkerConnection( - inputStream: _stdinController.stream, - outputStream: _stdoutController.sink)); + inputStream: _stdinController.stream, + outputStream: _stdoutController.sink, + ), + ); workerLoop.run(); } @@ -260,8 +302,10 @@ class MockWorker implements Process { int get pid => throw UnsupportedError('Not needed.'); @override - bool kill( - [ProcessSignal processSignal = ProcessSignal.sigterm, int exitCode = 0]) { + bool kill([ + ProcessSignal processSignal = ProcessSignal.sigterm, + int exitCode = 0, + ]) { if (_killed) return false; () async { await _stdoutController.close(); diff --git a/pkgs/bazel_worker/test/message_grouper_test.dart b/pkgs/bazel_worker/test/message_grouper_test.dart index 475190ed8..fd99911d1 100644 --- a/pkgs/bazel_worker/test/message_grouper_test.dart +++ b/pkgs/bazel_worker/test/message_grouper_test.dart @@ -18,8 +18,10 @@ void main() { }); } -void runTests(TestStdin Function() stdinFactory, - MessageGrouper Function(Stdin) messageGrouperFactory) { +void runTests( + TestStdin Function() stdinFactory, + MessageGrouper Function(Stdin) messageGrouperFactory, +) { late MessageGrouper messageGrouper; late TestStdin stdinStream; @@ -52,16 +54,12 @@ void runTests(TestStdin Function() stdinFactory, }); test('Short message', () async { - await check([ - 5, - 10, - 20, - 30, - 40, - 50 - ], [ - [10, 20, 30, 40, 50] - ]); + await check( + [5, 10, 20, 30, 40, 50], + [ + [10, 20, 30, 40, 50], + ], + ); }); test('Message with 2-byte length', () async { @@ -79,57 +77,44 @@ void runTests(TestStdin Function() stdinFactory, }); test('Multiple messages', () async { - await check([ - 2, - 10, - 20, - 2, - 30, - 40 - ], [ - [10, 20], - [30, 40] - ]); + await check( + [2, 10, 20, 2, 30, 40], + [ + [10, 20], + [30, 40], + ], + ); }); test('Empty message at start', () async { - await check([ - 0, - 2, - 10, - 20 - ], [ - [], - [10, 20] - ]); + await check( + [0, 2, 10, 20], + [ + [], + [10, 20], + ], + ); }); test('Empty message at end', () async { - await check([ - 2, - 10, - 20, - 0 - ], [ - [10, 20], - [] - ]); + await check( + [2, 10, 20, 0], + [ + [10, 20], + [], + ], + ); }); test('Empty message in the middle', () async { - await check([ - 2, - 10, - 20, - 0, - 2, - 30, - 40 - ], [ - [10, 20], - [], - [30, 40] - ]); + await check( + [2, 10, 20, 0, 2, 30, 40], + [ + [10, 20], + [], + [30, 40], + ], + ); }); test('Handles the case when stdin gives an error instead of EOF', () async { diff --git a/pkgs/bazel_worker/test/worker_loop_test.dart b/pkgs/bazel_worker/test/worker_loop_test.dart index 50d21512e..24068b1d8 100644 --- a/pkgs/bazel_worker/test/worker_loop_test.dart +++ b/pkgs/bazel_worker/test/worker_loop_test.dart @@ -11,36 +11,45 @@ import 'package:test/test.dart'; void main() { group('SyncWorkerLoop', () { - runTests(TestStdinSync.new, TestSyncWorkerConnection.new, - TestSyncWorkerLoop.new); + runTests( + TestStdinSync.new, + TestSyncWorkerConnection.new, + TestSyncWorkerLoop.new, + ); }); group('AsyncWorkerLoop', () { - runTests(TestStdinAsync.new, TestAsyncWorkerConnection.new, - TestAsyncWorkerLoop.new); + runTests( + TestStdinAsync.new, + TestAsyncWorkerConnection.new, + TestAsyncWorkerLoop.new, + ); }); group('SyncWorkerLoopWithPrint', () { runTests( - TestStdinSync.new, - TestSyncWorkerConnection.new, - (TestSyncWorkerConnection connection) => - TestSyncWorkerLoop(connection, printMessage: 'Goodbye!')); + TestStdinSync.new, + TestSyncWorkerConnection.new, + (TestSyncWorkerConnection connection) => + TestSyncWorkerLoop(connection, printMessage: 'Goodbye!'), + ); }); group('AsyncWorkerLoopWithPrint', () { runTests( - TestStdinAsync.new, - TestAsyncWorkerConnection.new, - (TestAsyncWorkerConnection connection) => - TestAsyncWorkerLoop(connection, printMessage: 'Goodbye!')); + TestStdinAsync.new, + TestAsyncWorkerConnection.new, + (TestAsyncWorkerConnection connection) => + TestAsyncWorkerLoop(connection, printMessage: 'Goodbye!'), + ); }); } void runTests( - TestStdin Function() stdinFactory, - T Function(Stdin, Stdout) workerConnectionFactory, - TestWorkerLoop Function(T) workerLoopFactory) { + TestStdin Function() stdinFactory, + T Function(Stdin, Stdout) workerConnectionFactory, + TestWorkerLoop Function(T) workerLoopFactory, +) { late TestStdin stdinStream; late TestStdoutStream stdoutStream; late T connection; @@ -63,19 +72,29 @@ void runTests( // Make sure `print` never gets called in the parent zone. var printMessages = []; - await runZoned(() => workerLoop.run(), zoneSpecification: - ZoneSpecification(print: (self, parent, zone, message) { - printMessages.add(message); - })); - expect(printMessages, isEmpty, - reason: 'The worker loop should hide all print calls from the parent ' - 'zone.'); + await runZoned( + () => workerLoop.run(), + zoneSpecification: ZoneSpecification( + print: (self, parent, zone, message) { + printMessages.add(message); + }, + ), + ); + expect( + printMessages, + isEmpty, + reason: 'The worker loop should hide all print calls from the parent ' + 'zone.', + ); expect(connection.responses, hasLength(1)); expect(connection.responses[0], response); if (workerLoop.printMessage != null) { - expect(response.output, endsWith(workerLoop.printMessage!), - reason: 'Print messages should get appended to the response output.'); + expect( + response.output, + endsWith(workerLoop.printMessage!), + reason: 'Print messages should get appended to the response output.', + ); } // Check that a serialized version was written to std out. diff --git a/pkgs/clock/analysis_options.yaml b/pkgs/clock/analysis_options.yaml index 9ee7c2b6a..db6072da7 100644 --- a/pkgs/clock/analysis_options.yaml +++ b/pkgs/clock/analysis_options.yaml @@ -11,4 +11,3 @@ linter: rules: - avoid_private_typedef_functions - avoid_redundant_argument_values - - use_super_parameters diff --git a/pkgs/coverage/analysis_options.yaml b/pkgs/coverage/analysis_options.yaml index 82ce5e0a5..bb1afe05a 100644 --- a/pkgs/coverage/analysis_options.yaml +++ b/pkgs/coverage/analysis_options.yaml @@ -9,14 +9,9 @@ analyzer: linter: rules: - - always_declare_return_types - avoid_slow_async_io - cancel_subscriptions - - comment_references - literal_only_boolean_expressions - prefer_final_locals - sort_constructors_first - sort_unnamed_constructors_first - - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis diff --git a/pkgs/test_reflective_loader/pubspec.yaml b/pkgs/test_reflective_loader/pubspec.yaml index 953ece944..569933f23 100644 --- a/pkgs/test_reflective_loader/pubspec.yaml +++ b/pkgs/test_reflective_loader/pubspec.yaml @@ -10,4 +10,4 @@ dependencies: test: ^1.16.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 From 4dcd4d9075a1306e7c8edb49776bafccfb5879cf Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Mon, 16 Dec 2024 11:42:03 -0600 Subject: [PATCH 1210/1215] bazel_worker: Fix broken bad action (#1680) --- .github/workflows/bazel_worker.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/bazel_worker.yaml b/.github/workflows/bazel_worker.yaml index 29c0a0d07..b448219d1 100644 --- a/.github/workflows/bazel_worker.yaml +++ b/.github/workflows/bazel_worker.yaml @@ -38,6 +38,6 @@ jobs: sdk: ${{ matrix.sdk }} - run: dart pub get - run: "dart format --output=none --set-exit-if-changed ." - if: ${{ matrix.sdk == dev }} + if: ${{ matrix.sdk == 'dev' }} - name: Test run: ./tool/travis.sh From c72a0aeb6a20809ae7adc7aede25dba556846f1a Mon Sep 17 00:00:00 2001 From: Moritz Date: Tue, 17 Dec 2024 10:57:32 +0100 Subject: [PATCH 1211/1215] Add changelog --- pkgs/string_scanner/CHANGELOG.md | 4 ++++ pkgs/string_scanner/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/string_scanner/CHANGELOG.md b/pkgs/string_scanner/CHANGELOG.md index ee75f7338..082e9f201 100644 --- a/pkgs/string_scanner/CHANGELOG.md +++ b/pkgs/string_scanner/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.1 + +* Move to `dart-lang/tools` monorepo. + ## 1.4.0 * Fix `LineScanner`'s handling of `\r\n`'s to preventing errors scanning diff --git a/pkgs/string_scanner/pubspec.yaml b/pkgs/string_scanner/pubspec.yaml index 0930cda49..9b259cf7b 100644 --- a/pkgs/string_scanner/pubspec.yaml +++ b/pkgs/string_scanner/pubspec.yaml @@ -1,5 +1,5 @@ name: string_scanner -version: 1.4.0 +version: 1.4.1 description: A class for parsing strings using a sequence of patterns. repository: https://github.com/dart-lang/tools/tree/main/pkgs/string_scanner From 4a260a86fdde74aff242db4cfa064a33795b30d3 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 20 Dec 2024 13:58:31 +0100 Subject: [PATCH 1212/1215] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/pubspec_parse.md | 5 +++++ pkgs/pubspec_parse/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/pubspec_parse.md diff --git a/.github/ISSUE_TEMPLATE/pubspec_parse.md b/.github/ISSUE_TEMPLATE/pubspec_parse.md new file mode 100644 index 000000000..2d6588102 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/pubspec_parse.md @@ -0,0 +1,5 @@ +--- +name: "package:pubspec_parse" +about: "Create a bug or file a feature request against package:pubspec_parse." +labels: "package:pubspec_parse" +--- \ No newline at end of file diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index bcdaa31ff..cb29d02d5 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -3,7 +3,7 @@ version: 1.4.0-wip description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. -repository: https://github.com/dart-lang/pubspec_parse +repository: https://github.com/dart-lang/tools/tree/main/pkgs/pubspec_parse topics: - dart-pub From 9a9a7e510a01c0bd2c21493085773c86548df7c8 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 20 Dec 2024 14:02:11 +0100 Subject: [PATCH 1213/1215] Moving fixes --- .github/labeler.yml | 4 ++++ .../workflows/pubspec_parse.yaml | 17 ++++++++++++++--- README.md | 1 + pkgs/pubspec_parse/.github/dependabot.yml | 15 --------------- .../.github/workflows/publish.yaml | 17 ----------------- pkgs/pubspec_parse/CHANGELOG.md | 3 ++- pkgs/pubspec_parse/README.md | 2 +- pkgs/pubspec_parse/pubspec.yaml | 2 +- 8 files changed, 23 insertions(+), 38 deletions(-) rename pkgs/pubspec_parse/.github/workflows/test-package.yml => .github/workflows/pubspec_parse.yaml (83%) delete mode 100644 pkgs/pubspec_parse/.github/dependabot.yml delete mode 100644 pkgs/pubspec_parse/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index bfef3164e..3ab79c051 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -92,6 +92,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/pub_semver/**' +'package:pubspec_parse': + - changed-files: + - any-glob-to-any-file: 'pkgs/pubspec_parse/**' + 'package:source_map_stack_trace': - changed-files: - any-glob-to-any-file: 'pkgs/source_map_stack_trace/**' diff --git a/pkgs/pubspec_parse/.github/workflows/test-package.yml b/.github/workflows/pubspec_parse.yaml similarity index 83% rename from pkgs/pubspec_parse/.github/workflows/test-package.yml rename to .github/workflows/pubspec_parse.yaml index 922d6c28e..ebe705912 100644 --- a/pkgs/pubspec_parse/.github/workflows/test-package.yml +++ b/.github/workflows/pubspec_parse.yaml @@ -1,17 +1,28 @@ -name: Dart CI +name: package:pubspec_parse on: # Run on PRs and pushes to the default branch. push: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/pubspec_parse.yaml' + - 'pkgs/pubspec_parse/**' pull_request: - branches: [ master ] + branches: [ main ] + paths: + - '.github/workflows/pubspec_parse.yaml' + - 'pkgs/pubspec_parse/**' schedule: - cron: "0 0 * * 0" env: PUB_ENVIRONMENT: bot.github + +defaults: + run: + working-directory: pkgs/pubspec_parse/ + jobs: # Check code formatting and static analysis on a single OS (linux) # against Dart dev. diff --git a/README.md b/README.md index d1a1d0416..0201aa284 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ don't naturally belong to other topic monorepos (like | [package_config](pkgs/package_config/) | Support for reading and writing Dart Package Configuration files. | [![package issues](https://img.shields.io/badge/package:package_config-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apackage_config) | [![pub package](https://img.shields.io/pub/v/package_config.svg)](https://pub.dev/packages/package_config) | | [pool](pkgs/pool/) | Manage a finite pool of resources. Useful for controlling concurrent file system or network requests. | [![package issues](https://img.shields.io/badge/package:pool-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apool) | [![pub package](https://img.shields.io/pub/v/pool.svg)](https://pub.dev/packages/pool) | | [pub_semver](pkgs/pub_semver/) | Versions and version constraints implementing pub's versioning policy. This is very similar to vanilla semver, with a few corner cases. | [![package issues](https://img.shields.io/badge/package:pub_semver-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apub_semver) | [![pub package](https://img.shields.io/pub/v/pub_semver.svg)](https://pub.dev/packages/pub_semver) | +| [pubspec_parse](pkgs/pubspec_parse/) | Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. | [![package issues](https://img.shields.io/badge/package:pubspec_parse-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Apubspec_parse) | [![pub package](https://img.shields.io/pub/v/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![package issues](https://img.shields.io/badge/package:source_map_stack_trace-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_map_stack_trace) | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | | [source_maps](pkgs/source_maps/) | A library to programmatically manipulate source map files. | [![package issues](https://img.shields.io/badge/package:source_maps-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_maps) | [![pub package](https://img.shields.io/pub/v/source_maps.svg)](https://pub.dev/packages/source_maps) | | [source_span](pkgs/source_span/) | Provides a standard representation for source code locations and spans. | [![package issues](https://img.shields.io/badge/package:source_span-4774bc)](https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Asource_span) | [![pub package](https://img.shields.io/pub/v/source_span.svg)](https://pub.dev/packages/source_span) | diff --git a/pkgs/pubspec_parse/.github/dependabot.yml b/pkgs/pubspec_parse/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/pubspec_parse/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/pubspec_parse/.github/workflows/publish.yaml b/pkgs/pubspec_parse/.github/workflows/publish.yaml deleted file mode 100644 index 27157a046..000000000 --- a/pkgs/pubspec_parse/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ master ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/pubspec_parse/CHANGELOG.md b/pkgs/pubspec_parse/CHANGELOG.md index 251d4cc47..a5f0f1a30 100644 --- a/pkgs/pubspec_parse/CHANGELOG.md +++ b/pkgs/pubspec_parse/CHANGELOG.md @@ -1,9 +1,10 @@ -## 1.4.0-wip +## 1.4.0 - Require Dart 3.2 - Seal the `Dependency` class. - Set `Pubspec.environment` to non-nullable. - Remove deprecated package_api_docs rule +- Move to `dart-lang/tools` monorepo. ## 1.3.0 diff --git a/pkgs/pubspec_parse/README.md b/pkgs/pubspec_parse/README.md index 916742a63..1d04aa486 100644 --- a/pkgs/pubspec_parse/README.md +++ b/pkgs/pubspec_parse/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/pubspec_parse/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/pubspec_parse/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/pubspec_parse.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/pubspec_parse.yaml) [![pub package](https://img.shields.io/pub/v/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse) [![package publisher](https://img.shields.io/pub/publisher/pubspec_parse.svg)](https://pub.dev/packages/pubspec_parse/publisher) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index cb29d02d5..9d1c8db76 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -1,5 +1,5 @@ name: pubspec_parse -version: 1.4.0-wip +version: 1.4.0 description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. From b1e27824e429cebb6f80b052818fd9946ada424a Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 20 Dec 2024 14:04:53 +0100 Subject: [PATCH 1214/1215] Add newline --- pkgs/pubspec_parse/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/pubspec_parse/pubspec.yaml b/pkgs/pubspec_parse/pubspec.yaml index 9d1c8db76..ad0c55e67 100644 --- a/pkgs/pubspec_parse/pubspec.yaml +++ b/pkgs/pubspec_parse/pubspec.yaml @@ -4,6 +4,7 @@ description: >- Simple package for parsing pubspec.yaml files with a type-safe API and rich error reporting. repository: https://github.com/dart-lang/tools/tree/main/pkgs/pubspec_parse + topics: - dart-pub From 4ebcd8ed2107dcbe8069a12782d68bdd0eb68748 Mon Sep 17 00:00:00 2001 From: Moritz Date: Fri, 20 Dec 2024 14:09:57 +0100 Subject: [PATCH 1215/1215] Update test --- pkgs/pubspec_parse/test/ensure_build_test.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/pubspec_parse/test/ensure_build_test.dart b/pkgs/pubspec_parse/test/ensure_build_test.dart index 689f6fe66..0e4371c13 100644 --- a/pkgs/pubspec_parse/test/ensure_build_test.dart +++ b/pkgs/pubspec_parse/test/ensure_build_test.dart @@ -11,5 +11,8 @@ import 'package:build_verify/build_verify.dart'; import 'package:test/test.dart'; void main() { - test('ensure_build', expectBuildClean); + test( + 'ensure_build', + () => expectBuildClean(packageRelativeDirectory: 'pkgs/pubspec_parse/'), + ); }