Skip to content

Commit f22e32e

Browse files
committed
feat(compiler-sfc): expose type resolve APIs
1 parent 6b13e04 commit f22e32e

File tree

3 files changed

+83
-33
lines changed

3 files changed

+83
-33
lines changed

Diff for: packages/compiler-sfc/src/index.ts

+6
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export { compileTemplate } from './compileTemplate'
66
export { compileStyle, compileStyleAsync } from './compileStyle'
77
export { compileScript } from './compileScript'
88
export { rewriteDefault, rewriteDefaultAST } from './rewriteDefault'
9+
export { resolveTypeElements, inferRuntimeType } from './script/resolveType'
910
export {
1011
shouldTransform as shouldTransformRef,
1112
transform as transformRef,
@@ -52,6 +53,11 @@ export type {
5253
SFCStyleCompileResults
5354
} from './compileStyle'
5455
export type { SFCScriptCompileOptions } from './compileScript'
56+
export type { ScriptCompileContext } from './script/context'
57+
export type {
58+
TypeResolveContext,
59+
SimpleTypeResolveContext
60+
} from './script/resolveType'
5561
export type {
5662
AssetURLOptions,
5763
AssetURLTagConfig

Diff for: packages/compiler-sfc/src/script/context.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,14 @@ export class ScriptCompileContext {
1616
scriptAst: Program | null
1717
scriptSetupAst: Program | null
1818

19-
s = new MagicString(this.descriptor.source)
19+
source = this.descriptor.source
20+
filename = this.descriptor.filename
21+
s = new MagicString(this.source)
2022
startOffset = this.descriptor.scriptSetup?.loc.start.offset
2123
endOffset = this.descriptor.scriptSetup?.loc.end.offset
2224

2325
// import / type analysis
24-
scope: TypeScope | undefined
26+
scope?: TypeScope
2527
userImports: Record<string, ImportBinding> = Object.create(null)
2628

2729
// macros presence check
@@ -69,7 +71,7 @@ export class ScriptCompileContext {
6971

7072
constructor(
7173
public descriptor: SFCDescriptor,
72-
public options: SFCScriptCompileOptions
74+
public options: Partial<SFCScriptCompileOptions>
7375
) {
7476
const { script, scriptSetup } = descriptor
7577
const scriptLang = script && script.lang

Diff for: packages/compiler-sfc/src/script/resolveType.ts

+72-30
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,32 @@ import { createCache } from '../cache'
3636
import type TS from 'typescript'
3737
import { join, extname, dirname } from 'path'
3838

39+
/**
40+
* TypeResolveContext is compatible with ScriptCompileContext
41+
* but also allows a simpler version of it with minimal required properties
42+
* when resolveType needs to be used in a non-SFC context, e.g. in a babel
43+
* plugin. The simplest context can be just:
44+
* ```ts
45+
* const ctx: SimpleTypeResolveContext = {
46+
* filename: '...',
47+
* source: '...',
48+
* options: {},
49+
* error() {},
50+
* ast: []
51+
* }
52+
* ```
53+
*/
54+
export type SimpleTypeResolveContext = Pick<
55+
ScriptCompileContext,
56+
// required
57+
'source' | 'filename' | 'error' | 'options'
58+
> &
59+
Partial<Pick<ScriptCompileContext, 'scope' | 'deps'>> & {
60+
ast: Statement[]
61+
}
62+
63+
export type TypeResolveContext = ScriptCompileContext | SimpleTypeResolveContext
64+
3965
type Import = Pick<ImportBinding, 'source' | 'imported'>
4066

4167
export interface TypeScope {
@@ -79,7 +105,7 @@ interface ResolvedElements {
79105
* mapped to runtime props or emits.
80106
*/
81107
export function resolveTypeElements(
82-
ctx: ScriptCompileContext,
108+
ctx: TypeResolveContext,
83109
node: Node & WithScope & { _resolvedElements?: ResolvedElements },
84110
scope?: TypeScope
85111
): ResolvedElements {
@@ -94,7 +120,7 @@ export function resolveTypeElements(
94120
}
95121

96122
function innerResolveTypeElements(
97-
ctx: ScriptCompileContext,
123+
ctx: TypeResolveContext,
98124
node: Node,
99125
scope: TypeScope
100126
): ResolvedElements {
@@ -138,19 +164,19 @@ function innerResolveTypeElements(
138164
) {
139165
return resolveBuiltin(ctx, node, typeName as any, scope)
140166
}
141-
ctx.error(
167+
return ctx.error(
142168
`Unresolvable type reference or unsupported built-in utlility type`,
143169
node,
144170
scope
145171
)
146172
}
147173
}
148174
}
149-
ctx.error(`Unresolvable type: ${node.type}`, node, scope)
175+
return ctx.error(`Unresolvable type: ${node.type}`, node, scope)
150176
}
151177

152178
function typeElementsToMap(
153-
ctx: ScriptCompileContext,
179+
ctx: TypeResolveContext,
154180
elements: TSTypeElement[],
155181
scope = ctxToScope(ctx)
156182
): ResolvedElements {
@@ -227,7 +253,7 @@ function createProperty(
227253
}
228254

229255
function resolveInterfaceMembers(
230-
ctx: ScriptCompileContext,
256+
ctx: TypeResolveContext,
231257
node: TSInterfaceDeclaration & WithScope,
232258
scope: TypeScope
233259
): ResolvedElements {
@@ -246,7 +272,7 @@ function resolveInterfaceMembers(
246272
}
247273

248274
function resolveMappedType(
249-
ctx: ScriptCompileContext,
275+
ctx: TypeResolveContext,
250276
node: TSMappedType,
251277
scope: TypeScope
252278
): ResolvedElements {
@@ -266,7 +292,7 @@ function resolveMappedType(
266292
}
267293

268294
function resolveIndexType(
269-
ctx: ScriptCompileContext,
295+
ctx: TypeResolveContext,
270296
node: TSIndexedAccessType,
271297
scope: TypeScope
272298
): (TSType & WithScope)[] {
@@ -297,7 +323,7 @@ function resolveIndexType(
297323
}
298324

299325
function resolveArrayElementType(
300-
ctx: ScriptCompileContext,
326+
ctx: TypeResolveContext,
301327
node: Node,
302328
scope: TypeScope
303329
): TSType[] {
@@ -322,11 +348,15 @@ function resolveArrayElementType(
322348
}
323349
}
324350
}
325-
ctx.error('Failed to resolve element type from target type', node)
351+
return ctx.error(
352+
'Failed to resolve element type from target type',
353+
node,
354+
scope
355+
)
326356
}
327357

328358
function resolveStringType(
329-
ctx: ScriptCompileContext,
359+
ctx: TypeResolveContext,
330360
node: Node,
331361
scope: TypeScope
332362
): string[] {
@@ -373,11 +403,11 @@ function resolveStringType(
373403
}
374404
}
375405
}
376-
ctx.error('Failed to resolve index type into finite keys', node, scope)
406+
return ctx.error('Failed to resolve index type into finite keys', node, scope)
377407
}
378408

379409
function resolveTemplateKeys(
380-
ctx: ScriptCompileContext,
410+
ctx: TypeResolveContext,
381411
node: TemplateLiteral,
382412
scope: TypeScope
383413
): string[] {
@@ -420,7 +450,7 @@ const SupportedBuiltinsSet = new Set([
420450
type GetSetType<T> = T extends Set<infer V> ? V : never
421451

422452
function resolveBuiltin(
423-
ctx: ScriptCompileContext,
453+
ctx: TypeResolveContext,
424454
node: TSTypeReference | TSExpressionWithTypeArguments,
425455
name: GetSetType<typeof SupportedBuiltinsSet>,
426456
scope: TypeScope
@@ -460,7 +490,7 @@ function resolveBuiltin(
460490
}
461491

462492
function resolveTypeReference(
463-
ctx: ScriptCompileContext,
493+
ctx: TypeResolveContext,
464494
node: (TSTypeReference | TSExpressionWithTypeArguments) & {
465495
_resolvedReference?: Node
466496
},
@@ -481,7 +511,7 @@ function resolveTypeReference(
481511
}
482512

483513
function innerResolveTypeReference(
484-
ctx: ScriptCompileContext,
514+
ctx: TypeResolveContext,
485515
scope: TypeScope,
486516
name: string | string[],
487517
node: TSTypeReference | TSExpressionWithTypeArguments,
@@ -536,14 +566,17 @@ function qualifiedNameToPath(node: Identifier | TSQualifiedName): string[] {
536566

537567
let ts: typeof TS
538568

569+
/**
570+
* @private
571+
*/
539572
export function registerTS(_ts: any) {
540573
ts = _ts
541574
}
542575

543576
type FS = NonNullable<SFCScriptCompileOptions['fs']>
544577

545578
function resolveTypeFromImport(
546-
ctx: ScriptCompileContext,
579+
ctx: TypeResolveContext,
547580
node: TSTypeReference | TSExpressionWithTypeArguments,
548581
name: string,
549582
scope: TypeScope
@@ -685,13 +718,16 @@ function resolveWithTS(
685718

686719
const fileToScopeCache = createCache<TypeScope>()
687720

721+
/**
722+
* @private
723+
*/
688724
export function invalidateTypeCache(filename: string) {
689725
fileToScopeCache.delete(filename)
690726
tsConfigCache.delete(filename)
691727
}
692728

693729
function fileToScope(
694-
ctx: ScriptCompileContext,
730+
ctx: TypeResolveContext,
695731
filename: string,
696732
fs: FS
697733
): TypeScope {
@@ -717,7 +753,7 @@ function fileToScope(
717753
}
718754

719755
function parseFile(
720-
ctx: ScriptCompileContext,
756+
ctx: TypeResolveContext,
721757
filename: string,
722758
content: string
723759
): Statement[] {
@@ -763,24 +799,30 @@ function parseFile(
763799
return []
764800
}
765801

766-
function ctxToScope(ctx: ScriptCompileContext): TypeScope {
802+
function ctxToScope(ctx: TypeResolveContext): TypeScope {
767803
if (ctx.scope) {
768804
return ctx.scope
769805
}
770806

807+
const body =
808+
'ast' in ctx
809+
? ctx.ast
810+
: ctx.scriptAst
811+
? [...ctx.scriptAst.body, ...ctx.scriptSetupAst!.body]
812+
: ctx.scriptSetupAst!.body
813+
771814
const scope: TypeScope = {
772-
filename: ctx.descriptor.filename,
773-
source: ctx.descriptor.source,
774-
offset: ctx.startOffset!,
775-
imports: Object.create(ctx.userImports),
815+
filename: ctx.filename,
816+
source: ctx.source,
817+
offset: 'startOffset' in ctx ? ctx.startOffset! : 0,
818+
imports:
819+
'userImports' in ctx
820+
? Object.create(ctx.userImports)
821+
: recordImports(body),
776822
types: Object.create(null),
777823
exportedTypes: Object.create(null)
778824
}
779825

780-
const body = ctx.scriptAst
781-
? [...ctx.scriptAst.body, ...ctx.scriptSetupAst!.body]
782-
: ctx.scriptSetupAst!.body
783-
784826
recordTypes(body, scope)
785827

786828
return (ctx.scope = scope)
@@ -894,7 +936,7 @@ function recordImport(node: Node, imports: TypeScope['imports']) {
894936
}
895937

896938
export function inferRuntimeType(
897-
ctx: ScriptCompileContext,
939+
ctx: TypeResolveContext,
898940
node: Node & WithScope,
899941
scope = node._ownerScope || ctxToScope(ctx)
900942
): string[] {
@@ -1052,7 +1094,7 @@ export function inferRuntimeType(
10521094
}
10531095

10541096
function flattenTypes(
1055-
ctx: ScriptCompileContext,
1097+
ctx: TypeResolveContext,
10561098
types: TSType[],
10571099
scope: TypeScope
10581100
): string[] {

0 commit comments

Comments
 (0)