-
Notifications
You must be signed in to change notification settings - Fork 58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FED-1863 Required props lint #871
Conversation
…o required-props-lint
import 'package:analyzer/dart/element/element.dart'; | ||
import 'package:over_react_analyzer_plugin/src/util/util.dart'; | ||
|
||
// Performance optimization notes: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I spent quite a bit of time optimizing this function, and I feel pretty happy about its performance!
In practice, usage is optimized further via the caching done with _cachedGetAllRequiredProps
.
@@ -147,59 +150,71 @@ class _DiagnosticGenerator { | |||
/// by the given [unitResult]. If any of the contributors throws an exception, | |||
/// also create a non-fatal 'plugin.error' notification. | |||
Future<_GeneratorResult<List<AnalysisError>>> generateErrors(ResolvedUnitResult unitResult) async { | |||
return _generateErrors(unitResult, DiagnosticCollectorImpl(shouldComputeFixes: false)); | |||
return _generateErrors(unitResult, DiagnosticCollectorImpl(shouldComputeFixes: false), | |||
catchInconsistentAnalysisException: true); | |||
} | |||
|
|||
/// Creates an 'edit.getFixes' response for the location in the file specified | |||
/// by the given [request]. If any of the contributors throws an exception, | |||
/// also create a non-fatal 'plugin.error' notification. | |||
Future<_GeneratorResult<EditGetFixesResult>> generateFixesResponse(DartFixesRequest request) async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd recommend using whitespace-agnostic diff for these diffs
@@ -53,62 +54,121 @@ render() { | |||
// </editor-fold> | |||
|
|||
class MissingRequiredPropDiagnostic extends ComponentUsageDiagnosticContributor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this diagnostic always existed but was only partially implemented, was always disabled, and was never fully reviewed, this full file should be reviewed as if it were newly-added, as opposed to reviewing just the diff
/// Represents a prop that was considered required in its declaration, | ||
/// but is ignored by the consuming class. | ||
ignoredByConsumingClass(isRequired: false, requirednessLevel: 1), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is currently unused, but will get used as part of updates to this file in FED-2015.
While working on that, I wanted to come back to this PR to do a little bit of refactoring, and also added requirednessLevel
and new PropRequiredness
enum test cases, so I figured I'd just stub it in now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple questions.
Insane test coverage. 🥇
/// Returns whether the debug helper should be enabled, caching results per result | ||
/// so we don't have to run it in in every [computeErrorsForUsage]. | ||
/// | ||
/// TODO Add shared debug flag computation in DiagnosticContributor/DiagnosticCollector |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be addressed in this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, but I would love to circle back to it later on, maybe next time we add a new debug flag
// DOM and SVG components are common and have a large number of props, none of which are required; | ||
// short-circuit here for performance. | ||
if (const {'DomProps', 'SvgProps'}.contains(propsClassElement.name)) return; // [1] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
over_react: | ||
errors: | ||
# Opt into this diagnostic that's disabled by default. | ||
over_react_annotation_required_prop: info |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is info
the default severity of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't really have a default severity since it's disabled by default, and to enable it you also have to specify a severity
final incompleteBuilder = WithLateRequired(); | ||
incompleteBuilder(); | ||
|
||
WithLateRequired()(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't looked at this PR, but I was just messing around in the playground and wondering if it shouldn't be linting when required prop validation is disabled on the usage like this: (or maybe I missed something)
(WithLateRequired()..disableRequiredPropValidation())();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh good catch, I forgot about that. Hmm. Yeah either we could not lint when that call is present, or make them also add an ignore comment when it's present.
I'm leaning toward not linting when it's present? What do you guys think? @sydneyjodon-wk @aaronlademann-wf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also like not linting when it's present
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// FIXME(FED-2015) remove once these are properly ignored in generated code | ||
.where((e) => e.errorCode.name.toLowerCase() != 'invalid_use_of_visible_for_overriding_member') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Starting QA on this :loading: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QA +1 Smoke tested
- Manually verify that diagnostic behaves as expected in tools/analyzer_plugin/playground/web/missing_required_props.dart
- Remove the
over_react_annotation_required_prop
line in the playground's analysis_options.yaml and verify that annotation-required props don't lint by default - Try typing in the playground and verify there are virtually no
InconsistentAnalysisExceptions
errors compared to the base branch - Verify behavior of debug flag comments looks good:
-
// debug: over_react_metrics
- Verify new behavior mentioned in Changes section looks good
- Verify the performance of this diagnostic looks good
-
// debug: over_react_required_props
- shows information about required props for each builder
-
Dependent PR
This PR is dependent on #870
Motivation
To help provide a good developer experience when working with required late props, we want to provide a lint that warns when a component is missing required props.
That way, devs can get static warnings, and not wait until they hit our runtime errors to find out they were missing props.
This lint should be similar to the warnings you get when you are missing required function parameters.
We had a partial implementation of this lint, and we needed to get it production-ready.
Changes
MissingRequiredPropDiagnostic
implementation, enable it, add testslate
required and@requiredProp
required props, but after some back and forth I opted to only lint forlate
required by default. For a more detailed explanation, see comment in tools/analyzer_plugin/lib/src/plugin.dartgetAllProps
to get all props for a props class and its supertypesgetAllRequiredProps
to collect info on which props are requiredisRequiredPropValidationDisabled
InconsistentAnalysisException
, unrelated to this PR. I found similar issues documented in Dart SDK tooling, and applied a similar workaround.debug: over_react_metrics
output to aid in performance optimizinggetAllComponentUsages
overheadAnalyzerDebugHelper
- make log message and location computation lazy by default, so that we're not slowing down performance when debug flags aren't enabledRelease Notes
Review
See CONTRIBUTING.md for more details on review types (+1 / QA +1 / +10) and code review process.
Please review:
QA Checklist
over_react_annotation_required_prop
line in the playground's analysis_options.yaml and verify that annotation-required props don't lint by defaultInconsistentAnalysisExceptions
errors compared to the base branch// debug: over_react_metrics
// debug: over_react_required_props
- shows information about required props for each builderMerge Checklist
While we perform many automated checks before auto-merging, some manual checks are needed: