Skip to content

Commit

Permalink
feat: support PrivateIdentifier (#3808)
Browse files Browse the repository at this point in the history
Closes #3430
Resolves #2933
  • Loading branch information
bradzacher committed Oct 11, 2021
1 parent 22fa5c0 commit 0eefe5e
Show file tree
Hide file tree
Showing 49 changed files with 4,786 additions and 34 deletions.
1 change: 1 addition & 0 deletions packages/ast-spec/src/ast-node-types.ts
Expand Up @@ -61,6 +61,7 @@ export enum AST_NODE_TYPES {
NewExpression = 'NewExpression',
ObjectExpression = 'ObjectExpression',
ObjectPattern = 'ObjectPattern',
PrivateIdentifier = 'PrivateIdentifier',
Program = 'Program',
Property = 'Property',
PropertyDefinition = 'PropertyDefinition',
Expand Down
7 changes: 7 additions & 0 deletions packages/ast-spec/src/base/MethodDefinitionBase.ts
Expand Up @@ -3,6 +3,7 @@ import type { TSEmptyBodyFunctionExpression } from '../expression/TSEmptyBodyFun
import type { Decorator } from '../special/Decorator/spec';
import type { TSTypeParameterDeclaration } from '../special/TSTypeParameterDeclaration/spec';
import type {
ClassPropertyNameNonComputed,
PropertyName,
PropertyNameComputed,
PropertyNameNonComputed,
Expand Down Expand Up @@ -34,3 +35,9 @@ export interface MethodDefinitionNonComputedNameBase
key: PropertyNameNonComputed;
computed: false;
}

export interface ClassMethodDefinitionNonComputedNameBase
extends MethodDefinitionBase {
key: ClassPropertyNameNonComputed;
computed: false;
}
7 changes: 7 additions & 0 deletions packages/ast-spec/src/base/PropertyDefinitionBase.ts
Expand Up @@ -2,6 +2,7 @@ import type { Decorator } from '../special/Decorator/spec';
import type { TSTypeAnnotation } from '../special/TSTypeAnnotation/spec';
import type { Expression } from '../unions/Expression';
import type {
ClassPropertyNameNonComputed,
PropertyName,
PropertyNameComputed,
PropertyNameNonComputed,
Expand Down Expand Up @@ -35,3 +36,9 @@ export interface PropertyDefinitionNonComputedNameBase
key: PropertyNameNonComputed;
computed: false;
}

export interface ClassPropertyDefinitionNonComputedNameBase
extends PropertyDefinitionBase {
key: ClassPropertyNameNonComputed;
computed: false;
}
4 changes: 2 additions & 2 deletions packages/ast-spec/src/element/MethodDefinition/spec.ts
@@ -1,7 +1,7 @@
import type { AST_NODE_TYPES } from '../../ast-node-types';
import type {
ClassMethodDefinitionNonComputedNameBase,
MethodDefinitionComputedNameBase,
MethodDefinitionNonComputedNameBase,
} from '../../base/MethodDefinitionBase';

export interface MethodDefinitionComputedName
Expand All @@ -10,7 +10,7 @@ export interface MethodDefinitionComputedName
}

export interface MethodDefinitionNonComputedName
extends MethodDefinitionNonComputedNameBase {
extends ClassMethodDefinitionNonComputedNameBase {
type: AST_NODE_TYPES.MethodDefinition;
}

Expand Down
4 changes: 2 additions & 2 deletions packages/ast-spec/src/element/PropertyDefinition/spec.ts
@@ -1,7 +1,7 @@
import type { AST_NODE_TYPES } from '../../ast-node-types';
import type {
ClassPropertyDefinitionNonComputedNameBase,
PropertyDefinitionComputedNameBase,
PropertyDefinitionNonComputedNameBase,
} from '../../base/PropertyDefinitionBase';

export interface PropertyDefinitionComputedName
Expand All @@ -10,7 +10,7 @@ export interface PropertyDefinitionComputedName
}

export interface PropertyDefinitionNonComputedName
extends PropertyDefinitionNonComputedNameBase {
extends ClassPropertyDefinitionNonComputedNameBase {
type: AST_NODE_TYPES.PropertyDefinition;
}

Expand Down
Expand Up @@ -10,6 +10,7 @@ export interface TSAbstractMethodDefinitionComputedName
}

export interface TSAbstractMethodDefinitionNonComputedName
// this does not extend ClassMethodDefinitionNonComputedNameBase because abstract private names are not allowed
extends MethodDefinitionNonComputedNameBase {
type: AST_NODE_TYPES.TSAbstractMethodDefinition;
}
Expand Down
Expand Up @@ -11,6 +11,7 @@ export interface TSAbstractPropertyDefinitionComputedName
}

export interface TSAbstractPropertyDefinitionNonComputedName
// this does not extend ClassPropertyDefinitionNonComputedNameBase because abstract private names are not allowed
extends PropertyDefinitionNonComputedNameBase {
type: AST_NODE_TYPES.TSAbstractPropertyDefinition;
value: null;
Expand Down
5 changes: 3 additions & 2 deletions packages/ast-spec/src/expression/MemberExpression/spec.ts
@@ -1,12 +1,13 @@
import type { AST_NODE_TYPES } from '../../ast-node-types';
import type { BaseNode } from '../../base/BaseNode';
import type { PrivateIdentifier } from '../../special/PrivateIdentifier/spec';
import type { Expression } from '../../unions/Expression';
import type { LeftHandSideExpression } from '../../unions/LeftHandSideExpression';
import type { Identifier } from '../Identifier/spec';

interface MemberExpressionBase extends BaseNode {
object: LeftHandSideExpression;
property: Expression | Identifier;
property: Expression | Identifier | PrivateIdentifier;
computed: boolean;
optional: boolean;
}
Expand All @@ -19,7 +20,7 @@ export interface MemberExpressionComputedName extends MemberExpressionBase {

export interface MemberExpressionNonComputedName extends MemberExpressionBase {
type: AST_NODE_TYPES.MemberExpression;
property: Identifier;
property: Identifier | PrivateIdentifier;
computed: false;
}

Expand Down
7 changes: 7 additions & 0 deletions packages/ast-spec/src/special/PrivateIdentifier/spec.ts
@@ -0,0 +1,7 @@
import type { AST_NODE_TYPES } from '../../ast-node-types';
import type { BaseNode } from '../../base/BaseNode';

export interface PrivateIdentifier extends BaseNode {
type: AST_NODE_TYPES.PrivateIdentifier;
name: string;
}
1 change: 1 addition & 0 deletions packages/ast-spec/src/special/spec.ts
Expand Up @@ -6,6 +6,7 @@ export * from './ExportSpecifier/spec';
export * from './ImportDefaultSpecifier/spec';
export * from './ImportNamespaceSpecifier/spec';
export * from './ImportSpecifier/spec';
export * from './PrivateIdentifier/spec';
export * from './Program/spec';
export * from './SwitchCase/spec';
export * from './TSClassImplements/spec';
Expand Down
2 changes: 2 additions & 0 deletions packages/ast-spec/src/unions/Node.ts
Expand Up @@ -82,6 +82,7 @@ import type { ExportSpecifier } from '../special/ExportSpecifier/spec';
import type { ImportDefaultSpecifier } from '../special/ImportDefaultSpecifier/spec';
import type { ImportNamespaceSpecifier } from '../special/ImportNamespaceSpecifier/spec';
import type { ImportSpecifier } from '../special/ImportSpecifier/spec';
import type { PrivateIdentifier } from '../special/PrivateIdentifier/spec';
import type { Program } from '../special/Program/spec';
import type { SwitchCase } from '../special/SwitchCase/spec';
import type { TemplateElement } from '../special/TemplateElement/spec';
Expand Down Expand Up @@ -228,6 +229,7 @@ export type Node =
| NewExpression
| ObjectExpression
| ObjectPattern
| PrivateIdentifier
| Program
| Property
| PropertyDefinition
Expand Down
10 changes: 9 additions & 1 deletion packages/ast-spec/src/unions/PropertyName.ts
@@ -1,11 +1,19 @@
import type { Identifier } from '../expression/Identifier/spec';
import type { NumberLiteral } from '../expression/literal/NumberLiteral/spec';
import type { StringLiteral } from '../expression/literal/StringLiteral/spec';
import type { PrivateIdentifier } from '../special/PrivateIdentifier/spec';
import type { Expression } from '../unions/Expression';

export type PropertyName = PropertyNameComputed | PropertyNameNonComputed;
export type PropertyName =
| ClassPropertyNameNonComputed
| PropertyNameComputed
| PropertyNameNonComputed;
export type PropertyNameComputed = Expression;
export type PropertyNameNonComputed =
| Identifier
| NumberLiteral
| StringLiteral;
export type ClassPropertyNameNonComputed =
| PrivateIdentifier
// only class properties can have private identifiers as their names
| PropertyNameNonComputed;
15 changes: 10 additions & 5 deletions packages/eslint-plugin/src/rules/adjacent-overload-signatures.ts
Expand Up @@ -25,7 +25,7 @@ export default util.createRule({
},
schema: [],
messages: {
adjacentSignature: "All '{{name}}' signatures should be adjacent.",
adjacentSignature: 'All {{name}} signatures should be adjacent.',
},
},
defaultOptions: [],
Expand All @@ -36,6 +36,7 @@ export default util.createRule({
name: string;
static: boolean;
callSignature: boolean;
type: util.MemberNameType;
}

/**
Expand Down Expand Up @@ -71,11 +72,12 @@ export default util.createRule({
name,
static: isStatic,
callSignature: false,
type: util.MemberNameType.Normal,
};
}
case AST_NODE_TYPES.TSMethodSignature:
return {
name: util.getNameFromMember(member, sourceCode),
...util.getNameFromMember(member, sourceCode),
static: isStatic,
callSignature: false,
};
Expand All @@ -84,16 +86,18 @@ export default util.createRule({
name: 'call',
static: isStatic,
callSignature: true,
type: util.MemberNameType.Normal,
};
case AST_NODE_TYPES.TSConstructSignatureDeclaration:
return {
name: 'new',
static: isStatic,
callSignature: false,
type: util.MemberNameType.Normal,
};
case AST_NODE_TYPES.MethodDefinition:
return {
name: util.getNameFromMember(member, sourceCode),
...util.getNameFromMember(member, sourceCode),
static: isStatic,
callSignature: false,
};
Expand All @@ -107,7 +111,8 @@ export default util.createRule({
!!method2 &&
method1.name === method2.name &&
method1.static === method2.static &&
method1.callSignature === method2.callSignature
method1.callSignature === method2.callSignature &&
method1.type === method2.type
);
}

Expand Down Expand Up @@ -150,7 +155,7 @@ export default util.createRule({
node: member,
messageId: 'adjacentSignature',
data: {
name: (method.static ? 'static ' : '') + method.name,
name: `${method.static ? 'static ' : ''}${method.name}`,
},
});
} else if (index === -1) {
Expand Down
Expand Up @@ -113,6 +113,10 @@ export default util.createRule<Options, MessageIds>({
function checkMethodAccessibilityModifier(
methodDefinition: TSESTree.MethodDefinition,
): void {
if (methodDefinition.key.type === AST_NODE_TYPES.PrivateIdentifier) {
return;
}

let nodeType = 'method definition';
let check = baseCheck;
switch (methodDefinition.kind) {
Expand All @@ -129,7 +133,10 @@ export default util.createRule<Options, MessageIds>({
break;
}

const methodName = util.getNameFromMember(methodDefinition, sourceCode);
const { name: methodName } = util.getNameFromMember(
methodDefinition,
sourceCode,
);

if (check === 'off' || ignoredMethodNames.has(methodName)) {
return;
Expand Down Expand Up @@ -205,7 +212,7 @@ export default util.createRule<Options, MessageIds>({
): void {
const nodeType = 'class property';

const propertyName = util.getNameFromMember(
const { name: propertyName } = util.getNameFromMember(
propertyDefinition,
sourceCode,
);
Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin/src/rules/member-ordering.ts
Expand Up @@ -280,12 +280,12 @@ function getMemberName(
case AST_NODE_TYPES.TSMethodSignature:
case AST_NODE_TYPES.TSAbstractPropertyDefinition:
case AST_NODE_TYPES.PropertyDefinition:
return util.getNameFromMember(node, sourceCode);
return util.getNameFromMember(node, sourceCode).name;
case AST_NODE_TYPES.TSAbstractMethodDefinition:
case AST_NODE_TYPES.MethodDefinition:
return node.kind === 'constructor'
? 'constructor'
: util.getNameFromMember(node, sourceCode);
: util.getNameFromMember(node, sourceCode).name;
case AST_NODE_TYPES.TSConstructSignatureDeclaration:
return 'new';
case AST_NODE_TYPES.TSCallSignatureDeclaration:
Expand Down Expand Up @@ -428,7 +428,7 @@ export default util.createRule<Options, MessageIds>({
},
messages: {
incorrectOrder:
'Member "{{member}}" should be declared before member "{{beforeMember}}".',
'Member {{member}} should be declared before member {{beforeMember}}.',
incorrectGroupOrder:
'Member {{name}} should be declared before all {{rank}} definitions.',
},
Expand Down
Expand Up @@ -60,7 +60,7 @@ interface NormalizedSelector {
}

type ValidatorFunction = (
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
modifiers?: Set<Modifiers>,
) => void;
type ParsedOptions = Record<SelectorsString, null | ValidatorFunction>;
Expand Down
Expand Up @@ -25,7 +25,9 @@ function createValidator(
type: SelectorsString,
context: Context,
allConfigs: NormalizedSelector[],
): (node: TSESTree.Identifier | TSESTree.Literal) => void {
): (
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
) => void {
// make sure the "highest priority" configs are checked first
const selectorType = Selectors[type];
const configs = allConfigs
Expand Down Expand Up @@ -70,11 +72,14 @@ function createValidator(
});

return (
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
modifiers: Set<Modifiers> = new Set<Modifiers>(),
): void => {
const originalName =
node.type === AST_NODE_TYPES.Identifier ? node.name : `${node.value}`;
node.type === AST_NODE_TYPES.Identifier ||
node.type === AST_NODE_TYPES.PrivateIdentifier
? node.name
: `${node.value}`;

// return will break the loop and stop checking configs
// it is only used when the name is known to have failed or succeeded a config.
Expand Down Expand Up @@ -178,7 +183,7 @@ function createValidator(
position: 'leading' | 'trailing',
config: NormalizedSelector,
name: string,
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
originalName: string,
): string | null {
const option =
Expand Down Expand Up @@ -299,7 +304,7 @@ function createValidator(
position: 'prefix' | 'suffix',
config: NormalizedSelector,
name: string,
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
originalName: string,
): string | null {
const affixes = config[position];
Expand Down Expand Up @@ -339,7 +344,7 @@ function createValidator(
function validateCustom(
config: NormalizedSelector,
name: string,
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
originalName: string,
): boolean {
const custom = config.custom;
Expand Down Expand Up @@ -372,7 +377,7 @@ function createValidator(
function validatePredefinedFormat(
config: NormalizedSelector,
name: string,
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.PrivateIdentifier | TSESTree.Literal,
originalName: string,
): boolean {
const formats = config.format;
Expand Down
7 changes: 5 additions & 2 deletions packages/eslint-plugin/src/rules/naming-convention.ts
Expand Up @@ -620,11 +620,14 @@ function isGlobal(scope: TSESLint.Scope.Scope | null): boolean {
}

function requiresQuoting(
node: TSESTree.Identifier | TSESTree.Literal,
node: TSESTree.Identifier | TSESTree.Literal | TSESTree.PrivateIdentifier,
target: ScriptTarget | undefined,
): boolean {
const name =
node.type === AST_NODE_TYPES.Identifier ? node.name : `${node.value}`;
node.type === AST_NODE_TYPES.Identifier ||
node.type === AST_NODE_TYPES.PrivateIdentifier
? node.name
: `${node.value}`;
return util.requiresQuoting(name, target);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/rules/prefer-for-of.ts
Expand Up @@ -42,7 +42,7 @@ export default util.createRule({
}

function isMatchingIdentifier(
node: TSESTree.Expression,
node: TSESTree.Expression | TSESTree.PrivateIdentifier,
name: string,
): boolean {
return node.type === AST_NODE_TYPES.Identifier && node.name === name;
Expand Down

0 comments on commit 0eefe5e

Please sign in to comment.