Skip to content

Commit

Permalink
refactor: split generate function (#49)
Browse files Browse the repository at this point in the history
* refactor: move interface emission to separate function

* refactor: move replacement emission to new function
  • Loading branch information
uhyo authored Aug 13, 2024
1 parent cc2f714 commit e0c10d4
Showing 1 changed file with 124 additions and 88 deletions.
212 changes: 124 additions & 88 deletions build/logic/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,98 +58,22 @@ export function generate(
consumedReplacements.add(name);

if (!ts.isInterfaceDeclaration(statement)) {
// Find the replacement target of same kind.
const replacementTargetOfSameKind = replacementTarget.flatMap((target) =>
target.type === "non-interface" ? [target] : [],
result += generateFullReplacement(
originalFile,
statement,
replacementTarget,
emitOriginalAsComment,
);
if (replacementTargetOfSameKind.length === 0) {
result += statement.getFullText(originalFile);
continue;
}
// Emit replaced statements
result +=
replacementTargetOfSameKind
.map(({ statement, sourceFile }) => statement.getFullText(sourceFile))
.join("") ?? "";
if (emitOriginalAsComment) {
// Replaced statements are emitted as comments
// to make it easier to detect original lib changes
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
}
continue;
}
const replaceInterfaces = replacementTarget.flatMap((target) =>
target.type === "interface" ? [target] : [],
);
if (
replaceInterfaces.some(
(target) =>
!isPartialReplacement(
statement,
originalFile,
target.originalStatement,
target.sourceFile,
),
)
) {
// This needs to be a full replacement
for (const target of replaceInterfaces) {
result += target.originalStatement.getFullText(target.sourceFile);
}
if (emitOriginalAsComment) {
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
}
continue;
}

const replaceInterfaceMembers = new Map<
string,
{
member: ts.TypeElement;
text: string;
}[]
>();
for (const target of replacementTarget) {
if (target.type !== "interface") {
continue;
}
for (const [memberName, elements] of target.members) {
upsert(replaceInterfaceMembers, memberName, (members = []) => {
members.push(...elements);
return members;
});
}
}
const emittedMembers = new Map<string, ts.TypeElement[]>();
const memberList = statement.members.flatMap((mem) => {
const nameStr = mem.name?.getText(originalFile) ?? "";
if (emittedMembers.has(nameStr)) {
emittedMembers.get(nameStr)?.push(mem);
return [];
}
const replacedMembers = replaceInterfaceMembers.get(nameStr);
if (replacedMembers !== undefined) {
emittedMembers.set(nameStr, [mem]);
return replacedMembers;
}
return [
{
member: mem,
text: mem.getFullText(originalFile),
},
];
});
result += printInterface(printer, statement, memberList, originalFile);

if (emitOriginalAsComment) {
result += "\n";
for (const originalMems of emittedMembers.values()) {
for (const originalMem of originalMems) {
result += commentOut(originalMem.getFullText(originalFile));
}
}
result += "\n";
}
result += generateInterface(
printer,
originalFile,
statement,
replacementTarget,
emitOriginalAsComment,
);
}
result += originalFile.text.slice(originalFile.endOfFileToken.pos);

Expand All @@ -172,6 +96,118 @@ export function generate(
return result;
}

function generateFullReplacement(
originalFile: ts.SourceFile,
statement: ts.Statement,
replacementTarget: readonly ReplacementTarget[],
emitOriginalAsComment: boolean,
) {
// Find the replacement target of same kind.
const replacementTargetOfSameKind = replacementTarget.flatMap((target) =>
target.type === "non-interface" ? [target] : [],
);
if (replacementTargetOfSameKind.length === 0) {
return statement.getFullText(originalFile);
}
// Emit replaced statements
let result =
replacementTargetOfSameKind
.map(({ statement, sourceFile }) => statement.getFullText(sourceFile))
.join("") ?? "";
if (emitOriginalAsComment) {
// Replaced statements are emitted as comments
// to make it easier to detect original lib changes
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
}
return result;
}

function generateInterface(
printer: ts.Printer,
originalFile: ts.SourceFile,
statement: ts.InterfaceDeclaration,
replacementTarget: readonly ReplacementTarget[],
emitOriginalAsComment: boolean,
) {
const replaceInterfaces = replacementTarget.flatMap((target) =>
target.type === "interface" ? [target] : [],
);
if (
replaceInterfaces.some(
(target) =>
!isPartialReplacement(
statement,
originalFile,
target.originalStatement,
target.sourceFile,
),
)
) {
// This needs to be a full replacement
let result = "";
for (const target of replaceInterfaces) {
result += target.originalStatement.getFullText(target.sourceFile);
}
if (emitOriginalAsComment) {
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
}
return result;
}

const replaceInterfaceMembers = new Map<
string,
{
member: ts.TypeElement;
text: string;
}[]
>();
for (const target of replacementTarget) {
if (target.type !== "interface") {
continue;
}
for (const [memberName, elements] of target.members) {
upsert(replaceInterfaceMembers, memberName, (members = []) => {
members.push(...elements);
return members;
});
}
}
const emittedMembers = new Map<string, ts.TypeElement[]>();
const memberList = statement.members.flatMap((mem) => {
const nameStr = mem.name?.getText(originalFile) ?? "";
if (emittedMembers.has(nameStr)) {
emittedMembers.get(nameStr)?.push(mem);
return [];
}
const replacedMembers = replaceInterfaceMembers.get(nameStr);
if (replacedMembers !== undefined) {
emittedMembers.set(nameStr, [mem]);
return replacedMembers;
}
return [
{
member: mem,
text: mem.getFullText(originalFile),
},
];
});

let result = "";
result += printInterface(printer, statement, memberList, originalFile);

if (emitOriginalAsComment) {
result += "\n";
for (const originalMems of emittedMembers.values()) {
for (const originalMem of originalMems) {
result += commentOut(originalMem.getFullText(originalFile));
}
}
result += "\n";
}

return result;
}

type ReplacementTarget = (
| {
type: "interface";
Expand Down

0 comments on commit e0c10d4

Please sign in to comment.