web 3d图形渲染器
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.

287 lines
37 KiB

  1. 'use strict';var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _resolve = require('eslint-module-utils/resolve');var _resolve2 = _interopRequireDefault(_resolve);
  2. var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];return arr2;} else {return Array.from(arr);}}function _toArray(arr) {return Array.isArray(arr) ? arr : Array.from(arr);}
  3. function checkImports(imported, context) {
  4. for (const _ref of imported.entries()) {var _ref2 = _slicedToArray(_ref, 2);const module = _ref2[0];const nodes = _ref2[1];
  5. if (nodes.length > 1) {
  6. const message = `'${module}' imported multiple times.`;var _nodes = _toArray(
  7. nodes);const first = _nodes[0],rest = _nodes.slice(1);
  8. const sourceCode = context.getSourceCode();
  9. const fix = getFix(first, rest, sourceCode);
  10. context.report({
  11. node: first.source,
  12. message,
  13. fix // Attach the autofix (if any) to the first import.
  14. });
  15. for (const node of rest) {
  16. context.report({
  17. node: node.source,
  18. message });
  19. }
  20. }
  21. }
  22. }
  23. function getFix(first, rest, sourceCode) {
  24. // Sorry ESLint <= 3 users, no autofix for you. Autofixing duplicate imports
  25. // requires multiple `fixer.whatever()` calls in the `fix`: We both need to
  26. // update the first one, and remove the rest. Support for multiple
  27. // `fixer.whatever()` in a single `fix` was added in ESLint 4.1.
  28. // `sourceCode.getCommentsBefore` was added in 4.0, so that's an easy thing to
  29. // check for.
  30. if (typeof sourceCode.getCommentsBefore !== 'function') {
  31. return undefined;
  32. }
  33. // Adjusting the first import might make it multiline, which could break
  34. // `eslint-disable-next-line` comments and similar, so bail if the first
  35. // import has comments. Also, if the first import is `import * as ns from
  36. // './foo'` there's nothing we can do.
  37. if (hasProblematicComments(first, sourceCode) || hasNamespace(first)) {
  38. return undefined;
  39. }
  40. const defaultImportNames = new Set(
  41. [first].concat(_toConsumableArray(rest)).map(getDefaultImportName).filter(Boolean));
  42. // Bail if there are multiple different default import names – it's up to the
  43. // user to choose which one to keep.
  44. if (defaultImportNames.size > 1) {
  45. return undefined;
  46. }
  47. // Leave it to the user to handle comments. Also skip `import * as ns from
  48. // './foo'` imports, since they cannot be merged into another import.
  49. const restWithoutComments = rest.filter(node => !(
  50. hasProblematicComments(node, sourceCode) ||
  51. hasNamespace(node)));
  52. const specifiers = restWithoutComments.
  53. map(node => {
  54. const tokens = sourceCode.getTokens(node);
  55. const openBrace = tokens.find(token => isPunctuator(token, '{'));
  56. const closeBrace = tokens.find(token => isPunctuator(token, '}'));
  57. if (openBrace == null || closeBrace == null) {
  58. return undefined;
  59. }
  60. return {
  61. importNode: node,
  62. text: sourceCode.text.slice(openBrace.range[1], closeBrace.range[0]),
  63. hasTrailingComma: isPunctuator(sourceCode.getTokenBefore(closeBrace), ','),
  64. isEmpty: !hasSpecifiers(node) };
  65. }).
  66. filter(Boolean);
  67. const unnecessaryImports = restWithoutComments.filter(node =>
  68. !hasSpecifiers(node) &&
  69. !hasNamespace(node) &&
  70. !specifiers.some(specifier => specifier.importNode === node));
  71. const shouldAddDefault = getDefaultImportName(first) == null && defaultImportNames.size === 1;
  72. const shouldAddSpecifiers = specifiers.length > 0;
  73. const shouldRemoveUnnecessary = unnecessaryImports.length > 0;
  74. if (!(shouldAddDefault || shouldAddSpecifiers || shouldRemoveUnnecessary)) {
  75. return undefined;
  76. }
  77. return fixer => {
  78. const tokens = sourceCode.getTokens(first);
  79. const openBrace = tokens.find(token => isPunctuator(token, '{'));
  80. const closeBrace = tokens.find(token => isPunctuator(token, '}'));
  81. const firstToken = sourceCode.getFirstToken(first);var _defaultImportNames = _slicedToArray(
  82. defaultImportNames, 1);const defaultImportName = _defaultImportNames[0];
  83. const firstHasTrailingComma =
  84. closeBrace != null &&
  85. isPunctuator(sourceCode.getTokenBefore(closeBrace), ',');
  86. const firstIsEmpty = !hasSpecifiers(first);var _specifiers$reduce =
  87. specifiers.reduce(
  88. (_ref3, specifier) => {var _ref4 = _slicedToArray(_ref3, 2);let result = _ref4[0],needsComma = _ref4[1];
  89. return [
  90. needsComma && !specifier.isEmpty ?
  91. `${result},${specifier.text}` :
  92. `${result}${specifier.text}`,
  93. specifier.isEmpty ? needsComma : true];
  94. },
  95. ['', !firstHasTrailingComma && !firstIsEmpty]),_specifiers$reduce2 = _slicedToArray(_specifiers$reduce, 1);const specifiersText = _specifiers$reduce2[0];
  96. const fixes = [];
  97. if (shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
  98. // `import './foo'` → `import def, {...} from './foo'`
  99. fixes.push(
  100. fixer.insertTextAfter(firstToken, ` ${defaultImportName}, {${specifiersText}} from`));
  101. } else if (shouldAddDefault && openBrace == null && !shouldAddSpecifiers) {
  102. // `import './foo'` → `import def from './foo'`
  103. fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName} from`));
  104. } else if (shouldAddDefault && openBrace != null && closeBrace != null) {
  105. // `import {...} from './foo'` → `import def, {...} from './foo'`
  106. fixes.push(fixer.insertTextAfter(firstToken, ` ${defaultImportName},`));
  107. if (shouldAddSpecifiers) {
  108. // `import def, {...} from './foo'` → `import def, {..., ...} from './foo'`
  109. fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
  110. }
  111. } else if (!shouldAddDefault && openBrace == null && shouldAddSpecifiers) {
  112. if (first.specifiers.length === 0) {
  113. // `import './foo'` → `import {...} from './foo'`
  114. fixes.push(fixer.insertTextAfter(firstToken, ` {${specifiersText}} from`));
  115. } else {
  116. // `import def from './foo'` → `import def, {...} from './foo'`
  117. fixes.push(fixer.insertTextAfter(first.specifiers[0], `, {${specifiersText}}`));
  118. }
  119. } else if (!shouldAddDefault && openBrace != null && closeBrace != null) {
  120. // `import {...} './foo'` → `import {..., ...} from './foo'`
  121. fixes.push(fixer.insertTextBefore(closeBrace, specifiersText));
  122. }
  123. // Remove imports whose specifiers have been moved into the first import.
  124. for (const specifier of specifiers) {
  125. fixes.push(fixer.remove(specifier.importNode));
  126. }
  127. // Remove imports whose default import has been moved to the first import,
  128. // and side-effect-only imports that are unnecessary due to the first
  129. // import.
  130. for (const node of unnecessaryImports) {
  131. fixes.push(fixer.remove(node));
  132. }
  133. return fixes;
  134. };
  135. }
  136. function isPunctuator(node, value) {
  137. return node.type === 'Punctuator' && node.value === value;
  138. }
  139. // Get the name of the default import of `node`, if any.
  140. function getDefaultImportName(node) {
  141. const defaultSpecifier = node.specifiers.
  142. find(specifier => specifier.type === 'ImportDefaultSpecifier');
  143. return defaultSpecifier != null ? defaultSpecifier.local.name : undefined;
  144. }
  145. // Checks whether `node` has a namespace import.
  146. function hasNamespace(node) {
  147. const specifiers = node.specifiers.
  148. filter(specifier => specifier.type === 'ImportNamespaceSpecifier');
  149. return specifiers.length > 0;
  150. }
  151. // Checks whether `node` has any non-default specifiers.
  152. function hasSpecifiers(node) {
  153. const specifiers = node.specifiers.
  154. filter(specifier => specifier.type === 'ImportSpecifier');
  155. return specifiers.length > 0;
  156. }
  157. // It's not obvious what the user wants to do with comments associated with
  158. // duplicate imports, so skip imports with comments when autofixing.
  159. function hasProblematicComments(node, sourceCode) {
  160. return (
  161. hasCommentBefore(node, sourceCode) ||
  162. hasCommentAfter(node, sourceCode) ||
  163. hasCommentInsideNonSpecifiers(node, sourceCode));
  164. }
  165. // Checks whether `node` has a comment (that ends) on the previous line or on
  166. // the same line as `node` (starts).
  167. function hasCommentBefore(node, sourceCode) {
  168. return sourceCode.getCommentsBefore(node).
  169. some(comment => comment.loc.end.line >= node.loc.start.line - 1);
  170. }
  171. // Checks whether `node` has a comment (that starts) on the same line as `node`
  172. // (ends).
  173. function hasCommentAfter(node, sourceCode) {
  174. return sourceCode.getCommentsAfter(node).
  175. some(comment => comment.loc.start.line === node.loc.end.line);
  176. }
  177. // Checks whether `node` has any comments _inside,_ except inside the `{...}`
  178. // part (if any).
  179. function hasCommentInsideNonSpecifiers(node, sourceCode) {
  180. const tokens = sourceCode.getTokens(node);
  181. const openBraceIndex = tokens.findIndex(token => isPunctuator(token, '{'));
  182. const closeBraceIndex = tokens.findIndex(token => isPunctuator(token, '}'));
  183. // Slice away the first token, since we're no looking for comments _before_
  184. // `node` (only inside). If there's a `{...}` part, look for comments before
  185. // the `{`, but not before the `}` (hence the `+1`s).
  186. const someTokens = openBraceIndex >= 0 && closeBraceIndex >= 0 ?
  187. tokens.slice(1, openBraceIndex + 1).concat(tokens.slice(closeBraceIndex + 1)) :
  188. tokens.slice(1);
  189. return someTokens.some(token => sourceCode.getCommentsBefore(token).length > 0);
  190. }
  191. module.exports = {
  192. meta: {
  193. type: 'problem',
  194. docs: {
  195. url: (0, _docsUrl2.default)('no-duplicates') },
  196. fixable: 'code',
  197. schema: [
  198. {
  199. type: 'object',
  200. properties: {
  201. considerQueryString: {
  202. type: 'boolean' } },
  203. additionalProperties: false }] },
  204. create: function (context) {
  205. // Prepare the resolver from options.
  206. const considerQueryStringOption = context.options[0] &&
  207. context.options[0]['considerQueryString'];
  208. const defaultResolver = sourcePath => (0, _resolve2.default)(sourcePath, context) || sourcePath;
  209. const resolver = considerQueryStringOption ? sourcePath => {
  210. const parts = sourcePath.match(/^([^?]*)\?(.*)$/);
  211. if (!parts) {
  212. return defaultResolver(sourcePath);
  213. }
  214. return defaultResolver(parts[1]) + '?' + parts[2];
  215. } : defaultResolver;
  216. const imported = new Map();
  217. const nsImported = new Map();
  218. const typesImported = new Map();
  219. return {
  220. 'ImportDeclaration': function (n) {
  221. // resolved path will cover aliased duplicates
  222. const resolvedPath = resolver(n.source.value);
  223. const importMap = n.importKind === 'type' ? typesImported :
  224. hasNamespace(n) ? nsImported : imported;
  225. if (importMap.has(resolvedPath)) {
  226. importMap.get(resolvedPath).push(n);
  227. } else {
  228. importMap.set(resolvedPath, [n]);
  229. }
  230. },
  231. 'Program:exit': function () {
  232. checkImports(imported, context);
  233. checkImports(nsImported, context);
  234. checkImports(typesImported, context);
  235. } };
  236. } };
  237. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby1kdXBsaWNhdGVzLmpzIl0sIm5hbWVzIjpbImNoZWNrSW1wb3J0cyIsImltcG9ydGVkIiwiY29udGV4dCIsImVudHJpZXMiLCJtb2R1bGUiLCJub2RlcyIsImxlbmd0aCIsIm1lc3NhZ2UiLCJmaXJzdCIsInJlc3QiLCJzb3VyY2VDb2RlIiwiZ2V0U291cmNlQ29kZSIsImZpeCIsImdldEZpeCIsInJlcG9ydCIsIm5vZGUiLCJzb3VyY2UiLCJnZXRDb21tZW50c0JlZm9yZSIsInVuZGVmaW5lZCIsImhhc1Byb2JsZW1hdGljQ29tbWVudHMiLCJoYXNOYW1lc3BhY2UiLCJkZWZhdWx0SW1wb3J0TmFtZXMiLCJTZXQiLCJtYXAiLCJnZXREZWZhdWx0SW1wb3J0TmFtZSIsImZpbHRlciIsIkJvb2xlYW4iLCJzaXplIiwicmVzdFdpdGhvdXRDb21tZW50cyIsInNwZWNpZmllcnMiLCJ0b2tlbnMiLCJnZXRUb2tlbnMiLCJvcGVuQnJhY2UiLCJmaW5kIiwidG9rZW4iLCJpc1B1bmN0dWF0b3IiLCJjbG9zZUJyYWNlIiwiaW1wb3J0Tm9kZSIsInRleHQiLCJzbGljZSIsInJhbmdlIiwiaGFzVHJhaWxpbmdDb21tYSIsImdldFRva2VuQmVmb3JlIiwiaXNFbXB0eSIsImhhc1NwZWNpZmllcnMiLCJ1bm5lY2Vzc2FyeUltcG9ydHMiLCJzb21lIiwic3BlY2lmaWVyIiwic2hvdWxkQWRkRGVmYXVsdCIsInNob3VsZEFkZFNwZWNpZmllcnMiLCJzaG91bGRSZW1vdmVVbm5lY2Vzc2FyeSIsImZpeGVyIiwiZmlyc3RUb2tlbiIsImdldEZpcnN0VG9rZW4iLCJkZWZhdWx0SW1wb3J0TmFtZSIsImZpcnN0SGFzVHJhaWxpbmdDb21tYSIsImZpcnN0SXNFbXB0eSIsInJlZHVjZSIsInJlc3VsdCIsIm5lZWRzQ29tbWEiLCJzcGVjaWZpZXJzVGV4dCIsImZpeGVzIiwicHVzaCIsImluc2VydFRleHRBZnRlciIsImluc2VydFRleHRCZWZvcmUiLCJyZW1vdmUiLCJ2YWx1ZSIsInR5cGUiLCJkZWZhdWx0U3BlY2lmaWVyIiwibG9jYWwiLCJuYW1lIiwiaGFzQ29tbWVudEJlZm9yZSIsImhhc0NvbW1lbnRBZnRlciIsImhhc0NvbW1lbnRJbnNpZGVOb25TcGVjaWZpZXJzIiwiY29tbWVudCIsImxvYyIsImVuZCIsImxpbmUiLCJzdGFydCIsImdldENvbW1lbnRzQWZ0ZXIiLCJvcGVuQnJhY2VJbmRleCIsImZpbmRJbmRleCIsImNsb3NlQnJhY2VJbmRleCIsInNvbWVUb2tlbnMiLCJjb25jYXQiLCJleHBvcnRzIiwibWV0YSIsImRvY3MiLCJ1cmwiLCJmaXhhYmxlIiwic2NoZW1hIiwicHJvcGVydGllcyIsImNvbnNpZGVyUXVlcnlTdHJpbmciLCJhZGRpdGlvbmFsUHJvcGVydGllcyIsImNyZWF0ZSIsImNvbnNpZGVyUXVlcnlTdHJpbmdPcHRpb24iLCJvcHRpb25zIiwiZGVmYXVsdFJlc29sdmVyIiwic291cmNlUGF0aCIsInJlc29sdmVyIiwicGFydHMiLCJtYXRjaCIsIk1hcCIsIm5zSW1wb3J0ZWQiLCJ0eXBlc0ltcG9ydGVkIiwibiIsInJlc29sdmVkUGF0aCIsImltcG9ydE1hcCIsImltcG9ydEtpbmQiLCJoYXMiLCJnZXQiLCJzZXQiXSwibWFwcGluZ3MiOiJxb0JBQUEsc0Q7QUFDQSxxQzs7QUFFQSxTQUFTQSxZQUFULENBQXNCQyxRQUF0QixFQUFnQ0MsT0FBaEMsRUFBeUM7QUFDdkMscUJBQThCRCxTQUFTRSxPQUFULEVBQTlCLEVBQWtELDJDQUF0Q0MsTUFBc0Msa0JBQTlCQyxLQUE4QjtBQUNoRCxRQUFJQSxNQUFNQyxNQUFOLEdBQWUsQ0FBbkIsRUFBc0I7QUFDcEIsWUFBTUMsVUFBVyxJQUFHSCxNQUFPLDRCQUEzQixDQURvQjtBQUVLQyxXQUZMLFFBRWJHLEtBRmEsYUFFSEMsSUFGRztBQUdwQixZQUFNQyxhQUFhUixRQUFRUyxhQUFSLEVBQW5CO0FBQ0EsWUFBTUMsTUFBTUMsT0FBT0wsS0FBUCxFQUFjQyxJQUFkLEVBQW9CQyxVQUFwQixDQUFaOztBQUVBUixjQUFRWSxNQUFSLENBQWU7QUFDYkMsY0FBTVAsTUFBTVEsTUFEQztBQUViVCxlQUZhO0FBR2JLLFdBSGEsQ0FHUjtBQUhRLE9BQWY7O0FBTUEsV0FBSyxNQUFNRyxJQUFYLElBQW1CTixJQUFuQixFQUF5QjtBQUN2QlAsZ0JBQVFZLE1BQVIsQ0FBZTtBQUNiQyxnQkFBTUEsS0FBS0MsTUFERTtBQUViVCxpQkFGYSxFQUFmOztBQUlEO0FBQ0Y7QUFDRjtBQUNGOztBQUVELFNBQVNNLE1BQVQsQ0FBZ0JMLEtBQWhCLEVBQXVCQyxJQUF2QixFQUE2QkMsVUFBN0IsRUFBeUM7QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSSxPQUFPQSxXQUFXTyxpQkFBbEIsS0FBd0MsVUFBNUMsRUFBd0Q7QUFDdEQsV0FBT0MsU0FBUDtBQUNEOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSUMsdUJBQXVCWCxLQUF2QixFQUE4QkUsVUFBOUIsS0FBNkNVLGFBQWFaLEtBQWIsQ0FBakQsRUFBc0U7QUFDcEUsV0FBT1UsU0FBUDtBQUNEOztBQUVELFFBQU1HLHFCQUFxQixJQUFJQyxHQUFKO0FBQ3pCLEdBQUNkLEtBQUQsNEJBQVdDLElBQVgsR0FBaUJjLEdBQWpCLENBQXFCQyxvQkFBckIsRUFBMkNDLE1BQTNDLENBQWtEQyxPQUFsRCxDQUR5QixDQUEzQjs7O0FBSUE7QUFDQTtBQUNBLE1BQUlMLG1CQUFtQk0sSUFBbkIsR0FBMEIsQ0FBOUIsRUFBaUM7QUFDL0IsV0FBT1QsU0FBUDtBQUNEOztBQUVEO0FBQ0E7QUFDQSxRQUFNVSxzQkFBc0JuQixLQUFLZ0IsTUFBTCxDQUFZVixRQUFRO0FBQzlDSSx5QkFBdUJKLElBQXZCLEVBQTZCTCxVQUE3QjtBQUNBVSxlQUFhTCxJQUFiLENBRjhDLENBQXBCLENBQTVCOzs7QUFLQSxRQUFNYyxhQUFhRDtBQUNoQkwsS0FEZ0IsQ0FDWlIsUUFBUTtBQUNYLFVBQU1lLFNBQVNwQixXQUFXcUIsU0FBWCxDQUFxQmhCLElBQXJCLENBQWY7QUFDQSxVQUFNaUIsWUFBWUYsT0FBT0csSUFBUCxDQUFZQyxTQUFTQyxhQUFhRCxLQUFiLEVBQW9CLEdBQXBCLENBQXJCLENBQWxCO0FBQ0EsVUFBTUUsYUFBYU4sT0FBT0csSUFBUCxDQUFZQyxTQUFTQyxhQUFhRCxLQUFiLEVBQW9CLEdBQXBCLENBQXJCLENBQW5COztBQUVBLFFBQUlGLGFBQWEsSUFBYixJQUFxQkksY0FBYyxJQUF2QyxFQUE2QztBQUMzQyxhQUFPbEIsU0FBUDtBQUNEOztBQUVELFdBQU87QUFDTG1CLGtCQUFZdEIsSUFEUDtBQUVMdUIsWUFBTTVCLFdBQVc0QixJQUFYLENBQWdCQyxLQUFoQixDQUFzQlAsVUFBVVEsS0FBVixDQUF