ng-module-imports.js 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. "use strict";
  2. /**
  3. * @license
  4. * Copyright Google LLC All Rights Reserved.
  5. *
  6. * Use of this source code is governed by an MIT-style license that can be
  7. * found in the LICENSE file at https://angular.io/license
  8. */
  9. Object.defineProperty(exports, "__esModule", { value: true });
  10. const schematics_1 = require("@angular-devkit/schematics");
  11. const ts = require("typescript");
  12. /**
  13. * Whether the Angular module in the given path imports the specified module class name.
  14. */
  15. function hasNgModuleImport(tree, modulePath, className) {
  16. const moduleFileContent = tree.read(modulePath);
  17. if (!moduleFileContent) {
  18. throw new schematics_1.SchematicsException(`Could not read Angular module file: ${modulePath}`);
  19. }
  20. const parsedFile = ts.createSourceFile(modulePath, moduleFileContent.toString(), ts.ScriptTarget.Latest, true);
  21. const ngModuleMetadata = findNgModuleMetadata(parsedFile);
  22. if (!ngModuleMetadata) {
  23. throw new schematics_1.SchematicsException(`Could not find NgModule declaration inside: "${modulePath}"`);
  24. }
  25. for (let property of ngModuleMetadata.properties) {
  26. if (!ts.isPropertyAssignment(property) || property.name.getText() !== 'imports' ||
  27. !ts.isArrayLiteralExpression(property.initializer)) {
  28. continue;
  29. }
  30. if (property.initializer.elements.some(element => element.getText() === className)) {
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36. exports.hasNgModuleImport = hasNgModuleImport;
  37. /**
  38. * Resolves the last identifier that is part of the given expression. This helps resolving
  39. * identifiers of nested property access expressions (e.g. myNamespace.core.NgModule).
  40. */
  41. function resolveIdentifierOfExpression(expression) {
  42. if (ts.isIdentifier(expression)) {
  43. return expression;
  44. }
  45. else if (ts.isPropertyAccessExpression(expression)) {
  46. return expression.name;
  47. }
  48. return null;
  49. }
  50. /**
  51. * Finds a NgModule declaration within the specified TypeScript node and returns the
  52. * corresponding metadata for it. This function searches breadth first because
  53. * NgModule's are usually not nested within other expressions or declarations.
  54. */
  55. function findNgModuleMetadata(rootNode) {
  56. // Add immediate child nodes of the root node to the queue.
  57. const nodeQueue = [...rootNode.getChildren()];
  58. while (nodeQueue.length) {
  59. const node = nodeQueue.shift();
  60. if (ts.isDecorator(node) && ts.isCallExpression(node.expression) &&
  61. isNgModuleCallExpression(node.expression)) {
  62. return node.expression.arguments[0];
  63. }
  64. else {
  65. nodeQueue.push(...node.getChildren());
  66. }
  67. }
  68. return null;
  69. }
  70. /** Whether the specified call expression is referring to a NgModule definition. */
  71. function isNgModuleCallExpression(callExpression) {
  72. if (!callExpression.arguments.length ||
  73. !ts.isObjectLiteralExpression(callExpression.arguments[0])) {
  74. return false;
  75. }
  76. const decoratorIdentifier = resolveIdentifierOfExpression(callExpression.expression);
  77. return decoratorIdentifier ? decoratorIdentifier.text === 'NgModule' : false;
  78. }
  79. //# sourceMappingURL=ng-module-imports.js.map