Skip to content

Commit

Permalink
feat(prettier-plugin-jsdoc): use a dependency injection container
Browse files Browse the repository at this point in the history
  • Loading branch information
homer0 committed Oct 28, 2020
1 parent 7ca2669 commit 633f6de
Show file tree
Hide file tree
Showing 37 changed files with 512 additions and 327 deletions.
1 change: 1 addition & 0 deletions .jestrc-e2e.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage-e2e',
coveragePathIgnorePatterns: ['/node_modules/', 'app.js'],
testPathIgnorePatterns: ['/node_modules/'],
unmockedModulePathPatterns: ['/node_modules/', '/utils/'],
testEnvironment: './test/e2e/utils/environment.js',
Expand Down
2 changes: 1 addition & 1 deletion .jestrc-unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage-unit',
testPathIgnorePatterns: ['/node_modules/'],
unmockedModulePathPatterns: ['/node_modules/'],
unmockedModulePathPatterns: ['/node_modules/', 'app.js', 'utils.js'],
testEnvironment: 'node',
testMatch: ['**/unit/**/*.test.js'],
};
66 changes: 66 additions & 0 deletions src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/* eslint-disable jsdoc/require-jsdoc */
const path = require('path');

const registry = new Map();
const providerKey = Symbol('provider-secret');
/**
* Adds a new function to the app registry.
*
* @param {Function} originalFn The original function to add.
*/
const addFn = (originalFn) => {
registry.set(originalFn, originalFn);
};
/**
* Overrides a function on the app registry.
*
* @param {OG} originalFn The reference to the original function that will be overriden.
* @param {OG} fn The override function.
* @template OG
*/
const setFn = (originalFn, fn) => {
registry.set(originalFn, fn);
};
/**
* Gets a function or a function override from the app registry.
*
* @param {OG} originalFn The reference to the original function.
* @returns {OG}
* @template OG
*/
const getFn = (originalFn) => registry.get(originalFn) || originalFn;

const registerModule = (id, fns) => {
const useFns = Array.isArray(fns) ? fns : Object.values(fns);
useFns
.filter((fn) => fn.providerKey !== providerKey)
.forEach((fn) => {
// eslint-disable-next-line no-param-reassign
fn.moduleId = id;
addFn(fn);
});
};

const provider = (id, fns) => {
const fn = () => registerModule(id, fns);
fn.providerKey = providerKey;
return fn;
};

const loadProviders = (directoryPath, list) => list
.map((modName) => {
// eslint-disable-next-line global-require, import/no-dynamic-require
const { provider: modProvider } = require(path.join(directoryPath, `${modName}.js`));
return modProvider;
})
.filter((modProvider) => modProvider)
.forEach((modProvider) => {
modProvider();
});

module.exports.addFn = addFn;
module.exports.setFn = setFn;
module.exports.getFn = getFn;
module.exports.registerModule = registerModule;
module.exports.provider = provider;
module.exports.loadProviders = loadProviders;
7 changes: 5 additions & 2 deletions src/fns/formatAccessTag.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const R = require('ramda');
const { findTagIndex } = require('./utils');
const { getFn, provider } = require('../app');

/**
* @typedef {import('../types').PJPAccessTagOptions} PJPAccessTagOptions
Expand All @@ -19,10 +20,11 @@ const { findTagIndex } = require('./utils');
* @type {FormatAccessTagFn}
*/
const formatAccessTag = R.curry((tags, options) => {
const useFindTagIndex = getFn(findTagIndex);
const indexes = tags.reduce(
R.compose(
findTagIndex('access', 'accessTag'),
findTagIndex(
useFindTagIndex('access', 'accessTag'),
useFindTagIndex(
['public', 'protected', 'private'],
'typeTag',
),
Expand Down Expand Up @@ -87,3 +89,4 @@ const formatAccessTag = R.curry((tags, options) => {
});

module.exports.formatAccessTag = formatAccessTag;
module.exports.provider = provider('formatAccessTag', module.exports);
9 changes: 6 additions & 3 deletions src/fns/formatArrays.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const R = require('ramda');
const { isMatch, replaceDotOnTypeGeneric } = require('./utils');
const { getFn, provider } = require('../app');
/**
* @typedef {import('../types').PJPTypesOptions} PJPTypesOptions
*/
Expand All @@ -21,7 +22,7 @@ const { isMatch, replaceDotOnTypeGeneric } = require('./utils');
const processType = R.curry((options, type) => R.compose(
R.when(
R.always(options.jsdocFormatDotForArraysAndObjects),
replaceDotOnTypeGeneric('Array', options.jsdocUseDotForArraysAndObjects),
getFn(replaceDotOnTypeGeneric)('Array', options.jsdocUseDotForArraysAndObjects),
),
R.when(
R.always(options.jsdocUseShortArrays),
Expand All @@ -43,8 +44,10 @@ const processType = R.curry((options, type) => R.compose(
* @type {FormatArraysFn}
*/
const formatArrays = R.curry((type, options) => R.when(
isMatch(/Array\s*\.?\s*</),
processType(options),
getFn(isMatch)(/Array\s*\.?\s*</),
getFn(processType)(options),
)(type));

module.exports.formatArrays = formatArrays;
module.exports.processType = processType;
module.exports.provider = provider('formatArrays', module.exports);
27 changes: 17 additions & 10 deletions src/fns/formatDescription.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const {
joinIfNotEmpty,
appendIfNotPresent,
} = require('./utils');
const { getFn, provider } = require('../app');

/**
* @typedef {import('../types').PJPDescriptionTagOptions} PJPDescriptionTagOptions
* @typedef {import('../types').CommentTag} CommentTag
Expand Down Expand Up @@ -44,7 +46,7 @@ const findTag = R.curry((
unmatchHandlerFn,
step,
) => {
const targetTags = ensureArray(targetTag);
const targetTags = getFn(ensureArray)(targetTag);
return (acc, tag, index) => {
const nextAcc = targetTags.includes(tag.tag) ?
matchHandlerFn(acc, tag, index) :
Expand Down Expand Up @@ -73,9 +75,9 @@ const findTag = R.curry((
* @returns {FindTagHandlerFn<ProcessTagAccumulator>}
*/
const processTag = (descriptionProperty, saveIndex = false) => {
const descriptionProperties = ensureArray(descriptionProperty);
const descriptionProperties = getFn(ensureArray)(descriptionProperty);
const generateDescription = R.compose(
joinIfNotEmpty(' '),
getFn(joinIfNotEmpty)(' '),
R.values,
R.pick(descriptionProperties),
);
Expand All @@ -87,7 +89,7 @@ const processTag = (descriptionProperty, saveIndex = false) => {

return (acc, tag, index) => R.evolve(
{
parts: appendIfNotPresent(generateDescription(tag)),
parts: getFn(appendIfNotPresent)(generateDescription(tag)),
tags: R.append(R.mergeRight(tag, emptyProps)),
tagIndex: R.when(R.always(saveIndex), R.always(index)),
},
Expand Down Expand Up @@ -116,19 +118,21 @@ const formatDescription = R.curry((block, options) => {
* @type {FindTagHandlerFn<ProcessTagAccumulator>}
*/
const pushTag = (acc, tag) => R.evolve({ tags: R.append(tag) }, acc);
const useFindTag = getFn(findTag);
const useProcessTag = getFn(processTag);
const { parts, tags, tagIndex } = block.tags.reduce(
R.compose(
findTag(
useFindTag(
['typedef', 'callback', 'function'],
processTag('description'),
useProcessTag('description'),
R.identity,
),
findTag(
useFindTag(
'description',
processTag(['name', 'description'], true),
useProcessTag(['name', 'description'], true),
R.identity,
),
findTag(
useFindTag(
['description', 'typedef', 'callback', 'function'],
R.identity,
pushTag,
Expand All @@ -141,7 +145,7 @@ const formatDescription = R.curry((block, options) => {
},
);

const description = joinIfNotEmpty('\n\n', parts);
const description = getFn(joinIfNotEmpty)('\n\n', parts);
let blockDescription = block.description;
let blockTags = tags;
if (options.jsdocAllowDescriptionTag) {
Expand Down Expand Up @@ -181,3 +185,6 @@ const formatDescription = R.curry((block, options) => {
});

module.exports.formatDescription = formatDescription;
module.exports.findTag = findTag;
module.exports.processTag = processTag;
module.exports.provider = provider('formatDescription', module.exports);
10 changes: 7 additions & 3 deletions src/fns/formatObjects.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const R = require('ramda');
const { isMatch, replaceDotOnTypeGeneric } = require('./utils');
const { getFn, provider } = require('../app');

/**
* @typedef {import('../types').PJPTypesOptions} PJPTypesOptions
*/
Expand All @@ -19,7 +21,7 @@ const { isMatch, replaceDotOnTypeGeneric } = require('./utils');
*/
const processType = R.curry((options, type) => R.when(
R.always(options.jsdocFormatDotForArraysAndObjects),
replaceDotOnTypeGeneric('Object', options.jsdocUseDotForArraysAndObjects),
getFn(replaceDotOnTypeGeneric)('Object', options.jsdocUseDotForArraysAndObjects),
)(type));

/**
Expand All @@ -36,8 +38,10 @@ const processType = R.curry((options, type) => R.when(
* @type {FormatObjectsFn}
*/
const formatObjects = R.curry((type, options) => R.when(
isMatch(/Object\s*\.?\s*</i),
processType(options),
getFn(isMatch)(/Object\s*\.?\s*</i),
getFn(processType)(options),
)(type));

module.exports.formatObjects = formatObjects;
module.exports.processType = processType;
module.exports.provider = provider('formatObjects', module.exports);
19 changes: 10 additions & 9 deletions src/fns/formatStringLiterals.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const R = require('ramda');
const { getFn, provider } = require('../app');

/**
* @typedef {import('../types').PJPTypesOptions} PJPTypesOptions
*/
Expand Down Expand Up @@ -47,22 +49,17 @@ const getFormatter = (padding, quote) => R.compose(
const getReducer = (options) => {
const quote = options.jsdocUseSingleQuotesForStringLiterals ? '\'' : '"';
const padding = ' '.repeat(options.jsdocSpacesBetweenStringLiterals);
const formatter = getFormatter(padding, quote);
const formatter = getFn(getFormatter)(padding, quote);
return (type, literal) => R.replace(literal, formatter(literal), type);
};

/**
* Finds and extracts all the string literals on a type.
*
* @callback ExtractLiteralsFn
* @param {string} type The type that will be used to find the string literals.
* @returns {string[]}
*/

/**
* @type {ExtractLiteralsFn}
*/
const extractLiterals = R.match(/['"][\w\|\-\s'"]+['"](?:\s+)?/g);
const extractLiterals = (type) => R.match(/['"][\w\|\-\s'"]+['"](?:\s+)?/g, type);
/**
* Formats the styling of string literals inside a type. If the type doesn't use string literals,
* it will be returned without modification.
Expand All @@ -79,10 +76,14 @@ const extractLiterals = R.match(/['"][\w\|\-\s'"]+['"](?:\s+)?/g);
const formatStringLiterals = R.curry((type, options) => R.compose(
(literals) => (
literals.length ?
R.reduce(getReducer(options), type, literals) :
R.reduce(getFn(getReducer)(options), type, literals) :
type
),
extractLiterals,
getFn(extractLiterals),
)(type));

module.exports.formatStringLiterals = formatStringLiterals;
module.exports.getFormatter = getFormatter;
module.exports.getReducer = getReducer;
module.exports.extractLiterals = extractLiterals;
module.exports.provider = provider('formatStringLiterals', module.exports);
21 changes: 11 additions & 10 deletions src/fns/formatTSTypes.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const R = require('ramda');
const { capitalize, ensureArray } = require('./utils');
const { getFn, provider } = require('../app');

/**
* Utility function generated by {@link getFormater} and that can be used to modify a type name.
Expand Down Expand Up @@ -35,23 +36,23 @@ const getFormater = (type, modifier) => R.compose(
(_, before, rawType, after) => `${before}${modifier(rawType)}${after}`,
),
R.join('|'),
ensureArray,
getFn(ensureArray),
)(type);

/**
* Formats each type reference on a type in order to match the casing allowed by TypeScript.
*
* @callback FormatTSTypesFn
* @param {string} type The type to format.
* @returns {string}
*/

/**
* @type {FormatTSTypesFn}
*/
const formatTSTypes = R.compose(
getFormater(['array', 'object'], capitalize),
getFormater(['String', 'Number', 'Boolean'], R.toLower),
);
const formatTSTypes = (type) => {
const useGetFormatter = getFn(getFormater);
return R.compose(
useGetFormatter(['array', 'object'], getFn(capitalize)),
useGetFormatter(['String', 'Number', 'Boolean'], R.toLower),
)(type);
};

module.exports.formatTSTypes = formatTSTypes;
module.exports.getFormater = getFormater;
module.exports.provider = provider('formatTSTypes', module.exports);
12 changes: 7 additions & 5 deletions src/fns/formatTags.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { replaceTagsSynonyms } = require('./replaceTagsSynonyms');
const { sortTags } = require('./sortTags');
const { trimTagsProperties } = require('./trimTagsProperties');
const { formatTagsDescription } = require('./formatTagsDescription');
const { getFn, provider } = require('../app');

/**
* @typedef {import('../types').CommentTag} CommentTag
Expand All @@ -24,20 +25,21 @@ const { formatTagsDescription } = require('./formatTagsDescription');
*/
const formatTags = R.curry((tags, options) => {
const fns = [
formatTagsDescription,
trimTagsProperties,
formatAccessTag(R.__, options),
getFn(formatTagsDescription),
getFn(trimTagsProperties),
getFn(formatAccessTag)(R.__, options),
];

if (options.jsdocReplaceTagsSynonyms) {
fns.push(replaceTagsSynonyms);
fns.push(getFn(replaceTagsSynonyms));
}

if (options.jsdocSortTags) {
fns.push(sortTags(R.__, options));
fns.push(getFn(sortTags)(R.__, options));
}

return R.compose(...fns.reverse())(tags);
});

module.exports.formatTags = formatTags;
module.exports.provider = provider('formatTags', module.exports);

0 comments on commit 633f6de

Please sign in to comment.