-
Notifications
You must be signed in to change notification settings - Fork 170
Add a lint for missing files in conditional imports #3080
Add a lint for missing files in conditional imports #3080
Conversation
class MissingConditionalImport extends LintRule { | ||
MissingConditionalImport() | ||
: super( | ||
name: 'missing_conditional_import', |
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.
As for naming, I might suggest that we use a name similar to the error code (URI_DOES_NOT_EXIST
) such as conditional_uri_does_not_exist
. There's a companion error code in the analyzer (URI_HAS_NOT_BEEN_GENERATED
) and we might want to have two separate messages for this lint to distinguish between those cases, but that's less clear to me.
(The only convention that I'm aware of for naming lints is that we're now actively discouraging using 'avoid', 'prefer' and other such designations from the style guide because those tend to change over time leaving us with misleading lint names. Other than that, lints should be named to either express the condition they're trying to ensure or the condition they're trying to prevent.)
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.
Thanks! I've changed it to conditional_uri_does_not_exist
.
There's a companion error code in the analyzer (URI_HAS_NOT_BEEN_GENERATED) and we might want to have two separate messages for this lint to distinguish between those cases, but that's less clear to me.
I don't know much about that so have no opinion, but if you think it would also be useful here I'm happy to add it - it doesn't seem like a complicated change (just changing the code/error depending on whether the uri ends with these suffixes?).
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.
Thinking about it a bit more, I'd propose that we leave it as is. If we get feedback from users that a different message would be helpful we can always update it later.
static const LintCode code = LintCode('missing_conditional_import', | ||
"The target of the conditional URI '{0}' doesn't exist.", | ||
correctionMessage: 'Try creating the file referenced by the URI, or ' | ||
'Try using a URI for a file that does exist.'); |
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.
nit: "Try" --> "try"
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.
Done, thanks!
String? uriContent = configuration.uri.stringValue; | ||
if (uriContent != null) { | ||
Source? source = configuration.uriSource; | ||
if (!(source?.exists() ?? false)) { |
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.
As you noted, this will probably work most of the time, but it would be better if we could ask the resource provider. Unfortunately there doesn't appear to be any way to access it currently.
My personal opinion is that we need to update LinterContext
to provide access to the resource provider and then pass that in when constructing the visitor. Unfortunately, that's a multi-step process, and I'm not sure we want to delay merging this rule while that happens.
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'm happy to go with your decision here. If you think it's worth doing (and I know enough to do it), I'm happy to. Although I'm not sure if having to support package:
URIs complicates using the resource provider. This exists()
call seemed to handle that (and dart:
URIs) for me which I thought might have complicated things :-)
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'm fine with leaving it as-is. You might consider adding a comment for future reference, because the fact that it isn't checking for overlays might not occur to a future reader.
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.
Done!
Would this lint be invalidated/updated correctly if the user saved a new file with the name that was used here? Would the server know if a file has import 'file_a.dart'
but that file does not exist, that creating a file at that location may require this file to be re-analyzed/linted?
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 don't know whether it is the case, but it ought to be re-analyzed when a new file is added, and we run lints as part of analyzing a file.
} | ||
|
||
@reflectiveTest | ||
class MissingConditionalImportTest extends LintRuleTest { |
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.
Yes, this is the preferred style for tests, thanks!
} | ||
} | ||
|
||
class _Visitor extends RecursiveAstVisitor<void> { |
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.
For performance reasons, the linter uses visitors as a dispatch mechanism rather than as a tree walking mechanism. Walking the tree is expensive, so we do it once and effectively run all of the lint rules simultaneously. As a result,
_Visitor
should extendSimpleAstVisitor
,- you should use
addConfiguration
rather thanaddCompilationUnit
on line 43, and - you should remove the invocation of
super
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.
Ah, apparently the file I duplicated as a starting point was the only one using a RecursiveAstVisitor (missing_whitespace_between_adjacent_strings.dart
) 😄
This makes sense and I've made those changes, thanks!
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.
That rule should definitely be updated. (But obviously not an issue for 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.
Ah, wasn't sure if there was a reason. I'll file a PR, seems like a trivial change. Thanks!
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.
💎
Awesome!
Should I update pubspec.yaml to 1.16.0 too, or is it done when ready to release? |
No need. I'll do that when I get the release cooking. |
Ok, cool :) I don't have permissions to merge here (or know the procedure) so I'll leave that to one of you two when appropriate. Thanks! |
…#3080) * Add a lint for missing files in conditional imports * Rename missing_conditional_import -> conditiona_uri_does_not_exist * Switch to SimpleAstVisitor * Improve Good/Bad examples * Add a comment above server overlays
An issue came up in Dart-Code abut conditional imports not being validated:
Originally this was added to the analysis server (https://dart-review.googlesource.com/c/sdk/+/202924) but it triggered a lot of warnings internally for files that haven't been generated yet and it was agreed it would be better as a lint.
This is an attempt to move convert it to a lint, although I have a few outstanding questions:
missing_conditional_import
as a placeholder, but I suspect there are some conventions it should followtest_data
but from reading ☂ Improve linter test reliability and maintainability sdk#58520 I got the impression that might be the old way, and this may be the new wayconfiguration.uriSource.exists()
seems to do what I want (the comment notes it won't include overlays, but I think that's probably fine - running the script through the VM also wouldn't find the overlay):@pq @bwilkerson