valueImports
uses tcmts.core.ts.parse, which uses tcmts.core.ts.compiler, which uses process
text with its type-only imports of names made value imports, for code that now uses them as values:
import type { Placement } becomes import { Placement }, and one of several names moves to an import of its own.
import { applyEdits } from "#codebase/tcmts/cli/mirror"; import type { Edit } from "#codebase/tcmts/cli/mirror"; import { isTypeOnlyImport, parse } from "#codebase/tcmts/core/ts"; import { isImportDeclaration as ts_isImportDeclaration, isNamedImports as ts_isNamedImports } from "typescript/ast"; export function valueImports(file: string, text: string, names: Set<string>): string { if (!names.size) return text; const sf = parse(file, text); const edits: Edit[] = []; for (const st of sf.statements) { if (!ts_isImportDeclaration(st) || !st.importClause) continue; const clause = st.importClause; const named = clause.namedBindings && ts_isNamedImports(clause.namedBindings) ? [...clause.namedBindings.elements] : []; if (isTypeOnlyImport(clause)) { const moving = named.filter((e) => names.has(e.name.text)); const whole = (clause.name && names.has(clause.name.text)) || (moving.length && moving.length === named.length); if (whole) { // `import type` → `import` const at = text.indexOf("type", st.getStart(sf) + "import".length); edits.push({ start: at, end: at + "type".length + (/\s/.exec(text[at + 4] ?? "") ? 1 : 0), text: "" }); } else if (moving.length) { const from = text.slice(st.moduleSpecifier.getStart(sf), st.moduleSpecifier.end); const list = (es: typeof named) => es.map((e) => text.slice(e.getStart(sf), e.end)).join(", "); edits.push({ start: st.getStart(sf), end: st.end, text: `import type { ${list(named.filter((e) => !names.has(e.name.text)))} } from ${from};\nimport { ${list(moving)} } from ${from};` }); } continue; } // `import { type Placement }` → `import { Placement }` for (const e of named) { if (!e.isTypeOnly || !names.has(e.name.text)) continue; const at = e.getStart(sf); edits.push({ start: at, end: text.indexOf("type", at) + "type".length + 1, text: "" }); } } return applyEdits(text, edits); }