Skip to content

Commit 6f4c0ee

Browse files
authored
Merge pull request #35 from ony3000/fix-patching-process
Improves the process of applying patches
2 parents a600594 + a621bbb commit 6f4c0ee

File tree

11 files changed

+561
-49
lines changed

11 files changed

+561
-49
lines changed

pnpm-lock.yaml

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/packages/core-parts/index.ts

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,84 @@
11
import * as Diff from 'diff';
22

3-
enum PairingMode {
4-
EVEN = 'even',
5-
ODD = 'odd',
6-
}
7-
8-
export type SubstitutePatch = {
9-
from: string;
10-
to: string;
11-
};
3+
export type SubstitutePatch =
4+
| {
5+
type: 'keep';
6+
value: string;
7+
}
8+
| {
9+
type: 'change';
10+
from: string;
11+
to: string;
12+
};
1213

1314
export function makePatches(oldStr: string, newStr: string): SubstitutePatch[] {
1415
if (oldStr === newStr) {
1516
return [];
1617
}
1718

1819
const patches: SubstitutePatch[] = [];
19-
let temporaryText = '';
20-
let mode: PairingMode = PairingMode.EVEN;
21-
22-
Diff.diffLines(oldStr, newStr)
23-
.filter((change) => 'added' in change && 'removed' in change)
24-
.forEach((change) => {
25-
if (!change.added && change.removed) {
26-
if (mode === PairingMode.EVEN) {
27-
temporaryText = change.value;
28-
mode = PairingMode.ODD;
29-
} else {
30-
patches.push({ from: temporaryText, to: '' });
31-
temporaryText = change.value;
32-
}
33-
} else if (change.added && !change.removed) {
34-
if (mode === PairingMode.EVEN) {
35-
patches.push({ from: '', to: change.value });
36-
} else {
37-
patches.push({ from: temporaryText, to: change.value });
38-
mode = PairingMode.EVEN;
39-
}
20+
let temporaryText: string | null = null;
21+
22+
Diff.diffLines(oldStr, newStr).forEach((change) => {
23+
if (change.added && change.removed) {
24+
throw new Error('Unexpected change');
25+
} else if (change.removed) {
26+
if (temporaryText !== null) {
27+
patches.push({ type: 'change', from: temporaryText, to: '' });
4028
}
41-
});
29+
temporaryText = change.value;
30+
} else if (change.added) {
31+
if (temporaryText === null) {
32+
patches.push({ type: 'change', from: '', to: change.value });
33+
} else {
34+
patches.push({ type: 'change', from: temporaryText, to: change.value });
35+
temporaryText = null;
36+
}
37+
} else {
38+
if (temporaryText !== null) {
39+
patches.push({ type: 'change', from: temporaryText, to: '' });
40+
temporaryText = null;
41+
}
42+
patches.push({ type: 'keep', value: change.value });
43+
}
44+
});
4245

4346
return patches;
4447
}
4548

46-
export function applyPatches(text: string, patches: SubstitutePatch[]): string {
47-
return patches.reduce((patchedPrevText, { from, to }) => patchedPrevText.replace(from, to), text);
49+
export function applyPatches(text: string, patchesPerPlugin: SubstitutePatch[][]): string {
50+
return patchesPerPlugin.reduce((patchedPrevText, patches) => {
51+
if (patches.length === 0) {
52+
return patchedPrevText;
53+
}
54+
55+
let mutablePrevText = patchedPrevText;
56+
let scannedLength = 0;
57+
58+
patches.forEach((patch) => {
59+
if (patch.type === 'keep') {
60+
scannedLength += patch.value.length;
61+
} else {
62+
const prefix = mutablePrevText.slice(0, scannedLength);
63+
const suffix = mutablePrevText.slice(scannedLength);
64+
65+
if (suffix.indexOf(patch.from) === -1) {
66+
/**
67+
* A correction value to skip other corresponding patches when a specific patch fails to be applied.
68+
*/
69+
const skipLength = patch.from.length - patch.to.length;
70+
71+
scannedLength += patch.from.length + skipLength;
72+
} else {
73+
mutablePrevText = `${prefix}${suffix.replace(
74+
patch.from,
75+
patch.to.replace(/\$/g, '$$$$'),
76+
)}`;
77+
scannedLength += patch.to.length;
78+
}
79+
}
80+
});
81+
82+
return mutablePrevText;
83+
}, text);
4884
}

src/packages/v2-plugin/parsers.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ function sequentialFormattingAndTryMerging(
5656
: format(originalText, sequentialFormattingOptions);
5757

5858
/**
59-
* Changes that may be removed during the sequential formatting process.
59+
* List of output differences according to the presence or absence of each plugin.
6060
*/
61-
const patches: SubstitutePatch[] = [];
61+
const patchesPerPlugin: SubstitutePatch[][] = [];
6262

6363
const sequentiallyMergedText = plugins.reduce((formattedPrevText, plugin) => {
6464
const temporaryFormattedText =
@@ -77,13 +77,9 @@ function sequentialFormattingAndTryMerging(
7777
? formatAsCodeblock(temporaryFormattedText, sequentialFormattingOptions)
7878
: format(temporaryFormattedText, sequentialFormattingOptions);
7979

80-
patches.push(...makePatches(temporaryFormattedTextWithoutPlugin, temporaryFormattedText));
80+
patchesPerPlugin.push(makePatches(temporaryFormattedTextWithoutPlugin, temporaryFormattedText));
8181

82-
if (patches.length === 0) {
83-
return temporaryFormattedText;
84-
}
85-
86-
return applyPatches(temporaryFormattedTextWithoutPlugin, patches);
82+
return applyPatches(temporaryFormattedTextWithoutPlugin, patchesPerPlugin);
8783
}, firstFormattedText);
8884

8985
return sequentiallyMergedText;

src/packages/v3-plugin/parsers.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,9 @@ async function sequentialFormattingAndTryMerging(
5656
: format(originalText, sequentialFormattingOptions);
5757

5858
/**
59-
* Changes that may be removed during the sequential formatting process.
59+
* List of output differences according to the presence or absence of each plugin.
6060
*/
61-
const patches: SubstitutePatch[] = [];
61+
const patchesPerPlugin: SubstitutePatch[][] = [];
6262

6363
const sequentiallyMergedText = await plugins.reduce<Promise<string>>(
6464
async (formattedPrevTextPromise, plugin) => {
@@ -80,13 +80,11 @@ async function sequentialFormattingAndTryMerging(
8080
? await formatAsCodeblock(temporaryFormattedText, sequentialFormattingOptions)
8181
: await format(temporaryFormattedText, sequentialFormattingOptions);
8282

83-
patches.push(...makePatches(temporaryFormattedTextWithoutPlugin, temporaryFormattedText));
84-
85-
if (patches.length === 0) {
86-
return temporaryFormattedText;
87-
}
83+
patchesPerPlugin.push(
84+
makePatches(temporaryFormattedTextWithoutPlugin, temporaryFormattedText),
85+
);
8886

89-
return applyPatches(temporaryFormattedTextWithoutPlugin, patches);
87+
return applyPatches(temporaryFormattedTextWithoutPlugin, patchesPerPlugin);
9088
},
9189
firstFormattedTextPromise,
9290
);

tests/v2-test/babel/single-plugin.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,40 @@ export function Callout({ children }) {
420420
endOfLine: 'crlf',
421421
},
422422
},
423+
{
424+
name: 'issue #34 (1) - standalone use',
425+
input: `
426+
export function $1_$$2_$$$3_$$$$4({ children }) {
427+
return <div>{children}</div>;
428+
}
429+
`,
430+
output: `export function $1_$$2_$$$3_$$$$4({ children })
431+
{
432+
return <div>{children}</div>;
433+
}
434+
`,
435+
options: {
436+
plugins: ['prettier-plugin-brace-style'],
437+
...braceStylePluginOptions,
438+
},
439+
},
440+
{
441+
name: 'issue #34 (2) - a combination of a single plugin and a merge plugin also has no effect',
442+
input: `
443+
export function $1_$$2_$$$3_$$$$4({ children }) {
444+
return <div>{children}</div>;
445+
}
446+
`,
447+
output: `export function $1_$$2_$$$3_$$$$4({ children })
448+
{
449+
return <div>{children}</div>;
450+
}
451+
`,
452+
options: {
453+
plugins: ['prettier-plugin-brace-style', thisPlugin],
454+
...braceStylePluginOptions,
455+
},
456+
},
423457
];
424458

425459
testEach(fixtures, options);

tests/v2-test/typescript/single-plugin.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,40 @@ export function Callout({ children }) {
420420
endOfLine: 'crlf',
421421
},
422422
},
423+
{
424+
name: 'issue #34 (1) - standalone use',
425+
input: `
426+
export function $1_$$2_$$$3_$$$$4({ children }) {
427+
return <div>{children}</div>;
428+
}
429+
`,
430+
output: `export function $1_$$2_$$$3_$$$$4({ children })
431+
{
432+
return <div>{children}</div>;
433+
}
434+
`,
435+
options: {
436+
plugins: ['prettier-plugin-brace-style'],
437+
...braceStylePluginOptions,
438+
},
439+
},
440+
{
441+
name: 'issue #34 (2) - a combination of a single plugin and a merge plugin also has no effect',
442+
input: `
443+
export function $1_$$2_$$$3_$$$$4({ children }) {
444+
return <div>{children}</div>;
445+
}
446+
`,
447+
output: `export function $1_$$2_$$$3_$$$$4({ children })
448+
{
449+
return <div>{children}</div>;
450+
}
451+
`,
452+
options: {
453+
plugins: ['prettier-plugin-brace-style', thisPlugin],
454+
...braceStylePluginOptions,
455+
},
456+
},
423457
];
424458

425459
testEach(fixtures, options);

0 commit comments

Comments
 (0)