2018-09-20 22:24:52 +00:00
|
|
|
// tslint:disable no-console
|
|
|
|
|
|
|
|
import { readFileSync } from 'fs';
|
|
|
|
import { join, relative } from 'path';
|
2020-02-27 01:53:39 +00:00
|
|
|
import normalizePath from 'normalize-path';
|
2018-09-20 22:24:52 +00:00
|
|
|
|
2020-02-21 23:40:04 +00:00
|
|
|
import { sync as fgSync } from 'fast-glob';
|
2018-09-20 22:24:52 +00:00
|
|
|
import { forEach, some, values } from 'lodash';
|
|
|
|
|
|
|
|
import { ExceptionType, REASONS, RuleType } from './types';
|
2018-10-02 21:38:02 +00:00
|
|
|
import { ENCODING, loadJSON, sortExceptions } from './util';
|
2018-09-20 22:24:52 +00:00
|
|
|
|
|
|
|
const ALL_REASONS = REASONS.join('|');
|
|
|
|
const now = new Date();
|
|
|
|
|
|
|
|
function getExceptionKey(exception: any) {
|
|
|
|
return `${exception.rule}-${exception.path}-${exception.lineNumber}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function createLookup(list: Array<any>) {
|
|
|
|
const lookup = Object.create(null);
|
|
|
|
|
|
|
|
forEach(list, exception => {
|
|
|
|
const key = getExceptionKey(exception);
|
|
|
|
|
|
|
|
if (lookup[key]) {
|
|
|
|
throw new Error(`Duplicate exception found for key ${key}`);
|
|
|
|
}
|
|
|
|
|
|
|
|
lookup[key] = exception;
|
|
|
|
});
|
|
|
|
|
|
|
|
return lookup;
|
|
|
|
}
|
|
|
|
|
|
|
|
const rulesPath = join(__dirname, 'rules.json');
|
|
|
|
const exceptionsPath = join(__dirname, 'exceptions.json');
|
|
|
|
const basePath = join(__dirname, '../../..');
|
|
|
|
|
2020-02-27 01:53:39 +00:00
|
|
|
const searchPattern = normalizePath(join(basePath, '**/*.{js,ts,tsx}'));
|
2018-09-20 22:24:52 +00:00
|
|
|
|
|
|
|
const rules: Array<RuleType> = loadJSON(rulesPath);
|
|
|
|
const exceptions: Array<ExceptionType> = loadJSON(exceptionsPath);
|
|
|
|
const exceptionsLookup = createLookup(exceptions);
|
|
|
|
let scannedCount = 0;
|
|
|
|
|
2020-02-21 23:40:04 +00:00
|
|
|
const allSourceFiles = fgSync(searchPattern, { onlyFiles: true });
|
2018-09-20 22:24:52 +00:00
|
|
|
|
|
|
|
const results: Array<ExceptionType> = [];
|
|
|
|
|
|
|
|
const excludedFiles = [
|
2019-12-17 20:25:57 +00:00
|
|
|
// Non-distributed files
|
|
|
|
'\\.d\\.ts$',
|
|
|
|
|
2019-01-15 18:03:16 +00:00
|
|
|
// High-traffic files in our project
|
2019-03-13 20:38:28 +00:00
|
|
|
'^js/models/messages.js',
|
2020-09-04 01:25:19 +00:00
|
|
|
'^js/models/conversations.js',
|
2019-01-15 18:03:16 +00:00
|
|
|
'^js/views/conversation_view.js',
|
2019-01-24 18:28:29 +00:00
|
|
|
'^js/background.js',
|
2020-03-31 20:03:38 +00:00
|
|
|
'^ts/Crypto.js',
|
|
|
|
'^ts/Crypto.ts',
|
2020-04-14 18:32:11 +00:00
|
|
|
'^ts/textsecure/MessageReceiver.js',
|
|
|
|
'^ts/textsecure/MessageReceiver.ts',
|
2020-07-10 18:28:49 +00:00
|
|
|
'^ts/ConversationController.js',
|
|
|
|
'^ts/ConversationController.ts',
|
2019-01-15 18:03:16 +00:00
|
|
|
|
2018-09-20 22:24:52 +00:00
|
|
|
// Generated files
|
|
|
|
'^js/components.js',
|
2019-03-28 17:09:26 +00:00
|
|
|
'^js/curve/',
|
2018-09-20 22:24:52 +00:00
|
|
|
'^js/libtextsecure.js',
|
|
|
|
'^js/util_worker.js',
|
|
|
|
'^libtextsecure/components.js',
|
|
|
|
'^libtextsecure/test/test.js',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^sticker-creator/dist/bundle.js',
|
2018-09-20 22:24:52 +00:00
|
|
|
'^test/test.js',
|
|
|
|
|
|
|
|
// From libsignal-protocol-javascript project
|
|
|
|
'^js/libsignal-protocol-worker.js',
|
|
|
|
'^libtextsecure/libsignal-protocol.js',
|
|
|
|
|
|
|
|
// Copied from dependency
|
|
|
|
'^js/Mp3LameEncoder.min.js',
|
|
|
|
|
|
|
|
// Test files
|
2020-05-05 21:18:27 +00:00
|
|
|
'^libtextsecure/test/.+',
|
|
|
|
'^test/.+',
|
2018-09-20 22:24:52 +00:00
|
|
|
|
2019-01-14 21:49:58 +00:00
|
|
|
// Modules we trust
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/core-js-pure/.+',
|
|
|
|
'^node_modules/core-js/.+',
|
|
|
|
'^node_modules/fbjs/.+',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/lodash/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/react/.+',
|
|
|
|
'^node_modules/react-contextmenu/.+',
|
|
|
|
'^node_modules/react-dom/.+',
|
|
|
|
'^node_modules/react-dropzone/.+',
|
|
|
|
'^node_modules/react-hot-loader/.+',
|
|
|
|
'^node_modules/react-icon-base/.+',
|
|
|
|
'^node_modules/react-input-autosize/.+',
|
|
|
|
'^node_modules/react-measure/.+',
|
|
|
|
'^node_modules/react-popper/.+',
|
|
|
|
'^node_modules/react-redux/.+',
|
|
|
|
'^node_modules/react-router/.+',
|
|
|
|
'^node_modules/react-router-dom/.+',
|
|
|
|
'^node_modules/react-select/.+',
|
|
|
|
'^node_modules/react-sortable-hoc/.+',
|
|
|
|
'^node_modules/react-transition-group/.+',
|
|
|
|
'^node_modules/react-virtualized/.+',
|
|
|
|
'^node_modules/reactcss/.+',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/snyk/.+',
|
|
|
|
'^node_modules/snyk-resolve-deps/.+',
|
|
|
|
'^node_modules/snyk-try-require/.+',
|
|
|
|
'^node_modules/@snyk/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
|
|
|
|
// Submodules we trust
|
|
|
|
'^node_modules/react-color/.+/(?:core-js|fbjs|lodash)/.+',
|
2019-01-14 21:49:58 +00:00
|
|
|
|
2018-09-20 22:24:52 +00:00
|
|
|
// Modules used only in test/development scenarios
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/@babel/.+',
|
|
|
|
'^node_modules/@svgr/.+',
|
|
|
|
'^node_modules/@types/.+',
|
|
|
|
'^node_modules/@webassemblyjs/.+',
|
|
|
|
'^node_modules/ajv/.+',
|
|
|
|
'^node_modules/amdefine/.+',
|
|
|
|
'^node_modules/ansi-colors/.+',
|
|
|
|
'^node_modules/anymatch/.+',
|
|
|
|
'^node_modules/app-builder-lib/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/archiver-utils/.+', // Used by spectron
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/archiver/.+', // Used by spectron
|
|
|
|
'^node_modules/asn1\\.js/.+',
|
|
|
|
'^node_modules/autoprefixer/.+',
|
|
|
|
'^node_modules/babel.+',
|
|
|
|
'^node_modules/bluebird/.+',
|
|
|
|
'^node_modules/body-parser/.+',
|
|
|
|
'^node_modules/bower/.+',
|
|
|
|
'^node_modules/buble/.+',
|
|
|
|
'^node_modules/builder-util-runtime/.+',
|
|
|
|
'^node_modules/builder-util/.+',
|
|
|
|
'^node_modules/catharsis/.+',
|
|
|
|
'^node_modules/chai/.+',
|
|
|
|
'^node_modules/clean-css/.+',
|
|
|
|
'^node_modules/cli-table2/.+',
|
|
|
|
'^node_modules/codemirror/.+',
|
|
|
|
'^node_modules/coffee-script/.+',
|
|
|
|
'^node_modules/compression/.+',
|
|
|
|
'^node_modules/cross-env/.+',
|
|
|
|
'^node_modules/css-loader/.+',
|
|
|
|
'^node_modules/css-modules-loader-core/.+',
|
|
|
|
'^node_modules/css-selector-tokenizer/.+',
|
|
|
|
'^node_modules/css-tree/.+',
|
|
|
|
'^node_modules/csso/.+',
|
|
|
|
'^node_modules/degenerator/.+',
|
|
|
|
'^node_modules/detect-port-alt/.+',
|
|
|
|
'^node_modules/electron-builder/.+',
|
|
|
|
'^node_modules/electron-chromedriver/.+',
|
|
|
|
'^node_modules/electron-icon-maker/.+',
|
2019-08-19 22:26:45 +00:00
|
|
|
'^node_modules/electron-mocha/',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/electron-osx-sign/.+',
|
|
|
|
'^node_modules/electron-publish/.+',
|
|
|
|
'^node_modules/emotion/.+', // Currently only used in storybook
|
|
|
|
'^node_modules/es-abstract/.+',
|
|
|
|
'^node_modules/es5-shim/.+', // Currently only used in storybook
|
|
|
|
'^node_modules/es6-shim/.+', // Currently only used in storybook
|
|
|
|
'^node_modules/escodegen/.+',
|
|
|
|
'^node_modules/eslint.+',
|
|
|
|
'^node_modules/esprima/.+',
|
|
|
|
'^node_modules/express/.+',
|
|
|
|
'^node_modules/file-loader/.+',
|
|
|
|
'^node_modules/file-system-cache/.+', // Currently only used in storybook
|
|
|
|
'^node_modules/finalhandler/.+',
|
|
|
|
'^node_modules/fsevents/.+',
|
|
|
|
'^node_modules/globule/.+',
|
|
|
|
'^node_modules/grunt-cli/.+',
|
|
|
|
'^node_modules/grunt-contrib-concat/.+',
|
|
|
|
'^node_modules/grunt-contrib-watch/.+',
|
|
|
|
'^node_modules/grunt-gitinfo/.+',
|
|
|
|
'^node_modules/grunt-legacy-log-utils/.+',
|
|
|
|
'^node_modules/grunt-legacy-log/.+',
|
|
|
|
'^node_modules/grunt-legacy-util/.+',
|
|
|
|
'^node_modules/grunt/.+',
|
|
|
|
'^node_modules/handle-thing/.+',
|
|
|
|
'^node_modules/handlebars/.+', // Used by nyc#istanbul-reports
|
|
|
|
'^node_modules/har-validator/.+',
|
|
|
|
'^node_modules/highlight\\.js/.+',
|
|
|
|
'^node_modules/hpack\\.js/.+',
|
|
|
|
'^node_modules/http-proxy-middlewar/.+',
|
|
|
|
'^node_modules/icss-utils/.+',
|
|
|
|
'^node_modules/intl-tel-input/examples/.+',
|
|
|
|
'^node_modules/istanbul.+',
|
|
|
|
'^node_modules/jimp/.+',
|
|
|
|
'^node_modules/jquery/.+',
|
|
|
|
'^node_modules/jsdoc/.+',
|
|
|
|
'^node_modules/jss-global/.+',
|
|
|
|
'^node_modules/jss/.+',
|
|
|
|
'^node_modules/livereload-js/.+',
|
|
|
|
'^node_modules/lolex/.+',
|
|
|
|
'^node_modules/magic-string/.+',
|
|
|
|
'^node_modules/markdown-it/.+',
|
|
|
|
'^node_modules/minimatch/.+',
|
|
|
|
'^node_modules/mocha/.+',
|
|
|
|
'^node_modules/nise/.+',
|
|
|
|
'^node_modules/node-sass-import-once/.+',
|
|
|
|
'^node_modules/node-sass/.+',
|
|
|
|
'^node_modules/npm-run-all/.+',
|
|
|
|
'^node_modules/nsp/.+',
|
|
|
|
'^node_modules/nyc/.+',
|
|
|
|
'^node_modules/phantomjs-prebuilt/.+',
|
|
|
|
'^node_modules/postcss.+',
|
|
|
|
'^node_modules/preserve/.+',
|
|
|
|
'^node_modules/prettier/.+',
|
|
|
|
'^node_modules/prop-types/.+',
|
|
|
|
'^node_modules/protobufjs/cli/.+',
|
|
|
|
'^node_modules/ramda/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/react-dev-utils/.+',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/react-docgen/.+',
|
|
|
|
'^node_modules/react-error-overlay/.+',
|
|
|
|
'^node_modules/read-pkg/.+', // Used by npm-run-all
|
|
|
|
'^node_modules/recast/.+',
|
|
|
|
'^node_modules/reduce-css-calc/.+',
|
|
|
|
'^node_modules/requizzle/.+',
|
|
|
|
'^node_modules/resolve/.+',
|
|
|
|
'^node_modules/sass-graph/.+',
|
|
|
|
'^node_modules/sass-loader/.+',
|
|
|
|
'^node_modules/scss-tokenizer/.+',
|
|
|
|
'^node_modules/send/.+',
|
|
|
|
'^node_modules/serve-index/.+',
|
|
|
|
'^node_modules/sinon/.+',
|
|
|
|
'^node_modules/snapdragon-util/.+',
|
|
|
|
'^node_modules/snapdragon/.+',
|
|
|
|
'^node_modules/sockjs-client/.+',
|
|
|
|
'^node_modules/spectron/.+',
|
|
|
|
'^node_modules/style-loader/.+',
|
|
|
|
'^node_modules/svgo/.+',
|
|
|
|
'^node_modules/terser/.+',
|
|
|
|
'^node_modules/testcheck/.+',
|
|
|
|
'^node_modules/text-encoding/.+',
|
|
|
|
'^node_modules/tiny-lr/.+', // Used by grunt-contrib-watch
|
|
|
|
'^node_modules/tinycolor2/.+',
|
|
|
|
'^node_modules/to-ast/.+',
|
|
|
|
'^node_modules/trough/.+',
|
|
|
|
'^node_modules/ts-loader/.+',
|
|
|
|
'^node_modules/ts-node/.+',
|
|
|
|
'^node_modules/tslint.+',
|
|
|
|
'^node_modules/tweetnacl/.+',
|
|
|
|
'^node_modules/typed-scss-modules/.+',
|
|
|
|
'^node_modules/typescript/.+',
|
|
|
|
'^node_modules/uglify-es/.+',
|
|
|
|
'^node_modules/uglify-js/.+',
|
|
|
|
'^node_modules/url-loader/.+',
|
|
|
|
'^node_modules/use/.+',
|
|
|
|
'^node_modules/vary/.+',
|
|
|
|
'^node_modules/vm-browserify/.+',
|
|
|
|
'^node_modules/webdriverio/.+',
|
|
|
|
'^node_modules/webpack/.+',
|
|
|
|
'^node_modules/xml-parse-from-string/.+',
|
|
|
|
'^node_modules/xmlbuilder/.+',
|
|
|
|
'^node_modules/xmldom/.+',
|
2019-08-19 22:26:45 +00:00
|
|
|
'^node_modules/yargs-unparser/',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/yargs/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
|
|
|
|
// Used by Storybook
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/@emotion/.+',
|
|
|
|
'^node_modules/@storybook/.+',
|
|
|
|
'^node_modules/cosmiconfig/.+',
|
|
|
|
'^node_modules/create-emotion/.+',
|
2020-08-27 18:52:26 +00:00
|
|
|
'^node_modules/gzip-size/.+',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/markdown-to-jsx/.+',
|
|
|
|
'^node_modules/mini-css-extract-plugin/.+',
|
|
|
|
'^node_modules/polished.+',
|
|
|
|
'^node_modules/prismjs/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/react-draggable/.+',
|
2020-05-05 21:18:27 +00:00
|
|
|
'^node_modules/refractor/.+',
|
|
|
|
'^node_modules/regexpu-core/.+',
|
|
|
|
'^node_modules/shelljs/.+',
|
|
|
|
'^node_modules/simplebar/.+',
|
|
|
|
'^node_modules/store2/.+',
|
|
|
|
'^node_modules/telejson/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
|
|
|
|
// Used by Webpack
|
|
|
|
'^node_modules/css-select/.+', // Used by html-webpack-plugin
|
|
|
|
'^node_modules/dotenv-webpack/.+',
|
|
|
|
'^node_modules/follow-redirects/.+', // Used by webpack-dev-server
|
|
|
|
'^node_modules/html-webpack-plugin/.+',
|
2020-09-04 01:25:19 +00:00
|
|
|
'^node_modules/selfsigned/.+', // Used by webpack-dev-server
|
2020-08-27 18:52:26 +00:00
|
|
|
'^node_modules/portfinder/.+',
|
2019-12-17 20:25:57 +00:00
|
|
|
'^node_modules/renderkid/.+', // Used by html-webpack-plugin
|
|
|
|
'^node_modules/spdy-transport/.+', // Used by webpack-dev-server
|
|
|
|
'^node_modules/spdy/.+', // Used by webpack-dev-server
|
|
|
|
'^node_modules/uglifyjs-webpack-plugin/.+',
|
|
|
|
'^node_modules/v8-compile-cache/.+', // Used by webpack-cli
|
|
|
|
'^node_modules/watchpack/.+', // Used by webpack
|
|
|
|
'^node_modules/webpack-cli/.+',
|
|
|
|
'^node_modules/webpack-dev-middleware/.+',
|
|
|
|
'^node_modules/webpack-dev-server/.+',
|
|
|
|
'^node_modules/webpack-hot-middleware/.+',
|
|
|
|
'^node_modules/webpack-merge/.+',
|
|
|
|
'^node_modules/webpack/.+',
|
2018-09-20 22:24:52 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
function setupRules(allRules: Array<RuleType>) {
|
|
|
|
forEach(allRules, (rule, index) => {
|
|
|
|
if (!rule.name) {
|
|
|
|
throw new Error(`Rule at index ${index} is missing a name`);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!rule.expression) {
|
|
|
|
throw new Error(`Rule '${rule.name}' is missing an expression`);
|
|
|
|
}
|
|
|
|
|
|
|
|
rule.regex = new RegExp(rule.expression, 'g');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
setupRules(rules);
|
|
|
|
|
|
|
|
forEach(allSourceFiles, file => {
|
|
|
|
const relativePath = relative(basePath, file).replace(/\\/g, '/');
|
|
|
|
if (
|
|
|
|
some(excludedFiles, excluded => {
|
|
|
|
const regex = new RegExp(excluded);
|
|
|
|
|
|
|
|
return regex.test(relativePath);
|
|
|
|
})
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
scannedCount += 1;
|
|
|
|
|
|
|
|
const fileContents = readFileSync(file, ENCODING);
|
|
|
|
const lines = fileContents.split('\n');
|
|
|
|
|
|
|
|
forEach(rules, (rule: RuleType) => {
|
|
|
|
const excludedModules = rule.excludedModules || [];
|
|
|
|
if (some(excludedModules, module => relativePath.startsWith(module))) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
forEach(lines, (rawLine, lineIndex) => {
|
|
|
|
const line = rawLine.replace(/\r/g, '');
|
|
|
|
if (!rule.regex.test(line)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const path = relativePath;
|
|
|
|
const lineNumber = lineIndex + 1;
|
|
|
|
|
|
|
|
const exceptionKey = getExceptionKey({
|
|
|
|
rule: rule.name,
|
|
|
|
path: relativePath,
|
|
|
|
lineNumber,
|
|
|
|
});
|
|
|
|
|
|
|
|
const exception = exceptionsLookup[exceptionKey];
|
|
|
|
if (exception && (!exception.line || exception.line === line)) {
|
2019-01-14 21:49:58 +00:00
|
|
|
// tslint:disable-next-line no-dynamic-delete
|
2018-09-20 22:24:52 +00:00
|
|
|
delete exceptionsLookup[exceptionKey];
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
results.push({
|
|
|
|
rule: rule.name,
|
|
|
|
path,
|
|
|
|
line: line.length < 300 ? line : undefined,
|
|
|
|
lineNumber,
|
|
|
|
reasonCategory: ALL_REASONS,
|
|
|
|
updated: now.toJSON(),
|
|
|
|
reasonDetail: '<optional>',
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
const unusedExceptions = values(exceptionsLookup);
|
|
|
|
|
|
|
|
console.log(
|
|
|
|
`${scannedCount} files scanned.`,
|
|
|
|
`${results.length} questionable lines,`,
|
|
|
|
`${unusedExceptions.length} unused exceptions,`,
|
|
|
|
`${exceptions.length} total exceptions.`
|
|
|
|
);
|
|
|
|
|
|
|
|
if (results.length === 0 && unusedExceptions.length === 0) {
|
|
|
|
process.exit();
|
|
|
|
}
|
|
|
|
|
|
|
|
console.log();
|
|
|
|
console.log('Questionable lines:');
|
2018-10-02 21:38:02 +00:00
|
|
|
console.log(JSON.stringify(sortExceptions(results), null, ' '));
|
2018-09-20 22:24:52 +00:00
|
|
|
|
|
|
|
if (unusedExceptions.length) {
|
|
|
|
console.log();
|
|
|
|
console.log('Unused exceptions!');
|
2018-10-02 21:38:02 +00:00
|
|
|
console.log(JSON.stringify(sortExceptions(unusedExceptions), null, ' '));
|
2018-09-20 22:24:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
process.exit(1);
|