Tracking de l'application VApp (IHM du jeu)
This commit is contained in:
88
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/index.js
generated
vendored
Normal file
88
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/index.js
generated
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
const {
|
||||
isTypeNode,
|
||||
extractRuntimeProps,
|
||||
isTSTypeLiteral,
|
||||
isTSTypeLiteralOrTSFunctionType,
|
||||
extractRuntimeEmits,
|
||||
flattenTypeNodes,
|
||||
isTSInterfaceBody
|
||||
} = require('./ts-ast')
|
||||
const {
|
||||
getComponentPropsFromTypeDefineTypes,
|
||||
getComponentEmitsFromTypeDefineTypes
|
||||
} = require('./ts-types')
|
||||
|
||||
/**
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.TypeNode} TSESTreeTypeNode
|
||||
*/
|
||||
/**
|
||||
* @typedef {import('../index').ComponentTypeProp} ComponentTypeProp
|
||||
* @typedef {import('../index').ComponentInferTypeProp} ComponentInferTypeProp
|
||||
* @typedef {import('../index').ComponentUnknownProp} ComponentUnknownProp
|
||||
* @typedef {import('../index').ComponentTypeEmit} ComponentTypeEmit
|
||||
* @typedef {import('../index').ComponentInferTypeEmit} ComponentInferTypeEmit
|
||||
* @typedef {import('../index').ComponentUnknownEmit} ComponentUnknownEmit
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
isTypeNode,
|
||||
getComponentPropsFromTypeDefine,
|
||||
getComponentEmitsFromTypeDefine
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all props by looking at all component's properties
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TypeNode} propsNode Type with props definition
|
||||
* @return {(ComponentTypeProp|ComponentInferTypeProp|ComponentUnknownProp)[]} Array of component props
|
||||
*/
|
||||
function getComponentPropsFromTypeDefine(context, propsNode) {
|
||||
/** @type {(ComponentTypeProp|ComponentInferTypeProp|ComponentUnknownProp)[]} */
|
||||
const result = []
|
||||
for (const defNode of flattenTypeNodes(
|
||||
context,
|
||||
/** @type {TSESTreeTypeNode} */ (propsNode)
|
||||
)) {
|
||||
if (isTSInterfaceBody(defNode) || isTSTypeLiteral(defNode)) {
|
||||
result.push(...extractRuntimeProps(context, defNode))
|
||||
} else {
|
||||
result.push(
|
||||
...getComponentPropsFromTypeDefineTypes(
|
||||
context,
|
||||
/** @type {TypeNode} */ (defNode)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all emits by looking at all component's properties
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TypeNode} emitsNode Type with emits definition
|
||||
* @return {(ComponentTypeEmit|ComponentInferTypeEmit|ComponentUnknownEmit)[]} Array of component emits
|
||||
*/
|
||||
function getComponentEmitsFromTypeDefine(context, emitsNode) {
|
||||
/** @type {(ComponentTypeEmit|ComponentInferTypeEmit|ComponentUnknownEmit)[]} */
|
||||
const result = []
|
||||
for (const defNode of flattenTypeNodes(
|
||||
context,
|
||||
/** @type {TSESTreeTypeNode} */ (emitsNode)
|
||||
)) {
|
||||
if (
|
||||
isTSInterfaceBody(defNode) ||
|
||||
isTSTypeLiteralOrTSFunctionType(defNode)
|
||||
) {
|
||||
result.push(...extractRuntimeEmits(defNode))
|
||||
} else {
|
||||
result.push(
|
||||
...getComponentEmitsFromTypeDefineTypes(
|
||||
context,
|
||||
/** @type {TypeNode} */ (defNode)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
568
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/ts-ast.js
generated
vendored
Normal file
568
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/ts-ast.js
generated
vendored
Normal file
@ -0,0 +1,568 @@
|
||||
const { getScope } = require('../scope')
|
||||
const { findVariable } = require('@eslint-community/eslint-utils')
|
||||
const { inferRuntimeTypeFromTypeNode } = require('./ts-types')
|
||||
/**
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.TypeNode} TSESTreeTypeNode
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.TSInterfaceBody} TSESTreeTSInterfaceBody
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.TSTypeLiteral} TSESTreeTSTypeLiteral
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.TSFunctionType} TSESTreeTSFunctionType
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.Parameter} TSESTreeParameter
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.Node} TSESTreeNode
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @typedef {import('../index').ComponentTypeProp} ComponentTypeProp
|
||||
* @typedef {import('../index').ComponentUnknownProp} ComponentUnknownProp
|
||||
* @typedef {import('../index').ComponentTypeEmit} ComponentTypeEmit
|
||||
* @typedef {import('../index').ComponentUnknownEmit} ComponentUnknownEmit
|
||||
*/
|
||||
|
||||
const noop = Function.prototype
|
||||
|
||||
module.exports = {
|
||||
isTypeNode,
|
||||
flattenTypeNodes,
|
||||
isTSInterfaceBody,
|
||||
isTSTypeLiteral,
|
||||
isTSTypeLiteralOrTSFunctionType,
|
||||
extractRuntimeProps,
|
||||
extractRuntimeEmits
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ASTNode} node
|
||||
* @returns {node is TypeNode}
|
||||
*/
|
||||
function isTypeNode(node) {
|
||||
if (
|
||||
node.type === 'TSAbstractKeyword' ||
|
||||
node.type === 'TSAnyKeyword' ||
|
||||
node.type === 'TSAsyncKeyword' ||
|
||||
node.type === 'TSArrayType' ||
|
||||
node.type === 'TSBigIntKeyword' ||
|
||||
node.type === 'TSBooleanKeyword' ||
|
||||
node.type === 'TSConditionalType' ||
|
||||
node.type === 'TSConstructorType' ||
|
||||
node.type === 'TSDeclareKeyword' ||
|
||||
node.type === 'TSExportKeyword' ||
|
||||
node.type === 'TSFunctionType' ||
|
||||
node.type === 'TSImportType' ||
|
||||
node.type === 'TSIndexedAccessType' ||
|
||||
node.type === 'TSInferType' ||
|
||||
node.type === 'TSIntersectionType' ||
|
||||
node.type === 'TSIntrinsicKeyword' ||
|
||||
node.type === 'TSLiteralType' ||
|
||||
node.type === 'TSMappedType' ||
|
||||
node.type === 'TSNamedTupleMember' ||
|
||||
node.type === 'TSNeverKeyword' ||
|
||||
node.type === 'TSNullKeyword' ||
|
||||
node.type === 'TSNumberKeyword' ||
|
||||
node.type === 'TSObjectKeyword' ||
|
||||
node.type === 'TSOptionalType' ||
|
||||
node.type === 'TSQualifiedName' ||
|
||||
node.type === 'TSPrivateKeyword' ||
|
||||
node.type === 'TSProtectedKeyword' ||
|
||||
node.type === 'TSPublicKeyword' ||
|
||||
node.type === 'TSReadonlyKeyword' ||
|
||||
node.type === 'TSRestType' ||
|
||||
node.type === 'TSStaticKeyword' ||
|
||||
node.type === 'TSStringKeyword' ||
|
||||
node.type === 'TSSymbolKeyword' ||
|
||||
node.type === 'TSTemplateLiteralType' ||
|
||||
node.type === 'TSThisType' ||
|
||||
node.type === 'TSTupleType' ||
|
||||
node.type === 'TSTypeLiteral' ||
|
||||
node.type === 'TSTypeOperator' ||
|
||||
node.type === 'TSTypePredicate' ||
|
||||
node.type === 'TSTypeQuery' ||
|
||||
node.type === 'TSTypeReference' ||
|
||||
node.type === 'TSUndefinedKeyword' ||
|
||||
node.type === 'TSUnionType' ||
|
||||
node.type === 'TSUnknownKeyword' ||
|
||||
node.type === 'TSVoidKeyword'
|
||||
) {
|
||||
/** @type {TypeNode['type']} for type check */
|
||||
const type = node.type
|
||||
noop(type)
|
||||
return true
|
||||
}
|
||||
/** @type {Exclude<ASTNode['type'], TypeNode['type']>} for type check */
|
||||
const type = node.type
|
||||
noop(type)
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TSESTreeTypeNode|TSESTreeTSInterfaceBody} node
|
||||
* @returns {node is TSESTreeTSInterfaceBody}
|
||||
*/
|
||||
function isTSInterfaceBody(node) {
|
||||
return node.type === 'TSInterfaceBody'
|
||||
}
|
||||
/**
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @returns {node is TSESTreeTSTypeLiteral}
|
||||
*/
|
||||
function isTSTypeLiteral(node) {
|
||||
return node.type === 'TSTypeLiteral'
|
||||
}
|
||||
/**
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @returns {node is TSESTreeTSFunctionType}
|
||||
*/
|
||||
function isTSFunctionType(node) {
|
||||
return node.type === 'TSFunctionType'
|
||||
}
|
||||
/**
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @returns {node is TSESTreeTSTypeLiteral | TSESTreeTSFunctionType}
|
||||
*/
|
||||
function isTSTypeLiteralOrTSFunctionType(node) {
|
||||
return isTSTypeLiteral(node) || isTSFunctionType(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 | ComponentUnknownProp>}
|
||||
*/
|
||||
function* extractRuntimeProps(context, node) {
|
||||
const members = node.type === 'TSTypeLiteral' ? node.members : node.body
|
||||
for (const member of members) {
|
||||
if (
|
||||
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 (member.type === 'TSMethodSignature') {
|
||||
types = ['Function']
|
||||
} else if (member.typeAnnotation) {
|
||||
types = inferRuntimeType(context, member.typeAnnotation.typeAnnotation)
|
||||
}
|
||||
yield {
|
||||
type: 'type',
|
||||
key: /** @type {Identifier | Literal} */ (member.key),
|
||||
propName:
|
||||
member.key.type === 'Identifier'
|
||||
? member.key.name
|
||||
: `${member.key.value}`,
|
||||
node: /** @type {TSPropertySignature | TSMethodSignature} */ (member),
|
||||
|
||||
required: !member.optional,
|
||||
types: types || [`null`]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TSESTreeTSTypeLiteral | TSESTreeTSInterfaceBody | TSESTreeTSFunctionType} node
|
||||
* @returns {IterableIterator<ComponentTypeEmit | ComponentUnknownEmit>}
|
||||
*/
|
||||
function* extractRuntimeEmits(node) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {TSESTreeParameter} eventName
|
||||
* @param {TSCallSignatureDeclaration | TSFunctionType} member
|
||||
* @returns {IterableIterator<ComponentTypeEmit>}
|
||||
*/
|
||||
function* extractEventNames(eventName, member) {
|
||||
if (
|
||||
eventName &&
|
||||
eventName.type === 'Identifier' &&
|
||||
eventName.typeAnnotation &&
|
||||
eventName.typeAnnotation.type === 'TSTypeAnnotation'
|
||||
) {
|
||||
const typeNode = eventName.typeAnnotation.typeAnnotation
|
||||
if (
|
||||
typeNode.type === 'TSLiteralType' &&
|
||||
typeNode.literal.type === 'Literal'
|
||||
) {
|
||||
const emitName = String(typeNode.literal.value)
|
||||
yield {
|
||||
type: 'type',
|
||||
key: /** @type {TSLiteralType} */ (typeNode),
|
||||
emitName,
|
||||
node: member
|
||||
}
|
||||
} else if (typeNode.type === 'TSUnionType') {
|
||||
for (const t of typeNode.types) {
|
||||
if (t.type === 'TSLiteralType' && t.literal.type === 'Literal') {
|
||||
const emitName = String(t.literal.value)
|
||||
yield {
|
||||
type: 'type',
|
||||
key: /** @type {TSLiteralType} */ (t),
|
||||
emitName,
|
||||
node: member
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @returns {(TSESTreeTypeNode|TSESTreeTSInterfaceBody)[]}
|
||||
*/
|
||||
function flattenTypeNodes(context, node) {
|
||||
/**
|
||||
* @typedef {object} TraversedData
|
||||
* @property {Set<TSESTreeTypeNode|TSESTreeTSInterfaceBody>} nodes
|
||||
* @property {boolean} finished
|
||||
*/
|
||||
/** @type {Map<TSESTreeTypeNode,TraversedData>} */
|
||||
const traversed = new Map()
|
||||
|
||||
return [...flattenImpl(node)]
|
||||
/**
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @returns {Iterable<TSESTreeTypeNode|TSESTreeTSInterfaceBody>}
|
||||
*/
|
||||
function* flattenImpl(node) {
|
||||
if (node.type === 'TSUnionType' || node.type === 'TSIntersectionType') {
|
||||
for (const typeNode of node.types) {
|
||||
yield* flattenImpl(typeNode)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (
|
||||
node.type === 'TSTypeReference' &&
|
||||
node.typeName.type === 'Identifier'
|
||||
) {
|
||||
const refName = node.typeName.name
|
||||
const variable = findVariable(
|
||||
getScope(context, /** @type {any} */ (node)),
|
||||
refName
|
||||
)
|
||||
if (variable && variable.defs.length === 1) {
|
||||
const defNode = /** @type {TSESTreeNode} */ (variable.defs[0].node)
|
||||
if (defNode.type === 'TSInterfaceDeclaration') {
|
||||
yield defNode.body
|
||||
return
|
||||
} else if (defNode.type === 'TSTypeAliasDeclaration') {
|
||||
const typeAnnotation = defNode.typeAnnotation
|
||||
let traversedData = traversed.get(typeAnnotation)
|
||||
if (traversedData) {
|
||||
const copy = [...traversedData.nodes]
|
||||
yield* copy
|
||||
if (!traversedData.finished) {
|
||||
// Include the node because it will probably be referenced recursively.
|
||||
yield typeAnnotation
|
||||
}
|
||||
return
|
||||
}
|
||||
traversedData = { nodes: new Set(), finished: false }
|
||||
traversed.set(typeAnnotation, traversedData)
|
||||
for (const e of flattenImpl(typeAnnotation)) {
|
||||
traversedData.nodes.add(e)
|
||||
}
|
||||
traversedData.finished = true
|
||||
yield* traversedData.nodes
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
yield node
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TSESTreeTypeNode} node
|
||||
* @param {Set<TSESTreeTypeNode>} [checked]
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferRuntimeType(context, node, checked = new Set()) {
|
||||
switch (node.type) {
|
||||
case 'TSStringKeyword':
|
||||
case 'TSTemplateLiteralType': {
|
||||
return ['String']
|
||||
}
|
||||
case 'TSNumberKeyword': {
|
||||
return ['Number']
|
||||
}
|
||||
case 'TSBooleanKeyword': {
|
||||
return ['Boolean']
|
||||
}
|
||||
case 'TSObjectKeyword': {
|
||||
return ['Object']
|
||||
}
|
||||
case 'TSTypeLiteral': {
|
||||
return inferTypeLiteralType(node)
|
||||
}
|
||||
case 'TSFunctionType': {
|
||||
return ['Function']
|
||||
}
|
||||
case 'TSArrayType':
|
||||
case 'TSTupleType': {
|
||||
return ['Array']
|
||||
}
|
||||
case 'TSSymbolKeyword': {
|
||||
return ['Symbol']
|
||||
}
|
||||
|
||||
case 'TSLiteralType': {
|
||||
if (node.literal.type === 'Literal') {
|
||||
switch (typeof node.literal.value) {
|
||||
case 'boolean': {
|
||||
return ['Boolean']
|
||||
}
|
||||
case 'string': {
|
||||
return ['String']
|
||||
}
|
||||
case 'number':
|
||||
case 'bigint': {
|
||||
return ['Number']
|
||||
}
|
||||
}
|
||||
if (node.literal.value instanceof RegExp) {
|
||||
return ['RegExp']
|
||||
}
|
||||
}
|
||||
return inferRuntimeTypeFromTypeNode(
|
||||
context,
|
||||
/** @type {TypeNode} */ (node)
|
||||
)
|
||||
}
|
||||
case 'TSTypeReference': {
|
||||
if (node.typeName.type === 'Identifier') {
|
||||
const variable = findVariable(
|
||||
getScope(context, /** @type {any} */ (node)),
|
||||
node.typeName.name
|
||||
)
|
||||
if (variable && variable.defs.length === 1) {
|
||||
const defNode = /** @type {TSESTreeNode} */ (variable.defs[0].node)
|
||||
if (defNode.type === 'TSInterfaceDeclaration') {
|
||||
return [`Object`]
|
||||
}
|
||||
if (defNode.type === 'TSTypeAliasDeclaration') {
|
||||
const typeAnnotation = defNode.typeAnnotation
|
||||
if (!checked.has(typeAnnotation)) {
|
||||
checked.add(typeAnnotation)
|
||||
return inferRuntimeType(context, typeAnnotation, checked)
|
||||
}
|
||||
}
|
||||
if (defNode.type === 'TSEnumDeclaration') {
|
||||
return inferEnumType(context, defNode)
|
||||
}
|
||||
}
|
||||
for (const name of [
|
||||
node.typeName.name,
|
||||
...(node.typeName.name.startsWith('Readonly')
|
||||
? [node.typeName.name.slice(8)]
|
||||
: [])
|
||||
]) {
|
||||
switch (name) {
|
||||
case 'Array':
|
||||
case 'Function':
|
||||
case 'Object':
|
||||
case 'Set':
|
||||
case 'Map':
|
||||
case 'WeakSet':
|
||||
case 'WeakMap':
|
||||
case 'Date': {
|
||||
return [name]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.typeName.name) {
|
||||
case 'Record':
|
||||
case 'Partial':
|
||||
case 'Readonly':
|
||||
case 'Pick':
|
||||
case 'Omit':
|
||||
case 'Required':
|
||||
case 'InstanceType': {
|
||||
return ['Object']
|
||||
}
|
||||
case 'Uppercase':
|
||||
case 'Lowercase':
|
||||
case 'Capitalize':
|
||||
case 'Uncapitalize': {
|
||||
return ['String']
|
||||
}
|
||||
case 'Parameters':
|
||||
case 'ConstructorParameters': {
|
||||
return ['Array']
|
||||
}
|
||||
case 'NonNullable': {
|
||||
const typeArguments =
|
||||
'typeArguments' in node
|
||||
? node.typeArguments
|
||||
: /** @type {any} typescript-eslint v5 */ (node).typeParameters
|
||||
if (typeArguments && typeArguments.params[0]) {
|
||||
return inferRuntimeType(
|
||||
context,
|
||||
typeArguments.params[0],
|
||||
checked
|
||||
).filter((t) => t !== 'null')
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Extract': {
|
||||
const typeArguments =
|
||||
'typeArguments' in node
|
||||
? node.typeArguments
|
||||
: /** @type {any} typescript-eslint v5 */ (node).typeParameters
|
||||
if (typeArguments && typeArguments.params[1]) {
|
||||
return inferRuntimeType(context, typeArguments.params[1], checked)
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'Exclude':
|
||||
case 'OmitThisParameter': {
|
||||
const typeArguments =
|
||||
'typeArguments' in node
|
||||
? node.typeArguments
|
||||
: /** @type {any} typescript-eslint v5 */ (node).typeParameters
|
||||
if (typeArguments && typeArguments.params[0]) {
|
||||
return inferRuntimeType(context, typeArguments.params[0], checked)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return inferRuntimeTypeFromTypeNode(
|
||||
context,
|
||||
/** @type {TypeNode} */ (node)
|
||||
)
|
||||
}
|
||||
|
||||
case 'TSUnionType':
|
||||
case 'TSIntersectionType': {
|
||||
return inferUnionType(node)
|
||||
}
|
||||
|
||||
default: {
|
||||
return inferRuntimeTypeFromTypeNode(
|
||||
context,
|
||||
/** @type {TypeNode} */ (node)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@typescript-eslint/types').TSESTree.TSUnionType|import('@typescript-eslint/types').TSESTree.TSIntersectionType} node
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferUnionType(node) {
|
||||
const types = new Set()
|
||||
for (const t of node.types) {
|
||||
for (const tt of inferRuntimeType(context, t, checked)) {
|
||||
types.add(tt)
|
||||
}
|
||||
}
|
||||
return [...types]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import('@typescript-eslint/types').TSESTree.TSTypeLiteral} node
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferTypeLiteralType(node) {
|
||||
const types = new Set()
|
||||
for (const m of node.members) {
|
||||
switch (m.type) {
|
||||
case 'TSCallSignatureDeclaration':
|
||||
case 'TSConstructSignatureDeclaration': {
|
||||
types.add('Function')
|
||||
break
|
||||
}
|
||||
default: {
|
||||
types.add('Object')
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.size > 0 ? [...types] : ['Object']
|
||||
}
|
||||
/**
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {import('@typescript-eslint/types').TSESTree.TSEnumDeclaration} node
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferEnumType(context, node) {
|
||||
const types = new Set()
|
||||
for (const m of node.members) {
|
||||
if (m.initializer) {
|
||||
if (m.initializer.type === 'Literal') {
|
||||
switch (typeof m.initializer.value) {
|
||||
case 'string': {
|
||||
types.add('String')
|
||||
break
|
||||
}
|
||||
case 'number':
|
||||
case 'bigint': {
|
||||
// Now it's a syntax error.
|
||||
types.add('Number')
|
||||
break
|
||||
}
|
||||
case 'boolean': {
|
||||
// Now it's a syntax error.
|
||||
types.add('Boolean')
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const type of inferRuntimeTypeFromTypeNode(
|
||||
context,
|
||||
/** @type {Expression} */ (m.initializer)
|
||||
)) {
|
||||
types.add(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return types.size > 0 ? [...types] : ['Number']
|
||||
}
|
276
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/ts-types.js
generated
vendored
Normal file
276
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/ts-types.js
generated
vendored
Normal file
@ -0,0 +1,276 @@
|
||||
const {
|
||||
getTypeScript,
|
||||
isAny,
|
||||
isUnknown,
|
||||
isNever,
|
||||
isNull,
|
||||
isObject,
|
||||
isFunction,
|
||||
isStringLike,
|
||||
isNumberLike,
|
||||
isBooleanLike,
|
||||
isBigIntLike,
|
||||
isArrayLikeObject,
|
||||
isReferenceObject
|
||||
} = require('./typescript')
|
||||
/**
|
||||
* @typedef {import('@typescript-eslint/types').TSESTree.Node} TSESTreeNode
|
||||
* @typedef {import('typescript').Type} Type
|
||||
* @typedef {import('typescript').TypeChecker} TypeChecker
|
||||
* @typedef {import('typescript').Node} TypeScriptNode
|
||||
*/
|
||||
/**
|
||||
* @typedef {import('../index').ComponentInferTypeProp} ComponentInferTypeProp
|
||||
* @typedef {import('../index').ComponentUnknownProp} ComponentUnknownProp
|
||||
* @typedef {import('../index').ComponentInferTypeEmit} ComponentInferTypeEmit
|
||||
* @typedef {import('../index').ComponentUnknownEmit} ComponentUnknownEmit
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
getComponentPropsFromTypeDefineTypes,
|
||||
getComponentEmitsFromTypeDefineTypes,
|
||||
inferRuntimeTypeFromTypeNode
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {object} Services
|
||||
* @property {typeof import("typescript")} ts
|
||||
* @property {Map<ESNode | TSNode | TSESTreeNode, TypeScriptNode>} tsNodeMap
|
||||
* @property {import('typescript').TypeChecker} checker
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get TypeScript parser services.
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @returns {Services|null}
|
||||
*/
|
||||
function getTSParserServices(context) {
|
||||
const sourceCode = context.getSourceCode()
|
||||
const tsNodeMap = sourceCode.parserServices.esTreeNodeToTSNodeMap
|
||||
if (!tsNodeMap) return null
|
||||
const hasFullTypeInformation =
|
||||
sourceCode.parserServices.hasFullTypeInformation !== false
|
||||
const checker =
|
||||
(hasFullTypeInformation &&
|
||||
sourceCode.parserServices.program &&
|
||||
sourceCode.parserServices.program.getTypeChecker()) ||
|
||||
null
|
||||
if (!checker) return null
|
||||
const ts = getTypeScript()
|
||||
if (!ts) return null
|
||||
|
||||
return {
|
||||
ts,
|
||||
tsNodeMap,
|
||||
checker
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all props by looking at all component's properties
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TypeNode} propsNode Type with props definition
|
||||
* @return {(ComponentInferTypeProp|ComponentUnknownProp)[]} Array of component props
|
||||
*/
|
||||
function getComponentPropsFromTypeDefineTypes(context, propsNode) {
|
||||
const services = getTSParserServices(context)
|
||||
const tsNode = services && services.tsNodeMap.get(propsNode)
|
||||
const type = tsNode && services.checker.getTypeAtLocation(tsNode)
|
||||
if (
|
||||
!type ||
|
||||
isAny(type) ||
|
||||
isUnknown(type) ||
|
||||
isNever(type) ||
|
||||
isNull(type)
|
||||
) {
|
||||
return [
|
||||
{
|
||||
type: 'unknown',
|
||||
propName: null,
|
||||
node: propsNode
|
||||
}
|
||||
]
|
||||
}
|
||||
return [...extractRuntimeProps(type, tsNode, propsNode, services)]
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all emits by looking at all component's properties
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TypeNode} emitsNode Type with emits definition
|
||||
* @return {(ComponentInferTypeEmit|ComponentUnknownEmit)[]} Array of component emits
|
||||
*/
|
||||
function getComponentEmitsFromTypeDefineTypes(context, emitsNode) {
|
||||
const services = getTSParserServices(context)
|
||||
const tsNode = services && services.tsNodeMap.get(emitsNode)
|
||||
const type = tsNode && services.checker.getTypeAtLocation(tsNode)
|
||||
if (
|
||||
!type ||
|
||||
isAny(type) ||
|
||||
isUnknown(type) ||
|
||||
isNever(type) ||
|
||||
isNull(type)
|
||||
) {
|
||||
return [
|
||||
{
|
||||
type: 'unknown',
|
||||
emitName: null,
|
||||
node: emitsNode
|
||||
}
|
||||
]
|
||||
}
|
||||
return [...extractRuntimeEmits(type, tsNode, emitsNode, services)]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RuleContext} context The ESLint rule context object.
|
||||
* @param {TypeNode|Expression} node
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferRuntimeTypeFromTypeNode(context, node) {
|
||||
const services = getTSParserServices(context)
|
||||
const tsNode = services && services.tsNodeMap.get(node)
|
||||
const type = tsNode && services.checker.getTypeAtLocation(tsNode)
|
||||
if (!type) {
|
||||
return ['null']
|
||||
}
|
||||
return inferRuntimeTypeInternal(type, services)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Type} type
|
||||
* @param {TypeScriptNode} tsNode
|
||||
* @param {TypeNode} propsNode Type with props definition
|
||||
* @param {Services} services
|
||||
* @returns {IterableIterator<ComponentInferTypeProp>}
|
||||
*/
|
||||
function* extractRuntimeProps(type, tsNode, propsNode, services) {
|
||||
const { ts, checker } = services
|
||||
for (const property of type.getProperties()) {
|
||||
const isOptional = (property.flags & ts.SymbolFlags.Optional) !== 0
|
||||
const name = property.getName()
|
||||
|
||||
const type = checker.getTypeOfSymbolAtLocation(property, tsNode)
|
||||
|
||||
yield {
|
||||
type: 'infer-type',
|
||||
propName: name,
|
||||
required: !isOptional,
|
||||
node: propsNode,
|
||||
types: inferRuntimeTypeInternal(type, services)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Type} type
|
||||
* @param {Services} services
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function inferRuntimeTypeInternal(type, services) {
|
||||
const { checker } = services
|
||||
/** @type {Set<string>} */
|
||||
const types = new Set()
|
||||
for (const targetType of iterateTypes(checker.getNonNullableType(type))) {
|
||||
if (
|
||||
isAny(targetType) ||
|
||||
isUnknown(targetType) ||
|
||||
isNever(targetType) ||
|
||||
isNull(targetType)
|
||||
) {
|
||||
types.add('null')
|
||||
} else if (isStringLike(targetType)) {
|
||||
types.add('String')
|
||||
} else if (isNumberLike(targetType) || isBigIntLike(targetType)) {
|
||||
types.add('Number')
|
||||
} else if (isBooleanLike(targetType)) {
|
||||
types.add('Boolean')
|
||||
} else if (isFunction(targetType)) {
|
||||
types.add('Function')
|
||||
} else if (
|
||||
isArrayLikeObject(targetType) ||
|
||||
(targetType.isClassOrInterface() &&
|
||||
['Array', 'ReadonlyArray'].includes(
|
||||
checker.getFullyQualifiedName(targetType.symbol)
|
||||
))
|
||||
) {
|
||||
types.add('Array')
|
||||
} else if (isObject(targetType)) {
|
||||
types.add('Object')
|
||||
}
|
||||
}
|
||||
|
||||
if (types.size <= 0) types.add('null')
|
||||
|
||||
return [...types]
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Type} type
|
||||
* @param {TypeScriptNode} tsNode
|
||||
* @param {TypeNode} emitsNode Type with emits definition
|
||||
* @param {Services} services
|
||||
* @returns {IterableIterator<ComponentInferTypeEmit|ComponentUnknownEmit>}
|
||||
*/
|
||||
function* extractRuntimeEmits(type, tsNode, emitsNode, services) {
|
||||
const { checker } = services
|
||||
if (isFunction(type)) {
|
||||
for (const signature of type.getCallSignatures()) {
|
||||
const param = signature.getParameters()[0]
|
||||
if (!param) {
|
||||
yield {
|
||||
type: 'unknown',
|
||||
emitName: null,
|
||||
node: emitsNode
|
||||
}
|
||||
continue
|
||||
}
|
||||
const type = checker.getTypeOfSymbolAtLocation(param, tsNode)
|
||||
|
||||
for (const targetType of iterateTypes(type)) {
|
||||
yield targetType.isStringLiteral()
|
||||
? {
|
||||
type: 'infer-type',
|
||||
emitName: targetType.value,
|
||||
node: emitsNode
|
||||
}
|
||||
: {
|
||||
type: 'unknown',
|
||||
emitName: null,
|
||||
node: emitsNode
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isObject(type)) {
|
||||
for (const property of type.getProperties()) {
|
||||
const name = property.getName()
|
||||
yield {
|
||||
type: 'infer-type',
|
||||
emitName: name,
|
||||
node: emitsNode
|
||||
}
|
||||
}
|
||||
} else {
|
||||
yield {
|
||||
type: 'unknown',
|
||||
emitName: null,
|
||||
node: emitsNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Type} type
|
||||
* @returns {Iterable<Type>}
|
||||
*/
|
||||
function* iterateTypes(type) {
|
||||
if (isReferenceObject(type) && type.target !== type) {
|
||||
yield* iterateTypes(type.target)
|
||||
} else if (type.isUnion() && !isBooleanLike(type)) {
|
||||
for (const t of type.types) {
|
||||
yield* iterateTypes(t)
|
||||
}
|
||||
} else {
|
||||
yield type
|
||||
}
|
||||
}
|
214
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/typescript.js
generated
vendored
Normal file
214
VApp/node_modules/eslint-plugin-vue/lib/utils/ts-utils/typescript.js
generated
vendored
Normal file
@ -0,0 +1,214 @@
|
||||
/**
|
||||
* @typedef {typeof import("typescript")} TypeScript
|
||||
* @typedef {import("typescript").Type} Type
|
||||
* @typedef {import("typescript").ObjectType} ObjectType
|
||||
* @typedef {import("typescript").InterfaceType} InterfaceType
|
||||
* @typedef {import("typescript").TypeReference} TypeReference
|
||||
* @typedef {import("typescript").UnionOrIntersectionType} UnionOrIntersectionType
|
||||
* @typedef {import("typescript").TypeParameter} TypeParameter
|
||||
*/
|
||||
|
||||
/** @type {TypeScript | undefined} */
|
||||
let cacheTypeScript
|
||||
|
||||
module.exports = {
|
||||
getTypeScript,
|
||||
isObject,
|
||||
isAny,
|
||||
isUnknown,
|
||||
isNever,
|
||||
isNull,
|
||||
isFunction,
|
||||
isArrayLikeObject,
|
||||
isStringLike,
|
||||
isNumberLike,
|
||||
isBooleanLike,
|
||||
isBigIntLike,
|
||||
isReferenceObject,
|
||||
extractTypeFlags,
|
||||
extractObjectFlags
|
||||
}
|
||||
|
||||
/**
|
||||
* Get TypeScript instance
|
||||
*/
|
||||
function getTypeScript() {
|
||||
if (cacheTypeScript) {
|
||||
return cacheTypeScript
|
||||
}
|
||||
try {
|
||||
return (cacheTypeScript = require('typescript'))
|
||||
} catch (error) {
|
||||
if (/** @type {any} */ (error).code === 'MODULE_NOT_FOUND') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
/**
|
||||
* For debug
|
||||
* @param {Type} tsType
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function extractTypeFlags(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
/** @type {string[]} */
|
||||
const result = []
|
||||
const keys = /** @type {(keyof (typeof ts.TypeFlags))[]} */ (
|
||||
Object.keys(ts.TypeFlags)
|
||||
)
|
||||
for (const k of keys) {
|
||||
if ((tsType.flags & ts.TypeFlags[k]) !== 0) {
|
||||
result.push(k)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
/**
|
||||
* For debug
|
||||
* @param {Type} tsType
|
||||
* @returns {string[]}
|
||||
*/
|
||||
function extractObjectFlags(tsType) {
|
||||
if (!isObject(tsType)) {
|
||||
return []
|
||||
}
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
/** @type {string[]} */
|
||||
const result = []
|
||||
const keys = /** @type {(keyof (typeof ts.ObjectFlags))[]} */ (
|
||||
Object.keys(ts.ObjectFlags)
|
||||
)
|
||||
for (const k of keys) {
|
||||
if ((tsType.objectFlags & ts.ObjectFlags[k]) !== 0) {
|
||||
result.push(k)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given type is an object type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {tsType is ObjectType}
|
||||
*/
|
||||
function isObject(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.Object) !== 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given type is an array-like type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isArrayLikeObject(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (
|
||||
isObject(tsType) &&
|
||||
(tsType.objectFlags &
|
||||
(ts.ObjectFlags.ArrayLiteral |
|
||||
ts.ObjectFlags.EvolvingArray |
|
||||
ts.ObjectFlags.Tuple)) !==
|
||||
0
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an any type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isAny(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.Any) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an unknown type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isUnknown(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.Unknown) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is a never type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isNever(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.Never) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an null type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isNull(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.Null) !== 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given type is a string-like type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {boolean} `true` if the type is a string-like type.
|
||||
*/
|
||||
function isStringLike(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.StringLike) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an number-like type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {boolean} `true` if the type is a number-like type.
|
||||
*/
|
||||
function isNumberLike(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.NumberLike) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an boolean-like type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {boolean} `true` if the type is a boolean-like type.
|
||||
*/
|
||||
function isBooleanLike(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.BooleanLike) !== 0
|
||||
}
|
||||
/**
|
||||
* Check if a given type is an bigint-like type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {boolean} `true` if the type is a bigint-like type.
|
||||
*/
|
||||
function isBigIntLike(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (tsType.flags & ts.TypeFlags.BigIntLike) !== 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given type is a reference type or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
* @returns {tsType is TypeReference} `true` if the type is a reference type.
|
||||
*/
|
||||
function isReferenceObject(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
return (
|
||||
isObject(tsType) && (tsType.objectFlags & ts.ObjectFlags.Reference) !== 0
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Check if a given type is `function` or not.
|
||||
* @param {Type} tsType The type to check.
|
||||
*/
|
||||
function isFunction(tsType) {
|
||||
const ts = /** @type {TypeScript} */ (getTypeScript())
|
||||
if (
|
||||
tsType.symbol &&
|
||||
(tsType.symbol.flags &
|
||||
(ts.SymbolFlags.Function | ts.SymbolFlags.Method)) !==
|
||||
0
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
const signatures = tsType.getCallSignatures()
|
||||
return signatures.length > 0
|
||||
}
|
Reference in New Issue
Block a user