private anonymizeFilePaths()

in src/common/baseTelemetryReporter.ts [182:234]


	private anonymizeFilePaths(stack?: string, anonymizeFilePaths?: boolean): string {
		let result: RegExpExecArray | null | undefined;
		if (stack === undefined || stack === null) {
			return "";
		}

		const cleanupPatterns = [];
		if (vscode.env.appRoot !== "") {
			cleanupPatterns.push(new RegExp(vscode.env.appRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi"));
		}
		if (this.extension) {
			cleanupPatterns.push(new RegExp(this.extension.extensionPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "gi"));
		}

		let updatedStack = stack;

		if (anonymizeFilePaths) {
			const cleanUpIndexes: [number, number][] = [];
			for (const regexp of cleanupPatterns) {
				while ((result = regexp.exec(stack))) {
					if (!result) {
						break;
					}
					cleanUpIndexes.push([result.index, regexp.lastIndex]);
				}
			}

			const nodeModulesRegex = /^[\\/]?(node_modules|node_modules\.asar)[\\/]/;
			const fileRegex = /(file:\/\/)?([a-zA-Z]:(\\\\|\\|\/)|(\\\\|\\|\/))?([\w-._]+(\\\\|\\|\/))+[\w-._]*/g;
			let lastIndex = 0;
			updatedStack = "";

			while ((result = fileRegex.exec(stack))) {
				if (!result) {
					break;
				}
				// Anoynimize user file paths that do not need to be retained or cleaned up.
				if (result[0] && !nodeModulesRegex.test(result[0]) && cleanUpIndexes.every(([x, y]) => result!.index < x || result!.index >= y)) {
					updatedStack += stack.substring(lastIndex, result.index) + "<REDACTED: user-file-path>";
					lastIndex = fileRegex.lastIndex;
				}
			}
			if (lastIndex < stack.length) {
				updatedStack += stack.substr(lastIndex);
			}
		}

		// sanitize with configured cleanup patterns
		for (const regexp of cleanupPatterns) {
			updatedStack = updatedStack.replace(regexp, "");
		}
		return updatedStack;
	}