Skip to content

Commit

Permalink
fix(eslint-plugin): [no-output-on-prefix] correct false positives (#525)
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaelss95 committed Jun 21, 2021
1 parent de37ee4 commit 3a66274
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 17 deletions.
10 changes: 6 additions & 4 deletions packages/eslint-plugin/src/rules/no-output-on-prefix.ts
Expand Up @@ -13,7 +13,7 @@ export default createESLintRule<Options, MessageIds>({
meta: {
type: 'suggestion',
docs: {
description: `Ensures that Output bindings, including aliases, are not named "on", nor prefixed with it. See more at ${STYLE_GUIDE_LINK}`,
description: `Ensures that output bindings, including aliases, are not named "on", nor prefixed with it. See more at ${STYLE_GUIDE_LINK}`,
category: 'Best Practices',
recommended: 'error',
},
Expand All @@ -24,12 +24,14 @@ export default createESLintRule<Options, MessageIds>({
},
defaultOptions: [],
create(context) {
const outputAliasSelector = `ClassProperty:has(${OUTPUT_DECORATOR}[expression.arguments.0.value=${OUTPUT_ON_PATTERN}])`;
const outputPropertySelector = `ClassProperty:has(${OUTPUT_DECORATOR}):has(Identifier[name=${OUTPUT_ON_PATTERN}])`;
const outputAliasSelector = `ClassProperty ${OUTPUT_DECORATOR} :matches(Literal[value=${OUTPUT_ON_PATTERN}], TemplateElement[value.raw=${OUTPUT_ON_PATTERN}])`;
const outputPropertySelector = `ClassProperty[computed=false]:has(${OUTPUT_DECORATOR}) > :matches(Identifier[name=${OUTPUT_ON_PATTERN}], Literal[value=${OUTPUT_ON_PATTERN}])`;
const selectors = [outputAliasSelector, outputPropertySelector].join(',');

return {
[selectors](node: TSESTree.ClassProperty) {
[selectors](
node: TSESTree.Identifier | TSESTree.Literal | TSESTree.TemplateElement,
) {
context.report({
node,
messageId: 'noOutputOnPrefix',
Expand Down
86 changes: 74 additions & 12 deletions packages/eslint-plugin/tests/rules/no-output-on-prefix.test.ts
Expand Up @@ -19,56 +19,118 @@ ruleTester.run(RULE_NAME, rule, {
`
@Component()
class Test {
@Output() change = new EventEmitter<void>();
on = new EventEmitter();
}
`,
`
@Directive()
class Test {
@Output() buttonChange = new EventEmitter<'on'>();
}
`,
`
@Component()
class Test {
@Output() On = new EventEmitter<{ on: onType }>();
}
`,
`
@Directive()
class Test {
@Output(\`one\`) ontype = new EventEmitter<{ bar: string, on: boolean }>();
}
`,
`
@Component()
class Test {
@Output('oneProp') common = new EventEmitter<ComplextOn>();
}
`,
`
@Directive()
class Test<On> {
@Output() ON = new EventEmitter<On>();
}
`,
`
const on = 'on';
@Component()
class Test {
@Output('testing') oneProp = new EventEmitter<void>();
@Output(on) touchMove: EventEmitter<{ action: 'on' | 'off' }> = new EventEmitter<{ action: 'on' | 'off' }>();
}
`,
`
const test = 'on';
const on = 'on';
@Directive()
class Test {
@Output() selectionChanged = new EventEmitter<void>();
@Output(test) [on]: EventEmitter<OnTest>;
}
`,
],
invalid: [
convertAnnotatedSourceToFailureCase({
description: `it should fail if a component output property's name is prefixed with "on"`,
description:
'should fail if output property is named "on" in `@Component`',
annotatedSource: `
@Component()
class Test {
@Output() onChange = new EventEmitter<void>();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Output() on: EventEmitter<any> = new EventEmitter<{}>();
~~
}
`,
messageId,
}),
convertAnnotatedSourceToFailureCase({
description: `it should fail if a component output property's alias is prefixed with "on"`,
description:
'should fail if output property is named with "\'on\'" prefix in `@Directive`',
annotatedSource: `
@Directive()
class Test {
@Output() @Custom('on') 'onPrefix' = new EventEmitter<void>();
~~~~~~~~~~
}
`,
messageId,
}),
convertAnnotatedSourceToFailureCase({
description:
'should fail if output property is aliased as "`on`" in `@Component`',
annotatedSource: `
@Component()
class Test {
@Output('onChange') test = new EventEmitter<void>();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Custom() @Output(\`on\`) _on = getOutput();
~~~~
}
`,
messageId,
}),
convertAnnotatedSourceToFailureCase({
description:
'it should fail if a directive output property name is equal to "on"',
'should fail if output property is aliased with "on" prefix in `@Directive`',
annotatedSource: `
@Directive()
class Test {
@Output() on = new EventEmitter<void>();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Output('onPrefix') _on = (this.subject$ as Subject<{on: boolean}>).pipe();
~~~~~~~~~~
}
`,
messageId,
}),
convertAnnotatedSourceToFailureCase({
description:
'should fail if output property is named with prefix "on" and aliased as "on" without `@Component` or `@Directive`',
annotatedSource: `
@Injectable()
class Test {
@Output('on') onPrefix = this.getOutput();
~~~~ ^^^^^^^^
}
`,
messages: [
{ char: '~', messageId },
{ char: '^', messageId },
],
}),
],
});
Expand Up @@ -20,7 +20,7 @@ __ROOT__/v1123-multi-project-manual-config/src/app/example.component.ts
12:3 error Use @Input rather than the \`inputs\` metadata property (https://angular.io/styleguide#style-05-12) @angular-eslint/no-inputs-metadata-property
13:3 error Use @Output rather than the \`outputs\` metadata property (https://angular.io/styleguide#style-05-12) @angular-eslint/no-outputs-metadata-property
14:3 error Use @HostBinding or @HostListener rather than the \`host\` metadata property (https://angular.io/styleguide#style-06-03) @angular-eslint/no-host-metadata-property
18:3 error Output bindings, including aliases, should not be named \\"on\\", nor prefixed with it (https://angular.io/guide/styleguide#style-05-16) @angular-eslint/no-output-on-prefix
18:13 error Output bindings, including aliases, should not be named \\"on\\", nor prefixed with it (https://angular.io/guide/styleguide#style-05-16) @angular-eslint/no-output-on-prefix
6:35 error Invalid binding syntax. Use [(expr)] instead @angular-eslint/template/banana-in-box
8:15 error Invalid binding syntax. Use [(expr)] instead @angular-eslint/template/banana-in-box
8:29 error Invalid binding syntax. Use [(expr)] instead @angular-eslint/template/banana-in-box
Expand Down

0 comments on commit 3a66274

Please sign in to comment.