Move to pkg:lints (#120)

Co-authored-by: Jacob MacDonald <jakemac@google.com>
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 7f965d2..b14bfc6 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,43 +1,34 @@
-include: package:pedantic/analysis_options.yaml
+include: package:lints/recommended.yaml
 analyzer:
   strong-mode:
     implicit-casts: false
 linter:
   rules:
-    - avoid_empty_else
-    - avoid_init_to_null
-    - avoid_null_checks_in_equality_operators
+    - avoid_catching_errors
+    - avoid_private_typedef_functions
+    - avoid_redundant_argument_values
     - avoid_unused_constructor_parameters
-    - await_only_futures
-    - camel_case_types
     - cancel_subscriptions
-    #- constant_identifier_names
-    - control_flow_in_finally
     - directives_ordering
-    - empty_catches
-    - empty_constructor_bodies
-    - empty_statements
-    - hash_and_equals
-    - implementation_imports
-    - iterable_contains_unrelated_type
-    - library_names
-    - library_prefixes
-    - list_remove_unrelated_type
-    - non_constant_identifier_names
-    - overridden_fields
+    - join_return_with_assignment
+    - lines_longer_than_80_chars
+    - missing_whitespace_between_adjacent_strings
+    - no_runtimeType_toString
+    - only_throw_errors
     - package_api_docs
-    - package_names
-    - package_prefixed_library_names
-    - prefer_equal_for_default_values
-    - prefer_final_fields
-    - prefer_generic_function_type_aliases
-    - prefer_is_not_empty
-    - slash_for_doc_comments
+    - prefer_asserts_in_initializer_lists
+    - prefer_const_declarations
+    - prefer_expression_function_bodies
+    - prefer_interpolation_to_compose_strings
+    - prefer_relative_imports
+    - prefer_single_quotes
+    - sort_pub_dependencies
     - test_types_in_equals
     - throw_in_finally
-    - type_init_formals
-    - unnecessary_brace_in_string_interps
-    - unnecessary_const
-    - unnecessary_new
-    - unrelated_type_equality_checks
-    - valid_regexps
+    - type_annotate_public_apis
+    - unnecessary_lambdas
+    - unnecessary_null_aware_assignments
+    - unnecessary_parenthesis
+    - unnecessary_statements
+    - use_is_even_rather_than_modulo
+    - use_string_buffers
diff --git a/benchmark/benchmark.dart b/benchmark/benchmark.dart
index adde6f8..bdb21db 100644
--- a/benchmark/benchmark.dart
+++ b/benchmark/benchmark.dart
@@ -11,14 +11,13 @@
 import 'dart:io';
 
 import 'package:path/path.dart' as p;
-
 import 'package:yaml/yaml.dart';
 
 const numTrials = 100;
 const runsPerTrial = 1000;
 
-final source = loadFile('input.yaml');
-final expected = loadFile('output.json');
+final source = _loadFile('input.yaml');
+final expected = _loadFile('output.json');
 
 void main(List<String> args) {
   var best = double.infinity;
@@ -29,7 +28,7 @@
     var start = DateTime.now();
 
     // For a single benchmark, convert the source multiple times.
-    var result;
+    Object? result;
     for (var j = 0; j < runsPerTrial; j++) {
       result = loadYaml(source);
     }
@@ -51,27 +50,18 @@
     // Don't print the first run. It's always terrible since the VM hasn't
     // warmed up yet.
     if (i == 0) continue;
-    printResult("Run ${padLeft('#$i', 3)}", elapsed);
+    _printResult("Run ${'#$i'.padLeft(3, '')}", elapsed);
   }
 
-  printResult('Best   ', best);
+  _printResult('Best   ', best);
 }
 
-String loadFile(String name) {
+String _loadFile(String name) {
   var path = p.join(p.dirname(p.fromUri(Platform.script)), name);
   return File(path).readAsStringSync();
 }
 
-void printResult(String label, double time) {
-  print('$label: ${padLeft(time.toStringAsFixed(3), 4)}ms '
+void _printResult(String label, double time) {
+  print('$label: ${time.toStringAsFixed(3).padLeft(4, '0')}ms '
       "${'=' * ((time * 100).toInt())}");
 }
-
-String padLeft(input, int length) {
-  var result = input.toString();
-  if (result.length < length) {
-    result = ' ' * (length - result.length) + result;
-  }
-
-  return result;
-}
diff --git a/example/example.dart b/example/example.dart
index 672ead9..bb283a3 100644
--- a/example/example.dart
+++ b/example/example.dart
@@ -8,6 +8,6 @@
 import 'package:yaml/yaml.dart';
 
 void main() {
-  var doc = loadYaml("YAML: YAML Ain't Markup Language");
+  var doc = loadYaml("YAML: YAML Ain't Markup Language") as Map;
   print(doc['YAML']);
 }
diff --git a/lib/src/equality.dart b/lib/src/equality.dart
index edaef89..f0755ca 100644
--- a/lib/src/equality.dart
+++ b/lib/src/equality.dart
@@ -19,7 +19,7 @@
 ///
 /// This considers `NaN` values to be equivalent, handles self-referential
 /// structures, and considers [YamlScalar]s to be equal to their values.
-bool deepEquals(obj1, obj2) => _DeepEquals().equals(obj1, obj2);
+bool deepEquals(Object? obj1, Object? obj2) => _DeepEquals().equals(obj1, obj2);
 
 /// A class that provides access to the list of parent objects used for loop
 /// detection.
@@ -28,7 +28,7 @@
   final _parents2 = [];
 
   /// Returns whether [obj1] and [obj2] are structurally equivalent.
-  bool equals(obj1, obj2) {
+  bool equals(Object? obj1, Object? obj2) {
     if (obj1 is YamlScalar) obj1 = obj1.value;
     if (obj2 is YamlScalar) obj2 = obj2.value;
 
@@ -100,7 +100,7 @@
 /// This supports deep equality for maps and lists, including those with
 /// self-referential structures, and returns the same hash code for
 /// [YamlScalar]s and their values.
-int deepHashCode(obj) {
+int deepHashCode(Object? obj) {
   var parents = [];
 
   int _deepHashCode(value) {
diff --git a/lib/src/loader.dart b/lib/src/loader.dart
index 4ec6017..f7cd6c9 100644
--- a/lib/src/loader.dart
+++ b/lib/src/loader.dart
@@ -6,10 +6,10 @@
 // https://opensource.org/licenses/MIT.
 
 import 'package:source_span/source_span.dart';
-import 'package:yaml/src/error_listener.dart';
 
 import 'charcodes.dart';
 import 'equality.dart';
+import 'error_listener.dart';
 import 'event.dart';
 import 'parser.dart';
 import 'yaml_document.dart';
@@ -91,7 +91,7 @@
       case EventType.mappingStart:
         return _loadMapping(firstEvent as MappingStartEvent);
       default:
-        throw 'Unreachable';
+        throw StateError('Unreachable');
     }
   }
 
diff --git a/lib/src/parser.dart b/lib/src/parser.dart
index 8a559c8..ddbfd4e 100644
--- a/lib/src/parser.dart
+++ b/lib/src/parser.dart
@@ -5,10 +5,12 @@
 // license that can be found in the LICENSE file or at
 // https://opensource.org/licenses/MIT.
 
+// ignore_for_file: constant_identifier_names
+
 import 'package:source_span/source_span.dart';
 import 'package:string_scanner/string_scanner.dart';
-import 'package:yaml/src/error_listener.dart';
 
+import 'error_listener.dart';
 import 'event.dart';
 import 'scanner.dart';
 import 'style.dart';
@@ -40,10 +42,10 @@
 
   /// Creates a parser that parses [source].
   ///
-  /// If [recover] is true, will attempt to recover from parse errors and may return
-  /// invalid or synthetic nodes. If [errorListener] is also supplied, its onError
-  /// method will be called for each error recovered from. It is not valid to
-  /// provide [errorListener] if [recover] is false.
+  /// If [recover] is true, will attempt to recover from parse errors and may
+  /// return invalid or synthetic nodes. If [errorListener] is also supplied,
+  /// its onError method will be called for each error recovered from. It is not
+  /// valid to provide [errorListener] if [recover] is false.
   Parser(String source,
       {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener})
       : assert(recover || errorListener == null),
@@ -117,7 +119,7 @@
       case _State.FLOW_MAPPING_EMPTY_VALUE:
         return _parseFlowMappingValue(empty: true);
       default:
-        throw 'Unreachable';
+        throw StateError('Unreachable');
     }
   }
 
@@ -226,7 +228,7 @@
       _scanner.scan();
       return DocumentEndEvent(token.span, isImplicit: false);
     } else {
-      return DocumentEndEvent(token.span.start.pointSpan(), isImplicit: true);
+      return DocumentEndEvent(token.span.start.pointSpan());
     }
   }
 
diff --git a/lib/src/scanner.dart b/lib/src/scanner.dart
index fcf6d27..e1c584f 100644
--- a/lib/src/scanner.dart
+++ b/lib/src/scanner.dart
@@ -5,11 +5,13 @@
 // license that can be found in the LICENSE file or at
 // https://opensource.org/licenses/MIT.
 
+// ignore_for_file: constant_identifier_names
+
 import 'package:collection/collection.dart';
 import 'package:source_span/source_span.dart';
 import 'package:string_scanner/string_scanner.dart';
-import 'package:yaml/src/error_listener.dart';
 
+import 'error_listener.dart';
 import 'style.dart';
 import 'token.dart';
 import 'utils.dart';
@@ -291,11 +293,10 @@
   /// indicator.
   ///
   /// If so, this sets the scanner's last match to that indicator.
-  bool get _isDocumentIndicator {
-    return _scanner.column == 0 &&
-        _isBlankOrEndAt(3) &&
-        (_scanner.matches('---') || _scanner.matches('...'));
-  }
+  bool get _isDocumentIndicator =>
+      _scanner.column == 0 &&
+      _isBlankOrEndAt(3) &&
+      (_scanner.matches('---') || _scanner.matches('...'));
 
   /// Creates a scanner that scans [source].
   Scanner(String source,
@@ -407,7 +408,7 @@
         _fetchAnchor(anchor: false);
         return;
       case AMPERSAND:
-        _fetchAnchor(anchor: true);
+        _fetchAnchor();
         return;
       case EXCLAMATION:
         _fetchTag();
@@ -416,7 +417,7 @@
         _fetchFlowScalar(singleQuote: true);
         return;
       case DOUBLE_QUOTE:
-        _fetchFlowScalar(singleQuote: false);
+        _fetchFlowScalar();
         return;
       case VERTICAL_BAR:
         if (!_inBlockContext) _invalidScalarCharacter();
@@ -424,7 +425,7 @@
         return;
       case RIGHT_ANGLE:
         if (!_inBlockContext) _invalidScalarCharacter();
-        _fetchBlockScalar(literal: false);
+        _fetchBlockScalar();
         return;
       case PERCENT:
       case AT:
@@ -1679,9 +1680,13 @@
   /// Whether this key must exist for the document to be scanned.
   final bool required;
 
-  _SimpleKey(this.tokenNumber, this.line, this.column, this.location,
-      {required bool required})
-      : required = required;
+  _SimpleKey(
+    this.tokenNumber,
+    this.line,
+    this.column,
+    this.location, {
+    required this.required,
+  });
 }
 
 /// The ways to handle trailing whitespace for a block scalar.
diff --git a/lib/src/style.dart b/lib/src/style.dart
index e3415d8..4121f09 100644
--- a/lib/src/style.dart
+++ b/lib/src/style.dart
@@ -5,6 +5,8 @@
 // license that can be found in the LICENSE file or at
 // https://opensource.org/licenses/MIT.
 
+// ignore_for_file: constant_identifier_names
+
 /// An enum of source scalar styles.
 class ScalarStyle {
   /// No source style was specified.
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 66ef3ed..db4612c 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -29,13 +29,14 @@
 /// [message] is the text of the warning. If [span] is passed, it's the portion
 /// of the document that the warning is associated with and should be included
 /// in the printed warning.
-typedef YamlWarningCallback = Function(String message, [SourceSpan? span]);
+typedef YamlWarningCallback = void Function(String message, [SourceSpan? span]);
 
 /// A callback for emitting a warning.
 ///
 /// In a very few cases, the YAML spec indicates that an implementation should
 /// emit a warning. To do so, it calls this callback. The default implementation
 /// prints a message using [print].
+// ignore: prefer_function_declarations_over_variables
 YamlWarningCallback yamlWarningCallback = (message, [SourceSpan? span]) {
   // TODO(nweiz): Print to stderr with color when issue 6943 is fixed and
   // dart:io is available.
diff --git a/lib/src/yaml_node.dart b/lib/src/yaml_node.dart
index 02c8439..458a61f 100644
--- a/lib/src/yaml_node.dart
+++ b/lib/src/yaml_node.dart
@@ -91,7 +91,7 @@
         super._(span);
 
   @override
-  dynamic operator [](key) => nodes[key]?.value;
+  dynamic operator [](Object? key) => nodes[key]?.value;
 }
 
 // TODO(nweiz): Use UnmodifiableListMixin when issue 18970 is fixed.
@@ -144,7 +144,7 @@
   dynamic operator [](int index) => nodes[index].value;
 
   @override
-  operator []=(int index, value) {
+  void operator []=(int index, Object? value) {
     throw UnsupportedError('Cannot modify an unmodifiable List');
   }
 }
diff --git a/lib/src/yaml_node_wrapper.dart b/lib/src/yaml_node_wrapper.dart
index fa6923d..5dbf486 100644
--- a/lib/src/yaml_node_wrapper.dart
+++ b/lib/src/yaml_node_wrapper.dart
@@ -19,7 +19,7 @@
     with pkg_collection.UnmodifiableMapMixin
     implements YamlMap {
   @override
-  final style;
+  final CollectionStyle style;
 
   final Map _dartMap;
 
@@ -39,10 +39,8 @@
       {CollectionStyle style = CollectionStyle.ANY})
       : this._(dartMap, NullSpan(sourceUrl), style: style);
 
-  YamlMapWrapper._(Map dartMap, SourceSpan span,
-      {this.style = CollectionStyle.ANY})
+  YamlMapWrapper._(Map dartMap, this.span, {this.style = CollectionStyle.ANY})
       : _dartMap = dartMap,
-        span = span,
         nodes = _YamlMapNodes(dartMap, span) {
     ArgumentError.checkNotNull(style, 'style');
   }
@@ -97,7 +95,7 @@
 /// A wrapper that makes a normal Dart list behave like a [YamlList].
 class YamlListWrapper extends ListBase implements YamlList {
   @override
-  final style;
+  final CollectionStyle style;
 
   final List _dartList;
 
@@ -122,10 +120,9 @@
       {CollectionStyle style = CollectionStyle.ANY})
       : this._(dartList, NullSpan(sourceUrl), style: style);
 
-  YamlListWrapper._(List dartList, SourceSpan span,
+  YamlListWrapper._(List dartList, this.span,
       {this.style = CollectionStyle.ANY})
       : _dartList = dartList,
-        span = span,
         nodes = _YamlListNodes(dartList, span) {
     ArgumentError.checkNotNull(style, 'style');
   }
@@ -139,7 +136,7 @@
   }
 
   @override
-  operator []=(int index, value) {
+  void operator []=(int index, Object? value) {
     throw UnsupportedError('Cannot modify an unmodifiable List.');
   }
 
@@ -173,7 +170,7 @@
   YamlNode operator [](int index) => _nodeForValue(_dartList[index], _span);
 
   @override
-  operator []=(int index, value) {
+  void operator []=(int index, Object? value) {
     throw UnsupportedError('Cannot modify an unmodifiable List.');
   }
 
diff --git a/lib/yaml.dart b/lib/yaml.dart
index 5c1e729..96869d3 100644
--- a/lib/yaml.dart
+++ b/lib/yaml.dart
@@ -35,10 +35,10 @@
 /// If [sourceUrl] is passed, it's used as the URL from which the YAML
 /// originated for error reporting.
 ///
-/// If [recover] is true, will attempt to recover from parse errors and may return
-/// invalid or synthetic nodes. If [errorListener] is also supplied, its onError
-/// method will be called for each error recovered from. It is not valid to
-/// provide [errorListener] if [recover] is false.
+/// If [recover] is true, will attempt to recover from parse errors and may
+/// return invalid or synthetic nodes. If [errorListener] is also supplied, its
+/// onError method will be called for each error recovered from. It is not valid
+/// to provide [errorListener] if [recover] is false.
 dynamic loadYaml(String yaml,
         {Uri? sourceUrl, bool recover = false, ErrorListener? errorListener}) =>
     loadYamlNode(yaml,
diff --git a/pubspec.yaml b/pubspec.yaml
index b9d836a..ace14a4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,11 @@
 name: yaml
-version: 3.1.0
+version: 3.1.1-dev
 
 description: A parser for YAML, a human-friendly data serialization standard
 homepage: https://github.com/dart-lang/yaml
 
 environment:
-  sdk: '>=2.12.0-0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   collection: ^1.15.0
@@ -13,6 +13,6 @@
   string_scanner: ^1.1.0
 
 dev_dependencies:
+  lints: ^1.0.0
   path: ^1.8.0
-  pedantic: ^1.10.0
-  test: ^1.16.0-nullsafety
+  test: ^1.16.0
diff --git a/test/utils.dart b/test/utils.dart
index 0aeaea5..5b85234 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -15,7 +15,7 @@
 /// Returns a matcher that asserts that the value equals [expected].
 ///
 /// This handles recursive loops and considers `NaN` to equal itself.
-Matcher deepEquals(expected) => predicate(
+Matcher deepEquals(Object? expected) => predicate(
     (actual) => equality.deepEquals(actual, expected), 'equals $expected');
 
 /// Constructs a new yaml.YamlMap, optionally from a normal Map.
@@ -35,7 +35,7 @@
 
 /// Asserts that a string containing a single YAML document produces a given
 /// value when loaded.
-void expectYamlLoads(expected, String source) {
+void expectYamlLoads(Object? expected, String source) {
   var actual = loadYaml(cleanUpLiteral(source));
   expect(actual, deepEquals(expected));
 }
diff --git a/test/yaml_node_wrapper_test.dart b/test/yaml_node_wrapper_test.dart
index a64ab58..a7bf6b1 100644
--- a/test/yaml_node_wrapper_test.dart
+++ b/test/yaml_node_wrapper_test.dart
@@ -220,7 +220,7 @@
   });
 }
 
-Matcher isNullSpan(sourceUrl) => predicate((SourceSpan span) {
+Matcher isNullSpan(Object sourceUrl) => predicate((SourceSpan span) {
       expect(span, TypeMatcher<SourceSpan>());
       expect(span.length, equals(0));
       expect(span.text, isEmpty);