Skip to content

Commit

Permalink
Merge pull request #513 from znarf/refactor/content
Browse files Browse the repository at this point in the history
Refactor: read content only when needed
  • Loading branch information
rumpl committed Jan 30, 2020
2 parents 4409936 + 2ef1cb8 commit 19f9dad
Show file tree
Hide file tree
Showing 49 changed files with 530 additions and 492 deletions.
100 changes: 46 additions & 54 deletions src/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { loadModuleData, readJSON } from './utils';
import getNodes from './utils/parser';
import { getAtTypesName } from './utils/typescript';
import { availableParsers } from './constants';
import { getContent } from './utils/file';

function isModule(dir) {
try {
Expand Down Expand Up @@ -48,61 +47,54 @@ function discoverPropertyDep(rootDir, deps, property, depName) {
return lodash.intersection(deps, propertyDeps);
}

function getDependencies(dir, filename, deps, parser, detectors) {
return new Promise((resolve, reject) => {
getContent(filename)
.then((content) => resolve(parser(content, filename, deps, dir)))
.catch((error) => reject(error));
}).then((ast) => {
// when parser returns string array, skip detector step and treat them as dependencies.
const dependencies =
lodash.isArray(ast) && ast.every(lodash.isString)
? ast
: lodash(getNodes(ast))
.map((node) => detect(detectors, node, deps))
.flatten()
.uniq()
.map(requirePackageName)
.thru((_dependencies) =>
parser === availableParsers.typescript
? // If this is a typescript file, importing foo would also use @types/foo, but
// only if @types/foo is already a specified dependency.
lodash(_dependencies)
.map((dependency) => {
const atTypesName = getAtTypesName(dependency);
return deps.includes(atTypesName)
? [dependency, atTypesName]
: [dependency];
})
.flatten()
.value()
: _dependencies,
)
.value();
async function getDependencies(dir, filename, deps, parser, detectors) {
const result = await parser(filename, deps, dir);

const discover = lodash.partial(discoverPropertyDep, dir, deps);
const discoverPeerDeps = lodash.partial(discover, 'peerDependencies');
const discoverOptionalDeps = lodash.partial(
discover,
'optionalDependencies',
);
const peerDeps = lodash(dependencies)
.map(discoverPeerDeps)
.flatten()
.value();
const optionalDeps = lodash(dependencies)
.map(discoverOptionalDeps)
.flatten()
.value();
// when parser returns string array, skip detector step and treat them as dependencies.
const dependencies =
lodash.isArray(result) && result.every(lodash.isString)
? result
: lodash(getNodes(result))
.map((node) => detect(detectors, node, deps))
.flatten()
.uniq()
.map(requirePackageName)
.thru((_dependencies) =>
parser === availableParsers.typescript
? // If this is a typescript file, importing foo would also use @types/foo, but
// only if @types/foo is already a specified dependency.
lodash(_dependencies)
.map((dependency) => {
const atTypesName = getAtTypesName(dependency);
return deps.includes(atTypesName)
? [dependency, atTypesName]
: [dependency];
})
.flatten()
.value()
: _dependencies,
)
.value();

return lodash(dependencies)
.concat(peerDeps)
.concat(optionalDeps)
.filter((dep) => dep && dep !== '.' && dep !== '..') // TODO why need check?
.filter((dep) => !lodash.includes(builtInModules, dep))
.uniq()
.value();
});
const discover = lodash.partial(discoverPropertyDep, dir, deps);
const discoverPeerDeps = lodash.partial(discover, 'peerDependencies');
const discoverOptionalDeps = lodash.partial(discover, 'optionalDependencies');
const peerDeps = lodash(dependencies)
.map(discoverPeerDeps)
.flatten()
.value();
const optionalDeps = lodash(dependencies)
.map(discoverOptionalDeps)
.flatten()
.value();

return lodash(dependencies)
.concat(peerDeps)
.concat(optionalDeps)
.filter((dep) => dep && dep !== '.' && dep !== '..') // TODO why need check?
.filter((dep) => !lodash.includes(builtInModules, dep))
.uniq()
.value();
}

function checkFile(dir, filename, deps, parsers, detectors) {
Expand Down
4 changes: 3 additions & 1 deletion src/parser/coffee.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import DepsRegex from 'deps-regex';
import { getContent } from '../utils/file';

const re = new DepsRegex({ matchES6: false });

export default function parseCoffeeScript(content) {
export default async function parseCoffeeScript(filename) {
const content = await getContent(filename);
return re.getDependencies(content);
}
4 changes: 3 additions & 1 deletion src/parser/es6.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { parse } from '@babel/parser';
import { getContent } from '../utils/file';

export default function parseES6(content) {
export default async function parseES6(filename) {
const content = await getContent(filename);
return parse(content, {
sourceType: 'module',
});
Expand Down
8 changes: 7 additions & 1 deletion src/parser/es7.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { parse } from '@babel/parser';
import { getContent } from '../utils/file';

export default function parseES7(content) {
export function parseES7Content(content) {
return parse(content, {
sourceType: 'module',

Expand Down Expand Up @@ -35,3 +36,8 @@ export default function parseES7(content) {
],
});
}

export default async function parseES7(filename) {
const content = await getContent(filename);
return parseES7Content(content);
}
4 changes: 3 additions & 1 deletion src/parser/jsx.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { parse } from '@babel/parser';
import { getContent } from '../utils/file';

export default function parseJSX(content) {
export default async function parseJSX(filename) {
const content = await getContent(filename);
return parse(content, {
sourceType: 'module',

Expand Down
6 changes: 3 additions & 3 deletions src/parser/sass.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { tryRequire } from '../utils';

const sass = tryRequire('node-sass');

export default function parseSASS(content, filePath, deps, rootDir) {
export default async function parseSASS(filename, deps, rootDir) {
const { stats } = sass.renderSync({
file: filePath,
includePaths: [path.dirname(filePath)],
file: filename,
includePaths: [path.dirname(filename)],
importer: tildeImporter,
});

Expand Down
4 changes: 3 additions & 1 deletion src/parser/typescript.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { parse } from '@babel/parser';
import { getContent } from '../utils/file';

export default function parseTypescript(content) {
export default async function parseTypescript(filename) {
const content = await getContent(filename);
// Enable all known compatible @babel/parser plugins at the time of writing.
// Because we only parse them, not evaluate any code, it is safe to do so.
// note that babel/parser 7+ does not support *, due to plugin incompatibilities
Expand Down
4 changes: 3 additions & 1 deletion src/parser/vue.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { parse } from '@babel/parser';
import { parseComponent } from 'vue-template-compiler';
import { getContent } from '../utils/file';

export default function parseVue(content) {
export default async function parseVue(filename) {
const content = await getContent(filename);
const parsed = parseComponent(content);
if (!parsed.script) {
return [];
Expand Down
8 changes: 5 additions & 3 deletions src/special/babel.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'path';
import lodash from 'lodash';
import { loadConfig } from '../utils/cli-tools';
import { getContent } from '../utils/file';

function parse(content) {
try {
Expand Down Expand Up @@ -83,14 +84,15 @@ function checkOptions(deps, options = {}) {

const regex = /^(\.babelrc|babelrc\.js|babel\.config\.js)?$/;

export default function parseBabel(content, filePath, deps, rootDir) {
const config = loadConfig('babel', regex, filePath, content, rootDir);
export default async function parseBabel(filename, deps, rootDir) {
const config = await loadConfig('babel', regex, filename, rootDir);

if (config) {
return checkOptions(deps, config);
}

if (path.basename(filePath) === 'package.json') {
if (path.basename(filename) === 'package.json') {
const content = await getContent(filename);
const metadata = parse(content);
return checkOptions(deps, metadata.babel);
}
Expand Down
4 changes: 2 additions & 2 deletions src/special/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function isBinaryInUse(dep, scripts, dir) {
);
}

export default function parseBinary(content, filepath, deps, dir) {
const scripts = getScripts(filepath, content);
export default async function parseBinary(filename, deps, dir) {
const scripts = await getScripts(filename);
return deps.filter((dep) => isBinaryInUse(dep, scripts, dir));
}
7 changes: 5 additions & 2 deletions src/special/commitizen.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import path from 'path';
import requirePackageName from 'require-package-name';
import { getContent } from '../utils/file';

export default function parseCommitizen(content, filePath, deps, rootDir) {
export default async function parseCommitizen(filename, deps, rootDir) {
const packageJsonPath = path.resolve(rootDir, 'package.json');
const resolvedFilePath = path.resolve(filePath);
const resolvedFilePath = path.resolve(filename);

if (resolvedFilePath === packageJsonPath) {
const content = await getContent(filename);

const metadata = JSON.parse(content);

if (
Expand Down
12 changes: 4 additions & 8 deletions src/special/eslint.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import lodash from 'lodash';
import requirePackageName from 'require-package-name';
import { loadModuleData, wrapToArray } from '../utils';
import { loadConfig } from '../utils/cli-tools';
import { getContent } from '../utils/file';

function resolveConfigModule(preset, rootDir) {
const presetParts = preset.split('/');
Expand Down Expand Up @@ -139,14 +140,8 @@ function checkConfig(config, rootDir, includedDeps = []) {

const configNameRegex = /^\.eslintrc(\.(json|js|yml|yaml))?$/;

export default function parseESLint(content, filename, _, rootDir) {
const config = loadConfig(
'eslint',
configNameRegex,
filename,
content,
rootDir,
);
export default async function parseESLint(filename, deps, rootDir) {
const config = await loadConfig('eslint', configNameRegex, filename, rootDir);

if (config) {
return checkConfig(config, rootDir);
Expand All @@ -156,6 +151,7 @@ export default function parseESLint(content, filename, _, rootDir) {
const resolvedFilePath = path.resolve(rootDir, filename);

if (resolvedFilePath === packageJsonPath) {
const content = await getContent(filename);
const parsed = JSON.parse(content);
if (parsed.eslintConfig) {
return checkConfig(parsed.eslintConfig, rootDir);
Expand Down
6 changes: 4 additions & 2 deletions src/special/feross-standard.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import path from 'path';
import { getContent } from '../utils/file';

export default function parseFerossStandard(content, filePath, deps, rootDir) {
export default async function parseFerossStandard(filename, deps, rootDir) {
const packageJsonPath = path.resolve(rootDir, 'package.json');
const resolvedFilePath = path.resolve(filePath);
const resolvedFilePath = path.resolve(filename);
if (resolvedFilePath === packageJsonPath && deps.indexOf('standard') !== -1) {
const content = await getContent(filename);
const metadata = JSON.parse(content);
const config = metadata.standard || {};
const { parser } = config;
Expand Down
17 changes: 8 additions & 9 deletions src/special/gatsby.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import path from 'path';
import lodash from 'lodash';
import parseES7 from '../parser/es7';
import { parseES7Content } from '../parser/es7';
import getNodes from '../utils/parser';
import { getContent } from '../utils/file';

function parseConfigModuleExports(node) {
// node.left must be assigning to module.exports
Expand Down Expand Up @@ -33,8 +34,9 @@ function parseConfigModuleExports(node) {
}
return null;
}
function parseConfig(content) {
const ast = parseES7(content);

async function parseConfig(content) {
const ast = parseES7Content(content);
return lodash(getNodes(ast))
.map((node) => parseConfigModuleExports(node))
.flatten()
Expand All @@ -43,17 +45,14 @@ function parseConfig(content) {
.first();
}

function loadConfig(filename, content) {
export default async function parseGatsbyConfig(filename) {
const basename = path.basename(filename);

const GatbyConfig = 'gatsby-config.js';
if (GatbyConfig === basename) {
const config = parseConfig(content);
const content = await getContent(filename);
const config = await parseConfig(content);
return config.plugins || [];
}
return [];
}

export default function parseGatsbyConfig(content, filename) {
return loadConfig(filename, content);
}
10 changes: 6 additions & 4 deletions src/special/gulp-load-plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ import lodash from 'lodash';
import minimatch from 'minimatch';
import traverse from '@babel/traverse';

import esParser from '../parser/es7';
import { parseES7Content } from '../parser/es7';
import importDetector from '../detector/importDeclaration';
import requireDetector from '../detector/requireCallExpression';
import { getContent } from '../utils/file';

function getPluginLookup(deps) {
const patterns = ['gulp-*', 'gulp.*', '@*/gulp{-,.}*'];
Expand Down Expand Up @@ -164,8 +165,8 @@ function check(content, deps, path) {
return [];
}

export default function parseGulpPlugins(content, filePath, deps, rootDir) {
const resolvedPath = resolve(filePath);
export default async function parseGulpPlugins(filename, deps, rootDir) {
const resolvedPath = resolve(filename);
if (
resolvedPath !== resolve(rootDir, 'gulpfile.js') &&
resolvedPath !== resolve(rootDir, 'gulpfile.babel.js')
Expand All @@ -174,7 +175,8 @@ export default function parseGulpPlugins(content, filePath, deps, rootDir) {
}

const pluginLookup = getPluginLookup(deps);
const ast = esParser(content);
const content = await getContent(filename);
const ast = await parseES7Content(content);
const results = [];
traverse(ast, {
enter(path) {
Expand Down
4 changes: 3 additions & 1 deletion src/special/husky.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import * as path from 'path';
import { getContent } from '../utils/file';

export default function parseHusky(content, filename) {
export default async function parseHusky(filename) {
const basename = path.basename(filename);

if (basename === 'package.json') {
const content = await getContent(filename);
const pkg = JSON.parse(content);
return pkg.husky ? ['husky'] : [];
}
Expand Down

0 comments on commit 19f9dad

Please sign in to comment.