From a08a6cb063afe85ce3e13ff8073ce21a8355e77a Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Thu, 11 Nov 2021 10:41:50 -0600 Subject: [PATCH 1/5] Fixes `no-empty-file` false positive with triple-slash directives. --- rules/no-empty-file.js | 2 +- test/no-empty-file.mjs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rules/no-empty-file.js b/rules/no-empty-file.js index db24d82f21..50b606bfa6 100644 --- a/rules/no-empty-file.js +++ b/rules/no-empty-file.js @@ -16,7 +16,7 @@ const isEmpty = node => const create = context => { const filename = context.getPhysicalFilename().toLowerCase(); - if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename)) { + if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename) || filename.endsWith('.d.ts')) { return {}; } diff --git a/test/no-empty-file.mjs b/test/no-empty-file.mjs index 1669056099..3bd3aaa341 100644 --- a/test/no-empty-file.mjs +++ b/test/no-empty-file.mjs @@ -37,6 +37,7 @@ test.snapshot({ 'svelte', 'tsx', ].map(extension => ({code: '', filename: `example.${extension}`})), + {code: '/// ', filename: 'example.d.ts'}, ], invalid: [ ...[ From 64f18129e2b2cb83feaeba70d298a7bc2534f740 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 12 Nov 2021 10:32:53 -0600 Subject: [PATCH 2/5] Looks for triple-slash directive instead of filename. --- rules/no-empty-file.js | 19 +++++++++++++++---- test/no-empty-file.mjs | 5 ++++- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/rules/no-empty-file.js b/rules/no-empty-file.js index 50b606bfa6..f0f89fc691 100644 --- a/rules/no-empty-file.js +++ b/rules/no-empty-file.js @@ -5,18 +5,29 @@ const messages = { [MESSAGE_ID]: 'Empty files are not allowed.', }; +const isTripleSlashDirective = node => + node.type === 'Line' && node.value.startsWith('/'); + const isEmpty = node => ( - (node.type === 'Program' || node.type === 'BlockStatement') + node.type === 'Program' + && node.body.every(currentNode => isEmpty(currentNode)) + && node.comments.every(currentNode => !isTripleSlashDirective(currentNode)) + ) + || ( + node.type === 'BlockStatement' && node.body.every(currentNode => isEmpty(currentNode)) ) - || node.type === 'EmptyStatement' - || (node.type === 'ExpressionStatement' && 'directive' in node); + || ( + node.type === 'ExpressionStatement' + && 'directive' in node + ) + || node.type === 'EmptyStatement'; const create = context => { const filename = context.getPhysicalFilename().toLowerCase(); - if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename) || filename.endsWith('.d.ts')) { + if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename)) { return {}; } diff --git a/test/no-empty-file.mjs b/test/no-empty-file.mjs index 3bd3aaa341..1fa0816494 100644 --- a/test/no-empty-file.mjs +++ b/test/no-empty-file.mjs @@ -37,7 +37,10 @@ test.snapshot({ 'svelte', 'tsx', ].map(extension => ({code: '', filename: `example.${extension}`})), - {code: '/// ', filename: 'example.d.ts'}, + ...[ + 'd.ts', + 'ts', + ].map(extension => ({code: '/// ', filename: `example.${extension}`})), ], invalid: [ ...[ From 66a16164d14211adde920bde017ed8d59b0783e9 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 12 Nov 2021 11:11:47 -0600 Subject: [PATCH 3/5] Changes comments from node lookup to `sourceCode.getAllComments()`. --- rules/no-empty-file.js | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/rules/no-empty-file.js b/rules/no-empty-file.js index f0f89fc691..da0532be98 100644 --- a/rules/no-empty-file.js +++ b/rules/no-empty-file.js @@ -5,27 +5,24 @@ const messages = { [MESSAGE_ID]: 'Empty files are not allowed.', }; -const isTripleSlashDirective = node => - node.type === 'Line' && node.value.startsWith('/'); - const isEmpty = node => ( - node.type === 'Program' - && node.body.every(currentNode => isEmpty(currentNode)) - && node.comments.every(currentNode => !isTripleSlashDirective(currentNode)) - ) - || ( - node.type === 'BlockStatement' + (node.type === 'Program' || node.type === 'BlockStatement') && node.body.every(currentNode => isEmpty(currentNode)) ) - || ( - node.type === 'ExpressionStatement' - && 'directive' in node - ) - || node.type === 'EmptyStatement'; + || node.type === 'EmptyStatement' + || (node.type === 'ExpressionStatement' && 'directive' in node); + +const isTripleSlashDirective = node => + node.type === 'Line' && node.value.startsWith('/'); + +const hasTripeSlashDirectives = comments => + !comments.every(currentNode => !isTripleSlashDirective(currentNode)); const create = context => { const filename = context.getPhysicalFilename().toLowerCase(); + const sourceCode = context.getSourceCode(); + const comments = sourceCode.getAllComments(); if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename)) { return {}; @@ -33,7 +30,7 @@ const create = context => { return { Program(node) { - if (!isEmpty(node)) { + if (!isEmpty(node) || hasTripeSlashDirectives(comments)) { return; } From c4cfca78e9b24b9b9782f38efebd244ae6ad07e4 Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 12 Nov 2021 11:36:40 -0600 Subject: [PATCH 4/5] Simplifies directive check by removing double negative. --- rules/no-empty-file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/no-empty-file.js b/rules/no-empty-file.js index 19e124aee3..80648c9aa5 100644 --- a/rules/no-empty-file.js +++ b/rules/no-empty-file.js @@ -17,7 +17,7 @@ const isTripleSlashDirective = node => node.type === 'Line' && node.value.startsWith('/'); const hasTripeSlashDirectives = comments => - !comments.every(currentNode => !isTripleSlashDirective(currentNode)); + comments.some(currentNode => isTripleSlashDirective(currentNode)); /** @param {import('eslint').Rule.RuleContext} context */ const create = context => { From d9f76cd8e51b3b90704290e4b608a5a77645738c Mon Sep 17 00:00:00 2001 From: Michael Novotny Date: Fri, 12 Nov 2021 12:05:14 -0600 Subject: [PATCH 5/5] Splits triple-slash directive check into it's own check for better performance. --- rules/no-empty-file.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/rules/no-empty-file.js b/rules/no-empty-file.js index 80648c9aa5..948a8e6969 100644 --- a/rules/no-empty-file.js +++ b/rules/no-empty-file.js @@ -22,8 +22,6 @@ const hasTripeSlashDirectives = comments => /** @param {import('eslint').Rule.RuleContext} context */ const create = context => { const filename = context.getPhysicalFilename().toLowerCase(); - const sourceCode = context.getSourceCode(); - const comments = sourceCode.getAllComments(); if (!/\.(?:js|mjs|cjs|ts|mts|cts)$/.test(filename)) { return {}; @@ -31,7 +29,14 @@ const create = context => { return { Program(node) { - if (!isEmpty(node) || hasTripeSlashDirectives(comments)) { + if (!isEmpty(node)) { + return; + } + + const sourceCode = context.getSourceCode(); + const comments = sourceCode.getAllComments(); + + if (hasTripeSlashDirectives(comments)) { return; }