source-code-utils.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /**
  2. * @fileoverview Tools for obtaining SourceCode objects.
  3. * @author Ian VanSchooten
  4. */
  5. "use strict";
  6. //------------------------------------------------------------------------------
  7. // Requirements
  8. //------------------------------------------------------------------------------
  9. const { CLIEngine } = require("../cli-engine");
  10. /*
  11. * This is used for:
  12. *
  13. * 1. Enumerate target file because we have not expose such a API on `CLIEngine`
  14. * (https://github.com/eslint/eslint/issues/11222).
  15. * 2. Create `SourceCode` instances. Because we don't have any function which
  16. * instantiate `SourceCode` so it needs to take the created `SourceCode`
  17. * instance out after linting.
  18. *
  19. * TODO1: Expose the API that enumerates target files.
  20. * TODO2: Extract the creation logic of `SourceCode` from `Linter` class.
  21. */
  22. const { getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); // eslint-disable-line node/no-restricted-require
  23. const debug = require("debug")("eslint:source-code-utils");
  24. //------------------------------------------------------------------------------
  25. // Helpers
  26. //------------------------------------------------------------------------------
  27. /**
  28. * Get the SourceCode object for a single file
  29. * @param {string} filename The fully resolved filename to get SourceCode from.
  30. * @param {Object} engine A CLIEngine.
  31. * @returns {Array} Array of the SourceCode object representing the file
  32. * and fatal error message.
  33. */
  34. function getSourceCodeOfFile(filename, engine) {
  35. debug("getting sourceCode of", filename);
  36. const results = engine.executeOnFiles([filename]);
  37. if (results && results.results[0] && results.results[0].messages[0] && results.results[0].messages[0].fatal) {
  38. const msg = results.results[0].messages[0];
  39. throw new Error(`(${filename}:${msg.line}:${msg.column}) ${msg.message}`);
  40. }
  41. // TODO: extract the logic that creates source code objects to `SourceCode#parse(text, options)` or something like.
  42. const { linter } = getCLIEngineInternalSlots(engine);
  43. const sourceCode = linter.getSourceCode();
  44. return sourceCode;
  45. }
  46. //------------------------------------------------------------------------------
  47. // Public Interface
  48. //------------------------------------------------------------------------------
  49. /**
  50. * This callback is used to measure execution status in a progress bar
  51. * @callback progressCallback
  52. * @param {number} The total number of times the callback will be called.
  53. */
  54. /**
  55. * Gets the SourceCode of a single file, or set of files.
  56. * @param {string[]|string} patterns A filename, directory name, or glob, or an array of them
  57. * @param {Object} options A CLIEngine options object. If not provided, the default cli options will be used.
  58. * @param {progressCallback} callback Callback for reporting execution status
  59. * @returns {Object} The SourceCode of all processed files.
  60. */
  61. function getSourceCodeOfFiles(patterns, options, callback) {
  62. const sourceCodes = {};
  63. const globPatternsList = typeof patterns === "string" ? [patterns] : patterns;
  64. const engine = new CLIEngine({ ...options, rules: {} });
  65. // TODO: make file iteration as a public API and use it.
  66. const { fileEnumerator } = getCLIEngineInternalSlots(engine);
  67. const filenames =
  68. Array.from(fileEnumerator.iterateFiles(globPatternsList))
  69. .filter(entry => !entry.ignored)
  70. .map(entry => entry.filePath);
  71. if (filenames.length === 0) {
  72. debug(`Did not find any files matching pattern(s): ${globPatternsList}`);
  73. }
  74. filenames.forEach(filename => {
  75. const sourceCode = getSourceCodeOfFile(filename, engine);
  76. if (sourceCode) {
  77. debug("got sourceCode of", filename);
  78. sourceCodes[filename] = sourceCode;
  79. }
  80. if (callback) {
  81. callback(filenames.length); // eslint-disable-line node/callback-return
  82. }
  83. });
  84. return sourceCodes;
  85. }
  86. module.exports = {
  87. getSourceCodeOfFiles
  88. };