Skip to content

Commit

Permalink
stupidly check for variable types
Browse files Browse the repository at this point in the history
  • Loading branch information
StyleShit committed Apr 24, 2024
1 parent 26e7be7 commit e57985a
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 0 deletions.
68 changes: 68 additions & 0 deletions packages/eslint-plugin/src/rules/require-types-exports.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Reference } from '@typescript-eslint/scope-manager';
import { DefinitionType } from '@typescript-eslint/scope-manager';
import type { TSESTree } from '@typescript-eslint/utils';
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
Expand All @@ -12,6 +13,12 @@ type FunctionNode =
| TSESTree.ArrowFunctionExpression
| TSESTree.FunctionExpression;

type TypeReference = Reference & {
identifier: {
parent: TSESTree.TSTypeReference;
};
};

export default createRule<[], MessageIds>({
name: 'require-types-exports',
meta: {
Expand All @@ -28,9 +35,23 @@ export default createRule<[], MessageIds>({
},
defaultOptions: [],
create(context) {
const typeReferences = new Set<TypeReference>();
const externalizedTypes = new Set<string>();
const reportedTypes = new Set<string>();

function collectTypeReferences(node: TSESTree.Program): void {
const scope = context.sourceCode.getScope(node);

scope.references.forEach(r => {
if (
r.resolved?.isTypeVariable &&
r.identifier.parent.type === AST_NODE_TYPES.TSTypeReference
) {
typeReferences.add(r as TypeReference);
}
});
}

function collectImportedTypes(node: TSESTree.ImportSpecifier): void {
externalizedTypes.add(node.local.name);
}
Expand Down Expand Up @@ -60,6 +81,8 @@ export default createRule<[], MessageIds>({
for (const declaration of node.declaration.declarations) {
if (declaration.init?.type === AST_NODE_TYPES.ArrowFunctionExpression) {
checkFunctionTypes(declaration.init);
} else {
checkVariableTypes(declaration);
}
}
}
Expand Down Expand Up @@ -107,6 +130,21 @@ export default createRule<[], MessageIds>({
.forEach(checkTypeNode);
}

function checkVariableTypes(
node: TSESTree.LetOrConstOrVarDeclarator,
): void {
if (node.id.type !== AST_NODE_TYPES.Identifier) {
return;
}

typeReferences.forEach(r => {
// TODO: Probably not the best way to do it...
if (isLocationOverlapping(r.identifier.loc, node.loc)) {
checkTypeNode(r.identifier.parent);
}
});
}

function checkTypeNode(node: TSESTree.TSTypeReference): void {
const name = getTypeName(node);

Expand Down Expand Up @@ -141,7 +179,37 @@ export default createRule<[], MessageIds>({
return '';
}

function isLocationOverlapping(
location: TSESTree.Node['loc'],
container: TSESTree.Node['loc'],
): boolean {
if (
location.start.line < container.start.line ||
location.end.line > container.end.line
) {
return false;
}

if (
location.start.line === container.start.line &&
location.start.column < container.start.column
) {
return false;
}

if (
location.end.line === container.end.line &&
location.end.column > container.end.column
) {
return false;
}

return true;
}

return {
Program: collectTypeReferences,

'ImportDeclaration ImportSpecifier, ImportSpecifier':
collectImportedTypes,

Expand Down
58 changes: 58 additions & 0 deletions packages/eslint-plugin/tests/rules/require-types-exports.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ ruleTester.run('require-types-exports', rule, {
return value;
}
`,

`
import type { A } from './types';
export type T1 = number;
export interface T2 {
key: number;
}
export const value: { a: { b: { c: T1 } } } | [string, T2 | A] = {
a: {
b: {
c: 1,
},
},
};
`,
],

invalid: [
Expand Down Expand Up @@ -1739,5 +1757,45 @@ ruleTester.run('require-types-exports', rule, {
},
],
},

{
code: `
import type { A } from './types';
type T1 = number;
interface T2 {
key: number;
}
export const value: { a: { b: { c: T1 } } } | [string, T2 | A] = {
a: {
b: {
c: 1,
},
},
};
`,
errors: [
{
messageId: 'requireTypeExport',
line: 10,
column: 44,
endColumn: 46,
data: {
name: 'T1',
},
},
{
messageId: 'requireTypeExport',
line: 10,
column: 64,
endColumn: 66,
data: {
name: 'T2',
},
},
],
},
],
});

0 comments on commit e57985a

Please sign in to comment.