refactor: update to use flutter default analysis (#114)

This commit is contained in:
James Collins
2024-10-14 18:57:30 +13:00
committed by GitHub
parent f368088a0a
commit 0753342599
6 changed files with 85 additions and 209 deletions

View File

@ -1,175 +1,28 @@
# ~ Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file # This file configures the analyzer, which statically analyzes Dart code to
# ~ for details. All rights reserved. Use of this source code is governed by a # check for errors, warnings, and lints.
# ~ BSD-style license that can be found in the LICENSE file.
# ~
# ~ A living list of rules following the Effective Dart guide.
# ~ https://www.dartlang.org/guides/language/effective-dart
# ~
# ~ Note: not everything suggested in the guide has a rule associated with it.
analyzer:
#strong-mode:
#implicit-casts: false
#implicit-dynamic: false
errors:
todo: ignore
#exclude:
# ~ Effective dart lint rules form https://github.com/dart-lang/linter
# ~ We have implemented all but lines_longer_than_80_chars & public_member_api_docs
linter:
rules:
# ~ --- STYLE
# ~ identifiers
- camel_case_types
- library_names
- file_names
- library_prefixes
- non_constant_identifier_names
- constant_identifier_names # ~ prefer
# ~ ordering
- directives_ordering
# ~ formating
- curly_braces_in_flow_control_structures
# ~ --- DOCUMENTATION
# ~ comments
# ~ doc comments
- slash_for_doc_comments
- package_api_docs # ~ prefer
- comment_references
# ~ markdown
# ~ writing
# ~ --- USAGE
# ~ libraries
- implementation_imports
- avoid_relative_lib_imports
# ~ strings
- prefer_adjacent_string_concatenation
- prefer_interpolation_to_compose_strings # ~ prefer
- unnecessary_brace_in_string_interps # ~ avoid
# ~ collections
- prefer_collection_literals
- avoid_function_literals_in_foreach_calls # ~ avoid
- prefer_iterable_whereType
# ~ functions
- prefer_function_declarations_over_variables
- unnecessary_lambdas
# ~ variables
- avoid_init_to_null
# ~ members
- unnecessary_getters_setters
- prefer_final_fields
- prefer_expression_function_bodies # consider
- unnecessary_this
- prefer_typing_uninitialized_variables
# ~ constructors
- prefer_initializing_formals
- type_init_formals
- empty_constructor_bodies
- unnecessary_new
- unnecessary_const
# ~ error handling
- avoid_catches_without_on_clauses # ~ avoid
- use_rethrow_when_possible
# ~ asynchrony
# ~ --- DESIGN
# ~ names
- use_to_and_as_if_applicable
# ~ libraries
# ~ classes
- one_member_abstracts # ~ avoid
- avoid_classes_with_only_static_members # ~ avoid
# ~ constructors
- prefer_constructors_over_static_methods
# ~ members
- use_setters_to_change_properties
- avoid_setters_without_getters
- avoid_returning_this # ~ avoid
# ~ types
- type_annotate_public_apis # ~ prefer
- omit_local_variable_types # ~ avoid
- avoid_types_on_closure_parameters # ~ avoid
- avoid_return_types_on_setters
- prefer_generic_function_type_aliases
- avoid_private_typedef_functions # ~ prefer
# ~ parameters
- avoid_positional_boolean_parameters # ~ avoid
# ~ equality
- hash_and_equals
- avoid_null_checks_in_equality_operators
# ~ Rules that are not used but are recommended by effective dart:
# #
# - public_member_api_docs # ~ We don't have time to document everything yet # The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# - lines_longer_than_80_chars # prefer # ~ Doesn't seem reasonable # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# ~ Rules that are not used # The following line activates a set of recommended lints for Flutter apps,
# - always_declare_return_types # packages, and plugins designed to encourage good coding practices.
# - always_put_control_body_on_new_line include: package:flutter_lints/flutter.yaml
# - always_put_required_named_parameters_first
# - always_require_non_null_named_parameters linter:
# - always_specify_types # The lint rules applied to this project can be customized in the
# - annotate_overrides # section below to disable rules from the `package:flutter_lints/flutter.yaml`
# - avoid_annotating_with_dynamic # included above or to enable additional rules. A list of all available lints
# - avoid_as # and their documentation is published at https://dart.dev/lints.
# - avoid_bool_literals_in_conditional_expressions #
# - avoid_catching_errors # Instead of disabling a lint rule for the entire project in the
# - avoid_double_and_int_checks # section below, it can also be suppressed for a single line of code
# - avoid_empty_else # or a specific dart file by using the `// ignore: name_of_lint` and
# - avoid_field_initializers_in_const_classes # `// ignore_for_file: name_of_lint` syntax on the line or in the file
# - avoid_js_rounded_ints # producing the lint.
# - avoid_renaming_method_parameters rules:
# - avoid_single_cascade_in_expression_statements # avoid_print: false # Uncomment to disable the `avoid_print` rule
# - avoid_slow_async_io # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
# - avoid_types_as_parameter_names
# - avoid_unused_constructor_parameters # Additional information about this file can be found at
# - await_only_futures # https://dart.dev/guides/language/analysis-options
# - cancel_subscriptions
# - cascade_invocations
# - close_sinks
# - control_flow_in_finally
# - empty_catches
# - empty_statements
# - invariant_booleans
# - iterable_contains_unrelated_type
# - join_return_with_assignment
# - list_remove_unrelated_type
# - literal_only_boolean_expressions
# - no_adjacent_strings_in_list
# - no_duplicate_case_values
# - null_closures
# - only_throw_errors
# - overridden_fields
# - package_names
# - package_prefixed_library_names
# - parameter_assignments
# - prefer_asserts_in_initializer_lists
# - prefer_bool_in_asserts
# - prefer_conditional_assignment
# - prefer_const_constructors
# - prefer_const_constructors_in_immutables
# - prefer_const_declarations
# - prefer_const_literals_to_create_immutables
# - prefer_contains
# - prefer_expression_function_bodies
# - prefer_final_locals
# - prefer_foreach
# - prefer_is_empty
# - prefer_is_not_empty
# - prefer_single_quotes
# - recursive_getters
# - sort_constructors_first
# - sort_unnamed_constructors_first
# - super_goes_last
# - test_types_in_equals
# - throw_in_finally
# - unawaited_futures
# - unnecessary_null_aware_assignments
# - unnecessary_null_in_if_null_operators
# - unnecessary_overrides
# - unnecessary_parenthesis
# - unnecessary_statements
# - unrelated_type_equality_checks
# - use_string_buffers
# - valid_regexps
# - void_checks

View File

@ -68,7 +68,7 @@ packages:
path: ".." path: ".."
relative: true relative: true
source: path source: path
version: "6.0.0" version: "5.1.0"
flutter_lints: flutter_lints:
dependency: "direct dev" dependency: "direct dev"
description: description:

View File

@ -102,7 +102,7 @@ class DotEnv {
} else if (['false', '0'].contains(value.toLowerCase())) { } else if (['false', '0'].contains(value.toLowerCase())) {
return false; return false;
} else { } else {
throw FormatException('Could not parse as a bool'); throw const FormatException('Could not parse as a bool');
} }
} }

View File

@ -54,6 +54,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_lints:
dependency: "direct dev"
description:
name: flutter_lints
sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -83,6 +91,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.0.1" version: "3.0.1"
lints:
dependency: transitive
description:
name: lints
sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235"
url: "https://pub.dev"
source: hosted
version: "4.0.0"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:

View File

@ -11,3 +11,10 @@ dependencies:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
sdk: flutter sdk: flutter
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is
# activated in the `analysis_options.yaml` file located at the root of your
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^4.0.0

View File

@ -7,48 +7,48 @@ const ceil = 100000;
void main() { void main() {
late Random rand; late Random rand;
const _psr = Parser(); const psr = Parser();
group('[Parser]', () { group('[Parser]', () {
setUp(() => rand = Random()); setUp(() => rand = Random());
test('it swallows leading "export"', () { test('it swallows leading "export"', () {
var out = _psr.swallow(' export foo = bar '); var out = psr.swallow(' export foo = bar ');
expect(out, equals('foo = bar')); expect(out, equals('foo = bar'));
out = _psr.swallow(' foo = bar export'); out = psr.swallow(' foo = bar export');
expect(out, equals('foo = bar export')); expect(out, equals('foo = bar export'));
}); });
test('it strips trailing comments', () { test('it strips trailing comments', () {
var out = _psr.strip( var out = psr.strip(
'needs="explanation" # It was the year when they finally immanentized the Eschaton.'); 'needs="explanation" # It was the year when they finally immanentized the Eschaton.');
expect(out, equals('needs="explanation"')); expect(out, equals('needs="explanation"'));
out = _psr.strip( out = psr.strip(
'needs="explanation # It was the year when they finally immanentized the Eschaton." '); 'needs="explanation # It was the year when they finally immanentized the Eschaton." ');
expect( expect(
out, out,
equals( equals(
'needs="explanation # It was the year when they finally immanentized the Eschaton."')); 'needs="explanation # It was the year when they finally immanentized the Eschaton."'));
out = _psr.strip( out = psr.strip(
'needs=explanation # It was the year when they finally immanentized the Eschaton."', 'needs=explanation # It was the year when they finally immanentized the Eschaton."',
includeQuotes: true); includeQuotes: true);
expect(out, equals('needs=explanation')); expect(out, equals('needs=explanation'));
out = _psr.strip(' # It was the best of times, it was a waste of time.'); out = psr.strip(' # It was the best of times, it was a waste of time.');
expect(out, isEmpty); expect(out, isEmpty);
}); });
test('it knows quoted # is not a comment', () { test('it knows quoted # is not a comment', () {
var doub = _psr.parseOne('foo = "ab#c"'); var doub = psr.parseOne('foo = "ab#c"');
var single = _psr.parseOne("foo = 'ab#c'"); var single = psr.parseOne("foo = 'ab#c'");
expect(doub['foo'], equals('ab#c')); expect(doub['foo'], equals('ab#c'));
expect(single['foo'], equals('ab#c')); expect(single['foo'], equals('ab#c'));
}); });
test('it handles quotes in a comment', () { test('it handles quotes in a comment', () {
// note terminal whitespace // note terminal whitespace
var sing = _psr.parseOne("fruit = 'banana' # comments can be 'sneaky!' "); var sing = psr.parseOne("fruit = 'banana' # comments can be 'sneaky!' ");
var doub = var doub =
_psr.parseOne('fruit = " banana" # comments can be "sneaky!" '); psr.parseOne('fruit = " banana" # comments can be "sneaky!" ');
var none = var none =
_psr.parseOne('fruit = banana # comments can be "sneaky!" '); psr.parseOne('fruit = banana # comments can be "sneaky!" ');
expect(sing['fruit'], equals('banana')); expect(sing['fruit'], equals('banana'));
expect(doub['fruit'], equals(' banana')); expect(doub['fruit'], equals(' banana'));
@ -56,24 +56,24 @@ void main() {
}); });
test('treats all # in unquoted as comments', () { test('treats all # in unquoted as comments', () {
var fail = var fail =
_psr.parseOne('fruit = banana # I\'m a comment with a final "quote"'); psr.parseOne('fruit = banana # I\'m a comment with a final "quote"');
expect(fail['fruit'], equals('banana')); expect(fail['fruit'], equals('banana'));
}); });
test('it handles unquoted values', () { test('it handles unquoted values', () {
var out = _psr.unquote(' str '); var out = psr.unquote(' str ');
expect(out, equals('str')); expect(out, equals('str'));
}); });
test('it handles double quoted values', () { test('it handles double quoted values', () {
var out = _psr.unquote('"val "'); var out = psr.unquote('"val "');
expect(out, equals('val ')); expect(out, equals('val '));
}); });
test('it handles single quoted values', () { test('it handles single quoted values', () {
var out = _psr.unquote("' val'"); var out = psr.unquote("' val'");
expect(out, equals(' val')); expect(out, equals(' val'));
}); });
test('retain trailing single quote', () { test('retain trailing single quote', () {
var out = _psr.unquote("retained'"); var out = psr.unquote("retained'");
expect(out, equals("retained'")); expect(out, equals("retained'"));
}); });
@ -85,7 +85,7 @@ void main() {
// }); // });
test('it skips empty lines', () { test('it skips empty lines', () {
var out = _psr.parse([ var out = psr.parse([
'# Define environment variables.', '# Define environment variables.',
' # comments will be stripped', ' # comments will be stripped',
'foo=bar # trailing junk', 'foo=bar # trailing junk',
@ -96,55 +96,55 @@ void main() {
}); });
test('it ignores duplicate keys', () { test('it ignores duplicate keys', () {
var out = _psr.parse(['foo=bar', 'foo=baz']); var out = psr.parse(['foo=bar', 'foo=baz']);
expect(out, equals({'foo': 'bar'})); expect(out, equals({'foo': 'bar'}));
}); });
test('it substitutes known variables into other values', () { test('it substitutes known variables into other values', () {
var out = _psr.parse(['foo=bar', r'baz=super$foo${foo}']); var out = psr.parse(['foo=bar', r'baz=super$foo${foo}']);
expect(out, equals({'foo': 'bar', 'baz': 'superbarbar'})); expect(out, equals({'foo': 'bar', 'baz': 'superbarbar'}));
}); });
test('it discards surrounding quotes', () { test('it discards surrounding quotes', () {
var out = _psr.parse([r"foo = 'bar'", r'export baz="qux"']); var out = psr.parse([r"foo = 'bar'", r'export baz="qux"']);
expect(out, equals({'foo': 'bar', 'baz': 'qux'})); expect(out, equals({'foo': 'bar', 'baz': 'qux'}));
}); });
test('it detects unquoted values', () { test('it detects unquoted values', () {
var out = _psr.surroundingQuote('no quotes here!'); var out = psr.surroundingQuote('no quotes here!');
expect(out, isEmpty); expect(out, isEmpty);
}); });
test('it detects double-quoted values', () { test('it detects double-quoted values', () {
var out = _psr.surroundingQuote('"double quoted"'); var out = psr.surroundingQuote('"double quoted"');
expect(out, equals('"')); expect(out, equals('"'));
}); });
test('it detects single-quoted values', () { test('it detects single-quoted values', () {
var out = _psr.surroundingQuote("'single quoted'"); var out = psr.surroundingQuote("'single quoted'");
expect(out, equals("'")); expect(out, equals("'"));
}); });
test('it performs variable substitution', () { test('it performs variable substitution', () {
var out = _psr.interpolate(r'a$foo$baz', {'foo': 'bar', 'baz': 'qux'}); var out = psr.interpolate(r'a$foo$baz', {'foo': 'bar', 'baz': 'qux'});
expect(out, equals('abarqux')); expect(out, equals('abarqux'));
}); });
test('it skips undefined variables', () { test('it skips undefined variables', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.interpolate('a\$jinx_$r', {}); var out = psr.interpolate('a\$jinx_$r', {});
expect(out, equals('a')); expect(out, equals('a'));
}); });
test('it handles explicitly null values in env', () { test('it handles explicitly null values in env', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.interpolate('a\$foo_$r\$baz_$r', {'foo_$r': null}); var out = psr.interpolate('a\$foo_$r\$baz_$r', {'foo_$r': null});
expect(out, equals('a')); expect(out, equals('a'));
}); });
test('it handles \${surrounding braces} on vars', () { test('it handles \${surrounding braces} on vars', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.interpolate('optional_\${foo_$r}', {'foo_$r': 'curlies'}); var out = psr.interpolate('optional_\${foo_$r}', {'foo_$r': 'curlies'});
expect(out, equals('optional_curlies')); expect(out, equals('optional_curlies'));
}); });
test('it handles equal signs in values', () { test('it handles equal signs in values', () {
var none = _psr.parseOne('foo=bar=qux'); var none = psr.parseOne('foo=bar=qux');
var sing = _psr.parseOne("foo='bar=qux'"); var sing = psr.parseOne("foo='bar=qux'");
var doub = _psr.parseOne('foo="bar=qux"'); var doub = psr.parseOne('foo="bar=qux"');
expect(none['foo'], equals('bar=qux')); expect(none['foo'], equals('bar=qux'));
expect(sing['foo'], equals('bar=qux')); expect(sing['foo'], equals('bar=qux'));
@ -153,17 +153,17 @@ void main() {
test('it skips var substitution in single quotes', () { test('it skips var substitution in single quotes', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.parseOne("some_var='my\$key_$r'", env: {'key_$r': 'val'}); var out = psr.parseOne("some_var='my\$key_$r'", env: {'key_$r': 'val'});
expect(out['some_var'], equals('my\$key_$r')); expect(out['some_var'], equals('my\$key_$r'));
}); });
test('it performs var subs in double quotes', () { test('it performs var subs in double quotes', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.parseOne('some_var="my\$key_$r"', env: {'key_$r': 'val'}); var out = psr.parseOne('some_var="my\$key_$r"', env: {'key_$r': 'val'});
expect(out['some_var'], equals('myval')); expect(out['some_var'], equals('myval'));
}); });
test('it performs var subs without quotes', () { test('it performs var subs without quotes', () {
var r = rand.nextInt(ceil); // avoid runtime collision with real env vars var r = rand.nextInt(ceil); // avoid runtime collision with real env vars
var out = _psr.parseOne("some_var=my\$key_$r", env: {'key_$r': 'val'}); var out = psr.parseOne("some_var=my\$key_$r", env: {'key_$r': 'val'});
expect(out['some_var'], equals('myval')); expect(out['some_var'], equals('myval'));
}); });
}); });