--- /dev/null
+/**
+ * @fileoverview Tools for obtaining SourceCode objects.
+ * @author Ian VanSchooten
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const { CLIEngine } = require("../cli-engine");
+
+/*
+ * This is used for:
+ *
+ * 1. Enumerate target file because we have not expose such a API on `CLIEngine`
+ * (https://github.com/eslint/eslint/issues/11222).
+ * 2. Create `SourceCode` instances. Because we don't have any function which
+ * instantiate `SourceCode` so it needs to take the created `SourceCode`
+ * instance out after linting.
+ *
+ * TODO1: Expose the API that enumerates target files.
+ * TODO2: Extract the creation logic of `SourceCode` from `Linter` class.
+ */
+const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line no-restricted-modules
+
+const debug = require("debug")("eslint:source-code-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Get the SourceCode object for a single file
+ * @param {string} filename The fully resolved filename to get SourceCode from.
+ * @param {Object} engine A CLIEngine.
+ * @returns {Array} Array of the SourceCode object representing the file
+ * and fatal error message.
+ */
+function getSourceCodeOfFile(filename, engine) {
+ debug("getting sourceCode of", filename);
+ const results = engine.executeOnFiles([filename]);
+
+ if (results && results.results[0] && results.results[0].messages[0] && results.results[0].messages[0].fatal) {
+ const msg = results.results[0].messages[0];
+
+ throw new Error(`(${filename}:${msg.line}:${msg.column}) ${msg.message}`);
+ }
+
+ // TODO: extract the logic that creates source code objects to `SourceCode#parse(text, options)` or something like.
+ const { linter } = getCLIEngineInternalSlots(engine);
+ const sourceCode = linter.getSourceCode();
+
+ return sourceCode;
+}
+
+//------------------------------------------------------------------------------
+// Public Interface
+//------------------------------------------------------------------------------
+
+
+/**
+ * This callback is used to measure execution status in a progress bar
+ * @callback progressCallback
+ * @param {number} The total number of times the callback will be called.
+ */
+
+/**
+ * Gets the SourceCode of a single file, or set of files.
+ * @param {string[]|string} patterns A filename, directory name, or glob, or an array of them
+ * @param {Object} options A CLIEngine options object. If not provided, the default cli options will be used.
+ * @param {progressCallback} callback Callback for reporting execution status
+ * @returns {Object} The SourceCode of all processed files.
+ */
+function getSourceCodeOfFiles(patterns, options, callback) {
+ const sourceCodes = {};
+ const globPatternsList = typeof patterns === "string" ? [patterns] : patterns;
+ const engine = new CLIEngine({ ...options, rules: {} });
+
+ // TODO: make file iteration as a public API and use it.
+ const { fileEnumerator } = getCLIEngineInternalSlots(engine);
+ const filenames =
+ Array.from(fileEnumerator.iterateFiles(globPatternsList))
+ .filter(entry => !entry.ignored)
+ .map(entry => entry.filePath);
+
+ if (filenames.length === 0) {
+ debug(`Did not find any files matching pattern(s): ${globPatternsList}`);
+ }
+
+ filenames.forEach(filename => {
+ const sourceCode = getSourceCodeOfFile(filename, engine);
+
+ if (sourceCode) {
+ debug("got sourceCode of", filename);
+ sourceCodes[filename] = sourceCode;
+ }
+ if (callback) {
+ callback(filenames.length); // eslint-disable-line callback-return
+ }
+ });
+
+ return sourceCodes;
+}
+
+module.exports = {
+ getSourceCodeOfFiles
+};