@tamagui/compiler-core 0.0.0-bootstrap.0 → 3.0.0-beta.1093.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +57 -1
- package/dist/cjs/ast.cjs +108 -0
- package/dist/cjs/contracts.cjs +61 -0
- package/dist/cjs/diagnostics.cjs +68 -0
- package/dist/cjs/evaluate.cjs +602 -0
- package/dist/cjs/graph.cjs +335 -0
- package/dist/cjs/hash.cjs +48 -0
- package/dist/cjs/index.cjs +43 -0
- package/dist/cjs/ir.cjs +32 -0
- package/dist/cjs/lower.cjs +232 -0
- package/dist/cjs/materialize.cjs +222 -0
- package/dist/cjs/normalize.cjs +628 -0
- package/dist/cjs/output.cjs +148 -0
- package/dist/cjs/planCache.cjs +262 -0
- package/dist/cjs/session.cjs +127 -0
- package/dist/cjs/yuku.cjs +166 -0
- package/dist/cjs/zero.cjs +389 -0
- package/dist/esm/ast.mjs +79 -0
- package/dist/esm/ast.mjs.map +1 -0
- package/dist/esm/contracts.mjs +34 -0
- package/dist/esm/contracts.mjs.map +1 -0
- package/dist/esm/diagnostics.mjs +44 -0
- package/dist/esm/diagnostics.mjs.map +1 -0
- package/dist/esm/evaluate.mjs +576 -0
- package/dist/esm/evaluate.mjs.map +1 -0
- package/dist/esm/graph.mjs +313 -0
- package/dist/esm/graph.mjs.map +1 -0
- package/dist/esm/hash.mjs +26 -0
- package/dist/esm/hash.mjs.map +1 -0
- package/dist/esm/index.mjs +30 -0
- package/dist/esm/ir.mjs +12 -0
- package/dist/esm/ir.mjs.map +1 -0
- package/dist/esm/lower.mjs +210 -0
- package/dist/esm/lower.mjs.map +1 -0
- package/dist/esm/materialize.mjs +203 -0
- package/dist/esm/materialize.mjs.map +1 -0
- package/dist/esm/normalize.mjs +604 -0
- package/dist/esm/normalize.mjs.map +1 -0
- package/dist/esm/output.mjs +119 -0
- package/dist/esm/output.mjs.map +1 -0
- package/dist/esm/planCache.mjs +232 -0
- package/dist/esm/planCache.mjs.map +1 -0
- package/dist/esm/session.mjs +108 -0
- package/dist/esm/session.mjs.map +1 -0
- package/dist/esm/yuku.mjs +144 -0
- package/dist/esm/yuku.mjs.map +1 -0
- package/dist/esm/zero.mjs +354 -0
- package/dist/esm/zero.mjs.map +1 -0
- package/package.json +42 -4
- package/src/ast.ts +106 -0
- package/src/contracts.ts +150 -0
- package/src/diagnostics.ts +96 -0
- package/src/evaluate.ts +875 -0
- package/src/graph.ts +425 -0
- package/src/hash.ts +36 -0
- package/src/index.ts +15 -0
- package/src/ir.ts +156 -0
- package/src/lower.ts +435 -0
- package/src/materialize.ts +383 -0
- package/src/normalize.ts +834 -0
- package/src/output.ts +175 -0
- package/src/planCache.ts +362 -0
- package/src/session.ts +192 -0
- package/src/yuku.ts +197 -0
- package/src/zero.ts +609 -0
- package/types/ast.d.ts +11 -0
- package/types/ast.d.ts.map +1 -0
- package/types/contracts.d.ts +99 -0
- package/types/contracts.d.ts.map +1 -0
- package/types/diagnostics.d.ts +31 -0
- package/types/diagnostics.d.ts.map +1 -0
- package/types/evaluate.d.ts +48 -0
- package/types/evaluate.d.ts.map +1 -0
- package/types/graph.d.ts +51 -0
- package/types/graph.d.ts.map +1 -0
- package/types/hash.d.ts +8 -0
- package/types/hash.d.ts.map +1 -0
- package/types/index.d.ts +16 -0
- package/types/index.d.ts.map +1 -0
- package/types/ir.d.ts +120 -0
- package/types/ir.d.ts.map +1 -0
- package/types/lower.d.ts +99 -0
- package/types/lower.d.ts.map +1 -0
- package/types/materialize.d.ts +121 -0
- package/types/materialize.d.ts.map +1 -0
- package/types/normalize.d.ts +7 -0
- package/types/normalize.d.ts.map +1 -0
- package/types/output.d.ts +32 -0
- package/types/output.d.ts.map +1 -0
- package/types/planCache.d.ts +123 -0
- package/types/planCache.d.ts.map +1 -0
- package/types/session.d.ts +52 -0
- package/types/session.d.ts.map +1 -0
- package/types/yuku.d.ts +4 -0
- package/types/yuku.d.ts.map +1 -0
- package/types/zero.d.ts +99 -0
- package/types/zero.d.ts.map +1 -0
package/src/session.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import type { HostModuleInput, ResolvedModuleId } from './contracts'
|
|
2
|
+
import type { GraphInvalidation } from './graph'
|
|
3
|
+
import { ProjectGraph } from './graph'
|
|
4
|
+
import type {
|
|
5
|
+
CompilerLoweringHost,
|
|
6
|
+
CompilerTarget,
|
|
7
|
+
LoweredModulePlan,
|
|
8
|
+
StructuralModulePass,
|
|
9
|
+
} from './lower'
|
|
10
|
+
import { lowerModule } from './lower'
|
|
11
|
+
import { materializeModule, type MaterializedModule } from './materialize'
|
|
12
|
+
import type { AppliedLoweredModule } from './output'
|
|
13
|
+
import { applyLoweredModule } from './output'
|
|
14
|
+
import type { ModulePlanCache } from './planCache'
|
|
15
|
+
import {
|
|
16
|
+
PLAN_CACHE_SCHEMA_VERSION,
|
|
17
|
+
createExternalClosureLookup,
|
|
18
|
+
moduleClosureDigest,
|
|
19
|
+
planCacheKey,
|
|
20
|
+
} from './planCache'
|
|
21
|
+
import { yukuFactory } from './yuku'
|
|
22
|
+
|
|
23
|
+
export interface CompilerAdapter {
|
|
24
|
+
target: CompilerTarget
|
|
25
|
+
projectGeneration: string
|
|
26
|
+
host: CompilerLoweringHost
|
|
27
|
+
load(id: ResolvedModuleId): Promise<HostModuleInput | null>
|
|
28
|
+
/**
|
|
29
|
+
* Runs after a module is materialized and before it lowers, once per uncached
|
|
30
|
+
* compile. The frontend evaluates component modules the host does not know
|
|
31
|
+
* yet here (element and styled() base provenance outside the configured
|
|
32
|
+
* `components`), so lowering never meets an import it could have resolved.
|
|
33
|
+
*/
|
|
34
|
+
prepare?(module: MaterializedModule): Promise<void>
|
|
35
|
+
/**
|
|
36
|
+
* Persistent per-module plan reuse across processes. Absent means the host
|
|
37
|
+
* could not produce a content stamp for this project, so nothing is cached
|
|
38
|
+
* rather than cached under a stamp that does not describe the config.
|
|
39
|
+
*/
|
|
40
|
+
planCache?: { store: ModulePlanCache; stamp: string }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface CompileModuleInput {
|
|
44
|
+
module: HostModuleInput
|
|
45
|
+
adapter: CompilerAdapter
|
|
46
|
+
structuralPass?: StructuralModulePass
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface CompilerSessionResult {
|
|
50
|
+
plan: LoweredModulePlan
|
|
51
|
+
output: AppliedLoweredModule
|
|
52
|
+
invalidatedIds: ResolvedModuleId[]
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function compareIds(left: ResolvedModuleId, right: ResolvedModuleId): number {
|
|
56
|
+
return left < right ? -1 : left > right ? 1 : 0
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Bundler-neutral compiler state. The adapter owns module resolution and loading;
|
|
61
|
+
* the session only accepts canonical host-resolved module records.
|
|
62
|
+
*/
|
|
63
|
+
export class CompilerSession {
|
|
64
|
+
readonly #graph = new ProjectGraph(yukuFactory, { modules: [] })
|
|
65
|
+
readonly #externalClosure = createExternalClosureLookup()
|
|
66
|
+
#queue: Promise<unknown> = Promise.resolve()
|
|
67
|
+
|
|
68
|
+
compile(input: CompileModuleInput): Promise<CompilerSessionResult> {
|
|
69
|
+
const operation = this.#queue.then(() => this.#compile(input))
|
|
70
|
+
this.#queue = operation.catch(() => undefined)
|
|
71
|
+
return operation
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
update(module: HostModuleInput): Promise<ResolvedModuleId[]> {
|
|
75
|
+
return this.#enqueue(() => this.#graph.updateModule(module).invalidatedIds)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
has(id: ResolvedModuleId): boolean {
|
|
79
|
+
return this.#graph.contentHash(id) !== null
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
dependentsOf(id: ResolvedModuleId): ResolvedModuleId[] {
|
|
83
|
+
return this.#graph.dependentsOf(id)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
remove(id: ResolvedModuleId): Promise<GraphInvalidation> {
|
|
87
|
+
return this.#enqueue(() => this.#graph.removeModule(id))
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
parseCount(id: ResolvedModuleId): number {
|
|
91
|
+
return this.#graph.parseCount(id)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#enqueue<T>(operation: () => T | Promise<T>): Promise<T> {
|
|
95
|
+
const queued = this.#queue.then(operation)
|
|
96
|
+
this.#queue = queued.catch(() => undefined)
|
|
97
|
+
return queued
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async #compile({
|
|
101
|
+
module,
|
|
102
|
+
adapter,
|
|
103
|
+
structuralPass,
|
|
104
|
+
}: CompileModuleInput): Promise<CompilerSessionResult> {
|
|
105
|
+
const invalidated = new Set<ResolvedModuleId>()
|
|
106
|
+
await this.#install(module, adapter, new Set(), invalidated)
|
|
107
|
+
const graph = this.#graph
|
|
108
|
+
// an empty stamp is not an identity: a key without one would be shared by
|
|
109
|
+
// every project and every config, so such a project simply does not cache
|
|
110
|
+
const cache = adapter.planCache?.stamp ? adapter.planCache : null
|
|
111
|
+
const closureDigest = cache
|
|
112
|
+
? moduleClosureDigest(module.id, (id) => {
|
|
113
|
+
const hash = graph.contentHash(id)
|
|
114
|
+
if (hash) {
|
|
115
|
+
return {
|
|
116
|
+
contentHash: hash,
|
|
117
|
+
dependencies: [...graph.dependenciesOf(id), ...graph.externalImportsOf(id)],
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return this.#externalClosure(id)
|
|
121
|
+
})
|
|
122
|
+
: null
|
|
123
|
+
const entry =
|
|
124
|
+
cache && closureDigest
|
|
125
|
+
? {
|
|
126
|
+
store: cache.store,
|
|
127
|
+
digest: closureDigest,
|
|
128
|
+
key: planCacheKey(
|
|
129
|
+
{
|
|
130
|
+
stamp: cache.stamp,
|
|
131
|
+
target: adapter.target,
|
|
132
|
+
structuralPassHash:
|
|
133
|
+
structuralPass?.versionHash ?? `${adapter.target}-noop-v1`,
|
|
134
|
+
},
|
|
135
|
+
module.id,
|
|
136
|
+
closureDigest
|
|
137
|
+
),
|
|
138
|
+
}
|
|
139
|
+
: null
|
|
140
|
+
|
|
141
|
+
const cached = entry
|
|
142
|
+
? await entry.store.read(entry.key, module.id, entry.digest)
|
|
143
|
+
: null
|
|
144
|
+
let plan = cached?.plan
|
|
145
|
+
if (!plan) {
|
|
146
|
+
const materialized = materializeModule(graph, module.id)
|
|
147
|
+
if (adapter.prepare) await adapter.prepare(materialized)
|
|
148
|
+
plan = lowerModule({
|
|
149
|
+
module: materialized,
|
|
150
|
+
source: module.source,
|
|
151
|
+
target: adapter.target,
|
|
152
|
+
host: adapter.host,
|
|
153
|
+
options: { projectGeneration: adapter.projectGeneration },
|
|
154
|
+
structuralPass,
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
if (entry && !cached) {
|
|
158
|
+
await entry.store.write(entry.key, {
|
|
159
|
+
schemaVersion: PLAN_CACHE_SCHEMA_VERSION,
|
|
160
|
+
moduleId: module.id,
|
|
161
|
+
closureDigest: entry.digest,
|
|
162
|
+
plan,
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
plan,
|
|
167
|
+
output: applyLoweredModule(module.source, module.id, plan),
|
|
168
|
+
invalidatedIds: [...invalidated].sort(compareIds),
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async #install(
|
|
173
|
+
module: HostModuleInput,
|
|
174
|
+
adapter: CompilerAdapter,
|
|
175
|
+
visited: Set<ResolvedModuleId>,
|
|
176
|
+
invalidated: Set<ResolvedModuleId>
|
|
177
|
+
): Promise<void> {
|
|
178
|
+
if (visited.has(module.id)) return
|
|
179
|
+
visited.add(module.id)
|
|
180
|
+
|
|
181
|
+
for (const dependency of module.imports) {
|
|
182
|
+
if (dependency.external || this.has(dependency.resolvedId)) continue
|
|
183
|
+
const loaded = await adapter.load(dependency.resolvedId)
|
|
184
|
+
if (loaded) {
|
|
185
|
+
await this.#install(loaded, adapter, visited, invalidated)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const update = this.#graph.updateModule(module)
|
|
190
|
+
for (const id of update.invalidatedIds) invalidated.add(id)
|
|
191
|
+
}
|
|
192
|
+
}
|
package/src/yuku.ts
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { Analyzer, type Module, type Symbol as YukuSymbol } from 'yuku-analyzer'
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
AnalyzerCandidate,
|
|
5
|
+
AstNode,
|
|
6
|
+
CandidateFactory,
|
|
7
|
+
DefinitionSite,
|
|
8
|
+
ParseDiagnostic,
|
|
9
|
+
ProjectInput,
|
|
10
|
+
ReferenceSite,
|
|
11
|
+
} from './contracts'
|
|
12
|
+
import { resolveFromHost, resolvedModuleId } from './contracts'
|
|
13
|
+
import { childNode, walkAst } from './ast'
|
|
14
|
+
import { asAstNode, definitionFromDeclaration, nodeAtSpan } from './normalize'
|
|
15
|
+
|
|
16
|
+
class YukuCandidate implements AnalyzerCandidate {
|
|
17
|
+
readonly name = 'yuku' as const
|
|
18
|
+
readonly #analyzer: Analyzer
|
|
19
|
+
readonly #parseCounts = new Map<string, number>()
|
|
20
|
+
|
|
21
|
+
constructor(private readonly project: ProjectInput) {
|
|
22
|
+
this.#analyzer = new Analyzer({
|
|
23
|
+
resolve: (specifier, importer) =>
|
|
24
|
+
resolveFromHost(this.project.resolutions, specifier, importer),
|
|
25
|
+
})
|
|
26
|
+
for (const [id, source] of project.files) this.addFile(id, source)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
addFile(id: string, source: string): void {
|
|
30
|
+
this.#analyzer.addFile(id, source, { preserveParens: true, sourceType: 'module' })
|
|
31
|
+
this.#parseCounts.set(id, (this.#parseCounts.get(id) ?? 0) + 1)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
removeFile(id: string): boolean {
|
|
35
|
+
return this.#analyzer.removeFile(id)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
link(): void {
|
|
39
|
+
this.#analyzer.link()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
#module(id: string): Module {
|
|
43
|
+
const module = this.#analyzer.module(id)
|
|
44
|
+
if (!module) throw new Error(`yuku: unknown module ${id}`)
|
|
45
|
+
return module
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#canonicalSymbol(id: string, localName: string): YukuSymbol | null {
|
|
49
|
+
const symbol = this.#module(id).resolve(localName)
|
|
50
|
+
return symbol ? (this.#analyzer.definitionOf(symbol)?.symbol ?? null) : null
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#definitionSite(symbol: YukuSymbol): DefinitionSite | null {
|
|
54
|
+
const declaration = symbol.declarations[0]
|
|
55
|
+
if (!declaration) return null
|
|
56
|
+
return definitionFromDeclaration(
|
|
57
|
+
symbol.module.path,
|
|
58
|
+
symbol.name,
|
|
59
|
+
asAstNode(declaration, `${symbol.name} declaration`),
|
|
60
|
+
(node) => symbol.module.parentOf(node as any) as AstNode | null
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
definitionOf(id: string, localName: string): DefinitionSite | null {
|
|
65
|
+
const symbol = this.#canonicalSymbol(id, localName)
|
|
66
|
+
return symbol ? this.#definitionSite(symbol) : null
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
definitionAt(id: string, start: number, end: number): DefinitionSite | null {
|
|
70
|
+
const module = this.#module(id)
|
|
71
|
+
const node = nodeAtSpan(asAstNode(module.ast, `${module.path} program`), start, end)
|
|
72
|
+
if (!node) return null
|
|
73
|
+
const symbol = module.symbolOf(node as any)
|
|
74
|
+
const definition = symbol && this.#analyzer.definitionOf(symbol)?.symbol
|
|
75
|
+
return definition ? this.#definitionSite(definition) : null
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
referencesOf(definition: DefinitionSite): ReferenceSite[] {
|
|
79
|
+
const symbol = this.#canonicalSymbol(definition.id, definition.name)
|
|
80
|
+
if (!symbol) return []
|
|
81
|
+
return this.#analyzer.referencesOf(symbol).map(({ module, reference }) => ({
|
|
82
|
+
id: resolvedModuleId(module.path),
|
|
83
|
+
name: reference.name,
|
|
84
|
+
start: reference.node.start,
|
|
85
|
+
end: reference.node.end,
|
|
86
|
+
}))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
dependenciesOf(id: string): string[] {
|
|
90
|
+
return this.#module(id)
|
|
91
|
+
.dependencies.map((module) => module.path)
|
|
92
|
+
.sort()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
dependentsOf(id: string): string[] {
|
|
96
|
+
return this.#module(id)
|
|
97
|
+
.dependents.map((module) => module.path)
|
|
98
|
+
.sort()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
affectedBy(id: string): string[] {
|
|
102
|
+
const affected = new Set([id])
|
|
103
|
+
const queue = [id]
|
|
104
|
+
while (queue.length) {
|
|
105
|
+
const current = queue.shift()!
|
|
106
|
+
for (const dependent of this.dependentsOf(current)) {
|
|
107
|
+
if (!affected.has(dependent)) {
|
|
108
|
+
affected.add(dependent)
|
|
109
|
+
queue.push(dependent)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return [...affected].sort()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
programOf(id: string) {
|
|
117
|
+
return asAstNode(this.#module(id).ast, `${id} program`)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
sourceOf(id: string): string {
|
|
121
|
+
return this.#module(id).source
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
parseCount(id: string): number {
|
|
125
|
+
return this.#parseCounts.get(id) ?? 0
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
diagnostics(): ParseDiagnostic[] {
|
|
129
|
+
const parseDiagnostics = [...this.#analyzer.modules.values()].flatMap((module) =>
|
|
130
|
+
module.diagnostics.map((diagnostic) => ({
|
|
131
|
+
kind: 'parse' as const,
|
|
132
|
+
id: resolvedModuleId(module.path),
|
|
133
|
+
message: diagnostic.message,
|
|
134
|
+
}))
|
|
135
|
+
)
|
|
136
|
+
return [
|
|
137
|
+
...parseDiagnostics,
|
|
138
|
+
...this.#analyzer.diagnostics.map((diagnostic) => ({
|
|
139
|
+
kind: 'link' as const,
|
|
140
|
+
id: resolvedModuleId(diagnostic.module),
|
|
141
|
+
message: diagnostic.message,
|
|
142
|
+
})),
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const yukuFactory: CandidateFactory = {
|
|
148
|
+
name: 'yuku',
|
|
149
|
+
create: (project) => new YukuCandidate(project),
|
|
150
|
+
scanImports(id, source) {
|
|
151
|
+
const candidate = new YukuCandidate({
|
|
152
|
+
files: new Map([[id, source]]),
|
|
153
|
+
resolutions: new Map(),
|
|
154
|
+
})
|
|
155
|
+
const found: { start: number; specifier: string }[] = []
|
|
156
|
+
walkAst(candidate.programOf(id), (node) => {
|
|
157
|
+
if (
|
|
158
|
+
node.type !== 'ImportDeclaration' &&
|
|
159
|
+
node.type !== 'ExportNamedDeclaration' &&
|
|
160
|
+
node.type !== 'ExportAllDeclaration' &&
|
|
161
|
+
node.type !== 'ImportExpression'
|
|
162
|
+
) {
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
const sourceNode = childNode(node, 'source')
|
|
166
|
+
if (sourceNode && typeof sourceNode.value === 'string') {
|
|
167
|
+
found.push({ start: node.start, specifier: sourceNode.value })
|
|
168
|
+
}
|
|
169
|
+
})
|
|
170
|
+
return [
|
|
171
|
+
...new Set(
|
|
172
|
+
found
|
|
173
|
+
.sort((left, right) => left.start - right.start)
|
|
174
|
+
.map(({ specifier }) => specifier)
|
|
175
|
+
),
|
|
176
|
+
]
|
|
177
|
+
},
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function parseModuleAst(
|
|
181
|
+
source: string,
|
|
182
|
+
id = '/tamagui/compiler-module.tsx'
|
|
183
|
+
): AstNode {
|
|
184
|
+
const candidate = yukuFactory.create({
|
|
185
|
+
files: new Map([[id, source]]),
|
|
186
|
+
resolutions: new Map(),
|
|
187
|
+
})
|
|
188
|
+
const diagnostics = candidate
|
|
189
|
+
.diagnostics()
|
|
190
|
+
.filter((diagnostic) => diagnostic.kind === 'parse')
|
|
191
|
+
if (diagnostics.length) {
|
|
192
|
+
throw new Error(
|
|
193
|
+
`Unable to parse ${id}: ${diagnostics.map(({ message }) => message).join('; ')}`
|
|
194
|
+
)
|
|
195
|
+
}
|
|
196
|
+
return candidate.programOf(id)
|
|
197
|
+
}
|