Skip to content

Commit 6c58f1a

Browse files
lihongda03Amorites
lihongda03
authored andcommitted
fix(no-undef-components): report error on type-only imports
1 parent 9b55f3c commit 6c58f1a

File tree

4 files changed

+74
-3
lines changed

4 files changed

+74
-3
lines changed

lib/rules/no-undef-components.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ module.exports = {
5050
}
5151
],
5252
messages: {
53-
undef: "The '<{{name}}>' component has been used, but not defined."
53+
undef: "The '<{{name}}>' component has been used, but not defined.",
54+
typeOnly:
55+
"The '<{{name}}>' component has been used, but '{{name}}' only refers to a type."
5456
}
5557
},
5658
/** @param {RuleContext} context */
@@ -121,6 +123,7 @@ module.exports = {
121123
// For <script setup>
122124
/** @type {Set<string>} */
123125
const scriptVariableNames = new Set()
126+
const scriptTypeOnlyNames = new Set()
124127
const globalScope = context.getSourceCode().scopeManager.globalScope
125128
if (globalScope) {
126129
for (const variable of globalScope.variables) {
@@ -130,7 +133,11 @@ module.exports = {
130133
(scope) => scope.type === 'module'
131134
)
132135
for (const variable of (moduleScope && moduleScope.variables) || []) {
133-
scriptVariableNames.add(variable.name)
136+
if (variable.isTypeVariable) {
137+
scriptTypeOnlyNames.add(variable.name)
138+
} else {
139+
scriptVariableNames.add(variable.name)
140+
}
134141
}
135142
}
136143
/**
@@ -167,7 +174,7 @@ module.exports = {
167174

168175
context.report({
169176
node: reportNode,
170-
messageId: 'undef',
177+
messageId: scriptTypeOnlyNames.has(rawName) ? 'typeOnly' : 'undef',
171178
data: {
172179
name: rawName
173180
}

tests/lib/rules/no-undef-components.js

+60
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,66 @@ tester.run('no-undef-components', rule, {
661661
}
662662
]
663663
},
664+
{
665+
filename: 'test.vue',
666+
code: `
667+
<script setup lang="ts">
668+
import type Foo from './Foo.vue'
669+
import type {HelloWorld1} from './components/HelloWorld'
670+
import { type HelloWorld2 } from './components/HelloWorld2'
671+
import type {HelloWorld as HelloWorld3} from './components/HelloWorld3'
672+
import { type HelloWorld as HelloWorld4 } from './components/HelloWorld4';
673+
import { type default as HelloWorld5 } from './components/HelloWorld5';
674+
</script>
675+
676+
<template>
677+
<Foo />
678+
<HelloWorld1 />
679+
<HelloWorld2 />
680+
<HelloWorld3 />
681+
<HelloWorld4 />
682+
<HelloWorld5 />
683+
</template>
684+
`,
685+
parserOptions: {
686+
ecmaVersion: 6,
687+
sourceType: 'module',
688+
parser: require.resolve('@typescript-eslint/parser')
689+
},
690+
parser: require.resolve('vue-eslint-parser'),
691+
errors: [
692+
{
693+
message:
694+
"The '<Foo>' component has been used, but 'Foo' only refers to a type.",
695+
line: 12
696+
},
697+
{
698+
message:
699+
"The '<HelloWorld1>' component has been used, but 'HelloWorld1' only refers to a type.",
700+
line: 13
701+
},
702+
{
703+
message:
704+
"The '<HelloWorld2>' component has been used, but 'HelloWorld2' only refers to a type.",
705+
line: 14
706+
},
707+
{
708+
message:
709+
"The '<HelloWorld3>' component has been used, but 'HelloWorld3' only refers to a type.",
710+
line: 15
711+
},
712+
{
713+
message:
714+
"The '<HelloWorld4>' component has been used, but 'HelloWorld4' only refers to a type.",
715+
line: 16
716+
},
717+
{
718+
message:
719+
"The '<HelloWorld5>' component has been used, but 'HelloWorld5' only refers to a type.",
720+
line: 17
721+
}
722+
]
723+
},
664724

665725
// options API
666726
{

typings/eslint-plugin-vue/util-types/ast/es-ast.ts

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ export interface ImportDeclaration extends HasParentNode {
268268
| ImportNamespaceSpecifier
269269
)[]
270270
source: Literal & { value: string }
271+
importKind?: 'type' | 'value'
271272
}
272273
export interface ImportSpecifier extends HasParentNode {
273274
type: 'ImportSpecifier'

typings/eslint/index.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ export namespace Scope {
5454
eslintExplicitGlobal?: boolean | undefined
5555
eslintExplicitGlobalComments?: Comment[] | undefined
5656
eslintImplicitGlobalSetting?: 'readonly' | 'writable' | undefined
57+
58+
isTypeVariable?: boolean
59+
isValueVariable?: boolean
5760
}
5861
interface Reference {
5962
identifier: VAST.Identifier

0 commit comments

Comments
 (0)