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

Report type-only imports in no-undef-components #1967

Merged
merged 3 commits into from Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 10 additions & 3 deletions lib/rules/no-undef-components.js
Expand Up @@ -50,7 +50,9 @@ module.exports = {
}
],
messages: {
undef: "The '<{{name}}>' component has been used, but not defined."
undef: "The '<{{name}}>' component has been used, but not defined.",
typeOnly:
"The '<{{name}}>' component has been used, but '{{name}}' only refers to a type."
}
},
/** @param {RuleContext} context */
Expand Down Expand Up @@ -121,6 +123,7 @@ module.exports = {
// For <script setup>
/** @type {Set<string>} */
const scriptVariableNames = new Set()
const scriptTypeOnlyNames = new Set()
const globalScope = context.getSourceCode().scopeManager.globalScope
if (globalScope) {
for (const variable of globalScope.variables) {
Expand All @@ -130,7 +133,11 @@ module.exports = {
(scope) => scope.type === 'module'
)
for (const variable of (moduleScope && moduleScope.variables) || []) {
scriptVariableNames.add(variable.name)
if (variable.isTypeVariable) {
scriptTypeOnlyNames.add(variable.name)
} else {
scriptVariableNames.add(variable.name)
}
}
}
/**
Expand Down Expand Up @@ -167,7 +174,7 @@ module.exports = {

context.report({
node: reportNode,
messageId: 'undef',
messageId: scriptTypeOnlyNames.has(rawName) ? 'typeOnly' : 'undef',
data: {
name: rawName
}
Expand Down
60 changes: 60 additions & 0 deletions tests/lib/rules/no-undef-components.js
Expand Up @@ -661,6 +661,66 @@ tester.run('no-undef-components', rule, {
}
]
},
{
filename: 'test.vue',
code: `
<script setup lang="ts">
import type Foo from './Foo.vue'
import type {HelloWorld1} from './components/HelloWorld'
import { type HelloWorld2 } from './components/HelloWorld2'
import type {HelloWorld as HelloWorld3} from './components/HelloWorld3'
import { type HelloWorld as HelloWorld4 } from './components/HelloWorld4';
import { type default as HelloWorld5 } from './components/HelloWorld5';
FloEdelmann marked this conversation as resolved.
Show resolved Hide resolved
</script>

<template>
<Foo />
<HelloWorld1 />
<HelloWorld2 />
<HelloWorld3 />
<HelloWorld4 />
<HelloWorld5 />
</template>
`,
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
parser: require.resolve('@typescript-eslint/parser')
},
parser: require.resolve('vue-eslint-parser'),
errors: [
{
message:
"The '<Foo>' component has been used, but 'Foo' only refers to a type.",
line: 12
},
{
message:
"The '<HelloWorld1>' component has been used, but 'HelloWorld1' only refers to a type.",
line: 13
},
{
message:
"The '<HelloWorld2>' component has been used, but 'HelloWorld2' only refers to a type.",
line: 14
},
{
message:
"The '<HelloWorld3>' component has been used, but 'HelloWorld3' only refers to a type.",
line: 15
},
{
message:
"The '<HelloWorld4>' component has been used, but 'HelloWorld4' only refers to a type.",
line: 16
},
{
message:
"The '<HelloWorld5>' component has been used, but 'HelloWorld5' only refers to a type.",
line: 17
}
]
},

// options API
{
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "ES2020",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This time I made vuepress support optional chaining operator by lowering the target version.

If it is not proper, please tell me and I will find another way to make it.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for looking into what is causing the vuepress build not to work. I didn't know that setting affects vuepress.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I just lost my mind at that moment 😢. This doesn't affect js files, errors just disappear accidentally.

"target": "ES2019",
"module": "commonjs",
"lib": ["es2020"],
"allowJs": true,
Expand Down
1 change: 1 addition & 0 deletions typings/eslint-plugin-vue/util-types/ast/es-ast.ts
Expand Up @@ -268,6 +268,7 @@ export interface ImportDeclaration extends HasParentNode {
| ImportNamespaceSpecifier
)[]
source: Literal & { value: string }
importKind?: 'type' | 'value'
}
export interface ImportSpecifier extends HasParentNode {
type: 'ImportSpecifier'
Expand Down
3 changes: 3 additions & 0 deletions typings/eslint/index.d.ts
Expand Up @@ -54,6 +54,9 @@ export namespace Scope {
eslintExplicitGlobal?: boolean | undefined
eslintExplicitGlobalComments?: Comment[] | undefined
eslintImplicitGlobalSetting?: 'readonly' | 'writable' | undefined

isTypeVariable?: boolean
isValueVariable?: boolean
}
interface Reference {
identifier: VAST.Identifier
Expand Down