UNPKG

@markandrus/effect-derive

Version:

Derive Covariant (Functor), Foldable, and Traversable instances, as well as base functors, for algebraic data types (ADTs)

138 lines (137 loc) 6.45 kB
export class OutFile { packages = new Set(); packageAsteriskImports = new Map; packageDefaultImports = new Map; packageImports = new Map; locals = new Set(); localDefaultImports = new Map; localImports = new Map; declarations = ''; addPackageAsteriskImport(module, alias, isTypeImport = false) { this.packages.add(module); const imports = this.packageAsteriskImports.get(module) ?? new Map(); this.packageAsteriskImports.set(module, imports); const existingAlias = imports.get(alias) ?? isTypeImport; imports.set(alias, isTypeImport ? existingAlias : false); return this; } addPackageDefaultImport(module, alias, isTypeImport = false) { this.packages.add(module); const imports = this.packageDefaultImports.get(module) ?? new Map(); this.packageDefaultImports.set(module, imports); const existingAlias = imports.get(alias) ?? isTypeImport; imports.set(alias, isTypeImport ? existingAlias : false); return this; } addPackageImport(module, imported, aliasOrIsTypeImport, isTypeImport) { const alias = typeof aliasOrIsTypeImport === 'string' ? aliasOrIsTypeImport : undefined; isTypeImport = typeof aliasOrIsTypeImport === 'boolean' ? aliasOrIsTypeImport : isTypeImport ?? false; this.packages.add(module); const imports = this.packageImports.get(module) ?? new Map(); this.packageImports.set(module, imports); const existingImport = imports.get(imported) ?? [alias, isTypeImport]; if (existingImport[0] !== alias) { throw new Error('Multiple import aliases are not supported'); } imports.set(imported, isTypeImport ? existingImport : [alias, false]); return this; } addLocalDefaultImport(module, alias, isTypeImport = false) { this.locals.add(module); const imports = this.localDefaultImports.get(module) ?? new Map(); this.localDefaultImports.set(module, imports); const existingAlias = imports.get(alias) ?? isTypeImport; imports.set(alias, isTypeImport ? existingAlias : false); return this; } addLocalImport(module, imported, aliasOrIsTypeImport, isTypeImport) { const alias = typeof aliasOrIsTypeImport === 'string' ? aliasOrIsTypeImport : undefined; isTypeImport = typeof aliasOrIsTypeImport === 'boolean' ? aliasOrIsTypeImport : isTypeImport ?? false; this.locals.add(module); const imports = this.localImports.get(module) ?? new Map(); this.localImports.set(module, imports); const existingImport = imports.get(imported) ?? [alias, isTypeImport]; if (existingImport[0] !== alias) { throw new Error('Multiple import aliases are not supported'); } imports.set(imported, isTypeImport ? existingImport : [alias, false]); return this; } addDeclarations(declarations) { this.declarations += declarations; return this; } merge(other) { for (const [module, imports] of other.packageAsteriskImports) { for (const [alias, isTypeImport] of imports) { this.addPackageAsteriskImport(module, alias, isTypeImport); } } for (const [module, imports] of other.packageDefaultImports) { for (const [alias, isTypeImport] of imports) { this.addPackageDefaultImport(module, alias, isTypeImport); } } for (const [module, imports] of other.packageImports) { for (const [imported, [alias, isTypeImport]] of imports) { this.addPackageImport(module, imported, alias, isTypeImport); } } for (const [module, imports] of other.localDefaultImports) { for (const [imported, isTypeImport] of imports) { this.addLocalDefaultImport(module, imported, isTypeImport); } } for (const [module, imports] of other.localImports) { for (const [imported, [alias, isTypeImport]] of imports) { this.addLocalImport(module, imported, alias, isTypeImport); } } this.declarations += other.declarations; return this; } toString() { let out = ''; const packages = Array.from(this.packages).sort(); for (const module of packages) { const asteriskImports = this.packageAsteriskImports.get(module) ?? new Map(); for (const [alias, isTypeImport] of asteriskImports) { out += `import ${isTypeImport ? 'type ' : ''}* as ${alias} from "${module}"\n`; } const defaultImports = this.packageDefaultImports.get(module) ?? new Map(); for (const [alias, isTypeImport] of defaultImports) { out += `import ${isTypeImport ? 'type ' : ''} ${alias} from "${module}"\n`; } const imports = this.packageImports.get(module); if (imports != null && imports.size > 0) { out += 'import { '; let i = 0; for (const [imported, [alias, isTypeImport]] of imports) { out += `${i++ === 0 ? '' : ', '}${isTypeImport ? 'type ' : ''}${imported}${alias == null ? '' : ` as ${alias}`}`; } out += ` } from "${module}"\n`; } } if (this.packageImports.size > 0) out += '\n'; const locals = Array.from(this.locals).sort(); for (const module of locals) { const defaultImports = this.localDefaultImports.get(module) ?? new Map(); for (const [alias, isTypeImport] of defaultImports) { out += `import ${isTypeImport ? 'type ' : ''} ${alias} from "${module}"\n`; } const imports = this.localImports.get(module); if (imports != null && imports.size > 0) { out += 'import { '; let i = 0; for (const [imported, [alias, isTypeImport]] of imports) { out += `${i++ === 0 ? '' : ', '}${isTypeImport ? 'type ' : ''}${imported}${alias == null ? '' : ` as ${alias}`}`; } out += ` } from "${module}"\n`; } } if (this.localImports.size > 0) out += '\n'; return out + this.declarations; } }