Skip to content
Permalink
Browse files

fix(eslint-plugin): [no-unused-vars] better handling for declared mod…

…ules (#2553)

Fixes #2523

- `declare global` should never be marked as unused.
- namespaces within declared namespaces all ambiently export their children
  • Loading branch information
bradzacher committed Sep 13, 2020
1 parent bf88c84 commit 02d72d480be7a8f7ddc66a028338cfb996886f3c
@@ -219,6 +219,19 @@ export default util.createRule<Options, MessageIds>({
markDeclarationChildAsUsed(node);
},

// global augmentation can be in any file, and they do not need exports
'TSModuleDeclaration[declare = true][global = true]'(): void {
context.markVariableAsUsed('global');
},

// children of a namespace that is a child of a declared namespace are auto-exported
[ambientDeclarationSelector(
'TSModuleDeclaration[declare = true] > TSModuleBlock TSModuleDeclaration > TSModuleBlock',
false,
)](node: DeclarationSelectorNode): void {
markDeclarationChildAsUsed(node);
},

// declared namespace handling
[ambientDeclarationSelector(
'TSModuleDeclaration[declare = true] > TSModuleBlock',
@@ -229,9 +242,12 @@ export default util.createRule<Options, MessageIds>({
util.NullThrowsReasons.MissingParent,
) as TSESTree.TSModuleDeclaration;

// declared modules with an `export =` statement will only export that one thing
// declared ambient modules with an `export =` statement will only export that one thing
// all other statements are not automatically exported in this case
if (checkModuleDeclForExportEquals(moduleDecl)) {
if (
moduleDecl.id.type === AST_NODE_TYPES.Literal &&
checkModuleDeclForExportEquals(moduleDecl)
) {
return;
}

@@ -284,7 +300,7 @@ export default util.createRule<Options, MessageIds>({
AST_NODE_TYPES.TSEnumDeclaration,
AST_NODE_TYPES.TSModuleDeclaration,
AST_NODE_TYPES.VariableDeclaration,
].join(', ')})${childDeclare ? '[declare=true]' : ''}`,
].join(', ')})${childDeclare ? '[declare = true]' : ''}`,
].join(', ');
}
function markDeclarationChildAsUsed(node: DeclarationSelectorNode): void {
@@ -858,6 +858,32 @@ declare module 'foo' {
type Test = 1;
const x: Test = 1;
export = x;
}
`,
// https://github.com/typescript-eslint/typescript-eslint/issues/2523
`
declare global {
interface Foo {}
}
`,
`
declare global {
namespace jest {
interface Matchers<R> {
toBeSeven: () => R;
}
}
}
`,
`
export declare namespace Foo {
namespace Bar {
namespace Baz {
namespace Bam {
const x = 1;
}
}
}
}
`,
],
@@ -1456,5 +1482,57 @@ declare module 'foo' {
},
],
},
{
code: `
// not declared
export namespace Foo {
namespace Bar {
namespace Baz {
namespace Bam {
const x = 1;
}
}
}
}
`,
errors: [
{
messageId: 'unusedVar',
line: 4,
data: {
varName: 'Bar',
action: 'defined',
additional: '',
},
},
{
messageId: 'unusedVar',
line: 5,
data: {
varName: 'Baz',
action: 'defined',
additional: '',
},
},
{
messageId: 'unusedVar',
line: 6,
data: {
varName: 'Bam',
action: 'defined',
additional: '',
},
},
{
messageId: 'unusedVar',
line: 7,
data: {
varName: 'x',
action: 'assigned a value',
additional: '',
},
},
],
},
],
});

0 comments on commit 02d72d4

Please sign in to comment.