Skip to content
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

refactor: general rename/clean up rules #754

Merged
merged 1 commit into from
Feb 24, 2019
Merged

refactor: general rename/clean up rules #754

merged 1 commit into from
Feb 24, 2019

Conversation

rafaelss95
Copy link
Collaborator

@rafaelss95 rafaelss95 commented Feb 10, 2019

Current name Proposed name
contextual-life-cycle contextual-lifecycle
no-conflicting-life-cycle-hooks no-conflicting-lifecycle
no-life-cycle-call no-lifecycle-call
use-life-cycle-interface use-lifecycle-interface
decorator-not-allowed contextual-decorator
enforce-component-selector use-component-selector
no-output-named-after-standard-event no-output-native
use-host-property-decorator no-host-metadata-property
use-input-property-decorator no-inputs-metadata-property
use-output-property-decorator no-outputs-metadata-property
no-queries-parameter no-queries-metadata-property
pipe-impure no-pipe-impure
use-view-encapsulation use-component-view-encapsulation
i18n template-i18n
banana-in-box template-banana-in-box
no-template-call-expression template-no-call-expression
templates-no-negated-async template-no-negated-async
trackBy-function template-use-track-by-function

Points:

1) EnforceComponentSelector -> UseComponentSelector: I decided to rename it to make it sync with other "use" rules... let me know what do you think about it.
2) NoOutputNamedAfterStandardEventRule -> NoOutputNative: not sure if it's a good name, please don't hesitate to suggest one :)
3) TemplatesNoNegatedAsync -> TemplateNoNegatedAsync: I'm not sure renaming it is a good idea, because in addition to this rule returning some false positives, it's not useful at all (see #615 (comment)) resolved in #615.
4) Since we are renaming, what about those below?

pipe-impure -> no-pipe-impure
use-host-property-decorator -> no-host-parameter (to be sync with no-queries-parameter)
use-input-property-decorator -> no-inputs-parameter (to be sync with no-queries-parameter)
use-output-property-decorator -> no-outputs-parameter (to be sync with no-queries-parameter)

Closes #653.

@rafaelss95 rafaelss95 requested review from mgechev and wKoza February 10, 2019 21:55
@rafaelss95 rafaelss95 changed the title refactor: general renaming/clean up rules refactor: general rename/clean up rules Feb 10, 2019
@mgechev
Copy link
Owner

mgechev commented Feb 11, 2019

This will require schematics transform of tslint.json when users execute ng update.

We'll have to discuss the change with @alexeagle and @hansl.

README.md Outdated
"use-component-selector": true,
"use-host-property-decorator": true,
"use-input-property-decorator": true,
"use-lifecycle-interface": true,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use this internally. Need to make sure we update g3.

super.visitNgPipe(controller, decorator);
}

private validateDecorator(
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job with this refactoring!

Copy link
Owner

@mgechev mgechev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic job! I reviewed half of the PR, I'll review the rest tomorrow.

@mgechev
Copy link
Owner

mgechev commented Feb 13, 2019

The renames you suggest make sense.

private validateInterfaces(node: ClassDeclaration): void {
const declaredLifecycleInterfaces = getDeclaredLifecycleInterfaces(node);

for (const key of Object.keys(LIFECYCLE_INTERFACE_CONFLICT_MAPPER)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop the for loop here, we don't really need it, nor LIFECYCLE_INTERFACE_CONFLICT_MAPPER

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

private validateMethods(node: ClassDeclaration): void {
const declaredLifecycleMethods = getDeclaredLifecycleMethods(node);

for (const key of Object.keys(LIFECYCLE_METHOD_CONFLICT_MAPPER)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
}

export class ExpressionCallMetadataWalker extends NgWalker {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to export this?

Copy link
Collaborator Author

@rafaelss95 rafaelss95 Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily, however, for some reason, we export the walker's in almost all rules. I'll remove the export here and in other files in this PR.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

import { NgWalker } from './angular/ngWalker';
import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor';

const INVALID_BOX = /\[(.*)\]/;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/\[(.*)\]/.test('[(ngModel)]') && /\[(.*)\]/.test('([ngModel])') which seems incorrect.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, however, the previous regex (which one is different only by a question mark) was also wrong, it gave the same result for the tests you wrote above.


After investigating why the specs pass even with this wrong regex, I discovered that the ast's name just cuts the parens, so:

Test 1: <input type="text" name="foo" ([ngModel])="foo">, test with regex returns true (the ast's name is just [ngModel]);
Test 2: <div (emitter)="emitter"></div> -> test with regex returns false (ast's name is emitter);
Test 3: <input type="text" name="foo" [ngModel]="foo"> -> test with regex returns false (ast's name is ngModelChange);
Test 4: <input type="text" name="foo" [(ngModel)]="foo"> -> never call visitEvent method.


I changed the regex a bit to: /^\[(?!\()(.*)(?<!\))\]$/.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, previous regex was absolutely wrong, I noticed that. Thanks for the update!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes @rafaelss95 , this rule used visitEvent, what explains this behavior.

private validateComponent(metadata: ComponentMetadata): void {
if (metadata.selector) return;

const failure = getFailureMessage(metadata.controller.name!.text);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're very confident here. Do we know for sure that name is not going to be null?

Copy link
Collaborator Author

@rafaelss95 rafaelss95 Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, to be honest, I really don't know if we can receive a null name here. It was copied from enforceComponentSelector, anyway, I'll add a check for this :)

@@ -0,0 +1,113 @@
import { getFailureMessage, Rule } from '../src/contextualLifecycleRule';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to keep the previous specs. This is not very readable, it's hard to keep track what are the interfaces and the methods.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, I'll update ASAP.

@@ -1,51 +1,46 @@
import { lifecycleHooksMethods, LifecycleHooksMethods, Rule } from '../src/noLifeCycleCallRule';
import { Rule } from '../src/noLifecycleCallRule';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. I see we've merged the template string snippets, but I have no idea what we are testing like this. Would you mind updating? Thanks 🙇🏼‍♂️

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problem, I'll update ASAP.

Copy link
Owner

@mgechev mgechev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually had an extra hour today. Fascinating job! I love the early return refactoring and the consistency! I left a few comments. Mostly about readability of the tests.

@rafaelss95
Copy link
Collaborator Author

Haha, thanks :) Btw, it's ready for the next round when you have time 💥

README.md Outdated
| `no-unused-css` | _Experimental_ |
| `pipe-prefix` | _Experimental_ |
| `template-i18n` | _Experimental_ |
| `template-conditional-complexity` | _Experimental_ |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Be careful when we'll merge this PR with #756

import { NgWalker } from './angular/ngWalker';
import { BasicTemplateAstVisitor } from './angular/templates/basicTemplateAstVisitor';

const INVALID_BOX = /\[(.*)\]/;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes @rafaelss95 , this rule used visitEvent, what explains this behavior.

Copy link
Collaborator

@wKoza wKoza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work @rafaelss95 , just some questions

decorator: Decorator,
allowedHookMethods: ReadonlySet<LifecycleMethodKeys>
): void {
if (!controller.name) return;
Copy link
Collaborator

@wKoza wKoza Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is It possible or it's just for not don't just after using '!' ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never seen a case where this could be null! I did it to jump the ! 😛

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Component({...})
export default class { ... }

Seems valid to me. In this case name is undefined.

Copy link
Collaborator

@wKoza wKoza Feb 21, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, In the Angular world, I'm not sure we can omit a Type. But, @mgechev , your example is interesting:
If we create a simple class like that:

export default class { ... }

and we launch ng lint, we have a big big crash [here] (https://github.com/mgechev/codelyzer/blob/master/src/propertyDecoratorBase.ts#L41) and many other places !

@mgechev , @rafaelss95 , I'm not very fan of the ! Non-Null Assertion. We cannot say that

const className = metadata.controller.name!.text

is the same that

if (!controller.name) return;
 const className = controllerName.text;

If we accept metadata.controller.name!.text, we should not write if (!controller.name) return;

Hence my question.

So, we must keep this test, but we must also use this test everywhere and stop to use the Non-Null Assertion.

Are you agree ?

for (const member of controller.members) {
const { name: memberName } = member;

if (!memberName) continue;
Copy link
Collaborator

@wKoza wKoza Feb 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is It possible or it's just for not don't just after using '!' ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've never seen a case where this could be null! I did it to jump the ! 😛

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep it.

describe('valid declaration of lifecycle hooks, using ng.hookName', () => {
it('should succeed when lifecycle hook is used with its interface', () => {
const source = `
class ${className} implements ng.OnInit {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: using namespace is a good practice ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't know, but I never saw someone using this in real world.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mgechev , what do you think about it ?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may have some implications in the dead code elimination, but it's fine to exist in our test cases.

@mgechev
Copy link
Owner

mgechev commented Feb 20, 2019

@rafaelss95 would you resolve the merge conflict? I think we're ready to merge.

@rafaelss95
Copy link
Collaborator Author

rafaelss95 commented Feb 20, 2019

@mgechev Sure! What about my three questions below the table?

@mgechev
Copy link
Owner

mgechev commented Feb 20, 2019

LGTM, the extra checks seem fine.

@rafaelss95
Copy link
Collaborator Author

@mgechev I was talking about the questions in the PR description (below the table) :)

@mgechev
Copy link
Owner

mgechev commented Feb 21, 2019

Oh, I was sure that I responded to these questions but it looks I didn't. Yes, it makes sense to rename the rest of the rules as well.

@rafaelss95
Copy link
Collaborator Author

rafaelss95 commented Feb 24, 2019

Hey @mgechev I've updated the code and the table in OP with the new proposed names.


I took a look in (almost) all the rules today and found some more rule names that can be improved:

component-change-detection:

  • Suggestions:
    • no-component-default-change-detection
    • prefer-component-change-detection-on-push
    • use-component-change-detection-on-push

relative-url-prefix:

  • Suggestions:
    • prefer-component-relative-url-prefix
    • use-component-relative-url-prefix

no-attribute-parameter-decorator:

  • Suggestions:
    • no-attribute-decorator
    • prefer-input-over-attribute-decorator

Let me know your opinion :)

@mgechev mgechev merged commit bbf7a32 into mgechev:master Feb 24, 2019
@mgechev
Copy link
Owner

mgechev commented Feb 24, 2019

@rafaelss95 let's rename the other rules as part of another PR:

  • prefer-on-push-component-change-detection
  • no-attribute-decorator

Sound good. About the relative prefix, it's still not obvious what's about. Maybe we should be more explicit about it.

@rafaelss95 rafaelss95 deleted the refactor/rename-rules branch February 25, 2019 05:21
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 1, 2019
Migration of the `tslint.json` file required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 1, 2019
Migration of the `tslint.json` file required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 4, 2019
Migration of the `tslint.json` file required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 6, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 7, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
@rafaelss95
Copy link
Collaborator Author

... About the relative prefix, it's still not obvious what's about. Maybe we should be more explicit about it.

@mgechev Do you have any suggestion?

@mgechev
Copy link
Owner

mgechev commented Mar 8, 2019

Let's not updated it for now.

mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 8, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 12, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 12, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
mgechev added a commit to mgechev/angular-cli that referenced this pull request Mar 12, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
pmstss added a commit to pmstss/amazing-time-picker that referenced this pull request Mar 14, 2019
- templates-use-public/no-access-missing-member (not more exist as handled by tsc - mgechev/codelyzer#260 (comment))
- invoke-injectable (not more exist as handled by ngc - mgechev/codelyzer#260 (comment))
- use-input*/use-output*/use-host* renamed - mgechev/codelyzer#754
- "typeof-compare is deprecated. Starting from TypeScript 2.2 the compiler includes this check which makes this rule redundant"
kyliau pushed a commit to angular/angular-cli that referenced this pull request Mar 27, 2019
Migration of the `tslint.json` and `package.json` files required by the refactoring of
codelyzer. For more information check this PR
mgechev/codelyzer#754.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

About rule names
3 participants