From 87fe6408a276b782c1a81f4194de20e8afabf95c Mon Sep 17 00:00:00 2001 From: Nikolas Rimikis Date: Wed, 16 Aug 2023 15:44:03 +0200 Subject: [PATCH] feat(neon_lints): add custom linting rules Signed-off-by: Nikolas Rimikis --- commitlint.yaml | 1 + packages/neon_lints/.gitignore | 12 ++ packages/neon_lints/CHANGELOG.md | 3 + packages/neon_lints/README.md | 8 + packages/neon_lints/analysis_options.yaml | 1 + packages/neon_lints/bin/neon_lints.dart | 67 +++++++ packages/neon_lints/lib/dart.yaml | 225 ++++++++++++++++++++++ packages/neon_lints/lib/flutter.yaml | 9 + packages/neon_lints/pubspec.yaml | 10 + 9 files changed, 336 insertions(+) create mode 100644 packages/neon_lints/.gitignore create mode 100644 packages/neon_lints/CHANGELOG.md create mode 100644 packages/neon_lints/README.md create mode 120000 packages/neon_lints/analysis_options.yaml create mode 100644 packages/neon_lints/bin/neon_lints.dart create mode 100644 packages/neon_lints/lib/dart.yaml create mode 100644 packages/neon_lints/lib/flutter.yaml create mode 100644 packages/neon_lints/pubspec.yaml diff --git a/commitlint.yaml b/commitlint.yaml index f017773e..8aea72a8 100644 --- a/commitlint.yaml +++ b/commitlint.yaml @@ -20,5 +20,6 @@ rules: - neon_news - neon_notes - neon_notifications + - neon_lints - nextcloud - sort_box diff --git a/packages/neon_lints/.gitignore b/packages/neon_lints/.gitignore new file mode 100644 index 00000000..840b0cc8 --- /dev/null +++ b/packages/neon_lints/.gitignore @@ -0,0 +1,12 @@ +# Files and directories created by pub. +.dart_tool/ +.packages + +# Conventional directory for build outputs. +build/ + +# Omit committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock + +coverage/ diff --git a/packages/neon_lints/CHANGELOG.md b/packages/neon_lints/CHANGELOG.md new file mode 100644 index 00000000..effe43c8 --- /dev/null +++ b/packages/neon_lints/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/packages/neon_lints/README.md b/packages/neon_lints/README.md new file mode 100644 index 00000000..846963e0 --- /dev/null +++ b/packages/neon_lints/README.md @@ -0,0 +1,8 @@ +A package containing a very strict set of linting rules. + +### Update rules: +To update the rules you need to update the `commitHash` variable in [neon_lints.dart](bin/neon_lints.dart) and execute it by running: +```sh +fvm dart run bin/neon_lints.dart +``` + diff --git a/packages/neon_lints/analysis_options.yaml b/packages/neon_lints/analysis_options.yaml new file mode 120000 index 00000000..38b1608a --- /dev/null +++ b/packages/neon_lints/analysis_options.yaml @@ -0,0 +1 @@ +lib/dart.yaml \ No newline at end of file diff --git a/packages/neon_lints/bin/neon_lints.dart b/packages/neon_lints/bin/neon_lints.dart new file mode 100644 index 00000000..ff62cd2e --- /dev/null +++ b/packages/neon_lints/bin/neon_lints.dart @@ -0,0 +1,67 @@ +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:yaml/yaml.dart'; + +/// Disabled rules. +/// +/// These rules will be added but disabled. +const disabledRules = [ + 'always_specify_types', + 'avoid_annotating_with_dynamic', + 'avoid_as', + 'avoid_catches_without_on_clauses', + 'avoid_catching_errors', + 'avoid_classes_with_only_static_members', + 'avoid_final_parameters', + 'avoid_print', + 'diagnostic_describe_all_properties', + 'lines_longer_than_80_chars', + 'no_default_cases', + 'one_member_abstracts', + 'prefer_double_quotes', + 'prefer_relative_imports', + 'unnecessary_final', +]; + +/// Rules that won't be added to the list. +/// +/// This is needed for rules not yet available in the current dart version. +const excludedRules = [ + 'no_self_assignments', + 'no_wildcard_variable_uses', +]; + +/// Commit hash to use to fetch the rules from upstream +const commitHash = '7f40f11'; + +Future main() async { + final uri = Uri.parse('https://raw.githubusercontent.com/dart-lang/linter/$commitHash/example/all.yaml'); + final result = await http.get(uri); + final document = loadYaml(result.body) as YamlMap; + final rules = (document['linter'] as YamlMap)['rules'] as YamlList; + + final buffer = StringBuffer(''' +analyzer: + language: + strict-casts: true + errors: + flutter_style_todos: ignore + todo: ignore + exclude: + - "**.g.dart" + - "**.mocks.dart" +linter: + rules: +'''); + + for (final line in rules) { + final excluded = excludedRules.contains(line); + if (!excluded) { + final disabled = disabledRules.contains(line); + buffer.writeln(' $line: ${!disabled}'); + } + } + + File('lib/dart.yaml').writeAsStringSync(buffer.toString()); +} diff --git a/packages/neon_lints/lib/dart.yaml b/packages/neon_lints/lib/dart.yaml new file mode 100644 index 00000000..881999a4 --- /dev/null +++ b/packages/neon_lints/lib/dart.yaml @@ -0,0 +1,225 @@ +analyzer: + language: + strict-casts: true + errors: + flutter_style_todos: ignore + todo: ignore + exclude: + - "**.g.dart" + - "**.mocks.dart" +linter: + rules: + always_declare_return_types: true + always_put_control_body_on_new_line: true + always_put_required_named_parameters_first: true + always_specify_types: false + always_use_package_imports: true + annotate_overrides: true + avoid_annotating_with_dynamic: false + avoid_bool_literals_in_conditional_expressions: true + avoid_catches_without_on_clauses: false + avoid_catching_errors: false + avoid_classes_with_only_static_members: false + avoid_double_and_int_checks: true + avoid_dynamic_calls: true + avoid_empty_else: true + avoid_equals_and_hash_code_on_mutable_classes: true + avoid_escaping_inner_quotes: true + avoid_field_initializers_in_const_classes: true + avoid_final_parameters: false + avoid_function_literals_in_foreach_calls: true + avoid_implementing_value_types: true + avoid_init_to_null: true + avoid_js_rounded_ints: true + avoid_multiple_declarations_per_line: true + avoid_null_checks_in_equality_operators: true + avoid_positional_boolean_parameters: true + avoid_print: false + avoid_private_typedef_functions: true + avoid_redundant_argument_values: true + avoid_relative_lib_imports: true + avoid_renaming_method_parameters: true + avoid_return_types_on_setters: true + avoid_returning_null_for_void: true + avoid_returning_this: true + avoid_setters_without_getters: true + avoid_shadowing_type_parameters: true + avoid_single_cascade_in_expression_statements: true + avoid_slow_async_io: true + avoid_type_to_string: true + avoid_types_as_parameter_names: true + avoid_types_on_closure_parameters: true + avoid_unnecessary_containers: true + avoid_unused_constructor_parameters: true + avoid_void_async: true + avoid_web_libraries_in_flutter: true + await_only_futures: true + camel_case_extensions: true + camel_case_types: true + cancel_subscriptions: true + cascade_invocations: true + cast_nullable_to_non_nullable: true + close_sinks: true + collection_methods_unrelated_type: true + combinators_ordering: true + comment_references: true + conditional_uri_does_not_exist: true + constant_identifier_names: true + control_flow_in_finally: true + curly_braces_in_flow_control_structures: true + dangling_library_doc_comments: true + depend_on_referenced_packages: true + deprecated_consistency: true + deprecated_member_use_from_same_package: true + diagnostic_describe_all_properties: false + directives_ordering: true + discarded_futures: true + do_not_use_environment: true + empty_catches: true + empty_constructor_bodies: true + empty_statements: true + eol_at_end_of_file: true + exhaustive_cases: true + file_names: true + flutter_style_todos: true + hash_and_equals: true + implementation_imports: true + implicit_call_tearoffs: true + implicit_reopen: true + invalid_case_patterns: true + join_return_with_assignment: true + leading_newlines_in_multiline_strings: true + library_annotations: true + library_names: true + library_prefixes: true + library_private_types_in_public_api: true + lines_longer_than_80_chars: false + literal_only_boolean_expressions: true + matching_super_parameters: true + missing_whitespace_between_adjacent_strings: true + no_adjacent_strings_in_list: true + no_default_cases: false + no_duplicate_case_values: true + no_leading_underscores_for_library_prefixes: true + no_leading_underscores_for_local_identifiers: true + no_literal_bool_comparisons: true + no_logic_in_create_state: true + no_runtimeType_toString: true + non_constant_identifier_names: true + noop_primitive_operations: true + null_check_on_nullable_type_parameter: true + null_closures: true + omit_local_variable_types: true + one_member_abstracts: false + only_throw_errors: true + overridden_fields: true + package_api_docs: true + package_names: true + package_prefixed_library_names: true + parameter_assignments: true + prefer_adjacent_string_concatenation: true + prefer_asserts_in_initializer_lists: true + prefer_asserts_with_message: true + prefer_collection_literals: true + prefer_conditional_assignment: true + prefer_const_constructors: true + prefer_const_constructors_in_immutables: true + prefer_const_declarations: true + prefer_const_literals_to_create_immutables: true + prefer_constructors_over_static_methods: true + prefer_contains: true + prefer_double_quotes: false + prefer_expression_function_bodies: true + prefer_final_fields: true + prefer_final_in_for_each: true + prefer_final_locals: true + prefer_final_parameters: true + prefer_for_elements_to_map_fromIterable: true + prefer_foreach: true + prefer_function_declarations_over_variables: true + prefer_generic_function_type_aliases: true + prefer_if_elements_to_conditional_expressions: true + prefer_if_null_operators: true + prefer_initializing_formals: true + prefer_inlined_adds: true + prefer_int_literals: true + prefer_interpolation_to_compose_strings: true + prefer_is_empty: true + prefer_is_not_empty: true + prefer_is_not_operator: true + prefer_iterable_whereType: true + prefer_mixin: true + prefer_null_aware_method_calls: true + prefer_null_aware_operators: true + prefer_relative_imports: false + prefer_single_quotes: true + prefer_spread_collections: true + prefer_typing_uninitialized_variables: true + prefer_void_to_null: true + provide_deprecation_message: true + public_member_api_docs: true + recursive_getters: true + require_trailing_commas: true + secure_pubspec_urls: true + sized_box_for_whitespace: true + sized_box_shrink_expand: true + slash_for_doc_comments: true + sort_child_properties_last: true + sort_constructors_first: true + sort_pub_dependencies: true + sort_unnamed_constructors_first: true + test_types_in_equals: true + throw_in_finally: true + tighten_type_of_initializing_formals: true + type_annotate_public_apis: true + type_init_formals: true + type_literal_in_constant_pattern: true + unawaited_futures: true + unnecessary_await_in_return: true + unnecessary_brace_in_string_interps: true + unnecessary_breaks: true + unnecessary_const: true + unnecessary_constructor_name: true + unnecessary_final: false + unnecessary_getters_setters: true + unnecessary_lambdas: true + unnecessary_late: true + unnecessary_library_directive: true + unnecessary_new: true + unnecessary_null_aware_assignments: true + unnecessary_null_aware_operator_on_extension_on_nullable: true + unnecessary_null_checks: true + unnecessary_null_in_if_null_operators: true + unnecessary_nullable_for_final_variable_declarations: true + unnecessary_overrides: true + unnecessary_parenthesis: true + unnecessary_raw_strings: true + unnecessary_statements: true + unnecessary_string_escapes: true + unnecessary_string_interpolations: true + unnecessary_this: true + unnecessary_to_list_in_spreads: true + unreachable_from_main: true + unrelated_type_equality_checks: true + unsafe_html: true + use_build_context_synchronously: true + use_colored_box: true + use_decorated_box: true + use_enums: true + use_full_hex_values_for_flutter_colors: true + use_function_type_syntax_for_parameters: true + use_if_null_to_convert_nulls_to_bools: true + use_is_even_rather_than_modulo: true + use_key_in_widget_constructors: true + use_late_for_private_fields_and_variables: true + use_named_constants: true + use_raw_strings: true + use_rethrow_when_possible: true + use_setters_to_change_properties: true + use_string_buffers: true + use_string_in_part_of_directives: true + use_super_parameters: true + use_test_throws_matchers: true + use_to_and_as_if_applicable: true + valid_regexps: true + void_checks: true diff --git a/packages/neon_lints/lib/flutter.yaml b/packages/neon_lints/lib/flutter.yaml new file mode 100644 index 00000000..46ae78a6 --- /dev/null +++ b/packages/neon_lints/lib/flutter.yaml @@ -0,0 +1,9 @@ +include: package:neon_lints/dart.yaml +linter: + rules: + public_member_api_docs: false + library_private_types_in_public_api: false + avoid_print: true +analyzer: + exclude: + - 'lib/generated_plugin_registrant.dart' diff --git a/packages/neon_lints/pubspec.yaml b/packages/neon_lints/pubspec.yaml new file mode 100644 index 00000000..7b10089f --- /dev/null +++ b/packages/neon_lints/pubspec.yaml @@ -0,0 +1,10 @@ +name: neon_lints +description: Linting package used in the nextcloud-neon project +version: 1.0.0 + +environment: + sdk: '>=3.0.0 <4.0.0' + +dependencies: + http: ^1.1.0 + yaml: ^3.1.2