Fixed sketch content changes when renaming a file.

Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
This commit is contained in:
Akos Kitta 2022-08-26 12:14:49 +02:00 committed by Akos Kitta
parent 3afc2d7e4b
commit 8beade0867
2 changed files with 82 additions and 3 deletions

View File

@ -93,7 +93,17 @@ export class SketchesServiceClientImpl
CurrentSketch.isValid(this._currentSketch) &&
new URI(this._currentSketch.uri).isEqualOrParent(resource)
) {
if (type === FileChangeType.UPDATED) {
// https://github.com/arduino/arduino-ide/pull/1351#pullrequestreview-1086666656
// On a sketch file rename, the FS watcher will contain two changes:
// - Deletion of the original file,
// - Update of the new file,
// Hence, `UPDATE` events must be processed but only and if only there is a `DELETED` change in the same event.
// Otherwise, IDE2 would ask CLI to reload the sketch content on every save event in IDE2.
if (
type === FileChangeType.UPDATED &&
event.changes.length === 1
) {
// If the event contains only one `UPDATE` change, it cannot be a rename.
return;
}
@ -112,8 +122,9 @@ export class SketchesServiceClientImpl
return;
}
// TODO: check if current is the same as reloaded?
this.useCurrentSketch(reloadedSketch, true);
if (!Sketch.sameAs(this._currentSketch, reloadedSketch)) {
this.useCurrentSketch(reloadedSketch, true);
}
return;
}
// We track main sketch files changes only. // TODO: check sketch folder changes. One can rename the folder without renaming the `.ino` file.

View File

@ -162,6 +162,74 @@ export namespace Sketch {
const { mainFileUri, otherSketchFileUris, additionalFileUris } = sketch;
return [mainFileUri, ...otherSketchFileUris, ...additionalFileUris];
}
const primitiveProps: Array<keyof Sketch> = ['name', 'uri', 'mainFileUri'];
const arrayProps: Array<keyof Sketch> = [
'additionalFileUris',
'otherSketchFileUris',
'rootFolderFileUris',
];
export function sameAs(left: Sketch, right: Sketch): boolean {
for (const prop of primitiveProps) {
const leftValue = left[prop];
const rightValue = right[prop];
assertIsNotArray(leftValue, prop, left);
assertIsNotArray(rightValue, prop, right);
if (leftValue !== rightValue) {
return false;
}
}
for (const prop of arrayProps) {
const leftValue = left[prop];
const rightValue = right[prop];
assertIsArray(leftValue, prop, left);
assertIsArray(rightValue, prop, right);
if (leftValue.length !== rightValue.length) {
return false;
}
}
for (const prop of arrayProps) {
const leftValue = left[prop];
const rightValue = right[prop];
assertIsArray(leftValue, prop, left);
assertIsArray(rightValue, prop, right);
if (
toSortedString(leftValue as string[]) !==
toSortedString(rightValue as string[])
) {
return false;
}
}
return true;
}
function toSortedString(array: string[]): string {
return array.slice().sort().join(',');
}
function assertIsNotArray(
toTest: unknown,
prop: keyof Sketch,
object: Sketch
): void {
if (Array.isArray(toTest)) {
throw new Error(
`Expected a non-array type. Got: ${toTest}. Property was: ${prop}. Object was: ${JSON.stringify(
object
)}`
);
}
}
function assertIsArray(
toTest: unknown,
prop: keyof Sketch,
object: Sketch
): void {
if (!Array.isArray(toTest)) {
throw new Error(
`Expected an array type. Got: ${toTest}. Property was: ${prop}. Object was: ${JSON.stringify(
object
)}`
);
}
}
}
export interface SketchContainer {