Skip to content

Commit

Permalink
Merge pull request #147 from epaew/feature/refactor_utils_pluralize
Browse files Browse the repository at this point in the history
Refactor utils/pluralize.ts
  • Loading branch information
epaew authored Oct 10, 2020
2 parents 527a694 + 44b9fcc commit fc414bc
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 101 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
## Others
* [#51](https://github.com/epaew/eslint-plugin-filenames-simple/pull/51)
Use `core-js` as replacement of my own polyfill implementation.
* [#147](https://github.com/epaew/eslint-plugin-filenames-simple/pull/147)
Refactor utils/pluralize: Remove dependency on `eslint` package.

# 0.4.0
## Features
Expand Down
66 changes: 23 additions & 43 deletions __tests__/utils/pluralize.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
import { Rule } from 'eslint';
import * as pluralize from '#/utils/pluralize';
import { Dictionaries, Pluralize } from '#/utils/pluralize';

describe('pluralize.correct', () => {
const subject = pluralize.correct;

describe('when the rule is undefined', () => {
const rule = undefined;

it('returns same name', () => {
const names = ['test', 'tests'];
expect(names.map(name => subject(name, rule))).toEqual(names);
});
});
const pluralize = new Pluralize();
const subject: typeof pluralize.correct = (name, rule) => pluralize.correct(name, rule);

describe('when the rule is singular', () => {
const rule = 'singular';
Expand All @@ -33,16 +24,8 @@ describe('pluralize.correct', () => {
});

describe('pluralize.isValidName', () => {
const subject = pluralize.isValidName;

describe('when the rule is undefined', () => {
const rule = undefined;

it('returns always true', () => {
const names = ['test', 'tests'];
expect(names.map(name => subject(name, rule))).toEqual([true, true]);
});
});
const pluralize = new Pluralize();
const subject: typeof pluralize.isValidName = (name, rule) => pluralize.isValidName(name, rule);

describe('when the rule is singular', () => {
const rule = 'singular';
Expand All @@ -64,36 +47,33 @@ describe('pluralize.isValidName', () => {
});

// NOTE: This test affects other tests because the instance of `pluralize` is a singleton.
describe('pluralize.initPluralize', () => {
const subject = (context: Pick<Rule.RuleContext, 'settings'>) => pluralize.initPluralize(context);
describe('new Pluralize()', () => {
const subject = (dictionaries?: Dictionaries) => new Pluralize(dictionaries);

describe('when dictionaries are empty', () => {
const context = { settings: {} };
describe('when the dictionaries are undefined', () => {
const dictionaries = undefined;

it('does not throw error', () => {
subject(context);
});
});

describe('when dictionaries are present', () => {
const dictionaries = {
irregular: [['regular', 'irregular']] as [string, string][],
plural: [['index', 'indexes']] as [string, string][],
singular: [['shoes', 'shoes']] as [string, string][],
uncountable: ['test'],
};
const context = { settings: { 'filenames-simple': { pluralize: dictionaries } } };
it('uses default dictionaries of pluralize.', () => {
const pluralize = subject(dictionaries);

it('set the dictionaries of pluralize', () => {
// before setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('regulars');
expect(pluralize.correct('index', 'plural')).toBe('indices');
expect(pluralize.correct('shoes', 'singular')).toBe('shoe');
expect(pluralize.correct('test', 'plural')).toBe('tests');
});
});

describe('when the dictionaries are present', () => {
const dictionaries: Dictionaries = {
irregular: [['regular', 'irregular']],
plural: [['index', 'indexes']],
singular: [['shoes', 'shoes']],
uncountable: ['test'],
};

subject(context);
it('uses customized dictionaries.', () => {
const pluralize = subject(dictionaries);

// after setDictionaries()
expect(pluralize.correct('regular', 'plural')).toBe('irregular');
expect(pluralize.correct('index', 'plural')).toBe('indexes');
expect(pluralize.correct('shoes', 'singular')).toBe('shoes');
Expand Down
10 changes: 5 additions & 5 deletions src/rules/named-export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Rule } from 'eslint';
import { Identifier, Program, ESTreeParser } from '../utils/estree-parser';
import { isSameName } from '../utils/is-same-name';
import { presetCaseConverters } from '../utils/preset-case-converters';
import { initPluralize, isValidName } from '../utils/pluralize';
import { Pluralize } from '../utils/pluralize';

type Pluralize = 'always' | 'singular' | 'plural';
type PluralizeRule = 'always' | 'singular' | 'plural';

const fetchFilename = (context: Rule.RuleContext) => {
const absolutePath = path.resolve(context.getFilename());
Expand Down Expand Up @@ -36,14 +36,14 @@ export const namedExport: Rule.RuleModule = {
schema: [{ enum: ['always', 'singular', 'plural'] }],
},
create: context => {
initPluralize(context);
const pluralize: Pluralize = context.options[0] ?? 'always';
const pluralize = new Pluralize(context.settings?.['filenames-simple']?.pluralize);
const rule: PluralizeRule = context.options[0] ?? 'always';

return {
Program: node => {
const filename = fetchFilename(context);

if (!(pluralize === 'always' || isValidName(filename, pluralize))) return;
if (!(rule === 'always' || pluralize.isValidName(filename, rule))) return;

const [target, ...rest] = fetchTargets(node as Program);
if (!target || rest.length !== 0) return;
Expand Down
18 changes: 13 additions & 5 deletions src/rules/pluralize.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';
import { Rule } from 'eslint';
import { correct, initPluralize, isValidName } from '../utils/pluralize';

import { Pluralize, PluralizeRule } from '../utils/pluralize';

type Rules = {
parentDir?: 'singular' | 'plural';
Expand Down Expand Up @@ -30,22 +31,29 @@ export const pluralize: Rule.RuleModule = {
],
},
create: context => {
initPluralize(context);
const pluralize = new Pluralize(context.settings?.['filenames-simple']?.pluralize);
const rules: Rules = context.options[0] ?? {};

const correctedName = (name: string, rule?: PluralizeRule) =>
rule ? pluralize.correct(name, rule) : name;
const isValidName = (name: string, rule?: PluralizeRule) =>
rule ? pluralize.isValidName(name, rule) : true;

return {
Program: node => {
const [dirname, [filename, ...rest]] = fetchFilename(context);

if (isValidName(dirname, rules.parentDir) && isValidName(filename, rules.file)) return;
if (isValidName(dirname, rules.parentDir) && isValidName(filename, rules.file)) {
return;
}

context.report({
node: node,
message:
'The filename must follow the pluralize rule. Should rename to {{ dirname }}/{{ filename }}.{{ extname }}',
data: {
dirname: correct(dirname, rules.parentDir),
filename: correct(filename, rules.file),
dirname: correctedName(dirname, rules.parentDir),
filename: correctedName(filename, rules.file),
extname: rest.join('.'),
},
});
Expand Down
48 changes: 0 additions & 48 deletions src/utils/pluralize.ts

This file was deleted.

43 changes: 43 additions & 0 deletions src/utils/pluralize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import pluralize from 'pluralize';

import { Dictionaries, PluralizeRule } from './types';
export { Dictionaries, PluralizeRule };

export class Pluralize {
readonly #pluralize: typeof pluralize;

constructor(dictionaries?: Dictionaries) {
this.#pluralize = pluralize;
dictionaries && this.setDictionaries(dictionaries);
}

correct(name: string, rule: PluralizeRule): string {
const corrector = {
singular: this.#pluralize.singular,
plural: this.#pluralize.plural,
};
return corrector[rule](name);
}

isValidName(name: string, rule: PluralizeRule): boolean {
const validator = {
singular: this.#pluralize.isSingular,
plural: this.#pluralize.isPlural,
};
return validator[rule](name);
}

private setDictionaries({ irregular, plural, singular, uncountable }: Dictionaries) {
irregular &&
irregular.forEach(([singular, plural]) => this.#pluralize.addIrregularRule(singular, plural));
plural &&
plural.forEach(([plural, singular]) =>
this.#pluralize.addPluralRule(new RegExp(plural), singular),
);
singular &&
singular.forEach(([singular, plural]) =>
this.#pluralize.addSingularRule(new RegExp(singular), plural),
);
uncountable && uncountable.forEach(this.#pluralize.addUncountableRule);
}
}
7 changes: 7 additions & 0 deletions src/utils/pluralize/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type Dictionaries = {
irregular?: [string, string][];
plural?: [string, string][];
singular?: [string, string][];
uncountable?: string[];
};
export type PluralizeRule = 'singular' | 'plural';

0 comments on commit fc414bc

Please sign in to comment.