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

feat: display tracking information about unused variables #125

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,25 @@ let unused = fusv.find('scss')
// Array of unused variables
console.log(unused.unused);
// ['$foo', '$bar', '$imunused']
console.log(unused.unusedOrigin);
// [
// {
// name: '$foo',
// column: x_1,
// line: y_2,
// file 'scss/dir1/dir2/foo.scss'
// },
// {
// name: '$bar',
// column: x_2,
// line: y_2
// file 'scss/bar.scss'
// }
//]
console.log(unused.total);
// Total number of variables in the files
// Total number of variables in the files in directory 'scss'
console.log(unused.totalUnused);
// Number of unused variables in the files in directory 'scss'

// ignoring variables
const ignoredVars = ['$my-var', '$my-second-var']
Expand All @@ -44,7 +61,13 @@ unused = fusv.find('scss', { ignore: ignoredVars })
* `dir`: string
* `options`: optional options Object

Returns an object with `unused` and `total`. `unused` has the array of unused variables and `total` has the sum of all variables in the files (unused and used ones).
Returns an object with `unusedOrigin`, `unused`, `totalUnused` and`total`.

* `unusedOrigin` is an array carrying objects containing unused sass variables and their origin,
Information included are the `name` of the variable as well as the `line` and `column` of the variable in their originating `file`,
* `unused` is an of array of unused variables without further information,
* `totalUnused` has the sum of all unused variables of all examined files in given `dir`,
* and `total` has the sum of all variables of all examined files in given `dir` (unused and used ones).

#### options.ignore

Expand Down
20 changes: 16 additions & 4 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,25 @@ function main(args) {
const unusedVars = fusv.find(dir, { ignore });

console.log(`${chalk.cyan.bold(unusedVars.total)} total variables.`);

unusedVars.unused.forEach(unusedVar => {
console.log(`Variable ${chalk.bold(unusedVar)} is not being used!`);
console.log(`${chalk.cyan.bold(unusedVars.totalUnusedVars)} total unused variables.`);

let currentFile = '';
const currentDirectory = process.cwd();
unusedVars.unusedInfo.forEach(unusedVar => {
if (currentFile !== unusedVar.file) {
currentFile = unusedVar.file;
const fileRelativePath = path.relative(currentDirectory, currentFile);
console.log(`\n${chalk.underline(fileRelativePath)}`);
}

console.log(
` ${unusedVar.line}:${unusedVar.column}\t` +
`Variable ${chalk.bold(unusedVar.name)} is not being used!`
);
});

// eslint-disable-next-line unicorn/prefer-spread
unusedList = unusedList.concat(unusedVars.unused);
unusedList = unusedList.concat(unusedVars.unusedInfo);
});

if (unusedList.length === 0) {
Expand Down
41 changes: 26 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,40 @@ function findUnusedVars(strDir, opts) {
// Array of all Sass files
const sassFiles = glob.sync(path.join(dir, '**/*.scss'));

// String of all Sass files' content
let sassFilesString = sassFiles.reduce((sassStr, file) => {
sassStr += fs.readFileSync(file, 'utf8');
return sassStr;
}, '');

// Remove jekyll comments
if (sassFilesString.includes('---')) {
sassFilesString = sassFilesString.replace(/---/g, '');
}
// Build sassFilesString as concatenation of all sassFiles
// Get all variables and their origin information
let variables = [];
const sassVarInfo = [];
let strSass = '';
let sassFilesString = '';
sassFiles.forEach((file, i) => {
strSass = fs.readFileSync(file, 'utf8');

// remove jekyl comments
if (strSass.includes('---')) {
strSass = strSass.replace(/---/g, '');
}

const variables = parse(sassFilesString, options.ignore);
sassVarInfo[i] = parse(strSass, options.ignore, file);

// eslint-disable-next-line unicorn/prefer-spread
variables = [].concat(...sassVarInfo);
sassFilesString += strSass;
});

// Store unused vars from all files and loop through each variable
// Get unused variables by filtering single occuring variables in in sassFilesString
const unusedVars = variables.filter(variable => {
const re = new RegExp(`(${escapeRegex(variable)})\\b(?!-)`, 'g');
const re = new RegExp(`(${escapeRegex(variable.name)})\\b(?!-)`, 'g');

return sassFilesString.match(re).length === 1;
});

// Unused and total for backwards compatibility
return {
unused: unusedVars,
total: variables.length
totalUnusedVars: unusedVars.map(({ name }) => name).length,
total: variables.length,
unusedInfo: unusedVars,
unused: unusedVars.map(({ name }) => name)
};
}

Expand Down
19 changes: 12 additions & 7 deletions lib/parse-variable.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,32 @@ const Declaration = require('postcss/lib/declaration');
const Comment = require('postcss/lib/comment');
let fusvEnabled = true;

function parseNodes(nodes, variables, ignoreList) {
function parseNodes(nodes, variables, ignoreList, file = '') {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

carefully adapt this
#134 (comment)
for file = '')

for (const node of nodes) {
findVars(node, variables, ignoreList);
findVars(node, variables, ignoreList, file);
}
}

function findVars(node, result, ignoreList) {
function findVars(node, result, ignoreList, file = '') {
if (node instanceof Comment) {
parseComment(node);

return;
}

if (node instanceof Declaration && node.prop.startsWith('$') && !ignoreList.includes(node.prop) && fusvEnabled) {
result.push(node.prop);
result.push({
name: node.prop,
line: node.source.start.line,
column: node.source.start.column,
file
});

return;
}

if (node.nodes) {
parseNodes(node.nodes, result, ignoreList);
parseNodes(node.nodes, result, ignoreList, file);
}
}

Expand All @@ -37,11 +42,11 @@ function parseComment(node) {
}
}

function parse(scssString, ignoreList) {
function parse(scssString, ignoreList, file = '') {
const parsedScss = scssParse(scssString);
const variables = [];

parseNodes(parsedScss.nodes, variables, ignoreList);
parseNodes(parsedScss.nodes, variables, ignoreList, file);
return variables;
}

Expand Down