src/vs/platform/userDataSync/common/extensionsMerge.ts/compare
function compare(from: Map<string, ISyncExtension> | null, to: Map<string, ISyncExtension>, ignoredExtensions: Set<string>, { checkInstalledProperty, checkVersionProperty }: { checkInstalledProperty: boolean; checkVersionProperty: boolean } = { checkInstalledProperty: false, checkVersionProperty: false }): { added: Set<string>; removed: Set<string>; updated: Set<string> } {
	const fromKeys = from ? [...from.keys()].filter(key => !ignoredExtensions.has(key)) : [];
	const toKeys = [...to.keys()].filter(key => !ignoredExtensions.has(key));
	const added = toKeys.filter(key => fromKeys.indexOf(key) === -1).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
	const removed = fromKeys.filter(key => toKeys.indexOf(key) === -1).reduce((r, key) => { r.add(key); return r; }, new Set<string>());
	const updated: Set<string> = new Set<string>();

	for (const key of fromKeys) {
		if (removed.has(key)) {
			continue;
		}
		const fromExtension = from!.get(key)!;
		const toExtension = to.get(key);
		if (!toExtension
			|| fromExtension.disabled !== toExtension.disabled
			|| (fromExtension.installed && toExtension.installed && fromExtension.preRelease !== toExtension.preRelease)
			|| !isSameExtensionState(fromExtension.state, toExtension.state)
			|| (checkVersionProperty && fromExtension.version !== toExtension.version)
			|| (checkInstalledProperty && fromExtension.installed !== toExtension.installed)
		) {
			updated.add(key);
		}
	}

	return { added, removed, updated };
}