utils.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.useCaseSensitiveFileNames = exports.isReferencedFile = exports.supportsSolutionBuild = exports.ensureProgram = exports.arrify = exports.collectAllDependants = exports.populateReverseDependencyGraph = exports.populateDependencyGraph = exports.unorderedRemoveItem = exports.appendSuffixesIfMatch = exports.appendSuffixIfMatch = exports.tsLoaderSource = exports.makeError = exports.fsReadFile = exports.formatErrors = void 0;
  4. const fs = require("fs");
  5. const micromatch = require("micromatch");
  6. const path = require("path");
  7. const webpack = require("webpack");
  8. const constants = require("./constants");
  9. const instances_1 = require("./instances");
  10. /**
  11. * The default error formatter.
  12. */
  13. function defaultErrorFormatter(error, colors) {
  14. const messageColor = error.severity === 'warning' ? colors.bold.yellow : colors.bold.red;
  15. return (colors.grey('[tsl] ') +
  16. messageColor(error.severity.toUpperCase()) +
  17. (error.file === ''
  18. ? ''
  19. : messageColor(' in ') +
  20. colors.bold.cyan(`${error.file}(${error.line},${error.character})`)) +
  21. constants.EOL +
  22. messageColor(` TS${error.code}: ${error.content}`));
  23. }
  24. /**
  25. * Take TypeScript errors, parse them and format to webpack errors
  26. * Optionally adds a file name
  27. */
  28. function formatErrors(diagnostics, loaderOptions, colors, compiler, merge, context) {
  29. return diagnostics === undefined
  30. ? []
  31. : diagnostics
  32. .filter(diagnostic => {
  33. if (loaderOptions.ignoreDiagnostics.indexOf(diagnostic.code) !== -1) {
  34. return false;
  35. }
  36. if (loaderOptions.reportFiles.length > 0 &&
  37. diagnostic.file !== undefined) {
  38. const relativeFileName = path.relative(context, diagnostic.file.fileName);
  39. const matchResult = micromatch([relativeFileName], loaderOptions.reportFiles);
  40. if (matchResult.length === 0) {
  41. return false;
  42. }
  43. }
  44. return true;
  45. })
  46. .map(diagnostic => {
  47. const file = diagnostic.file;
  48. const { start, end } = file === undefined || diagnostic.start === undefined
  49. ? { start: undefined, end: undefined }
  50. : getFileLocations(file, diagnostic.start, diagnostic.length);
  51. const errorInfo = {
  52. code: diagnostic.code,
  53. severity: compiler.DiagnosticCategory[diagnostic.category].toLowerCase(),
  54. content: compiler.flattenDiagnosticMessageText(diagnostic.messageText, constants.EOL),
  55. file: file === undefined ? '' : path.normalize(file.fileName),
  56. line: start === undefined ? 0 : start.line,
  57. character: start === undefined ? 0 : start.character,
  58. context,
  59. };
  60. const message = loaderOptions.errorFormatter === undefined
  61. ? defaultErrorFormatter(errorInfo, colors)
  62. : loaderOptions.errorFormatter(errorInfo, colors);
  63. const error = makeError(loaderOptions, message, merge.file === undefined ? errorInfo.file : merge.file, start, end);
  64. return Object.assign(error, merge);
  65. });
  66. }
  67. exports.formatErrors = formatErrors;
  68. function getFileLocations(file, position, length = 0) {
  69. const startLC = file.getLineAndCharacterOfPosition(position);
  70. const start = {
  71. line: startLC.line + 1,
  72. character: startLC.character + 1,
  73. };
  74. const endLC = length > 0
  75. ? file.getLineAndCharacterOfPosition(position + length)
  76. : undefined;
  77. const end = endLC === undefined
  78. ? undefined
  79. : { line: endLC.line + 1, character: endLC.character + 1 };
  80. return { start, end };
  81. }
  82. function fsReadFile(fileName, encoding = 'utf8') {
  83. fileName = path.normalize(fileName);
  84. try {
  85. return fs.readFileSync(fileName, encoding);
  86. }
  87. catch (e) {
  88. return undefined;
  89. }
  90. }
  91. exports.fsReadFile = fsReadFile;
  92. function makeError(loaderOptions, message, file, location, endLocation) {
  93. const error = new webpack.WebpackError(message);
  94. error.file = file;
  95. error.loc =
  96. location === undefined
  97. ? { name: file }
  98. : makeWebpackLocation(location, endLocation);
  99. error.details = tsLoaderSource(loaderOptions);
  100. return error;
  101. // return {
  102. // message,
  103. // file,
  104. // loc:
  105. // location === undefined
  106. // ? { name: file }
  107. // : makeWebpackLocation(location, endLocation),
  108. // details: tsLoaderSource(loaderOptions),
  109. // };
  110. }
  111. exports.makeError = makeError;
  112. function makeWebpackLocation(location, endLocation) {
  113. const start = {
  114. line: location.line,
  115. column: location.character - 1,
  116. };
  117. const end = endLocation === undefined
  118. ? undefined
  119. : { line: endLocation.line, column: endLocation.character - 1 };
  120. return { start, end };
  121. }
  122. function tsLoaderSource(loaderOptions) {
  123. return `ts-loader-${loaderOptions.instance}`;
  124. }
  125. exports.tsLoaderSource = tsLoaderSource;
  126. function appendSuffixIfMatch(patterns, filePath, suffix) {
  127. if (patterns.length > 0) {
  128. for (const regexp of patterns) {
  129. if (filePath.match(regexp) !== null) {
  130. return filePath + suffix;
  131. }
  132. }
  133. }
  134. return filePath;
  135. }
  136. exports.appendSuffixIfMatch = appendSuffixIfMatch;
  137. function appendSuffixesIfMatch(suffixDict, filePath) {
  138. let amendedPath = filePath;
  139. for (const suffix in suffixDict) {
  140. amendedPath = appendSuffixIfMatch(suffixDict[suffix], amendedPath, suffix);
  141. }
  142. return amendedPath;
  143. }
  144. exports.appendSuffixesIfMatch = appendSuffixesIfMatch;
  145. function unorderedRemoveItem(array, item) {
  146. for (let i = 0; i < array.length; i++) {
  147. if (array[i] === item) {
  148. // Fill in the "hole" left at `index`.
  149. array[i] = array[array.length - 1];
  150. array.pop();
  151. return true;
  152. }
  153. }
  154. return false;
  155. }
  156. exports.unorderedRemoveItem = unorderedRemoveItem;
  157. function populateDependencyGraph(resolvedModules, instance, containingFile) {
  158. resolvedModules = resolvedModules.filter(mod => mod !== null && mod !== undefined);
  159. if (resolvedModules.length) {
  160. const containingFileKey = instance.filePathKeyMapper(containingFile);
  161. instance.dependencyGraph.set(containingFileKey, resolvedModules);
  162. }
  163. }
  164. exports.populateDependencyGraph = populateDependencyGraph;
  165. function populateReverseDependencyGraph(instance) {
  166. const reverseDependencyGraph = new Map();
  167. for (const [fileKey, resolvedModules] of instance.dependencyGraph.entries()) {
  168. const inputFileName = instance.solutionBuilderHost &&
  169. (0, instances_1.getInputFileNameFromOutput)(instance, fileKey);
  170. const containingFileKey = inputFileName
  171. ? instance.filePathKeyMapper(inputFileName)
  172. : fileKey;
  173. resolvedModules.forEach(({ resolvedFileName }) => {
  174. const key = instance.filePathKeyMapper(instance.solutionBuilderHost
  175. ? (0, instances_1.getInputFileNameFromOutput)(instance, resolvedFileName) ||
  176. resolvedFileName
  177. : resolvedFileName);
  178. let map = reverseDependencyGraph.get(key);
  179. if (!map) {
  180. map = new Map();
  181. reverseDependencyGraph.set(key, map);
  182. }
  183. map.set(containingFileKey, true);
  184. });
  185. }
  186. return reverseDependencyGraph;
  187. }
  188. exports.populateReverseDependencyGraph = populateReverseDependencyGraph;
  189. /**
  190. * Recursively collect all possible dependants of passed file
  191. */
  192. function collectAllDependants(reverseDependencyGraph, fileName, result = new Map()) {
  193. result.set(fileName, true);
  194. const dependants = reverseDependencyGraph.get(fileName);
  195. if (dependants !== undefined) {
  196. for (const dependantFileName of dependants.keys()) {
  197. if (!result.has(dependantFileName)) {
  198. collectAllDependants(reverseDependencyGraph, dependantFileName, result);
  199. }
  200. }
  201. }
  202. return result;
  203. }
  204. exports.collectAllDependants = collectAllDependants;
  205. function arrify(val) {
  206. if (val === null || val === undefined) {
  207. return [];
  208. }
  209. return Array.isArray(val) ? val : [val];
  210. }
  211. exports.arrify = arrify;
  212. function ensureProgram(instance) {
  213. if (instance && instance.watchHost) {
  214. if (instance.hasUnaccountedModifiedFiles) {
  215. if (instance.changedFilesList) {
  216. instance.watchHost.updateRootFileNames();
  217. }
  218. if (instance.watchOfFilesAndCompilerOptions) {
  219. instance.builderProgram = instance.watchOfFilesAndCompilerOptions.getProgram();
  220. instance.program = instance.builderProgram.getProgram();
  221. }
  222. instance.hasUnaccountedModifiedFiles = false;
  223. }
  224. return instance.program;
  225. }
  226. if (instance.languageService) {
  227. return instance.languageService.getProgram();
  228. }
  229. return instance.program;
  230. }
  231. exports.ensureProgram = ensureProgram;
  232. function supportsSolutionBuild(instance) {
  233. return (!!instance.configFilePath &&
  234. !!instance.loaderOptions.projectReferences &&
  235. !!instance.configParseResult.projectReferences &&
  236. !!instance.configParseResult.projectReferences.length);
  237. }
  238. exports.supportsSolutionBuild = supportsSolutionBuild;
  239. function isReferencedFile(instance, filePath) {
  240. return (!!instance.solutionBuilderHost &&
  241. !!instance.solutionBuilderHost.watchedFiles.get(instance.filePathKeyMapper(filePath)));
  242. }
  243. exports.isReferencedFile = isReferencedFile;
  244. function useCaseSensitiveFileNames(compiler, loaderOptions) {
  245. return loaderOptions.useCaseSensitiveFileNames !== undefined
  246. ? loaderOptions.useCaseSensitiveFileNames
  247. : compiler.sys.useCaseSensitiveFileNames;
  248. }
  249. exports.useCaseSensitiveFileNames = useCaseSensitiveFileNames;
  250. //# sourceMappingURL=utils.js.map