bulk-suppressions-file.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. "use strict";
  2. // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
  3. // See LICENSE in the project root for license information.
  4. var __importDefault = (this && this.__importDefault) || function (mod) {
  5. return (mod && mod.__esModule) ? mod : { "default": mod };
  6. };
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. exports.getSuppressionsConfigForEslintConfigFolderPath = getSuppressionsConfigForEslintConfigFolderPath;
  9. exports.getAllBulkSuppressionsConfigsByEslintConfigFolderPath = getAllBulkSuppressionsConfigsByEslintConfigFolderPath;
  10. exports.writeSuppressionsJsonToFile = writeSuppressionsJsonToFile;
  11. exports.deleteBulkSuppressionsFileInEslintConfigFolder = deleteBulkSuppressionsFileInEslintConfigFolder;
  12. exports.serializeSuppression = serializeSuppression;
  13. const fs_1 = __importDefault(require("fs"));
  14. const constants_1 = require("./constants");
  15. const IS_RUNNING_IN_VSCODE = process.env[constants_1.VSCODE_PID_ENV_VAR_NAME] !== undefined;
  16. const TEN_SECONDS_MS = 10 * 1000;
  17. const SUPPRESSIONS_JSON_FILENAME = '.eslint-bulk-suppressions.json';
  18. function throwIfAnythingOtherThanNotExistError(e) {
  19. if ((e === null || e === void 0 ? void 0 : e.code) !== 'ENOENT') {
  20. // Throw an error if any other error than file not found
  21. throw e;
  22. }
  23. }
  24. const suppressionsJsonByFolderPath = new Map();
  25. function getSuppressionsConfigForEslintConfigFolderPath(eslintConfigFolderPath) {
  26. const cachedSuppressionsConfig = suppressionsJsonByFolderPath.get(eslintConfigFolderPath);
  27. let shouldLoad;
  28. let suppressionsConfig;
  29. if (cachedSuppressionsConfig) {
  30. shouldLoad = IS_RUNNING_IN_VSCODE && cachedSuppressionsConfig.readTime < Date.now() - TEN_SECONDS_MS;
  31. suppressionsConfig = cachedSuppressionsConfig.suppressionsConfig;
  32. }
  33. else {
  34. shouldLoad = true;
  35. }
  36. if (shouldLoad) {
  37. const suppressionsPath = `${eslintConfigFolderPath}/${SUPPRESSIONS_JSON_FILENAME}`;
  38. let rawJsonFile;
  39. try {
  40. rawJsonFile = fs_1.default.readFileSync(suppressionsPath).toString();
  41. }
  42. catch (e) {
  43. throwIfAnythingOtherThanNotExistError(e);
  44. }
  45. if (!rawJsonFile) {
  46. suppressionsConfig = {
  47. serializedSuppressions: new Set(),
  48. jsonObject: { suppressions: [] },
  49. newSerializedSuppressions: new Set(),
  50. newJsonObject: { suppressions: [] }
  51. };
  52. }
  53. else {
  54. const jsonObject = JSON.parse(rawJsonFile);
  55. validateSuppressionsJson(jsonObject);
  56. const serializedSuppressions = new Set();
  57. for (const suppression of jsonObject.suppressions) {
  58. serializedSuppressions.add(serializeSuppression(suppression));
  59. }
  60. suppressionsConfig = {
  61. serializedSuppressions,
  62. jsonObject,
  63. newSerializedSuppressions: new Set(),
  64. newJsonObject: { suppressions: [] }
  65. };
  66. }
  67. suppressionsJsonByFolderPath.set(eslintConfigFolderPath, { readTime: Date.now(), suppressionsConfig });
  68. }
  69. return suppressionsConfig;
  70. }
  71. function getAllBulkSuppressionsConfigsByEslintConfigFolderPath() {
  72. const result = [];
  73. for (const [eslintConfigFolderPath, { suppressionsConfig }] of suppressionsJsonByFolderPath) {
  74. result.push([eslintConfigFolderPath, suppressionsConfig]);
  75. }
  76. return result;
  77. }
  78. function writeSuppressionsJsonToFile(eslintConfigFolderPath, suppressionsConfig) {
  79. suppressionsJsonByFolderPath.set(eslintConfigFolderPath, { readTime: Date.now(), suppressionsConfig });
  80. const suppressionsPath = `${eslintConfigFolderPath}/${SUPPRESSIONS_JSON_FILENAME}`;
  81. if (suppressionsConfig.jsonObject.suppressions.length === 0) {
  82. deleteFile(suppressionsPath);
  83. }
  84. else {
  85. suppressionsConfig.jsonObject.suppressions.sort(compareSuppressions);
  86. fs_1.default.writeFileSync(suppressionsPath, JSON.stringify(suppressionsConfig.jsonObject, undefined, 2));
  87. }
  88. }
  89. function deleteBulkSuppressionsFileInEslintConfigFolder(eslintConfigFolderPath) {
  90. const suppressionsPath = `${eslintConfigFolderPath}/${SUPPRESSIONS_JSON_FILENAME}`;
  91. deleteFile(suppressionsPath);
  92. }
  93. function deleteFile(filePath) {
  94. try {
  95. fs_1.default.unlinkSync(filePath);
  96. }
  97. catch (e) {
  98. throwIfAnythingOtherThanNotExistError(e);
  99. }
  100. }
  101. function serializeSuppression({ file, scopeId, rule }) {
  102. return `${file}|${scopeId}|${rule}`;
  103. }
  104. function compareSuppressions(a, b) {
  105. if (a.file < b.file) {
  106. return -1;
  107. }
  108. else if (a.file > b.file) {
  109. return 1;
  110. }
  111. else if (a.scopeId < b.scopeId) {
  112. return -1;
  113. }
  114. else if (a.scopeId > b.scopeId) {
  115. return 1;
  116. }
  117. else if (a.rule < b.rule) {
  118. return -1;
  119. }
  120. else if (a.rule > b.rule) {
  121. return 1;
  122. }
  123. else {
  124. return 0;
  125. }
  126. }
  127. function validateSuppressionsJson(json) {
  128. if (typeof json !== 'object') {
  129. throw new Error(`Invalid JSON object: ${JSON.stringify(json, null, 2)}`);
  130. }
  131. if (!json) {
  132. throw new Error('JSON object is null.');
  133. }
  134. const EXPECTED_ROOT_PROPERTY_NAMES = new Set(['suppressions']);
  135. for (const propertyName of Object.getOwnPropertyNames(json)) {
  136. if (!EXPECTED_ROOT_PROPERTY_NAMES.has(propertyName)) {
  137. throw new Error(`Unexpected property name: ${propertyName}`);
  138. }
  139. }
  140. const { suppressions } = json;
  141. if (!suppressions) {
  142. throw new Error('Missing "suppressions" property.');
  143. }
  144. if (!Array.isArray(suppressions)) {
  145. throw new Error('"suppressions" property is not an array.');
  146. }
  147. const EXPECTED_SUPPRESSION_PROPERTY_NAMES = new Set(['file', 'scopeId', 'rule']);
  148. for (const suppression of suppressions) {
  149. if (typeof suppression !== 'object') {
  150. throw new Error(`Invalid suppression: ${JSON.stringify(suppression, null, 2)}`);
  151. }
  152. if (!suppression) {
  153. throw new Error(`Suppression is null: ${JSON.stringify(suppression, null, 2)}`);
  154. }
  155. for (const propertyName of Object.getOwnPropertyNames(suppression)) {
  156. if (!EXPECTED_SUPPRESSION_PROPERTY_NAMES.has(propertyName)) {
  157. throw new Error(`Unexpected property name: ${propertyName}`);
  158. }
  159. }
  160. for (const propertyName of EXPECTED_SUPPRESSION_PROPERTY_NAMES) {
  161. if (!suppression.hasOwnProperty(propertyName)) {
  162. throw new Error(`Missing "${propertyName}" property in suppression: ${JSON.stringify(suppression, null, 2)}`);
  163. }
  164. else if (typeof suppression[propertyName] !== 'string') {
  165. throw new Error(`"${propertyName}" property in suppression is not a string: ${JSON.stringify(suppression, null, 2)}`);
  166. }
  167. }
  168. }
  169. return true;
  170. }
  171. //# sourceMappingURL=bulk-suppressions-file.js.map