src/vs/workbench/services/search/common/ignoreFile.ts/IgnoreFile/parseIgnoreFile
class IgnoreFile:	private parseIgnoreFile(ignoreContents: string, dirPath: string, parent: IgnoreFile | undefined): (path: string, isDir: boolean) => boolean {
		const contentLines = ignoreContents
			.split('\n')
			.map(line => line.trim())
			.filter(line => line && line[0] !== '#');

		// Pull out all the lines that end with `/`, those only apply to directories
		const fileLines = contentLines.filter(line => !line.endsWith('/'));

		const fileIgnoreLines = fileLines.filter(line => !line.includes('!'));
		const isFileIgnored = this.gitignoreLinesToExpression(fileIgnoreLines, dirPath, true);

		// TODO: Slight hack... this naieve approach may reintroduce too many files in cases of weirdly complex .gitignores
		const fileIncludeLines = fileLines.filter(line => line.includes('!')).map(line => line.replace(/!/g, ''));
		const isFileIncluded = this.gitignoreLinesToExpression(fileIncludeLines, dirPath, false);

		// When checking if a dir is ignored we can use all lines
		const dirIgnoreLines = contentLines.filter(line => !line.includes('!'));
		const isDirIgnored = this.gitignoreLinesToExpression(dirIgnoreLines, dirPath, true);

		// Same hack.
		const dirIncludeLines = contentLines.filter(line => line.includes('!')).map(line => line.replace(/!/g, ''));
		const isDirIncluded = this.gitignoreLinesToExpression(dirIncludeLines, dirPath, false);

		const isPathIgnored = (path: string, isDir: boolean) => {
			if (!path.startsWith(dirPath)) { return false; }
			if (isDir && isDirIgnored(path) && !isDirIncluded(path)) { return true; }
			if (isFileIgnored(path) && !isFileIncluded(path)) { return true; }

			if (parent) { return parent.isPathIgnored(path, isDir); }

			return false;
		};

		return isPathIgnored;
	}