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 81783b7 commit 0d750cb
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 26 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
11 changes: 10 additions & 1 deletion typings/eslint-plugin-vue/util-types/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,21 @@ export type ComponentUnknownEmit = {
node: Expression | SpreadElement | TypeNode | null
}

export type ComponentTypeEmit = {
export type ComponentTypeEmitCallSignature = {
type: 'type'
key: TSLiteralType
emitName: string
node: TSCallSignatureDeclaration | TSFunctionType
}
export type ComponentTypeEmitPropertySignature = {
type: 'type'
key: Identifier | Literal
emitName: string
node: TSPropertySignature | TSMethodSignature
}
export type ComponentTypeEmit =
| ComponentTypeEmitCallSignature
| ComponentTypeEmitPropertySignature

export type ComponentInferTypeEmit = {
type: 'infer-type'
Expand Down

0 comments on commit 0d750cb

Please sign in to comment.