Currently in avoid_web_libraries_in_flutter we need to parse pubspecs to identify Flutter web plugins:
This happens _per_ compilation unit. It would be great if we could cache this information sensibly.
/cc @scheglov @bwilkerson @srawlins for thoughts.
Parsing a pubspec only works in a pub package. I assume we have (or will have) a different way of identifying flutter web plugins internally. It kind of seems like a package-specific test, so perhaps it should be added to WorkspacePackage (which really needs to be renamed to just Package, and the sooner the better).
That's my assumption too. Not sure what the plan is there.
a different way of identifying flutter web plugins internally.
Maybe @yjbanov or @hterkelsen know?
Some other art/hackery in this area: Dartdoc has a package information cache where, given a library element, we look up its package information. It has good properties for dartdoc at least and is extensible to other kinds of packages besides SDK and pub. https://github.com/dart-lang/dartdoc/blob/master/lib/src/package_meta.dart#L96
Do we know the performance impact of avoid_web_libraries_in_flutter? If we do not know, or if we know that it's negative, let's revert until this issue is resolved.
/cc @chingjun on how things work internally, but you probably want to take the discussion offline.
Doing some quick benchmarking, the numbers don't look terrible.
Running against flutter_gallery I'm seeing about 9ms spent in this lint (of 1107 total).
dart bin/linter.dart --benchmark -q -c ../flutter/packages/flutter/lib/analysis_options_user.yaml ../flutter/examples/flutter_gallery
------------------------------------------------------
Timings ms
------------------------------------------------------
prefer_relative_imports 232
flutter_style_todos 84
lines_longer_than_80_chars 79
prefer_double_quotes 63
invariant_booleans 61
unnecessary_this 34
cancel_subscriptions 27
prefer_const_constructors 27
prefer_const_declarations 23
avoid_returning_this 19
always_require_non_null_named_parameters 17
prefer_is_not_empty 17
public_member_api_docs 17
prefer_contains 16
null_closures 15
prefer_is_empty 15
close_sinks 14
directives_ordering 13
void_checks 13
avoid_positional_boolean_parameters 13
prefer_void_to_null 12
avoid_returning_null 10
prefer_final_fields 10
avoid_web_libraries_in_flutter 9
<snip ... />
Full run.
dart bin/linter.dart --benchmark -q -c ../flutter/packages/flutter/lib/analysis_options_user.yaml ../flutter/examples/flutter_gallery
------------------------------------------------------
Timings ms
------------------------------------------------------
prefer_relative_imports 232
flutter_style_todos 84
lines_longer_than_80_chars 79
prefer_double_quotes 63
invariant_booleans 61
unnecessary_this 34
cancel_subscriptions 27
prefer_const_constructors 27
prefer_const_declarations 23
avoid_returning_this 19
always_require_non_null_named_parameters 17
prefer_is_not_empty 17
public_member_api_docs 17
prefer_contains 16
null_closures 15
prefer_is_empty 15
close_sinks 14
directives_ordering 13
void_checks 13
avoid_positional_boolean_parameters 13
prefer_void_to_null 12
avoid_returning_null 10
prefer_final_fields 10
avoid_web_libraries_in_flutter 9
non_constant_identifier_names 9
package_api_docs 9
unnecessary_overrides 9
control_flow_in_finally 8
cascade_invocations 8
always_specify_types 7
avoid_unnecessary_containers 7
unnecessary_lambdas 6
avoid_print 6
annotate_overrides 6
iterable_contains_unrelated_type 5
omit_local_variable_types 5
always_put_control_body_on_new_line 5
file_names 5
avoid_renaming_method_parameters 5
overridden_fields 5
parameter_assignments 5
prefer_initializing_formals 5
avoid_slow_async_io 5
prefer_collection_literals 5
avoid_types_on_closure_parameters 5
recursive_getters 5
prefer_int_literals 4
unnecessary_const 4
join_return_with_assignment 4
avoid_void_async 4
sort_constructors_first 4
avoid_unused_constructor_parameters 4
use_setters_to_change_properties 4
constant_identifier_names 4
sort_child_properties_last 3
use_to_and_as_if_applicable 3
avoid_function_literals_in_foreach_calls 3
prefer_const_literals_to_create_immutables 3
always_put_required_named_parameters_first 3
avoid_types_as_parameter_names 3
prefer_single_quotes 3
prefer_expression_function_bodies 3
diagnostic_describe_all_properties 3
unrelated_type_equality_checks 2
avoid_returning_null_for_future 2
prefer_spread_collections 2
prefer_for_elements_to_map_fromIterable 2
prefer_final_locals 2
avoid_setters_without_getters 2
no_duplicate_case_values 2
unawaited_futures 2
unnecessary_statements 2
avoid_equals_and_hash_code_on_mutable_classes 2
prefer_iterable_whereType 2
hash_and_equals 2
implementation_imports 2
prefer_inlined_adds 2
curly_braces_in_flow_control_structures 2
prefer_if_null_operators 2
type_annotate_public_apis 2
list_remove_unrelated_type 2
unnecessary_getters_setters 2
slash_for_doc_comments 2
prefer_const_constructors_in_immutables 2
avoid_null_checks_in_equality_operators 2
camel_case_types 2
avoid_init_to_null 2
unnecessary_parenthesis 1
only_throw_errors 1
unsafe_html 1
prefer_asserts_in_initializer_lists 1
avoid_field_initializers_in_const_classes 1
valid_regexps 1
avoid_shadowing_type_parameters 1
unnecessary_await_in_return 1
avoid_returning_null_for_void 1
unnecessary_new 1
always_declare_return_types 1
avoid_annotating_with_dynamic 1
prefer_foreach 1
provide_deprecation_message 1
prefer_constructors_over_static_methods 1
avoid_relative_lib_imports 1
avoid_classes_with_only_static_members 1
sort_unnamed_constructors_first 1
use_full_hex_values_for_flutter_colors 1
unnecessary_brace_in_string_interps 1
use_string_buffers 1
literal_only_boolean_expressions 1
prefer_function_declarations_over_variables 1
prefer_interpolation_to_compose_strings 1
library_prefixes 1
use_function_type_syntax_for_parameters 0
avoid_catches_without_on_clauses 0
test_types_in_equals 0
library_names 0
empty_constructor_bodies 0
prefer_null_aware_operators 0
empty_catches 0
avoid_js_rounded_ints 0
package_prefixed_library_names 0
prefer_typing_uninitialized_variables 0
throw_in_finally 0
avoid_implementing_value_types 0
prefer_final_in_for_each 0
comment_references 0
no_adjacent_strings_in_list 0
avoid_double_and_int_checks 0
await_only_futures 0
prefer_bool_in_asserts 0
avoid_private_typedef_functions 0
avoid_catching_errors 0
unnecessary_null_aware_assignments 0
avoid_empty_else 0
prefer_generic_function_type_aliases 0
avoid_return_types_on_setters 0
unnecessary_null_in_if_null_operators 0
prefer_asserts_with_message 0
use_rethrow_when_possible 0
prefer_equal_for_default_values 0
avoid_as 0
avoid_single_cascade_in_expression_statements 0
one_member_abstracts 0
prefer_adjacent_string_concatenation 0
prefer_conditional_assignment 0
camel_case_extensions 0
avoid_bool_literals_in_conditional_expressions 0
empty_statements 0
super_goes_last 0
prefer_mixin 0
prefer_if_elements_to_conditional_expressions 0
prefer_is_not_operator 0
type_init_formals 0
------------------------------------------------------
Total 1107
------------------------------------------------------
/fyi @devoncarew
(Note that prefer_relative_imports is getting a tune-up in #1812.)
(Note that
prefer_relative_importsis getting a tune-up in #1812.)
Thanks for that! I didn't realize so much time was going towards it. Mea culpa!
Mea culpa!
No worries! I was surprised too. The extra good news is that as a result we have a way better approach for these kinds of checks moving forward (and one that should play nice in google3).
In google3 we depend on other mechanism and not on the linter to avoid web libraries in flutter.
Fantastic @chingjun. This is great to know!