src/vs/platform/userDataSync/common/extensionsMerge.ts/addExtensionToMap
export function merge(localExtensions: ISyncExtensionWithVersion[], remoteExtensions: ISyncExtension[] | null, lastSyncExtensions: ISyncExtension[] | null, skippedExtensions: ISyncExtension[], ignoredExtensions: string[]): IMergeResult {
	const added: ISyncExtension[] = [];
	const removed: IExtensionIdentifier[] = [];
	const updated: ISyncExtensionWithVersion[] = [];

	if (!remoteExtensions) {
		const remote = localExtensions.filter(({ identifier }) => ignoredExtensions.every(id => id.toLowerCase() !== identifier.id.toLowerCase()));
		return {
			local: {
				added,
				removed,
				updated,
			},
			remote: remote.length > 0 ? {
				added: remote,
				updated: [],
				removed: [],
				all: remote
			} : null
		};
	}

	localExtensions = localExtensions.map(massageIncomingExtension);
	remoteExtensions = remoteExtensions.map(massageIncomingExtension);
	lastSyncExtensions = lastSyncExtensions ? lastSyncExtensions.map(massageIncomingExtension) : null;

	const uuids: Map<string, string> = new Map<string, string>();
	const addUUID = (identifier: IExtensionIdentifier) => { if (identifier.uuid) { uuids.set(identifier.id.toLowerCase(), identifier.uuid); } };
	localExtensions.forEach(({ identifier }) => addUUID(identifier));
	remoteExtensions.forEach(({ identifier }) => addUUID(identifier));
	if (lastSyncExtensions) {
		lastSyncExtensions.forEach(({ identifier }) => addUUID(identifier));
	}

	const getKey = (extension: ISyncExtension): string => {
		const uuid = extension.identifier.uuid || uuids.get(extension.identifier.id.toLowerCase());
		return uuid ? `uuid:${uuid}` : `id:${extension.identifier.id.toLowerCase()}`;
	};
	const addExtensionToMap = <T extends ISyncExtension>(map: Map<string, T>, extension: T) => {
		map.set(getKey(extension), extension);
		return map;
	};
	const localExtensionsMap: Map<string, ISyncExtensionWithVersion> = localExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtensionWithVersion>());
	const remoteExtensionsMap = remoteExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
	const newRemoteExtensionsMap = remoteExtensions.reduce((map: Map<string, ISyncExtension>, extension: ISyncExtension) => {
		const key = getKey(extension);
		extension = deepClone(extension);
		const localExtension = localExtensionsMap.get(key);
		if (localExtension) {
			if (localExtension.installed) {
				extension.installed = true;
			}
			if (!extension.version) {
				extension.version = localExtension.version;
			}
		}
		return addExtensionToMap(map, extension);
	}, new Map<string, ISyncExtension>());
	const lastSyncExtensionsMap = lastSyncExtensions ? lastSyncExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>()) : null;
	const skippedExtensionsMap = skippedExtensions.reduce(addExtensionToMap, new Map<string, ISyncExtension>());
	const ignoredExtensionsSet = ignoredExtensions.reduce((set, id) => {
		const uuid = uuids.get(id.toLowerCase());
		return set.add(uuid ? `uuid:${uuid}` : `id:${id.toLowerCase()}`);
	}, new Set<string>());

	const localToRemote = compare(localExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet);
	if (localToRemote.added.size > 0 || localToRemote.removed.size > 0 || localToRemote.updated.size > 0) {

		const baseToLocal = compare(lastSyncExtensionsMap, localExtensionsMap, ignoredExtensionsSet);
		const baseToRemote = compare(lastSyncExtensionsMap, remoteExtensionsMap, ignoredExtensionsSet);

		const merge = (key: string, updatedInRemote: boolean): ISyncExtensionWithVersion | undefined => {
			const localExtension = localExtensionsMap.get(key);
			if (localExtension) {
				const remoteExtension = remoteExtensionsMap.get(key)!;
				return {
					...(updatedInRemote ? remoteExtension : localExtension),
					version: remoteExtension.version && semver.gt(remoteExtension.version, localExtension.version) ? localExtension.version : localExtension.version,
					state: mergeExtensionState(localExtension, remoteExtension, lastSyncExtensionsMap?.get(key))
				};

			}
			return undefined;
		};

		// Remotely removed extension.
		for (const key of baseToRemote.removed.values()) {
			const e = localExtensionsMap.get(key);
			if (e) {
				removed.push(e.identifier);
			}
		}

		// Remotely added extension
		for (const key of baseToRemote.added.values()) {
			// Got added in local
			if (baseToLocal.added.has(key)) {
				// Is different from local to remote
				if (localToRemote.updated.has(key)) {
					const mergedExtension = merge(key, true);
					if (mergedExtension) {
						updated.push(massageOutgoingExtension(mergedExtension, key));
						newRemoteExtensionsMap.set(key, mergedExtension);
					}
				}
			} else {
				// Add only installed extension to local
				const remoteExtension = remoteExtensionsMap.get(key)!;
				if (remoteExtension.installed) {
					added.push(massageOutgoingExtension(remoteExtension, key));
				}
			}
		}

		// Remotely updated extensions
		for (const key of baseToRemote.updated.values()) {
			// Update in local always
			const mergedExtension = merge(key, true);
			if (mergedExtension) {
				updated.push(massageOutgoingExtension(mergedExtension, key));
				newRemoteExtensionsMap.set(key, mergedExtension);
			}
		}

		// Locally added extensions
		for (const key of baseToLocal.added.values()) {
			// Not there in remote
			if (!baseToRemote.added.has(key)) {
				newRemoteExtensionsMap.set(key, localExtensionsMap.get(key)!);
			}
		}

		// Locally updated extensions
		for (const key of baseToLocal.updated.values()) {
			// If removed in remote
			if (baseToRemote.removed.has(key)) {
				continue;
			}

			// If not updated in remote
			if (!baseToRemote.updated.has(key)) {
				const mergedExtension = merge(key, false);
				if (mergedExtension) {
					// Retain installed property
					if (newRemoteExtensionsMap.get(key)?.installed) {
						mergedExtension.installed = true;
					}
					newRemoteExtensionsMap.set(key, mergedExtension);
				}
			}
		}

		// Locally removed extensions
		for (const key of baseToLocal.removed.values()) {
			// If not skipped and not updated in remote
			if (!skippedExtensionsMap.has(key) && !baseToRemote.updated.has(key)) {
				// Remove only if it is an installed extension
				if (lastSyncExtensionsMap?.get(key)?.installed) {
					newRemoteExtensionsMap.delete(key);
				}
			}
		}
	}

	const remote: ISyncExtension[] = [];
	const remoteChanges = compare(remoteExtensionsMap, newRemoteExtensionsMap, new Set<string>(), { checkInstalledProperty: true, checkVersionProperty: true });
	if (remoteChanges.added.size > 0 || remoteChanges.updated.size > 0 || remoteChanges.removed.size > 0) {
		newRemoteExtensionsMap.forEach((value, key) => remote.push(massageOutgoingExtension(value, key)));
	}

	return {
		local: { added, removed, updated },
		remote: remote.length ? {
			added: [...remoteChanges.added].map(id => newRemoteExtensionsMap.get(id)!),
			updated: [...remoteChanges.updated].map(id => newRemoteExtensionsMap.get(id)!),
			removed: [...remoteChanges.removed].map(id => remoteExtensionsMap.get(id)!),
			all: remote
		} : null
	};
}