Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: Extract files under /src/cli #9826

Merged
merged 2 commits into from Dec 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
149 changes: 149 additions & 0 deletions src/cli/context.js
@@ -0,0 +1,149 @@
"use strict";
const fromPairs = require("lodash/fromPairs");
const pick = require("lodash/pick");

// eslint-disable-next-line no-restricted-modules
const prettier = require("../index");
const { createLogger } = require("./logger");
const {
optionsModule,
optionsNormalizer,
utils: { arrayify },
} = require("./prettier-internal");
const minimist = require("./minimist");
const constant = require("./constant");
const {
createDetailedOptionMap,
normalizeDetailedOptionMap,
} = require("./option-map");
const createMinimistOptions = require("./create-minimist-options");

/**
* @typedef {Object} Context
* @property logger
* @property {string[]} args
* @property argv
* @property {string[]} filePatterns
* @property {any[]} supportOptions
* @property detailedOptions
* @property detailedOptionMap
* @property apiDefaultOptions
* @property languages
* @property {Partial<Context>[]} stack
*/

/** @returns {Context} */
function createContext(args) {
/** @type {Context} */
const context = { args, stack: [] };

updateContextArgv(context);
normalizeContextArgv(context, ["loglevel", "plugin", "plugin-search-dir"]);

context.logger = createLogger(context.argv.loglevel);

updateContextArgv(
context,
context.argv.plugin,
context.argv["plugin-search-dir"]
);

return context;
}

function initContext(context) {
// split into 2 step so that we could wrap this in a `try..catch` in cli/index.js
normalizeContextArgv(context);
}

/**
* @param {Context} context
* @param {string[]} plugins
* @param {string[]=} pluginSearchDirs
*/
function updateContextOptions(context, plugins, pluginSearchDirs) {
const { options: supportOptions, languages } = prettier.getSupportInfo({
showDeprecated: true,
showUnreleased: true,
showInternal: true,
plugins,
pluginSearchDirs,
});

const detailedOptionMap = normalizeDetailedOptionMap({
...createDetailedOptionMap(supportOptions),
...constant.options,
});

const detailedOptions = arrayify(detailedOptionMap, "name");

const apiDefaultOptions = {
...optionsModule.hiddenDefaults,
...fromPairs(
supportOptions
.filter(({ deprecated }) => !deprecated)
.map((option) => [option.name, option.default])
),
};

Object.assign(context, {
supportOptions,
detailedOptions,
detailedOptionMap,
apiDefaultOptions,
languages,
});
}

/**
* @param {Context} context
* @param {string[]} plugins
* @param {string[]=} pluginSearchDirs
*/
function pushContextPlugins(context, plugins, pluginSearchDirs) {
context.stack.push(
pick(context, [
"supportOptions",
"detailedOptions",
"detailedOptionMap",
"apiDefaultOptions",
"languages",
])
);
updateContextOptions(context, plugins, pluginSearchDirs);
}

/**
* @param {Context} context
*/
function popContextPlugins(context) {
Object.assign(context, context.stack.pop());
}

function updateContextArgv(context, plugins, pluginSearchDirs) {
pushContextPlugins(context, plugins, pluginSearchDirs);

const minimistOptions = createMinimistOptions(context.detailedOptions);
const argv = minimist(context.args, minimistOptions);

context.argv = argv;
context.filePatterns = argv._.map((file) => String(file));
}

function normalizeContextArgv(context, keys) {
const detailedOptions = !keys
? context.detailedOptions
: context.detailedOptions.filter((option) => keys.includes(option.name));
const argv = !keys ? context.argv : pick(context.argv, keys);

context.argv = optionsNormalizer.normalizeCliOptions(argv, detailedOptions, {
logger: context.logger,
});
}

module.exports = {
createContext,
initContext,
popContextPlugins,
pushContextPlugins,
};
58 changes: 58 additions & 0 deletions src/cli/core.js
@@ -0,0 +1,58 @@
"use strict";

const path = require("path");

const stringify = require("fast-json-stable-stringify");

// eslint-disable-next-line no-restricted-modules
const prettier = require("../index");

const { format, formatStdin, formatFiles } = require("./format");
const { createContext, initContext } = require("./context");
const {
normalizeDetailedOptionMap,
createDetailedOptionMap,
} = require("./option-map");
const { createDetailedUsage, createUsage } = require("./usage");

function logResolvedConfigPathOrDie(context) {
const configFile = prettier.resolveConfigFile.sync(
context.argv["find-config-path"]
);
if (configFile) {
context.logger.log(path.relative(process.cwd(), configFile));
} else {
process.exit(1);
}
}

function logFileInfoOrDie(context) {
const options = {
ignorePath: context.argv["ignore-path"],
withNodeModules: context.argv["with-node-modules"],
plugins: context.argv.plugin,
pluginSearchDirs: context.argv["plugin-search-dir"],
resolveConfig: context.argv.config !== false,
};

context.logger.log(
prettier.format(
stringify(prettier.getFileInfo.sync(context.argv["file-info"], options)),
{ parser: "json" }
)
);
}

module.exports = {
createContext,
createDetailedOptionMap,
createDetailedUsage,
createUsage,
format,
formatFiles,
formatStdin,
initContext,
logResolvedConfigPathOrDie,
logFileInfoOrDie,
normalizeDetailedOptionMap,
};
37 changes: 37 additions & 0 deletions src/cli/create-minimist-options.js
@@ -0,0 +1,37 @@
"use strict";

const partition = require("lodash/partition");
const flat = require("lodash/flatten");
const fromPairs = require("lodash/fromPairs");

module.exports = function createMinimistOptions(detailedOptions) {
const [boolean, string] = partition(
detailedOptions,
({ type }) => type === "boolean"
).map((detailedOptions) =>
flat(
detailedOptions.map(({ name, alias }) => (alias ? [name, alias] : [name]))
)
);

const defaults = fromPairs(
detailedOptions
.filter(
(option) =>
!option.deprecated &&
(!option.forwardToApi ||
option.name === "plugin" ||
option.name === "plugin-search-dir") &&
option.default !== undefined
)
.map((option) => [option.name, option.default])
);

return {
// we use vnopts' AliasSchema to handle aliases for better error messages
alias: {},
boolean,
string,
default: defaults,
};
};
2 changes: 1 addition & 1 deletion src/cli/expand-patterns.js
Expand Up @@ -5,7 +5,7 @@ const fs = require("fs");
const fastGlob = require("fast-glob");
const flat = require("lodash/flatten");

/** @typedef {import('./util').Context} Context */
/** @typedef {import('./context').Context} Context */

/**
* @param {Context} context
Expand Down