UNPKG

1.98 kBJavaScriptView Raw
1'use strict';
2var rocambole = require('rocambole');
3var defaults = require('lodash.defaults');
4var contains = require('lodash.contains');
5
6function parseContents(contents) {
7 if (!contents) {
8 return null;
9 }
10 var ast;
11 try {
12 ast = rocambole.parse(contents, {
13 tolerant: true,
14 loc: true
15 });
16 } catch (e) {
17 throw new Error('Error parsing contents', e);
18 }
19 return ast;
20}
21
22function checkAst(ast, options) {
23 var ignoredTypes = ['ObjectExpression', 'Property'];
24 var enforceConst = options.enforceConst;
25 var ignore = options.ignore;
26 var errors = [];
27
28 rocambole.moonwalk(ast, function (node) {
29 //only validate numbers
30 if (typeof node.value !== 'number') {
31 return;
32 }
33 //skip ignored numbers
34 if (contains(ignore, node.value)) {
35 return;
36 }
37 var parent = node.parent.parent;
38 //skip ignore types
39 if (contains(ignoredTypes, parent.type)) {
40 return;
41 }
42 //skip variable declaration unless
43 if (!enforceConst && parent.type === 'VariableDeclaration') {
44 return;
45 }
46 if (parent.left && parent.left.type === 'MemberExpression') {
47 return;
48 }
49 //if enforceConst
50 if (enforceConst && parent.kind === 'const') {
51 return;
52 }
53 errors.push({
54 file: options.file,
55 code: node.parent.toString(),
56 value: node.value,
57 loc: node.loc
58 });
59 });
60 return errors;
61}
62
63function checkConstants(contents, params) {
64 //set default options
65 var options = defaults(params || {}, {
66 enforceConst: false,
67 ignore: [0, 1]
68 });
69 //parse ast tree
70 var ast = parseContents(contents);
71 //check tree for constants
72 return checkAst(ast, options);
73}
74
75exports.checkConstants = checkConstants;
76exports.parseContents = parseContents;