Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lint-result-cache.js 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /**
  2. * @fileoverview Utility for caching lint results.
  3. * @author Kevin Partington
  4. */
  5. "use strict";
  6. //-----------------------------------------------------------------------------
  7. // Requirements
  8. //-----------------------------------------------------------------------------
  9. const assert = require("assert");
  10. const fs = require("fs");
  11. const fileEntryCache = require("file-entry-cache");
  12. const stringify = require("json-stable-stringify-without-jsonify");
  13. const pkg = require("../../package.json");
  14. const hash = require("./hash");
  15. const debug = require("debug")("eslint:lint-result-cache");
  16. //-----------------------------------------------------------------------------
  17. // Helpers
  18. //-----------------------------------------------------------------------------
  19. const configHashCache = new WeakMap();
  20. const nodeVersion = process && process.version;
  21. const validCacheStrategies = ["metadata", "content"];
  22. const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${validCacheStrategies
  23. .map(strategy => `"${strategy}"`)
  24. .join(", ")}`;
  25. /**
  26. * Tests whether a provided cacheStrategy is valid
  27. * @param {string} cacheStrategy The cache strategy to use
  28. * @returns {boolean} true if `cacheStrategy` is one of `validCacheStrategies`; false otherwise
  29. */
  30. function isValidCacheStrategy(cacheStrategy) {
  31. return (
  32. validCacheStrategies.indexOf(cacheStrategy) !== -1
  33. );
  34. }
  35. /**
  36. * Calculates the hash of the config
  37. * @param {ConfigArray} config The config.
  38. * @returns {string} The hash of the config
  39. */
  40. function hashOfConfigFor(config) {
  41. if (!configHashCache.has(config)) {
  42. configHashCache.set(config, hash(`${pkg.version}_${nodeVersion}_${stringify(config)}`));
  43. }
  44. return configHashCache.get(config);
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Public Interface
  48. //-----------------------------------------------------------------------------
  49. /**
  50. * Lint result cache. This wraps around the file-entry-cache module,
  51. * transparently removing properties that are difficult or expensive to
  52. * serialize and adding them back in on retrieval.
  53. */
  54. class LintResultCache {
  55. /**
  56. * Creates a new LintResultCache instance.
  57. * @param {string} cacheFileLocation The cache file location.
  58. * @param {"metadata" | "content"} cacheStrategy The cache strategy to use.
  59. */
  60. constructor(cacheFileLocation, cacheStrategy) {
  61. assert(cacheFileLocation, "Cache file location is required");
  62. assert(cacheStrategy, "Cache strategy is required");
  63. assert(
  64. isValidCacheStrategy(cacheStrategy),
  65. invalidCacheStrategyErrorMessage
  66. );
  67. debug(`Caching results to ${cacheFileLocation}`);
  68. const useChecksum = cacheStrategy === "content";
  69. debug(
  70. `Using "${cacheStrategy}" strategy to detect changes`
  71. );
  72. this.fileEntryCache = fileEntryCache.create(
  73. cacheFileLocation,
  74. void 0,
  75. useChecksum
  76. );
  77. this.cacheFileLocation = cacheFileLocation;
  78. }
  79. /**
  80. * Retrieve cached lint results for a given file path, if present in the
  81. * cache. If the file is present and has not been changed, rebuild any
  82. * missing result information.
  83. * @param {string} filePath The file for which to retrieve lint results.
  84. * @param {ConfigArray} config The config of the file.
  85. * @returns {Object|null} The rebuilt lint results, or null if the file is
  86. * changed or not in the filesystem.
  87. */
  88. getCachedLintResults(filePath, config) {
  89. /*
  90. * Cached lint results are valid if and only if:
  91. * 1. The file is present in the filesystem
  92. * 2. The file has not changed since the time it was previously linted
  93. * 3. The ESLint configuration has not changed since the time the file
  94. * was previously linted
  95. * If any of these are not true, we will not reuse the lint results.
  96. */
  97. const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
  98. const hashOfConfig = hashOfConfigFor(config);
  99. const changed =
  100. fileDescriptor.changed ||
  101. fileDescriptor.meta.hashOfConfig !== hashOfConfig;
  102. if (fileDescriptor.notFound) {
  103. debug(`File not found on the file system: ${filePath}`);
  104. return null;
  105. }
  106. if (changed) {
  107. debug(`Cache entry not found or no longer valid: ${filePath}`);
  108. return null;
  109. }
  110. // If source is present but null, need to reread the file from the filesystem.
  111. if (
  112. fileDescriptor.meta.results &&
  113. fileDescriptor.meta.results.source === null
  114. ) {
  115. debug(`Rereading cached result source from filesystem: ${filePath}`);
  116. fileDescriptor.meta.results.source = fs.readFileSync(filePath, "utf-8");
  117. }
  118. return fileDescriptor.meta.results;
  119. }
  120. /**
  121. * Set the cached lint results for a given file path, after removing any
  122. * information that will be both unnecessary and difficult to serialize.
  123. * Avoids caching results with an "output" property (meaning fixes were
  124. * applied), to prevent potentially incorrect results if fixes are not
  125. * written to disk.
  126. * @param {string} filePath The file for which to set lint results.
  127. * @param {ConfigArray} config The config of the file.
  128. * @param {Object} result The lint result to be set for the file.
  129. * @returns {void}
  130. */
  131. setCachedLintResults(filePath, config, result) {
  132. if (result && Object.prototype.hasOwnProperty.call(result, "output")) {
  133. return;
  134. }
  135. const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath);
  136. if (fileDescriptor && !fileDescriptor.notFound) {
  137. debug(`Updating cached result: ${filePath}`);
  138. // Serialize the result, except that we want to remove the file source if present.
  139. const resultToSerialize = Object.assign({}, result);
  140. /*
  141. * Set result.source to null.
  142. * In `getCachedLintResults`, if source is explicitly null, we will
  143. * read the file from the filesystem to set the value again.
  144. */
  145. if (Object.prototype.hasOwnProperty.call(resultToSerialize, "source")) {
  146. resultToSerialize.source = null;
  147. }
  148. fileDescriptor.meta.results = resultToSerialize;
  149. fileDescriptor.meta.hashOfConfig = hashOfConfigFor(config);
  150. }
  151. }
  152. /**
  153. * Persists the in-memory cache to disk.
  154. * @returns {void}
  155. */
  156. reconcile() {
  157. debug(`Persisting cached results: ${this.cacheFileLocation}`);
  158. this.fileEntryCache.reconcile();
  159. }
  160. }
  161. module.exports = LintResultCache;