Skip to content

Commit

Permalink
support new defineEmits type syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed May 12, 2023
1 parent f782877 commit fc32e9f
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 30 deletions.
82 changes: 57 additions & 25 deletions lib/utils/ts-utils/ts-ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ const { inferRuntimeTypeFromTypeNode } = require('./ts-types')
*/
/**
* @typedef {import('../index').ComponentTypeProp} ComponentTypeProp
* @typedef {import('../index').ComponentUnknownProp} ComponentUnknownProp
* @typedef {import('../index').ComponentTypeEmit} ComponentTypeEmit
* @typedef {import('../index').ComponentUnknownEmit} ComponentUnknownEmit
*/

const noop = Function.prototype
Expand Down Expand Up @@ -122,57 +124,87 @@ function isTSTypeLiteralOrTSFunctionType(node) {
* @see https://github.com/vuejs/vue-next/blob/253ca2729d808fc051215876aa4af986e4caa43c/packages/compiler-sfc/src/compileScript.ts#L1512
* @param {RuleContext} context The ESLint rule context object.
* @param {TSESTreeTSTypeLiteral | TSESTreeTSInterfaceBody} node
* @returns {IterableIterator<ComponentTypeProp>}
* @returns {IterableIterator<ComponentTypeProp | ComponentUnknownProp>}
*/
function* extractRuntimeProps(context, node) {
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
for (const m of members) {
for (const member of members) {
if (
(m.type === 'TSPropertySignature' || m.type === 'TSMethodSignature') &&
(m.key.type === 'Identifier' || m.key.type === 'Literal')
member.type === 'TSPropertySignature' ||
member.type === 'TSMethodSignature'
) {
if (member.key.type !== 'Identifier' && member.key.type !== 'Literal') {
yield {
type: 'unknown',
propName: null,
node: /** @type {Expression} */ (member.key)
}
continue
}
/** @type {string[]|undefined} */
let types
if (m.type === 'TSMethodSignature') {
if (member.type === 'TSMethodSignature') {
types = ['Function']
} else if (m.typeAnnotation) {
types = inferRuntimeType(context, m.typeAnnotation.typeAnnotation)
} else if (member.typeAnnotation) {
types = inferRuntimeType(context, member.typeAnnotation.typeAnnotation)
}
yield {
type: 'type',
key: /** @type {Identifier | Literal} */ (m.key),
propName: m.key.type === 'Identifier' ? m.key.name : `${m.key.value}`,
node: /** @type {TSPropertySignature | TSMethodSignature} */ (m),
key: /** @type {Identifier | Literal} */ (member.key),
propName:
member.key.type === 'Identifier'
? member.key.name
: `${member.key.value}`,
node: /** @type {TSPropertySignature | TSMethodSignature} */ (member),

required: !m.optional,
required: !member.optional,
types: types || [`null`]
}
}
}
}

/**
* @see https://github.com/vuejs/vue-next/blob/348c3b01e56383ffa70b180d1376fdf4ac12e274/packages/compiler-sfc/src/compileScript.ts#L1632
* @param {TSESTreeTSTypeLiteral | TSESTreeTSInterfaceBody | TSESTreeTSFunctionType} node
* @returns {IterableIterator<ComponentTypeEmit>}
* @returns {IterableIterator<ComponentTypeEmit | ComponentUnknownEmit>}
*/
function* extractRuntimeEmits(node) {
if (node.type === 'TSTypeLiteral' || node.type === 'TSInterfaceBody') {
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
for (const t of members) {
if (t.type === 'TSCallSignatureDeclaration') {
yield* extractEventNames(
t.params[0],
/** @type {TSCallSignatureDeclaration} */ (t)
)
}
}
return
} else {
if (node.type === 'TSFunctionType') {
yield* extractEventNames(
node.params[0],
/** @type {TSFunctionType} */ (node)
)
return
}
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
for (const member of members) {
if (member.type === 'TSCallSignatureDeclaration') {
yield* extractEventNames(
member.params[0],
/** @type {TSCallSignatureDeclaration} */ (member)
)
} else if (
member.type === 'TSPropertySignature' ||
member.type === 'TSMethodSignature'
) {
if (member.key.type !== 'Identifier' && member.key.type !== 'Literal') {
yield {
type: 'unknown',
emitName: null,
node: /** @type {Expression} */ (member.key)
}
continue
}
yield {
type: 'type',
key: /** @type {Identifier | Literal} */ (member.key),
emitName:
member.key.type === 'Identifier'
? member.key.name
: `${member.key.value}`,
node: /** @type {TSPropertySignature | TSMethodSignature} */ (member)
}
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions typings/eslint-plugin-vue/util-types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ export interface ScriptSetupVisitor extends ScriptSetupVisitorBase {
onDefinePropsExit?(node: CallExpression, props: ComponentProp[]): void
onDefineEmitsEnter?(node: CallExpression, emits: ComponentEmit[]): void
onDefineEmitsExit?(node: CallExpression, emits: ComponentEmit[]): void
onDefineOptionsEnter?(node: CallExpression): void
onDefineOptionsExit?(node: CallExpression): void
onDefineSlotsEnter?(node: CallExpression): void
onDefineSlotsExit?(node: CallExpression): void
[query: string]:
| ((node: VAST.ParamNode) => void)
| ((node: CallExpression, props: ComponentProp[]) => void)
Expand Down Expand Up @@ -167,7 +163,6 @@ export type ComponentTypeEmitPropertySignature = {
type: 'type'
key: Identifier | Literal
emitName: string
value: null
node: TSPropertySignature | TSMethodSignature
}
export type ComponentTypeEmit =
Expand Down

0 comments on commit fc32e9f

Please sign in to comment.