Skip to content

Commit 8f2b4e7

Browse files
eromanomgechev
authored andcommitted
don't prefix output properties check rule (#440)
* don't prefix output properties check rule * I18nRule export back * Update index.ts
1 parent 12159e4 commit 8f2b4e7

File tree

6 files changed

+78
-1
lines changed

6 files changed

+78
-1
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ Below you can find a recommended configuration which is based on the [Angular St
208208
"use-host-property-decorator": true,
209209
"no-attribute-parameter-decorator": true,
210210
"no-input-rename": true,
211+
"no-on-prefix-output-name": true,
211212
"no-output-rename": true,
212213
"no-forward-ref": true,
213214
"use-life-cycle-interface": true,
@@ -292,6 +293,8 @@ module.exports = {
292293
[<img alt="leosvelperez" src="https://avatars0.githubusercontent.com/u/12051310?v=3&s=117" width="117">](https://github.com/leosvelperez) |[<img alt="rtfpessoa" src="https://avatars3.githubusercontent.com/u/902384?v=3&s=117" width="117">](https://github.com/rtfpessoa) |[<img alt="scttcper" src="https://avatars0.githubusercontent.com/u/1400464?v=3&s=117" width="117">](https://github.com/scttcper) |[<img alt="laco0416" src="https://avatars0.githubusercontent.com/u/1529180?v=3&s=117" width="117">](https://github.com/laco0416) |[<img alt="tmair" src="https://avatars1.githubusercontent.com/u/1596276?v=3&s=117" width="117">](https://github.com/tmair) |[<img alt="cexbrayat" src="https://avatars0.githubusercontent.com/u/411874?v=3&s=117" width="117">](https://github.com/cexbrayat) |
293294
:---: |:---: |:---: |:---: |:---: |:---: |
294295
[leosvelperez](https://github.com/leosvelperez) |[rtfpessoa](https://github.com/rtfpessoa) |[scttcper](https://github.com/scttcper) |[laco0416](https://github.com/laco0416) |[tmair](https://github.com/tmair) |[cexbrayat](https://github.com/cexbrayat) |
296+
[<img alt="eromano" src="https://avatars0.githubusercontent.com/u/1030050?v=3&s=117" width="117">](https://github.com/eromano) | | | | | |
297+
[eromano](https://github.com/eromano) | | | | ||
295298

296299
## License
297300

docs/src/worker.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const rulesConfig = {
1010
'use-host-property-decorator': true,
1111
'no-input-rename': true,
1212
'no-output-rename': true,
13+
'no-on-prefix-output-name': true,
1314
'use-life-cycle-interface': true,
1415
'use-pipe-transform-interface': true,
1516
'component-class-suffix': true,

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323
"contributors": [
2424
"Minko Gechev <[email protected]>",
2525
"Preslav Semov <[email protected]>",
26-
"William Koza <[email protected]>"
26+
"William Koza <[email protected]>",
27+
"Eugenio Romano <[email protected]>"
2728
],
2829
"repository": {
2930
"type": "git",

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export { Rule as ImportDestructuringSpacingRule } from './importDestructuringSpa
1111
export { Rule as NoAttributeParameterDecoratorRule } from './noAttributeParameterDecoratorRule';
1212
export { Rule as NoForwardRefRule } from './noForwardRefRule';
1313
export { Rule as NoInputRenameRule } from './noInputRenameRule';
14+
export { Rule as NoOutputOnPrefixNameRule } from './noOutputOnPrefixNameRule';
1415
export { Rule as NoOutputRenameRule } from './noOutputRenameRule';
1516
export { Rule as NoUnusedCssRule } from './noUnusedCssRule';
1617
export { Rule as PipeImpureRule } from './pipeImpureRule';

src/noOutputOnPrefixNameRule.ts

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import * as Lint from 'tslint';
2+
import * as ts from 'typescript';
3+
import { sprintf } from 'sprintf-js';
4+
import { NgWalker } from './angular/ngWalker';
5+
6+
export class Rule extends Lint.Rules.AbstractRule {
7+
public static metadata: Lint.IRuleMetadata = {
8+
ruleName: 'no-on-prefix-output-name',
9+
type: 'maintainability',
10+
description: `Name events without the prefix on`,
11+
descriptionDetails: `See more at https://angular.io/guide/styleguide#dont-prefix-output-properties`,
12+
rationale: `Angular allows for an alternative syntax on-*. If the event itself was prefixed with on
13+
this would result in an on-onEvent binding expression`,
14+
options: null,
15+
optionsDescription: `Not configurable.`,
16+
typescriptOnly: true,
17+
};
18+
19+
static FAILURE_STRING: string = 'In the class "%s", the output ' +
20+
'property "%s" should not be prefixed with on';
21+
22+
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
23+
return this.applyWithWalker(
24+
new OutputWalker(sourceFile,
25+
this.getOptions()));
26+
}
27+
}
28+
29+
export class OutputWalker extends NgWalker {
30+
visitNgOutput(property: ts.PropertyDeclaration, output: ts.Decorator, args: string[]) {
31+
let className = (<any>property).parent.name.text;
32+
let memberName = (<any>property.name).text;
33+
34+
if (memberName && memberName.startsWith('on')) {
35+
let failureConfig: string[] = [className, memberName];
36+
failureConfig.unshift(Rule.FAILURE_STRING);
37+
this.addFailure(
38+
this.createFailure(
39+
property.getStart(),
40+
property.getWidth(),
41+
sprintf.apply(this, failureConfig)));
42+
}
43+
}
44+
}

test/noOutputOnPrefixNameRule.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { assertSuccess, assertAnnotated } from './testHelper';
2+
3+
describe('no-on-prefix-output-name', () => {
4+
describe('invalid directive output property', () => {
5+
it(`should fail, when a directive output property is named with on prefix`, () => {
6+
let source = `
7+
class ButtonComponent {
8+
@Output() onChange = new EventEmitter<any>();
9+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10+
}`;
11+
assertAnnotated({
12+
ruleName: 'no-on-prefix-output-name',
13+
source
14+
});
15+
});
16+
});
17+
18+
describe('valid directive output property', () => {
19+
it('should succeed, when a directive output property is properly named', () => {
20+
let source = `
21+
class ButtonComponent {
22+
@Output() change = new EventEmitter<any>();
23+
}`;
24+
assertSuccess('no-on-prefix-output-name', source);
25+
});
26+
});
27+
});

0 commit comments

Comments
 (0)