Skip to content
Permalink
Browse files

fix(eslint-plugin): [naming-convention] allow an array of selectors w…

…ith types and modifiers (#2415)
  • Loading branch information
ginger-kang committed Sep 14, 2020
1 parent 189162d commit 7ca54c3e4601ad07db5b882a67965cd67a18c4b3
@@ -278,28 +278,29 @@ function selectorsSchema(): JSONSchema.JSONSchema4 {
},
additionalItems: false,
},
modifiers: {
type: 'array',
items: {
type: 'string',
enum: util.getEnumNames(Modifiers),
},
additionalItems: false,
},
types: {
type: 'array',
items: {
type: 'string',
enum: util.getEnumNames(TypeModifiers),
},
additionalItems: false,
},
},
},
modifiers: {
type: 'array',
items: {
type: 'string',
enum: util.getEnumNames(Modifiers),
},
additionalItems: false,
},
types: {
type: 'array',
items: {
type: 'string',
enum: util.getEnumNames(TypeModifiers),
},
additionalItems: false,
},
required: ['selector', 'format'],
additionalProperties: false,
};
}

const SCHEMA: JSONSchema.JSONSchema4 = {
type: 'array',
items: {
@@ -819,7 +820,9 @@ type ParsedOptions = Record<SelectorsString, null | ValidatorFunction>;
type Context = Readonly<TSESLint.RuleContext<MessageIds, Options>>;

function parseOptions(context: Context): ParsedOptions {
const normalizedOptions = context.options.map(opt => normalizeOption(opt));
const normalizedOptions = context.options
.map(opt => normalizeOption(opt))
.reduce((acc, val) => acc.concat(val), []);
return util.getEnumNames(Selectors).reduce((acc, k) => {
acc[k] = createValidator(k, context, normalizedOptions);
return acc;
@@ -1257,7 +1260,8 @@ function isMetaSelector(
): selector is MetaSelectorsString {
return selector in MetaSelectors;
}
function normalizeOption(option: Selector): NormalizedSelector {

function normalizeOption(option: Selector): NormalizedSelector[] {
let weight = 0;
option.modifiers?.forEach(mod => {
weight |= Modifiers[mod];
@@ -1309,16 +1313,30 @@ function normalizeOption(option: Selector): NormalizedSelector {
? option.selector
: [option.selector];

return {
selector: selectors
.map(selector =>
isMetaSelector(selector)
? MetaSelectors[selector]
: Selectors[selector],
)
.reduce((accumulator, selector) => accumulator | selector),
...normalizedOption,
};
const selectorsAllowedToHaveTypes: (Selectors | MetaSelectors)[] = [
Selectors.variable,
Selectors.parameter,
Selectors.property,
Selectors.parameterProperty,
Selectors.accessor,
];

const config: NormalizedSelector[] = [];
selectors
.map(selector =>
isMetaSelector(selector) ? MetaSelectors[selector] : Selectors[selector],
)
.forEach(selector =>
selectorsAllowedToHaveTypes.includes(selector)
? config.push({ selector: selector, ...normalizedOption })
: config.push({
selector: selector,
...normalizedOption,
types: null,
}),
);

return config;
}

function isCorrectType(
@@ -835,6 +835,77 @@ ruleTester.run('naming-convention', rule, {
},
],
},
{
code: `
let isFoo = 1;
class foo {
shouldBoo: number;
}
`,
parserOptions,
options: [
{
selector: ['variable', 'parameter', 'property', 'accessor'],
types: ['number'],
format: ['PascalCase'],
prefix: ['is', 'should', 'has', 'can', 'did', 'will'],
},
],
},
{
code: `
class foo {
private readonly FooBoo: boolean;
}
`,
parserOptions,
options: [
{
selector: ['property', 'accessor'],
types: ['boolean'],
modifiers: ['private', 'readonly'],
format: ['PascalCase'],
},
],
},
{
code: `
class foo {
private fooBoo: number;
}
`,
options: [
{
selector: ['property', 'accessor'],
modifiers: ['private'],
format: ['camelCase'],
},
],
},
{
code: `
const isfooBar = 1;
function fun(goodfunFoo: number) {}
class foo {
private VanFooBar: number;
}
`,
parserOptions,
options: [
{
selector: ['property', 'accessor'],
modifiers: ['private'],
format: ['StrictPascalCase'],
prefix: ['Van'],
},
{
selector: ['variable', 'parameter'],
types: ['number'],
format: ['camelCase'],
prefix: ['is', 'good'],
},
],
},
],
invalid: [
{
@@ -871,19 +942,16 @@ ruleTester.run('naming-convention', rule, {
declare const any_camelCase01: any;
declare const any_camelCase02: any | null;
declare const any_camelCase03: any | null | undefined;
declare const string_camelCase01: string;
declare const string_camelCase02: string | null;
declare const string_camelCase03: string | null | undefined;
declare const string_camelCase04: 'a' | null | undefined;
declare const string_camelCase05: string | 'a' | null | undefined;
declare const number_camelCase06: number;
declare const number_camelCase07: number | null;
declare const number_camelCase08: number | null | undefined;
declare const number_camelCase09: 1 | null | undefined;
declare const number_camelCase10: number | 2 | null | undefined;
declare const boolean_camelCase11: boolean;
declare const boolean_camelCase12: boolean | null;
declare const boolean_camelCase13: boolean | null | undefined;
@@ -955,7 +1023,6 @@ ruleTester.run('naming-convention', rule, {
| undefined;
declare const array_camelCase6: [] | null | undefined;
declare const array_camelCase7: [number] | null | undefined;
declare const array_camelCase8:
| readonly number[]
| Array<string>
@@ -1166,5 +1233,54 @@ ruleTester.run('naming-convention', rule, {
},
],
},
{
code: `
const myfoo_bar = 'abcs';
function fun(myfoo: string) {}
class foo {
Myfoo: string;
}
`,
options: [
{
selector: ['variable', 'property', 'parameter'],
types: ['string'],
format: ['PascalCase'],
prefix: ['my', 'My'],
},
],
parserOptions,
errors: Array(3).fill({ messageId: 'doesNotMatchFormatTrimmed' }),
},
{
code: `
class foo {
private readonly fooBar: boolean;
}
`,
options: [
{
selector: ['property', 'accessor'],
modifiers: ['private', 'readonly'],
format: ['PascalCase'],
},
],
errors: [{ messageId: 'doesNotMatchFormat' }],
},
{
code: `
function my_foo_bar() {}
`,
parserOptions,
options: [
{
selector: ['variable', 'function'],
types: ['string'],
format: ['PascalCase'],
prefix: ['my', 'My'],
},
],
errors: [{ messageId: 'doesNotMatchFormatTrimmed' }],
},
],
});

0 comments on commit 7ca54c3

Please sign in to comment.