parse(file, { languageOptions }) {
		// Note: BOM already removed
		const { body: text, path: filePath } = file;
		const textToParse = text.replace(
			astUtils.shebangPattern,
			(match, captured) => `//${captured}`,
		);
		const { ecmaVersion, sourceType, parser } = languageOptions;
		const parserOptions = Object.assign(
			{ ecmaVersion, sourceType },
			languageOptions.parserOptions,
			{
				loc: true,
				range: true,
				raw: true,
				tokens: true,
				comment: true,
				eslintVisitorKeys: true,
				eslintScopeManager: true,
				filePath,
			},
		);

		/*
		 * Check for parsing errors first. If there's a parsing error, nothing
		 * else can happen. However, a parsing error does not throw an error
		 * from this method - it's just considered a fatal error message, a
		 * problem that ESLint identified just like any other.
		 */
		try {
			debug("Parsing:", filePath);
			const parseResult =
				typeof parser.parseForESLint === "function"
					? parser.parseForESLint(textToParse, parserOptions)
					: { ast: parser.parse(textToParse, parserOptions) };

			debug("Parsing successful:", filePath);

			const {
				ast,
				services: parserServices = {},
				visitorKeys = evk.KEYS,
				scopeManager,
			} = parseResult;

			return {
				ok: true,
				ast,
				parserServices,
				visitorKeys,
				scopeManager,
			};
		} catch (ex) {
			// If the message includes a leading line number, strip it:
			const message = ex.message.replace(/^line \d+:/iu, "").trim();

			debug("%s\n%s", message, ex.stack);

			return {
				ok: false,
				errors: [
					{
						message,
						line: ex.lineNumber,
						column: ex.column,
					},
				],
			};
		}
	}
Parses the given file into an AST.
@param {File} file The virtual file to parse.
@param {Object} options Additional options passed from ESLint.
@param {JSLanguageOptions} options.languageOptions The language options.
@returns {Object} The result of parsing.