import type TS from 'typescript'
import { join, extname, dirname } from 'path'
+/**
+ * TypeResolveContext is compatible with ScriptCompileContext
+ * but also allows a simpler version of it with minimal required properties
+ * when resolveType needs to be used in a non-SFC context, e.g. in a babel
+ * plugin. The simplest context can be just:
+ * ```ts
+ * const ctx: SimpleTypeResolveContext = {
+ * filename: '...',
+ * source: '...',
+ * options: {},
+ * error() {},
+ * ast: []
+ * }
+ * ```
+ */
+export type SimpleTypeResolveContext = Pick<
+ ScriptCompileContext,
+ // required
+ 'source' | 'filename' | 'error' | 'options'
+> &
+ Partial<Pick<ScriptCompileContext, 'scope' | 'deps'>> & {
+ ast: Statement[]
+ }
+
+export type TypeResolveContext = ScriptCompileContext | SimpleTypeResolveContext
+
type Import = Pick<ImportBinding, 'source' | 'imported'>
export interface TypeScope {
* mapped to runtime props or emits.
*/
export function resolveTypeElements(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: Node & WithScope & { _resolvedElements?: ResolvedElements },
scope?: TypeScope
): ResolvedElements {
}
function innerResolveTypeElements(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: Node,
scope: TypeScope
): ResolvedElements {
) {
return resolveBuiltin(ctx, node, typeName as any, scope)
}
- ctx.error(
+ return ctx.error(
`Unresolvable type reference or unsupported built-in utlility type`,
node,
scope
}
}
}
- ctx.error(`Unresolvable type: ${node.type}`, node, scope)
+ return ctx.error(`Unresolvable type: ${node.type}`, node, scope)
}
function typeElementsToMap(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
elements: TSTypeElement[],
scope = ctxToScope(ctx)
): ResolvedElements {
}
function resolveInterfaceMembers(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TSInterfaceDeclaration & WithScope,
scope: TypeScope
): ResolvedElements {
}
function resolveMappedType(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TSMappedType,
scope: TypeScope
): ResolvedElements {
}
function resolveIndexType(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TSIndexedAccessType,
scope: TypeScope
): (TSType & WithScope)[] {
}
function resolveArrayElementType(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: Node,
scope: TypeScope
): TSType[] {
}
}
}
- ctx.error('Failed to resolve element type from target type', node)
+ return ctx.error(
+ 'Failed to resolve element type from target type',
+ node,
+ scope
+ )
}
function resolveStringType(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: Node,
scope: TypeScope
): string[] {
}
}
}
- ctx.error('Failed to resolve index type into finite keys', node, scope)
+ return ctx.error('Failed to resolve index type into finite keys', node, scope)
}
function resolveTemplateKeys(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TemplateLiteral,
scope: TypeScope
): string[] {
type GetSetType<T> = T extends Set<infer V> ? V : never
function resolveBuiltin(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TSTypeReference | TSExpressionWithTypeArguments,
name: GetSetType<typeof SupportedBuiltinsSet>,
scope: TypeScope
}
function resolveTypeReference(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: (TSTypeReference | TSExpressionWithTypeArguments) & {
_resolvedReference?: Node
},
}
function innerResolveTypeReference(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
scope: TypeScope,
name: string | string[],
node: TSTypeReference | TSExpressionWithTypeArguments,
let ts: typeof TS
+/**
+ * @private
+ */
export function registerTS(_ts: any) {
ts = _ts
}
type FS = NonNullable<SFCScriptCompileOptions['fs']>
function resolveTypeFromImport(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: TSTypeReference | TSExpressionWithTypeArguments,
name: string,
scope: TypeScope
const fileToScopeCache = createCache<TypeScope>()
+/**
+ * @private
+ */
export function invalidateTypeCache(filename: string) {
fileToScopeCache.delete(filename)
tsConfigCache.delete(filename)
}
function fileToScope(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
filename: string,
fs: FS
): TypeScope {
}
function parseFile(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
filename: string,
content: string
): Statement[] {
return []
}
-function ctxToScope(ctx: ScriptCompileContext): TypeScope {
+function ctxToScope(ctx: TypeResolveContext): TypeScope {
if (ctx.scope) {
return ctx.scope
}
+ const body =
+ 'ast' in ctx
+ ? ctx.ast
+ : ctx.scriptAst
+ ? [...ctx.scriptAst.body, ...ctx.scriptSetupAst!.body]
+ : ctx.scriptSetupAst!.body
+
const scope: TypeScope = {
- filename: ctx.descriptor.filename,
- source: ctx.descriptor.source,
- offset: ctx.startOffset!,
- imports: Object.create(ctx.userImports),
+ filename: ctx.filename,
+ source: ctx.source,
+ offset: 'startOffset' in ctx ? ctx.startOffset! : 0,
+ imports:
+ 'userImports' in ctx
+ ? Object.create(ctx.userImports)
+ : recordImports(body),
types: Object.create(null),
exportedTypes: Object.create(null)
}
- const body = ctx.scriptAst
- ? [...ctx.scriptAst.body, ...ctx.scriptSetupAst!.body]
- : ctx.scriptSetupAst!.body
-
recordTypes(body, scope)
return (ctx.scope = scope)
}
export function inferRuntimeType(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
node: Node & WithScope,
scope = node._ownerScope || ctxToScope(ctx)
): string[] {
}
function flattenTypes(
- ctx: ScriptCompileContext,
+ ctx: TypeResolveContext,
types: TSType[],
scope: TypeScope
): string[] {