Skip to content

Commit e0c10d4

Browse files
authored
refactor: split generate function (#49)
* refactor: move interface emission to separate function * refactor: move replacement emission to new function
1 parent cc2f714 commit e0c10d4

File tree

1 file changed

+124
-88
lines changed

1 file changed

+124
-88
lines changed

build/logic/generate.ts

+124-88
Original file line numberDiff line numberDiff line change
@@ -58,98 +58,22 @@ export function generate(
5858
consumedReplacements.add(name);
5959

6060
if (!ts.isInterfaceDeclaration(statement)) {
61-
// Find the replacement target of same kind.
62-
const replacementTargetOfSameKind = replacementTarget.flatMap((target) =>
63-
target.type === "non-interface" ? [target] : [],
61+
result += generateFullReplacement(
62+
originalFile,
63+
statement,
64+
replacementTarget,
65+
emitOriginalAsComment,
6466
);
65-
if (replacementTargetOfSameKind.length === 0) {
66-
result += statement.getFullText(originalFile);
67-
continue;
68-
}
69-
// Emit replaced statements
70-
result +=
71-
replacementTargetOfSameKind
72-
.map(({ statement, sourceFile }) => statement.getFullText(sourceFile))
73-
.join("") ?? "";
74-
if (emitOriginalAsComment) {
75-
// Replaced statements are emitted as comments
76-
// to make it easier to detect original lib changes
77-
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
78-
}
79-
continue;
80-
}
81-
const replaceInterfaces = replacementTarget.flatMap((target) =>
82-
target.type === "interface" ? [target] : [],
83-
);
84-
if (
85-
replaceInterfaces.some(
86-
(target) =>
87-
!isPartialReplacement(
88-
statement,
89-
originalFile,
90-
target.originalStatement,
91-
target.sourceFile,
92-
),
93-
)
94-
) {
95-
// This needs to be a full replacement
96-
for (const target of replaceInterfaces) {
97-
result += target.originalStatement.getFullText(target.sourceFile);
98-
}
99-
if (emitOriginalAsComment) {
100-
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
101-
}
10267
continue;
10368
}
10469

105-
const replaceInterfaceMembers = new Map<
106-
string,
107-
{
108-
member: ts.TypeElement;
109-
text: string;
110-
}[]
111-
>();
112-
for (const target of replacementTarget) {
113-
if (target.type !== "interface") {
114-
continue;
115-
}
116-
for (const [memberName, elements] of target.members) {
117-
upsert(replaceInterfaceMembers, memberName, (members = []) => {
118-
members.push(...elements);
119-
return members;
120-
});
121-
}
122-
}
123-
const emittedMembers = new Map<string, ts.TypeElement[]>();
124-
const memberList = statement.members.flatMap((mem) => {
125-
const nameStr = mem.name?.getText(originalFile) ?? "";
126-
if (emittedMembers.has(nameStr)) {
127-
emittedMembers.get(nameStr)?.push(mem);
128-
return [];
129-
}
130-
const replacedMembers = replaceInterfaceMembers.get(nameStr);
131-
if (replacedMembers !== undefined) {
132-
emittedMembers.set(nameStr, [mem]);
133-
return replacedMembers;
134-
}
135-
return [
136-
{
137-
member: mem,
138-
text: mem.getFullText(originalFile),
139-
},
140-
];
141-
});
142-
result += printInterface(printer, statement, memberList, originalFile);
143-
144-
if (emitOriginalAsComment) {
145-
result += "\n";
146-
for (const originalMems of emittedMembers.values()) {
147-
for (const originalMem of originalMems) {
148-
result += commentOut(originalMem.getFullText(originalFile));
149-
}
150-
}
151-
result += "\n";
152-
}
70+
result += generateInterface(
71+
printer,
72+
originalFile,
73+
statement,
74+
replacementTarget,
75+
emitOriginalAsComment,
76+
);
15377
}
15478
result += originalFile.text.slice(originalFile.endOfFileToken.pos);
15579

@@ -172,6 +96,118 @@ export function generate(
17296
return result;
17397
}
17498

99+
function generateFullReplacement(
100+
originalFile: ts.SourceFile,
101+
statement: ts.Statement,
102+
replacementTarget: readonly ReplacementTarget[],
103+
emitOriginalAsComment: boolean,
104+
) {
105+
// Find the replacement target of same kind.
106+
const replacementTargetOfSameKind = replacementTarget.flatMap((target) =>
107+
target.type === "non-interface" ? [target] : [],
108+
);
109+
if (replacementTargetOfSameKind.length === 0) {
110+
return statement.getFullText(originalFile);
111+
}
112+
// Emit replaced statements
113+
let result =
114+
replacementTargetOfSameKind
115+
.map(({ statement, sourceFile }) => statement.getFullText(sourceFile))
116+
.join("") ?? "";
117+
if (emitOriginalAsComment) {
118+
// Replaced statements are emitted as comments
119+
// to make it easier to detect original lib changes
120+
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
121+
}
122+
return result;
123+
}
124+
125+
function generateInterface(
126+
printer: ts.Printer,
127+
originalFile: ts.SourceFile,
128+
statement: ts.InterfaceDeclaration,
129+
replacementTarget: readonly ReplacementTarget[],
130+
emitOriginalAsComment: boolean,
131+
) {
132+
const replaceInterfaces = replacementTarget.flatMap((target) =>
133+
target.type === "interface" ? [target] : [],
134+
);
135+
if (
136+
replaceInterfaces.some(
137+
(target) =>
138+
!isPartialReplacement(
139+
statement,
140+
originalFile,
141+
target.originalStatement,
142+
target.sourceFile,
143+
),
144+
)
145+
) {
146+
// This needs to be a full replacement
147+
let result = "";
148+
for (const target of replaceInterfaces) {
149+
result += target.originalStatement.getFullText(target.sourceFile);
150+
}
151+
if (emitOriginalAsComment) {
152+
result += "\n" + commentOut(statement.getFullText(originalFile)) + "\n";
153+
}
154+
return result;
155+
}
156+
157+
const replaceInterfaceMembers = new Map<
158+
string,
159+
{
160+
member: ts.TypeElement;
161+
text: string;
162+
}[]
163+
>();
164+
for (const target of replacementTarget) {
165+
if (target.type !== "interface") {
166+
continue;
167+
}
168+
for (const [memberName, elements] of target.members) {
169+
upsert(replaceInterfaceMembers, memberName, (members = []) => {
170+
members.push(...elements);
171+
return members;
172+
});
173+
}
174+
}
175+
const emittedMembers = new Map<string, ts.TypeElement[]>();
176+
const memberList = statement.members.flatMap((mem) => {
177+
const nameStr = mem.name?.getText(originalFile) ?? "";
178+
if (emittedMembers.has(nameStr)) {
179+
emittedMembers.get(nameStr)?.push(mem);
180+
return [];
181+
}
182+
const replacedMembers = replaceInterfaceMembers.get(nameStr);
183+
if (replacedMembers !== undefined) {
184+
emittedMembers.set(nameStr, [mem]);
185+
return replacedMembers;
186+
}
187+
return [
188+
{
189+
member: mem,
190+
text: mem.getFullText(originalFile),
191+
},
192+
];
193+
});
194+
195+
let result = "";
196+
result += printInterface(printer, statement, memberList, originalFile);
197+
198+
if (emitOriginalAsComment) {
199+
result += "\n";
200+
for (const originalMems of emittedMembers.values()) {
201+
for (const originalMem of originalMems) {
202+
result += commentOut(originalMem.getFullText(originalFile));
203+
}
204+
}
205+
result += "\n";
206+
}
207+
208+
return result;
209+
}
210+
175211
type ReplacementTarget = (
176212
| {
177213
type: "interface";

0 commit comments

Comments
 (0)