-
-
Notifications
You must be signed in to change notification settings - Fork 233
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
feat(eslint-plugin-template): add require-localize-metadata rule #844
feat(eslint-plugin-template): add require-localize-metadata rule #844
Conversation
f2bde02
to
5b2d478
Compare
☁️ Nx Cloud ReportCI ran the following commands for commit 10f48b8. Click to see the status, the terminal output, and the build insights. 📂 See all runs for this branch ✅ Successfully ran 7 targets
Sent with 💌 from NxCloud. |
|
||
const VALID_LOCALIZED_STRING_WITH_DESCRIPTION = new RegExp(/`:[^|]*:.*`/); | ||
|
||
// TODO: The following values are also used in eslint-plugin-template/i18n, and should likely be centralized |
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.
What is a good location for these values?
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 would remove the comment, I think having the small bit of repetition is fine and allows for them to remain independent and be more easily refactored if the structure of Angular guides changes in future
requireDescription: false, | ||
}; | ||
|
||
const VALID_LOCALIZED_STRING_WITH_DESCRIPTION = new RegExp(/`:[^|]*:.*`/); |
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.
Any thoughts on this RegExp?
taggedTemplateExpression: TSESTree.TaggedTemplateExpression, | ||
) { | ||
const identifierName = ( | ||
taggedTemplateExpression.tag as TSESTree.Identifier |
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.
why does it need casting?
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.
Because tag
is of type LeftHandSideExpression
, which is:
export declare type LeftHandSideExpression = ArrayExpression | ArrayPattern | ArrowFunctionExpression | CallExpression | ClassExpression | FunctionExpression | Identifier | JSXElement | JSXFragment | LiteralExpression | MemberExpression | MetaProperty | ObjectExpression | ObjectPattern | SequenceExpression | Super | TaggedTemplateExpression | ThisExpression | TSAsExpression | TSNonNullExpression | TSTypeAssertion;
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.
@adbaran1 It would be better to narrow the type through control flow analysis by actually checking the shape of the tag to check that it is an identifier.
You can use the utility TSESLintASTUtils.isIdentifier(...)
from @typescript-eslint/experimental-utils
to do exactly what you need and TypeScript will pick up on the types through the control flow analysis.
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 a lot for this @adbaran1, I'm really sorry for how long it has taken me to get back to you on this.
I moved countries a couple of times so things have been very chaotic.
|
||
const VALID_LOCALIZED_STRING_WITH_DESCRIPTION = new RegExp(/`:[^|]*:.*`/); | ||
|
||
// TODO: The following values are also used in eslint-plugin-template/i18n, and should likely be centralized |
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 would remove the comment, I think having the small bit of repetition is fine and allows for them to remain independent and be more easily refactored if the structure of Angular guides changes in future
}, | ||
defaultOptions: [DEFAULT_OPTIONS], | ||
create(context, [{ requireDescription }]) { | ||
function reportRequireLocalizeMetadataError( |
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.
Please can you refactor this implementation to just inline everything in the Node handler method?
There is very little code here but the dedication to wrapping every step into functions hurts readability in my opinion because of how it changes the flow of the document.
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.
See my comment below about eventually being able to support custom ID and meaning.
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.
Makes sense @adbaran1 👍
taggedTemplateExpression: TSESTree.TaggedTemplateExpression, | ||
) { | ||
const identifierName = ( | ||
taggedTemplateExpression.tag as TSESTree.Identifier |
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.
@adbaran1 It would be better to narrow the type through control flow analysis by actually checking the shape of the tag to check that it is an identifier.
You can use the utility TSESLintASTUtils.isIdentifier(...)
from @typescript-eslint/experimental-utils
to do exactly what you need and TypeScript will pick up on the types through the control flow analysis.
{ | ||
type: 'object', | ||
properties: { | ||
requireDescription: { |
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 understand what purpose this option serves given the whole rule is dedicated to this purpose?
This is further backed up by the fact you don't have tests for when it is disabled.
I would think that if someone does not want to require the description they would simply not use this rule right?
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.
@JamesHenry no worries, and I hope things are less chaotic now 😄 . The reason for this setup is to be able to support custom ID and meaning, which are the other two i18n metadata parameters (see i18n metadata for translation). This pull request is only to support description for the time being, which is why the implementation looks the way it does (i.e. having functions like testLocalizeTemplateElementWithDescription
).
With that all said, let me know what you think about the overall approach.
…es contain a description
2dfe0a9
to
1d4eed3
Compare
Codecov Report
@@ Coverage Diff @@
## master #844 +/- ##
==========================================
+ Coverage 86.36% 86.45% +0.09%
==========================================
Files 145 147 +2
Lines 2720 2746 +26
Branches 438 441 +3
==========================================
+ Hits 2349 2374 +25
Misses 220 220
- Partials 151 152 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
|
}, | ||
defaultOptions: [DEFAULT_OPTIONS], | ||
create(context, [{ requireDescription }]) { | ||
function reportRequireLocalizeMetadataError( |
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.
Makes sense @adbaran1 👍
@JamesHenry Looks like Adrian has addresses all the comments. Anything else needs to be done before it's merged? |
Thanks again for your patience on this @adbaran1 @alex-okrushko. I think the description of the overall rule matching the intent behind a subset of its intended features is still confusing but I will amend that post-merge |
Thank you @JamesHenry. Please let us know how we can assist you in making it all better. We can look to add support for Angular i18n meaning and IDs to make the overall setup more clear ASAP. |
This PR contains the following updates: | Package | Type | Update | Change | |---|---|---|---| | [@angular-eslint/builder](https://github.com/angular-eslint/angular-eslint) | devDependencies | minor | [`13.1.0` -> `13.2.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2fbuilder/13.1.0/13.2.0) | | [@angular-eslint/eslint-plugin](https://github.com/angular-eslint/angular-eslint) | devDependencies | minor | [`13.1.0` -> `13.2.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin/13.1.0/13.2.0) | | [@angular-eslint/eslint-plugin-template](https://github.com/angular-eslint/angular-eslint) | devDependencies | minor | [`13.1.0` -> `13.2.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2feslint-plugin-template/13.1.0/13.2.0) | | [@angular-eslint/schematics](https://github.com/angular-eslint/angular-eslint) | devDependencies | minor | [`13.1.0` -> `13.2.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2fschematics/13.1.0/13.2.0) | | [@angular-eslint/template-parser](https://github.com/angular-eslint/angular-eslint) | devDependencies | minor | [`13.1.0` -> `13.2.0`](https://renovatebot.com/diffs/npm/@angular-eslint%2ftemplate-parser/13.1.0/13.2.0) | --- ### Release Notes <details> <summary>angular-eslint/angular-eslint (@​angular-eslint/builder)</summary> ### [`v13.2.0`](https://github.com/angular-eslint/angular-eslint/blob/HEAD/packages/builder/CHANGELOG.md#​1320-httpsgithubcomangular-eslintangular-eslintcomparev1310v1320-2022-04-03) [Compare Source](angular-eslint/angular-eslint@v13.1.0...v13.2.0) **Note:** Version bump only for package [@​angular-eslint/builder](https://github.com/angular-eslint/builder) </details> <details> <summary>angular-eslint/angular-eslint (@​angular-eslint/eslint-plugin)</summary> ### [`v13.2.0`](https://github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin/CHANGELOG.md#​1320-httpsgithubcomangular-eslintangular-eslintcomparev1310v1320-2022-04-03) [Compare Source](angular-eslint/angular-eslint@v13.1.0...v13.2.0) ##### Features - **eslint-plugin-template:** add require-localize-metadata rule ([#​844](angular-eslint/angular-eslint#844)) ([ca1edf0](angular-eslint/angular-eslint@ca1edf0)) </details> <details> <summary>angular-eslint/angular-eslint (@​angular-eslint/eslint-plugin-template)</summary> ### [`v13.2.0`](https://github.com/angular-eslint/angular-eslint/blob/HEAD/packages/eslint-plugin-template/CHANGELOG.md#​1320-httpsgithubcomangular-eslintangular-eslintcomparev1310v1320-2022-04-03) [Compare Source](angular-eslint/angular-eslint@v13.1.0...v13.2.0) ##### Features - **parser:** propagate parse errors from angular compiler ([#​969](angular-eslint/angular-eslint#969)) ([ab9b496](angular-eslint/angular-eslint@ab9b496)) </details> <details> <summary>angular-eslint/angular-eslint (@​angular-eslint/schematics)</summary> ### [`v13.2.0`](https://github.com/angular-eslint/angular-eslint/blob/HEAD/packages/schematics/CHANGELOG.md#​1320-httpsgithubcomangular-eslintangular-eslintcomparev1310v1320-2022-04-03) [Compare Source](angular-eslint/angular-eslint@v13.1.0...v13.2.0) ##### Bug Fixes - **schematics:** support more permutations of ng-add ([#​970](angular-eslint/angular-eslint#970)) ([0bf549b](angular-eslint/angular-eslint@0bf549b)) </details> <details> <summary>angular-eslint/angular-eslint (@​angular-eslint/template-parser)</summary> ### [`v13.2.0`](https://github.com/angular-eslint/angular-eslint/blob/HEAD/packages/template-parser/CHANGELOG.md#​1320-httpsgithubcomangular-eslintangular-eslintcomparev1310v1320-2022-04-03) [Compare Source](angular-eslint/angular-eslint@v13.1.0...v13.2.0) ##### Features - **parser:** propagate parse errors from angular compiler ([#​969](angular-eslint/angular-eslint#969)) ([ab9b496](angular-eslint/angular-eslint@ab9b496)) </details> --- ### Configuration 📅 **Schedule**: At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, click this checkbox. --- This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate). Co-authored-by: cabr2-bot <[email protected]> Co-authored-by: 6543 <[email protected]> Reviewed-on: https://codeberg.org/Calciumdibromid/CaBr2/pulls/1281 Reviewed-by: 6543 <[email protected]> Co-authored-by: Calciumdibromid Bot <[email protected]> Co-committed-by: Calciumdibromid Bot <[email protected]>
Similar to #804, this pull request adds the option to enforce the requirement of a description for i18n metadata when using
$localize
in component code.TODO:
Pull request is in draft mode; please see my comments below!
FYI @JamesHenry , I know that you haven't used Angular i18n, but perhaps you could chime in on the creation of this new rule? See my comments for require-localize-metadata.ts.