Skip to content

Commit

Permalink
chore: add types to new-rule.js
Browse files Browse the repository at this point in the history
  • Loading branch information
lishaduck committed Jun 27, 2024
1 parent 493059c commit 0292dd0
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 13 deletions.
4 changes: 2 additions & 2 deletions lib/fs-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const {rimraf} = require('rimraf');
* @returns {Promise<unknown>}
*/
async function readJsonFile(file, reviver) {
const data = await readFile(file, {encoding: 'utf8', reviver});
const data = await readFile(file, {encoding: 'utf8'});

let json;
try {
Expand All @@ -40,7 +40,7 @@ function readJsonFileSync(file) {
* Read a file using Promises.
*
* @param {string} file
* @param {object} [options={encoding: 'utf8'}]
* @param {fs.BaseEncodingOptions & { flag?: fs.OpenMode | undefined }} [options={encoding: 'utf8'}]
* @returns {Promise<string>}
*/
async function readFile(file, options) {
Expand Down
4 changes: 3 additions & 1 deletion lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ function createExports() {
return Help.newRule();
}

return NewRule.create(options).catch(errorHandler);
return NewRule.create(/** @type {ReviewOptions} */ (options)).catch(
errorHandler
);
}

if (options.subcommand === 'new-package') {
Expand Down
118 changes: 108 additions & 10 deletions lib/new-rule.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@ const ErrorMessage = require('./error-message');

const packageNameRegex = /.+\/(elm-)?review-.+/;

/**
* @import {Options, ReviewOptions, RuleType} from './types/options';
* @import {PackageElmJson} from './types/content';
*/

/**
* @param {ReviewOptions} options
*/
async function create(options) {
const elmJson = readElmJson(options);

Expand All @@ -26,33 +34,43 @@ You can run ${chalk.cyan('elm-review new-package')} to get started with a new pr
validateRuleName(options.newRuleName);
}

const ruleName = options.newRuleName || (await askForRuleName());
const ruleName = options.newRuleName ?? (await askForRuleName());
if (!ruleName) {
return;
}

const ruleType = options.ruleType || (await askForRuleType());
const ruleType = options.ruleType ?? (await askForRuleType());
if (!ruleType) {
return;
}

await addRule(options, elmJson, ruleName, ruleType);
}

/**
* @param {Options} options
* @returns {PackageElmJson | null}
*/
function readElmJson(options) {
if (!options.elmJsonPath) {
return null;
}

try {
return FS.readJsonFileSync(options.elmJsonPath);
return /** @type {PackageElmJson} */ (
FS.readJsonFileSync(options.elmJsonPath)
);
} catch {
return null;
}
}

const ruleNameRegex = /^[A-Z]\w*(\.[A-Z]\w*)*$/;

/**
* @param {string} ruleName
* @returns {string}
*/
function validateRuleName(ruleName) {
if (!ruleNameRegex.test(ruleName)) {
throw new ErrorMessage.CustomError(
Expand Down Expand Up @@ -94,6 +112,9 @@ async function askForRuleName() {
return ruleName;
}

/**
* @returns {Promise<RuleType | null>}
*/
async function askForRuleType() {
let canceled = false;
const {ruleType} = await prompts(
Expand Down Expand Up @@ -131,10 +152,22 @@ async function askForRuleType() {
return ruleType;
}

/**
* @param {string} dir
* @param {string} fileName
* @param {string} content
*/
function writeFile(dir, fileName, content) {
fs.writeFileSync(path.join(dir, fileName), content);
}

/**
*
* @param {ReviewOptions} options
* @param {PackageElmJson} elmJson
* @param {string} ruleName
* @param {RuleType} ruleType
*/
async function addRule(options, elmJson, ruleName, ruleType) {
const ruleNameFolder = ruleName.split('.').slice(0, -1).join('/');
const dir = path.dirname(options.elmJsonPath);
Expand Down Expand Up @@ -174,10 +207,9 @@ async function addRule(options, elmJson, ruleName, ruleType) {
}

try {
const readmeContent = await FS.readFile(
path.join(dir, 'README.md'),
'utf8'
);
const readmeContent = await FS.readFile(path.join(dir, 'README.md'), {
encoding: 'utf8'
});
injectRuleInReadme(dir, elmJson, ruleName, readmeContent);
} catch {
console.log(
Expand All @@ -203,6 +235,11 @@ async function addRule(options, elmJson, ruleName, ruleType) {
}
}

/**
* @param {string} dir
* @param {PackageElmJson} elmJson
* @param {string} ruleName
*/
function injectRuleInPreview(dir, elmJson, ruleName) {
try {
const content = fs.readFileSync(
Expand All @@ -221,6 +258,12 @@ function injectRuleInPreview(dir, elmJson, ruleName) {
}
}

/**
* @param {string} dir
* @param {PackageElmJson} elmJson
* @param {string} ruleName
* @param {string} content
*/
function injectRuleInReadme(dir, elmJson, ruleName, content) {
const lines = content.split('\n');
insertRuleDescription(elmJson, ruleName, lines);
Expand All @@ -230,7 +273,12 @@ function injectRuleInReadme(dir, elmJson, ruleName, content) {

const ruleSectionRegex = /^#+.*rules/i;

// Mutates `lines`!
/**
* @param {PackageElmJson} elmJson
* @param {string} ruleName
* @param {string[]} lines
* @description - Mutates `lines`!
*/
function insertRuleDescription(elmJson, ruleName, lines) {
const rulesSectionIndex = lines.findIndex((line) =>
ruleSectionRegex.test(line)
Expand All @@ -254,6 +302,11 @@ function insertRuleDescription(elmJson, ruleName, lines) {
}
}

/**
* @param {string} ruleName
* @param {number} rulesSectionIndex
* @param {string[]} lines
*/
function alreadyHasRuleDescription(ruleName, rulesSectionIndex, lines) {
const nextSectionIndex = findNextSectionIndex(rulesSectionIndex, lines);

Expand All @@ -264,6 +317,10 @@ function alreadyHasRuleDescription(ruleName, rulesSectionIndex, lines) {
);
}

/**
* @param {number} previousSectionIndex
* @param {string[]} lines
*/
function findNextSectionIndex(previousSectionIndex, lines) {
const nextSectionIndex = lines
.slice(previousSectionIndex + 1)
Expand All @@ -276,7 +333,14 @@ function findNextSectionIndex(previousSectionIndex, lines) {
return previousSectionIndex + nextSectionIndex + 1;
}

// Mutates `lines`!
/**
* @remarks Mutates `lines`!
*
* @param {string} configurationPath
* @param {PackageElmJson} elmJson
* @param {string} ruleName
* @param {string[]} lines
*/
function insertRuleInConfiguration(
configurationPath,
elmJson,
Expand All @@ -288,11 +352,16 @@ function insertRuleInConfiguration(
return;
}

const someOtherRule = elmJson['exposed-modules'][0];
const someOtherRule = /** @type {string[]} */ (elmJson['exposed-modules'])[0];
insertImport(configurationPath, ruleName, lines);
insertRuleInConfigList(ruleName, someOtherRule, lines);
}

/**
* @param {string} configurationPath
* @param {string} ruleName
* @param {string[]} lines
*/
function insertImport(configurationPath, ruleName, lines) {
const firstImportIndex = lines.findIndex((line) => line.startsWith('import'));

Expand Down Expand Up @@ -320,6 +389,11 @@ function insertImport(configurationPath, ruleName, lines) {
lines.splice(firstImportIndex, numberOfImports, ...importLines);
}

/**
* @param {string} ruleName
* @param {string} someOtherRule
* @param {string[]} lines
*/
function insertRuleInConfigList(ruleName, someOtherRule, lines) {
const indexOfOtherRuleExample = lines.findIndex((line) =>
line.includes(`${someOtherRule}.rule`)
Expand All @@ -342,6 +416,11 @@ function insertRuleInConfigList(ruleName, someOtherRule, lines) {
}
}

/**
* @param {string} fullPackageName
* @param {string} ruleName
* @param {RuleType} ruleType
*/
function newSourceFile(fullPackageName, ruleName, ruleType) {
return `module ${ruleName} exposing (rule)
Expand Down Expand Up @@ -397,6 +476,10 @@ ${
}`;
}

/**
* @param {string} ruleName
* @returns {string}
*/
function moduleRuleTemplate(ruleName) {
return `rule : Rule
rule =
Expand Down Expand Up @@ -425,6 +508,11 @@ expressionVisitor node context =
`;
}

/**
* @param {string} ruleName
* @returns {string}
* @todo Create a branded `ElmSource` type.
*/
function projectRuleTemplate(ruleName) {
return `rule : Rule
rule =
Expand Down Expand Up @@ -488,6 +576,10 @@ expressionVisitor node context =
`;
}

/**
* @param {string} ruleName
* @returns {string}
*/
function newTestFile(ruleName) {
return `module ${ruleName}Test exposing (all)
Expand Down Expand Up @@ -523,6 +615,12 @@ a = 1
`;
}

/**
* @param {string} packageName
* @param {string} packageVersion
* @param {string} ruleName
* @returns {string}
*/
function ruleDescription(packageName, packageVersion, ruleName) {
const ruleNameAsUrl = ruleName.split('.').join('-');
return `- [\`${ruleName}\`](https://package.elm-lang.org/packages/${packageName}/${packageVersion}/${ruleNameAsUrl}) - Reports REPLACEME.`;
Expand Down
1 change: 1 addition & 0 deletions tsconfig.no-implicit-any.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"lib/help.js",
"lib/load-compiled-app.js",
"lib/min-version.js",
"lib/new-rule.js",
"lib/options.js",
"lib/os-helpers.js",
"lib/parse-elm.js",
Expand Down

0 comments on commit 0292dd0

Please sign in to comment.