Add class modifiers to dart:convert.

The usual approach:
Pure interfaces marked `interface`.
Pure implementation classes marked `final`.
Base classes marked `base` or nothing, and `mixin class` if reasonable.
Combined X/XBase/XMixin where possible.

CoreLibraryReviewExempt: Aske is away
Change-Id: I927f9bd488fb385ff9c17c8fc94920a1f5076347
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/289200
Reviewed-by: Stephen Adams <sra@google.com>
Reviewed-by: Slava Egorov <vegorov@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
Commit-Queue: Lasse Nielsen <lrn@google.com>
This commit is contained in:
Lasse R.H. Nielsen 2023-03-20 13:27:17 +00:00 committed by Commit Queue
parent 82d91ea541
commit b2f4cf3e01
26 changed files with 101 additions and 112 deletions

View file

@ -345,7 +345,7 @@ class PathMapEntry {
}
}
class _InputSink extends ChunkedConversionSink<String> {
class _InputSink implements ChunkedConversionSink<String> {
final Converter<String, Operation?> converter;
final Sink<Operation?> outSink;

View file

@ -8,7 +8,7 @@ import 'package:analysis_server/protocol/protocol.dart';
/// Instances of the class [ChannelChunkSink] uses a [Converter] to translate
/// chunks.
class ChannelChunkSink<S, T> extends ChunkedConversionSink<S> {
class ChannelChunkSink<S, T> implements ChunkedConversionSink<S> {
/// The converter used to translate chunks.
final Converter<S, T> converter;

View file

@ -254,9 +254,9 @@ class JsonCodec {
String encode(Object? value, {Object? toEncodable(dynamic object)?}) => '';
}
abstract class StringConversionSink { }
abstract mixin class StringConversionSink { }
abstract mixin class StringConversionSinkMixin implements StringConversionSink { }
typedef StringConversionSinkMixin = StringConversionSink;
''',
)
],

View file

@ -1553,7 +1553,7 @@ external double _parseDouble(String source, int start, int end);
* Implements the chunked conversion from a UTF-8 encoding of JSON
* to its corresponding object.
*/
class _JsonUtf8DecoderSink extends ByteConversionSinkBase {
class _JsonUtf8DecoderSink extends ByteConversionSink {
final _JsonUtf8Parser _parser;
final Sink<Object?> _sink;

View file

@ -21,7 +21,7 @@ const int _asciiMask = 0x7F;
/// An [AsciiCodec] allows encoding strings as ASCII bytes
/// and decoding ASCII bytes to strings.
class AsciiCodec extends Encoding {
final class AsciiCodec extends Encoding {
final bool _allowInvalid;
/// Instantiates a new [AsciiCodec].
@ -118,7 +118,7 @@ class AsciiEncoder extends _UnicodeSubsetEncoder {
/// This class encodes chunked strings to bytes (unsigned 8-bit
/// integers).
class _UnicodeSubsetEncoderSink extends StringConversionSinkBase {
class _UnicodeSubsetEncoderSink extends StringConversionSink {
final ByteConversionSink _sink;
final int _subsetMask;
@ -253,7 +253,7 @@ class AsciiDecoder extends _UnicodeSubsetDecoder {
}
}
class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase {
class _ErrorHandlingAsciiDecoderSink extends ByteConversionSink {
ByteConversionSink _utf8Sink;
_ErrorHandlingAsciiDecoderSink(this._utf8Sink);
@ -283,7 +283,7 @@ class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase {
}
}
class _SimpleAsciiDecoderSink extends ByteConversionSinkBase {
class _SimpleAsciiDecoderSink extends ByteConversionSink {
Sink _sink;
_SimpleAsciiDecoderSink(this._sink);

View file

@ -64,7 +64,7 @@ const int _paddingChar = 0x3d; // '='.
/// It does not allow invalid characters when decoding and it requires,
/// and generates, padding so that the input is always a multiple of four
/// characters.
class Base64Codec extends Codec<List<int>, String> {
final class Base64Codec extends Codec<List<int>, String> {
final Base64Encoder _encoder;
const Base64Codec() : _encoder = const Base64Encoder();
const Base64Codec.urlSafe() : _encoder = const Base64Encoder.urlSafe();
@ -231,7 +231,7 @@ class Base64Codec extends Codec<List<int>, String> {
/// final encodedSample = base64Encoder.convert(sample.codeUnits);
/// print(encodedSample); // RGFydCBpcyBvcGVuIHNvdXJjZQ==
/// ```
class Base64Encoder extends Converter<List<int>, String> {
final class Base64Encoder extends Converter<List<int>, String> {
final bool _urlSafe;
const Base64Encoder() : _urlSafe = false;
@ -416,7 +416,7 @@ class _BufferCachingBase64Encoder extends _Base64Encoder {
}
}
abstract class _Base64EncoderSink extends ByteConversionSinkBase {
abstract class _Base64EncoderSink extends ByteConversionSink {
void add(List<int> source) {
_add(source, 0, source.length, false);
}
@ -491,7 +491,7 @@ class _Utf8Base64EncoderSink extends _Base64EncoderSink {
/// // Print as string using UTF-8 decoder
/// print(utf8.decode(decodedBytes)); // Dart is open source
/// ```
class Base64Decoder extends Converter<String, List<int>> {
final class Base64Decoder extends Converter<String, List<int>> {
const Base64Decoder();
/// Decodes the characters of [input] from [start] to [end] as base64.
@ -850,7 +850,7 @@ class _Base64Decoder {
}
}
class _Base64DecoderSink extends StringConversionSinkBase {
class _Base64DecoderSink extends StringConversionSink {
/// Output sink
final Sink<List<int>> _sink;
final _Base64Decoder _decoder = _Base64Decoder();

View file

@ -9,12 +9,10 @@ part of dart.convert;
///
/// Instead of limiting the interface to one non-chunked list of bytes it
/// accepts its input in chunks (themselves being lists of bytes).
///
/// This abstract class will likely get more methods over time. Implementers are
/// urged to extend or mix in [ByteConversionSinkBase] to ensure that their
/// class covers the newly added methods.
abstract class ByteConversionSink extends ChunkedConversionSink<List<int>> {
ByteConversionSink();
abstract mixin class ByteConversionSink
implements ChunkedConversionSink<List<int>> {
const ByteConversionSink();
factory ByteConversionSink.withCallback(
void callback(List<int> accumulated)) = _ByteCallbackSink;
factory ByteConversionSink.from(Sink<List<int>> sink) = _ByteAdapterSink;
@ -25,31 +23,24 @@ abstract class ByteConversionSink extends ChunkedConversionSink<List<int>> {
///
/// If [isLast] is `true` closes `this`.
///
/// Contrary to `add` the given [chunk] must not be held onto. Once the method
/// returns, it is safe to overwrite the data in it.
void addSlice(List<int> chunk, int start, int end, bool isLast);
// TODO(floitsch): add more methods:
// - iterateBytes.
}
/// This class provides a base-class for converters that need to accept byte
/// inputs.
abstract class ByteConversionSinkBase extends ByteConversionSink {
void add(List<int> chunk);
void close();
/// Contrary to `add` the given [chunk] must not be held onto.
/// Once the method returns, it is safe to overwrite the data in it.
void addSlice(List<int> chunk, int start, int end, bool isLast) {
add(chunk.sublist(start, end));
if (isLast) close();
}
}
/// This class provides a base-class for converters that need to accept byte
/// inputs.
@Deprecated("Use ByteConversionSink instead")
typedef ByteConversionSinkBase = ByteConversionSink;
/// This class adapts a simple [Sink] to a [ByteConversionSink].
///
/// All additional methods of the [ByteConversionSink] (compared to the
/// ChunkedConversionSink) are redirected to the `add` method.
class _ByteAdapterSink extends ByteConversionSinkBase {
class _ByteAdapterSink extends ByteConversionSink {
final Sink<List<int>> _sink;
_ByteAdapterSink(this._sink);
@ -67,7 +58,7 @@ class _ByteAdapterSink extends ByteConversionSinkBase {
/// and invokes a callback when the sink is closed.
///
/// This class can be used to terminate a chunked conversion.
class _ByteCallbackSink extends ByteConversionSinkBase {
class _ByteCallbackSink extends ByteConversionSink {
static const _INITIAL_BUFFER_SIZE = 1024;
final void Function(List<int>) _callback;

View file

@ -10,10 +10,7 @@ part of dart.convert;
/// The basic `ChunkedConversionSink` is just a [Sink], and converters should
/// work with a plain `Sink`, but may work more efficiently with certain
/// specialized types of `ChunkedConversionSink`.
///
/// It is recommended that implementations of `ChunkedConversionSink` extend
/// this class, to inherit any further methods that may be added to the class.
abstract class ChunkedConversionSink<T> implements Sink<T> {
abstract interface class ChunkedConversionSink<T> implements Sink<T> {
ChunkedConversionSink();
factory ChunkedConversionSink.withCallback(
void callback(List<T> accumulated)) = _SimpleCallbackSink<T>;
@ -34,7 +31,7 @@ abstract class ChunkedConversionSink<T> implements Sink<T> {
/// the chunks when the sink is closed.
///
/// This class can be used to terminate a chunked conversion.
class _SimpleCallbackSink<T> extends ChunkedConversionSink<T> {
class _SimpleCallbackSink<T> implements ChunkedConversionSink<T> {
final void Function(List<T>) _callback;
final List<T> _accumulated = <T>[];

View file

@ -12,7 +12,11 @@ part of dart.convert;
///
/// Fused codecs generally attempt to optimize the operations and can be faster
/// than executing each step of an encoding separately.
abstract class Codec<S, T> {
///
/// The [Codec] class provides a default implementation of
/// [encode], [decode], [fuse] and [inverted].
/// Subclasses can choose to provide more efficient implementations of these.
abstract mixin class Codec<S, T> {
const Codec();
/// Encodes [input].

View file

@ -6,9 +6,9 @@ part of dart.convert;
/// A [Converter] converts data from one representation into another.
///
/// It is recommended that implementations of `Converter` extend this class,
/// to inherit any further methods that may be added to the class.
abstract class Converter<S, T> extends StreamTransformerBase<S, T> {
/// The [Converter] class provides a default implementation for every method
/// other than [convert].
abstract mixin class Converter<S, T> implements StreamTransformerBase<S, T> {
const Converter();
/// Adapts [source] to be a `Converter<TS, TT>`.

View file

@ -4,7 +4,14 @@
part of dart.convert;
/// Open-ended Encoding enum.
/// Open-ended set of encodings.
///
/// An encoding is a [Codec] encoding strings to lists of byte.
///
/// This class provides a default implementation of [decodeStream],
/// which is not incremental. It collects the entire input before
/// decoding. Subclasses can choose to use that implementation,
/// or implement a more efficient stream decoding.
abstract class Encoding extends Codec<String, List<int>> {
const Encoding();

View file

@ -70,7 +70,7 @@ const HtmlEscape htmlEscape = HtmlEscape();
/// escaped = htmlEscape.convert(unescaped);
/// print(escaped); // Path: /system/
/// ```
class HtmlEscapeMode {
final class HtmlEscapeMode {
final String _name;
/// Whether to escape '<' and '>'.
@ -193,7 +193,7 @@ class HtmlEscapeMode {
/// escaped = htmlEscape.convert(unescaped);
/// print(escaped); // Path: &#47;system&#47;
/// ```
class HtmlEscape extends Converter<String, String> {
final class HtmlEscape extends Converter<String, String> {
/// The [HtmlEscapeMode] used by the converter.
final HtmlEscapeMode mode;
@ -257,7 +257,7 @@ class HtmlEscape extends Converter<String, String> {
}
}
class _HtmlEscapeSink extends StringConversionSinkBase {
class _HtmlEscapeSink extends StringConversionSink {
final HtmlEscape _escape;
final StringConversionSink _sink;

View file

@ -162,7 +162,7 @@ dynamic jsonDecode(String source,
/// var encoded = json.encode([1, 2, { "a": null }]);
/// var decoded = json.decode('["foo", { "bar": 499 }]');
/// ```
class JsonCodec extends Codec<Object?, String> {
final class JsonCodec extends Codec<Object?, String> {
final Object? Function(Object? key, Object? value)? _reviver;
final Object? Function(dynamic)? _toEncodable;
@ -268,7 +268,7 @@ class JsonCodec extends Codec<Object?, String> {
/// // "value": "2"
/// // }
/// ```
class JsonEncoder extends Converter<Object?, String> {
final class JsonEncoder extends Converter<Object?, String> {
/// The string used for indention.
///
/// When generating multi-line output, this string is inserted once at the
@ -383,7 +383,7 @@ class JsonEncoder extends Converter<Object?, String> {
/// This encoder works equivalently to first converting the object to
/// a JSON string, and then UTF-8 encoding the string, but without
/// creating an intermediate string.
class JsonUtf8Encoder extends Converter<Object?, List<int>> {
final class JsonUtf8Encoder extends Converter<Object?, List<int>> {
/// Default buffer size used by the JSON-to-UTF-8 encoder.
static const int _defaultBufferSize = 256;
@ -585,7 +585,7 @@ class _JsonUtf8EncoderSink extends ChunkedConversionSink<Object?> {
/// When used as a [StreamTransformer], the input stream may emit
/// multiple strings. The concatenation of all of these strings must
/// be a valid JSON encoding of a single JSON value.
class JsonDecoder extends Converter<String, Object?> {
final class JsonDecoder extends Converter<String, Object?> {
final Object? Function(Object? key, Object? value)? _reviver;
/// Constructs a new JsonDecoder.

View file

@ -21,7 +21,7 @@ const int _latin1Mask = 0xFF;
/// A [Latin1Codec] encodes strings to ISO Latin-1 (aka ISO-8859-1) bytes
/// and decodes Latin-1 bytes to strings.
class Latin1Codec extends Encoding {
final class Latin1Codec extends Encoding {
final bool _allowInvalid;
/// Instantiates a new [Latin1Codec].
@ -72,7 +72,7 @@ class Latin1Codec extends Encoding {
/// final encoded = latin1Encoder.convert(sample);
/// print(encoded); // [224, 225, 226, 227, 228, 229]
/// ```
class Latin1Encoder extends _UnicodeSubsetEncoder {
final class Latin1Encoder extends _UnicodeSubsetEncoder {
const Latin1Encoder() : super(_latin1Mask);
}
@ -105,7 +105,7 @@ class Latin1Encoder extends _UnicodeSubsetEncoder {
/// final decoded = latin1Decoder.convert(encodedBytes);
/// print(decoded); // <EFBFBD>
/// ```
class Latin1Decoder extends _UnicodeSubsetDecoder {
final class Latin1Decoder extends _UnicodeSubsetDecoder {
/// Instantiates a new [Latin1Decoder].
///
/// The optional [allowInvalid] argument defines how [convert] deals
@ -134,7 +134,7 @@ class Latin1Decoder extends _UnicodeSubsetDecoder {
}
}
class _Latin1DecoderSink extends ByteConversionSinkBase {
class _Latin1DecoderSink extends ByteConversionSink {
StringConversionSink? _sink;
_Latin1DecoderSink(this._sink);

View file

@ -35,7 +35,7 @@ const int _CR = 13;
/// // 3: garbage-collected
/// // 4: language with C-style syntax
/// ```
class LineSplitter extends StreamTransformerBase<String, String> {
final class LineSplitter extends StreamTransformerBase<String, String> {
const LineSplitter();
/// Split [lines] into individual lines.
@ -84,7 +84,7 @@ class LineSplitter extends StreamTransformerBase<String, String> {
}
}
class _LineSplitterSink extends StringConversionSinkBase {
class _LineSplitterSink extends StringConversionSink {
final StringConversionSink _sink;
/// The carry-over from the previous chunk.

View file

@ -4,19 +4,18 @@
part of dart.convert;
/// This class provides an interface for converters to
/// efficiently transmit String data.
/// A sink for converters to efficiently transmit String data.
///
/// Instead of limiting the interface to one non-chunked String it accepts
/// Instead of limiting the interface to one non-chunked [String] it accepts
/// partial strings or can be transformed into a byte sink that
/// accepts UTF-8 code units.
///
/// This abstract class will likely get more methods over time. Implementers are
/// urged to extend [StringConversionSinkBase] or to mix in
/// [StringConversionSinkMixin], to ensure that their class covers the newly
/// added methods.
abstract class StringConversionSink extends ChunkedConversionSink<String> {
StringConversionSink();
/// The [StringConversionSink] class provides a default implementation of
/// [add], [asUtf8Sink] and [asStringSink].
abstract mixin class StringConversionSink
implements ChunkedConversionSink<String> {
const StringConversionSink();
factory StringConversionSink.withCallback(void callback(String accumulated)) =
_StringCallbackSink;
factory StringConversionSink.from(Sink<String> sink) = _StringAdapterSink;
@ -36,24 +35,30 @@ abstract class StringConversionSink extends ChunkedConversionSink<String> {
/// If [isLast] is `true` closes `this`.
void addSlice(String chunk, int start, int end, bool isLast);
void add(String str) {
addSlice(str, 0, str.length, false);
}
/// Returns `this` as a sink that accepts UTF-8 input.
///
/// If used, this method must be the first and only call to `this`. It
/// invalidates `this`. All further operations must be performed on the result.
ByteConversionSink asUtf8Sink(bool allowMalformed);
// - asRuneSink
// - asCodeUnitsSink
ByteConversionSink asUtf8Sink(bool allowMalformed) {
return _Utf8ConversionSink(this, allowMalformed);
}
/// Returns `this` as a [ClosableStringSink].
///
/// If used, this method must be the first and only call to `this`. It
/// invalidates `this`. All further operations must be performed on the result.
ClosableStringSink asStringSink();
ClosableStringSink asStringSink() {
return _StringConversionSinkAsStringSinkAdapter(this);
}
}
/// A [ClosableStringSink] extends the [StringSink] interface by adding a
/// `close` method.
abstract class ClosableStringSink extends StringSink {
abstract interface class ClosableStringSink implements StringSink {
/// Creates a new instance combining a [StringSink] [sink] and a callback
/// [onClose] which is invoked when the returned instance is closed.
factory ClosableStringSink.fromStringSink(StringSink sink, void onClose()) =
@ -151,30 +156,15 @@ class _StringConversionSinkAsStringSinkAdapter implements ClosableStringSink {
/// This class provides a base-class for converters that need to accept String
/// inputs.
abstract class StringConversionSinkBase extends StringConversionSinkMixin {}
typedef StringConversionSinkBase = StringConversionSink;
/// This class provides a mixin for converters that need to accept String
/// inputs.
abstract mixin class StringConversionSinkMixin implements StringConversionSink {
void addSlice(String str, int start, int end, bool isLast);
void close();
void add(String str) {
addSlice(str, 0, str.length, false);
}
ByteConversionSink asUtf8Sink(bool allowMalformed) {
return _Utf8ConversionSink(this, allowMalformed);
}
ClosableStringSink asStringSink() {
return _StringConversionSinkAsStringSinkAdapter(this);
}
}
typedef StringConversionSinkMixin = StringConversionSink;
/// This class is a [StringConversionSink] that wraps a [StringSink].
class _StringSinkConversionSink<TStringSink extends StringSink>
extends StringConversionSinkBase {
extends StringConversionSink {
final TStringSink _stringSink;
_StringSinkConversionSink(this._stringSink);
@ -229,7 +219,7 @@ class _StringCallbackSink extends _StringSinkConversionSink<StringBuffer> {
///
/// All additional methods of the [StringConversionSink] (compared to the
/// ChunkedConversionSink) are redirected to the `add` method.
class _StringAdapterSink extends StringConversionSinkBase {
class _StringAdapterSink extends StringConversionSink {
final Sink<String> _sink;
_StringAdapterSink(this._sink);

View file

@ -25,7 +25,7 @@ const Utf8Codec utf8 = Utf8Codec();
/// A [Utf8Codec] encodes strings to utf-8 code units (bytes) and decodes
/// UTF-8 code units to strings.
class Utf8Codec extends Encoding {
final class Utf8Codec extends Encoding {
final bool _allowMalformed;
/// Instantiates a new [Utf8Codec].
@ -82,7 +82,7 @@ class Utf8Codec extends Encoding {
/// final encodedSample = utf8Encoder.convert(sample);
/// print(encodedSample);
/// ```
class Utf8Encoder extends Converter<String, List<int>> {
final class Utf8Encoder extends Converter<String, List<int>> {
const Utf8Encoder();
/// Converts [string] to its UTF-8 code units (a list of
@ -232,7 +232,7 @@ class _Utf8Encoder {
/// This class encodes chunked strings to UTF-8 code units (unsigned 8-bit
/// integers).
class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin {
class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSink {
final ByteConversionSink _sink;
_Utf8EncoderSink(this._sink);
@ -318,7 +318,7 @@ class _Utf8EncoderSink extends _Utf8Encoder with StringConversionSinkMixin {
/// final decodedBytes = utf8Decoder.convert(encodedBytes);
/// print(decodedBytes); // <EFBFBD>
/// ```
class Utf8Decoder extends Converter<List<int>, String> {
final class Utf8Decoder extends Converter<List<int>, String> {
final bool _allowMalformed;
/// Instantiates a new [Utf8Decoder].

View file

@ -62,7 +62,7 @@ class _WindowsCodePageEncoder extends Converter<String, List<int>> {
external static List<int> _encodeString(String string);
}
class _WindowsCodePageEncoderSink extends StringConversionSinkBase {
class _WindowsCodePageEncoderSink extends StringConversionSink {
// TODO(floitsch): provide more efficient conversions when the input is
// not a String.
@ -106,7 +106,7 @@ class _WindowsCodePageDecoder extends Converter<List<int>, String> {
external static String _decodeBytes(List<int> bytes);
}
class _WindowsCodePageDecoderSink extends ByteConversionSinkBase {
class _WindowsCodePageDecoderSink extends ByteConversionSink {
// TODO(floitsch): provide more efficient conversions when the input is
// a slice.

View file

@ -9,7 +9,7 @@ import 'package:expect/expect.dart';
// This test implements a new special interface that can be used to
// send data more efficiently between two converters.
abstract class MyChunkedIntSink extends ChunkedConversionSink<int> {
abstract class MyChunkedIntSink implements ChunkedConversionSink<int> {
MyChunkedIntSink();
factory MyChunkedIntSink.from(sink) = IntAdapterSink;
factory MyChunkedIntSink.withCallback(callback) {
@ -32,7 +32,7 @@ class IntAdapterSink extends MyChunkedIntSink {
void specialI(int o) => add(o);
}
abstract class MyChunkedBoolSink extends ChunkedConversionSink<bool> {
abstract class MyChunkedBoolSink implements ChunkedConversionSink<bool> {
MyChunkedBoolSink();
factory MyChunkedBoolSink.from(sink) = BoolAdapterSink;
factory MyChunkedBoolSink.withCallback(callback) {
@ -115,7 +115,7 @@ class IdentityConverter<T> extends Converter<T, T> {
}
}
class IdentitySink<T> extends ChunkedConversionSink<T> {
class IdentitySink<T> implements ChunkedConversionSink<T> {
final _sink;
IdentitySink(this._sink);
void add(T o) => _sink.add(o);

View file

@ -9,7 +9,7 @@ import 'package:expect/expect.dart';
// Test that the String and ByteConversionSinks make a copy when they need to
// adapt.
class MyByteSink extends ByteConversionSinkBase {
class MyByteSink extends ByteConversionSink {
var accumulator = [];
add(List<int> bytes) {
accumulator.add(bytes);
@ -28,7 +28,7 @@ void testBase() {
Expect.equals(2, byteSink.accumulator[1][0]);
}
class MyChunkedSink extends ChunkedConversionSink<List<int>> {
class MyChunkedSink implements ChunkedConversionSink<List<int>> {
var accumulator = [];
add(List<int> bytes) {
accumulator.add(bytes);

View file

@ -57,7 +57,7 @@ final TESTS = [
[r'\foo', r'"\\foo"'],
];
class MyStringConversionSink extends StringConversionSinkBase {
class MyStringConversionSink extends StringConversionSink {
var buffer = new StringBuffer();
var callback;

View file

@ -5,7 +5,7 @@
import "package:expect/expect.dart";
import 'dart:convert';
class MySink extends ChunkedConversionSink<String> {
class MySink implements ChunkedConversionSink<String> {
final Function _add;
final Function _close;

View file

@ -11,7 +11,7 @@ import 'package:expect/expect.dart';
// This test implements a new special interface that can be used to
// send data more efficiently between two converters.
abstract class MyChunkedIntSink extends ChunkedConversionSink<int> {
abstract class MyChunkedIntSink implements ChunkedConversionSink<int> {
MyChunkedIntSink();
factory MyChunkedIntSink.from(sink) = IntAdapterSink;
factory MyChunkedIntSink.withCallback(callback) {
@ -34,7 +34,7 @@ class IntAdapterSink extends MyChunkedIntSink {
void specialI(int o) => add(o);
}
abstract class MyChunkedBoolSink extends ChunkedConversionSink<bool> {
abstract class MyChunkedBoolSink implements ChunkedConversionSink<bool> {
MyChunkedBoolSink();
factory MyChunkedBoolSink.from(sink) = BoolAdapterSink;
factory MyChunkedBoolSink.withCallback(callback) {
@ -117,7 +117,7 @@ class IdentityConverter<T> extends Converter<T, T> {
}
}
class IdentitySink<T> extends ChunkedConversionSink<T> {
class IdentitySink<T> implements ChunkedConversionSink<T> {
final _sink;
IdentitySink(this._sink);
void add(T o) => _sink.add(o);

View file

@ -11,7 +11,7 @@ import 'package:expect/expect.dart';
// Test that the String and ByteConversionSinks make a copy when they need to
// adapt.
class MyByteSink extends ByteConversionSinkBase {
class MyByteSink extends ByteConversionSink {
var accumulator = [];
add(List<int> bytes) {
accumulator.add(bytes);
@ -30,7 +30,7 @@ void testBase() {
Expect.equals(2, byteSink.accumulator[1][0]);
}
class MyChunkedSink extends ChunkedConversionSink<List<int>> {
class MyChunkedSink implements ChunkedConversionSink<List<int>> {
var accumulator = [];
add(List<int> bytes) {
accumulator.add(bytes);

View file

@ -59,7 +59,7 @@ final TESTS = [
[r'\foo', r'"\\foo"'],
];
class MyStringConversionSink extends StringConversionSinkBase {
class MyStringConversionSink extends StringConversionSink {
var buffer = new StringBuffer();
var callback;

View file

@ -7,7 +7,7 @@
import "package:expect/expect.dart";
import 'dart:convert';
class MySink extends ChunkedConversionSink<String> {
class MySink implements ChunkedConversionSink<String> {
final Function _add;
final Function _close;