Skip to content

Commit 202c767

Browse files
committed
Add no-untyped-underscore.ts
1 parent 9134a9d commit 202c767

4 files changed

Lines changed: 77 additions & 4 deletions

File tree

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
{
2-
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.5/includes/tsconfig-node.json"
2+
"extends": "./node_modules/@microsoft/rush-stack-compiler-3.5/includes/tsconfig-node.json",
3+
"compilerOptions": {
4+
"types": [
5+
"node"
6+
]
7+
}
38
}

‎stack/eslint-plugin/src/index.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import { TSESLint } from '@typescript-eslint/experimental-utils';
55

66
import { noNullRule } from './no-null';
7+
import { noUntypedUnderscoreRule } from './no-untyped-underscore';
78

89
interface IPlugin {
910
rules: { [ruleName: string]: TSESLint.RuleModule<string, unknown[]> };
@@ -12,7 +13,8 @@ interface IPlugin {
1213
const plugin: IPlugin = {
1314
rules: {
1415
// NOTE: The actual ESLint rule name will be "@rushstack/no-null".
15-
'no-null': noNullRule
16+
'no-null': noNullRule,
17+
'no-untyped-underscore': noUntypedUnderscoreRule
1618
}
1719
};
1820

‎stack/eslint-plugin/src/no-null.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ const noNullRule: TSESLint.RuleModule<MessageIds,Options> = {
2626
},
2727
create: (context: TSESLint.RuleContext<MessageIds, Options>) => {
2828
return {
29-
Literal: function(node: TSESTree.Node) {
29+
Literal: function(node: TSESTree.Literal) {
3030
// Is it a "null" literal?
31-
if (node.type === 'Literal' && node.value === null) {
31+
if (node.value === null) {
3232

3333
// Does the "null" appear in a comparison such as "if (x === null)"?
3434
let isComparison: boolean = false;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
2+
// See LICENSE in the project root for license information.
3+
4+
import {
5+
TSESTree,
6+
TSESLint
7+
} from '@typescript-eslint/experimental-utils';
8+
9+
type MessageIds = 'error-untyped-underscore';
10+
type Options = [ ];
11+
12+
const noUntypedUnderscoreRule: TSESLint.RuleModule<MessageIds,Options> = {
13+
meta: {
14+
type: 'problem',
15+
messages: {
16+
'error-untyped-underscore':
17+
'This expression appears to access a private member "{{memberName}}"; '
18+
+ 'either remove the underscore prefix or else declare a type for the containing object'
19+
},
20+
schema: [ ],
21+
docs: {
22+
description: 'Prevents usage of JavaScript\'s "null" keyword.',
23+
category: 'Stylistic Issues',
24+
recommended: "error",
25+
url: 'https://www.npmjs.com/package/@rushstack/eslint-config'
26+
}
27+
},
28+
create: (context: TSESLint.RuleContext<MessageIds, Options>) => {
29+
return {
30+
MemberExpression: function(node: TSESTree.MemberExpression) {
31+
// Is it an expression like "x.y"?
32+
let match: boolean = true;
33+
34+
// Ignore expressions such as "super.y", "this.y", and "that.y"
35+
const memberObject: TSESTree.LeftHandSideExpression = node.object;
36+
if (memberObject) {
37+
if (memberObject.type === 'Super' || memberObject.type === 'ThisExpression') {
38+
match = false;
39+
} else {
40+
if (memberObject.type === 'Identifier') {
41+
if (memberObject.name === 'this' || memberObject.name == 'that') {
42+
match = false;
43+
}
44+
}
45+
}
46+
}
47+
48+
// Does the member name start with an underscore? (e.g. "x._y")
49+
if (match && node.property && node.property.type === 'Identifier') {
50+
const memberName: string = node.property.name;
51+
if (memberName && memberName[0] === '_') {
52+
context.report({
53+
node,
54+
messageId: 'error-untyped-underscore',
55+
data: {
56+
memberName: memberName
57+
}
58+
});
59+
}
60+
}
61+
}
62+
};
63+
}
64+
};
65+
66+
export { noUntypedUnderscoreRule };

0 commit comments

Comments
 (0)