CaseSensitiveModulesWarning.js 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const WebpackError = require("./WebpackError");
  7. /** @typedef {import("./Module")} Module */
  8. /** @typedef {import("./ModuleGraph")} ModuleGraph */
  9. /**
  10. * Sorts the conflicting modules by identifier to keep warning output stable.
  11. * @param {Module[]} modules the modules to be sorted
  12. * @returns {Module[]} sorted version of original modules
  13. */
  14. const sortModules = (modules) =>
  15. modules.sort((a, b) => {
  16. const aIdent = a.identifier();
  17. const bIdent = b.identifier();
  18. /* istanbul ignore next */
  19. if (aIdent < bIdent) return -1;
  20. /* istanbul ignore next */
  21. if (aIdent > bIdent) return 1;
  22. /* istanbul ignore next */
  23. return 0;
  24. });
  25. /**
  26. * Formats the conflicting modules and one representative incoming reason for
  27. * each module into the warning body.
  28. * @param {Module[]} modules each module from throw
  29. * @param {ModuleGraph} moduleGraph the module graph
  30. * @returns {string} each message from provided modules
  31. */
  32. const createModulesListMessage = (modules, moduleGraph) =>
  33. modules
  34. .map((m) => {
  35. let message = `* ${m.identifier()}`;
  36. const validReasons = [
  37. ...moduleGraph.getIncomingConnectionsByOriginModule(m).keys()
  38. ].filter(Boolean);
  39. if (validReasons.length > 0) {
  40. message += `\n Used by ${validReasons.length} module(s), i. e.`;
  41. message += `\n ${
  42. /** @type {Module[]} */ (validReasons)[0].identifier()
  43. }`;
  44. }
  45. return message;
  46. })
  47. .join("\n");
  48. /**
  49. * Warning emitted when webpack finds modules whose identifiers differ only by
  50. * letter casing, which can behave inconsistently across filesystems.
  51. */
  52. class CaseSensitiveModulesWarning extends WebpackError {
  53. /**
  54. * Builds a warning message that lists the case-conflicting modules and
  55. * representative importers that caused them to be included.
  56. * @param {Iterable<Module>} modules modules that were detected
  57. * @param {ModuleGraph} moduleGraph the module graph
  58. */
  59. constructor(modules, moduleGraph) {
  60. const sortedModules = sortModules([...modules]);
  61. const modulesList = createModulesListMessage(sortedModules, moduleGraph);
  62. super(`There are multiple modules with names that only differ in casing.
  63. This can lead to unexpected behavior when compiling on a filesystem with other case-semantic.
  64. Use equal casing. Compare these module identifiers:
  65. ${modulesList}`);
  66. /** @type {string} */
  67. this.name = "CaseSensitiveModulesWarning";
  68. this.module = sortedModules[0];
  69. }
  70. }
  71. module.exports = CaseSensitiveModulesWarning;