Skip to content
This repository was archived by the owner on Aug 7, 2021. It is now read-only.

Commit 803afe1

Browse files
sis0k0DimitarTachev
authored andcommitted
fix pr comments
1 parent 39c7a6c commit 803afe1

8 files changed

+397
-140
lines changed

Diff for: index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const path = require("path");
22
const { existsSync } = require("fs");
3-
const { findBootstrapModulePath } = require("./utils/ast-utils")
3+
const { findBootstrapModulePath } = require("./utils/ast-utils");
44
const { ANDROID_APP_PATH } = require("./androidProjectHelpers");
55
const {
66
getPackageJson,

Diff for: templates/webpack.angular.js

+3
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ module.exports = env => {
6161
ngCompilerTransformers.push(nsReplaceBootstrap);
6262
}
6363

64+
// when "@angular/core" is external, it's not included in the bundles. In this way, it will be used
65+
// directly from node_modules and the Angular modules loader won't be able to resolve the lazy routes
66+
// fixes https://github.com/NativeScript/nativescript-cli/issues/4024
6467
if (env.externals.indexOf("@angular/core") > -1) {
6568
const appModuleRelativePath = nsWebpack.getMainModulePath(resolve(appFullPath, entryModule));
6669
if (appModuleRelativePath) {

Diff for: transformers/ns-replace-bootstrap.ts

+3-6
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,17 @@ import {
99
makeTransform,
1010
getFirstNode
1111
} from "@ngtools/webpack/src/transformers";
12-
import { workaroundResolve } from '@ngtools/webpack/src/compiler_host';
1312
import { AngularCompilerPlugin } from '@ngtools/webpack';
13+
import { getResolvedEntryModule } from "../utils/transformers-utils";
14+
1415

1516
export function nsReplaceBootstrap(getNgCompiler: () => AngularCompilerPlugin): ts.TransformerFactory<ts.SourceFile> {
1617
const shouldTransform = (fileName) => !fileName.endsWith('.ngfactory.ts') && !fileName.endsWith('.ngstyle.ts');
1718
const getTypeChecker = () => getNgCompiler().typeChecker;
1819

1920
const standardTransform: StandardTransform = function (sourceFile: ts.SourceFile) {
2021
const ops: TransformOperation[] = [];
21-
const ngCompiler = getNgCompiler();
22-
23-
const entryModule = ngCompiler.entryModule
24-
? { path: workaroundResolve(ngCompiler.entryModule.path), className: getNgCompiler().entryModule.className }
25-
: ngCompiler.entryModule;
22+
const entryModule = getResolvedEntryModule(getNgCompiler());
2623

2724
if (!shouldTransform(sourceFile.fileName) || !entryModule) {
2825
return ops;

Diff for: transformers/ns-replace-lazy-loader.spec.ts

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { tags } from '@angular-devkit/core';
1+
import { tags } from "@angular-devkit/core";
22
import { createTypescriptContext, transformTypescript } from "@ngtools/webpack/src/transformers";
3-
import { nsReplaceLazyLoader, NgLazyLoaderCode, getConfigObjectSetupCode } from './ns-replace-lazy-loader';
4-
import { AngularCompilerPlugin } from '@ngtools/webpack';
3+
import { nsReplaceLazyLoader, NgLazyLoaderCode, getConfigObjectSetupCode } from "./ns-replace-lazy-loader";
4+
import { AngularCompilerPlugin } from "@ngtools/webpack";
55

6-
describe('@ngtools/webpack transformers', () => {
7-
describe('ns-replace-lazy-loader', () => {
6+
describe("@ngtools/webpack transformers", () => {
7+
describe("ns-replace-lazy-loader", () => {
88
const configObjectName = "testIdentifier";
99
const configObjectSetupCode = getConfigObjectSetupCode(configObjectName, "providers", "NgModuleFactoryLoader", "{ provide: nsNgCoreImport_Generated.NgModuleFactoryLoader, useClass: NSLazyModulesLoader_Generated }");
1010
const testCases = [
@@ -115,7 +115,7 @@ describe('@ngtools/webpack transformers', () => {
115115
export { AppModule };`
116116
},
117117
{
118-
name: "should NOT add NgModuleFactoryLoader when its already defined",
118+
name: "should NOT add NgModuleFactoryLoader when it's already defined",
119119
rawAppModule: `
120120
import { NgModule } from "@angular/core";
121121
import { NativeScriptModule } from "nativescript-angular/nativescript.module";
@@ -214,8 +214,8 @@ describe('@ngtools/webpack transformers', () => {
214214
const ngCompiler = <AngularCompilerPlugin>{
215215
typeChecker: program.getTypeChecker(),
216216
entryModule: {
217-
path: '/project/src/test-file',
218-
className: 'AppModule',
217+
path: "/project/src/test-file",
218+
className: "AppModule",
219219
},
220220
};
221221
const transformer = nsReplaceLazyLoader(() => ngCompiler);

Diff for: transformers/ns-replace-lazy-loader.ts

+37-118
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// https://github.com/angular/angular-cli/blob/d202480a1707be6575b2c8cf0383cfe6db44413c/packages/schematics/angular/utility/ng-ast-utils.ts
44
// https://github.com/NativeScript/nativescript-schematics/blob/438b9e3ef613389980bfa9d071e28ca1f32ab04f/src/ast-utils.ts
55

6-
import { dirname, basename, extname, join } from 'path';
7-
import * as ts from 'typescript';
6+
import { dirname, basename, extname, join } from "path";
7+
import * as ts from "typescript";
88
import {
99
StandardTransform,
1010
TransformOperation,
@@ -13,20 +13,16 @@ import {
1313
ReplaceNodeOperation,
1414
makeTransform
1515
} from "@ngtools/webpack/src/transformers";
16-
import { workaroundResolve } from '@ngtools/webpack/src/compiler_host';
17-
import { AngularCompilerPlugin } from '@ngtools/webpack';
18-
import { findNode, getSourceNodes, getObjectPropertyMatches } from "../utils/ast-utils";
16+
import { AngularCompilerPlugin } from "@ngtools/webpack";
17+
import { findNode, getObjectPropertyMatches, getDecoratorMetadata } from "../utils/ast-utils";
18+
import { getResolvedEntryModule } from "../utils/transformers-utils";
1919

2020
export function nsReplaceLazyLoader(getNgCompiler: () => AngularCompilerPlugin): ts.TransformerFactory<ts.SourceFile> {
2121
const getTypeChecker = () => getNgCompiler().typeChecker;
2222

2323
const standardTransform: StandardTransform = function (sourceFile: ts.SourceFile) {
2424
let ops: TransformOperation[] = [];
25-
const ngCompiler = getNgCompiler();
26-
27-
const entryModule = ngCompiler.entryModule
28-
? { path: workaroundResolve(ngCompiler.entryModule.path), className: getNgCompiler().entryModule.className }
29-
: ngCompiler.entryModule;
25+
const entryModule = getResolvedEntryModule(getNgCompiler());
3026
const sourceFilePath = join(dirname(sourceFile.fileName), basename(sourceFile.fileName, extname(sourceFile.fileName)));
3127
if (!entryModule || sourceFilePath !== entryModule.path) {
3228
return ops;
@@ -50,7 +46,7 @@ export function addArrayPropertyValueToNgModule(
5046
newPropertyValueMatch: string,
5147
newPropertyValue: string
5248
): TransformOperation[] {
53-
const ngModuleConfigNodesInFile = getDecoratorMetadata(sourceFile, 'NgModule', '@angular/core');
49+
const ngModuleConfigNodesInFile = getDecoratorMetadata(sourceFile, "NgModule", "@angular/core");
5450
let ngModuleConfigNode: any = ngModuleConfigNodesInFile && ngModuleConfigNodesInFile[0];
5551
if (!ngModuleConfigNode) {
5652
return null;
@@ -63,23 +59,24 @@ export function addArrayPropertyValueToNgModule(
6359
}
6460

6561
const ngLazyLoaderNode = ts.createIdentifier(NgLazyLoaderCode);
66-
if (ngModuleConfigNode.kind == ts.SyntaxKind.Identifier) {
62+
if (ngModuleConfigNode.kind === ts.SyntaxKind.Identifier) {
63+
const ngModuleConfigIndentifierNode = ngModuleConfigNode as ts.Identifier;
6764
// cases like @NgModule(myCoolConfig)
6865
const configObjectDeclarationNodes = collectDeepNodes<ts.Node>(sourceFile, ts.SyntaxKind.VariableStatement).filter(imp => {
69-
return findNode(imp, ts.SyntaxKind.Identifier, ngModuleConfigNode.getText());
66+
return findNode(imp, ts.SyntaxKind.Identifier, ngModuleConfigIndentifierNode.getText());
7067
});
7168
// will be undefined when the object is imported from another file
7269
const configObjectDeclaration = (configObjectDeclarationNodes && configObjectDeclarationNodes[0]);
7370

74-
const configObjectName = ngModuleConfigNode.escapedText.trim();
71+
const configObjectName = (<string>ngModuleConfigIndentifierNode.escapedText).trim();
7572
const configObjectSetupCode = getConfigObjectSetupCode(configObjectName, targetPropertyName, newPropertyValueMatch, newPropertyValue);
7673
const configObjectSetupNode = ts.createIdentifier(configObjectSetupCode);
7774

7875
return [
7976
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode),
8077
new AddNodeOperation(sourceFile, configObjectDeclaration || lastImport, undefined, configObjectSetupNode)
8178
];
82-
} else if (ngModuleConfigNode.kind == ts.SyntaxKind.ObjectLiteralExpression) {
79+
} else if (ngModuleConfigNode.kind === ts.SyntaxKind.ObjectLiteralExpression) {
8380
// cases like @NgModule({ bootstrap: ... })
8481
const ngModuleConfigObjectNode = ngModuleConfigNode as ts.ObjectLiteralExpression;
8582
const matchingProperties: ts.ObjectLiteralElement[] = getObjectPropertyMatches(ngModuleConfigObjectNode, sourceFile, targetPropertyName);
@@ -88,8 +85,8 @@ export function addArrayPropertyValueToNgModule(
8885
return null;
8986
}
9087

91-
if (matchingProperties.length == 0) {
92-
if (ngModuleConfigObjectNode.properties.length == 0) {
88+
if (matchingProperties.length === 0) {
89+
if (ngModuleConfigObjectNode.properties.length === 0) {
9390
// empty object @NgModule({ })
9491
return null;
9592
}
@@ -100,7 +97,8 @@ export function addArrayPropertyValueToNgModule(
10097

10198
return [
10299
new AddNodeOperation(sourceFile, lastConfigObjPropertyNode, undefined, newTargetPropertyNode),
103-
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)];
100+
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
101+
];
104102

105103
}
106104

@@ -125,113 +123,34 @@ export function addArrayPropertyValueToNgModule(
125123
const lastPropertyValueNode = targetPropertyValues[targetPropertyValues.length - 1];
126124
const newPropertyValueNode = ts.createIdentifier(`${newPropertyValue}`);
127125

128-
return [new AddNodeOperation(sourceFile, lastPropertyValueNode, undefined, newPropertyValueNode),
129-
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)];
126+
return [
127+
new AddNodeOperation(sourceFile, lastPropertyValueNode, undefined, newPropertyValueNode),
128+
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
129+
];
130130
} else {
131131
// empty array @NgModule({ targetProperty: [ ] })
132132
const newTargetPropertyValuesNode = ts.createIdentifier(`[${newPropertyValue}]`);
133133

134-
return [new ReplaceNodeOperation(sourceFile, targetPropertyValuesNode, newTargetPropertyValuesNode),
135-
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)];
136-
}
137-
}
138-
}
139-
140-
function getDecoratorMetadata(source: ts.SourceFile, identifier: string,
141-
module: string): ts.Node[] {
142-
const angularImports: { [name: string]: string }
143-
= collectDeepNodes(source, ts.SyntaxKind.ImportDeclaration)
144-
.map((node: ts.ImportDeclaration) => _angularImportsFromNode(node, source))
145-
.reduce((acc: { [name: string]: string }, current: { [name: string]: string }) => {
146-
for (const key of Object.keys(current)) {
147-
acc[key] = current[key];
148-
}
149-
150-
return acc;
151-
}, {});
152-
153-
return getSourceNodes(source)
154-
.filter(node => {
155-
return node.kind == ts.SyntaxKind.Decorator
156-
&& (node as ts.Decorator).expression.kind == ts.SyntaxKind.CallExpression;
157-
})
158-
.map(node => (node as ts.Decorator).expression as ts.CallExpression)
159-
.filter(expr => {
160-
if (expr.expression.kind == ts.SyntaxKind.Identifier) {
161-
const id = expr.expression as ts.Identifier;
162-
163-
return id.getFullText(source) == identifier
164-
&& angularImports[id.getFullText(source)] === module;
165-
} else if (expr.expression.kind == ts.SyntaxKind.PropertyAccessExpression) {
166-
// This covers foo.NgModule when importing * as foo.
167-
const paExpr = expr.expression as ts.PropertyAccessExpression;
168-
// If the left expression is not an identifier, just give up at that point.
169-
if (paExpr.expression.kind !== ts.SyntaxKind.Identifier) {
170-
return false;
171-
}
172-
173-
const id = paExpr.name.text;
174-
const moduleId = (paExpr.expression as ts.Identifier).getText(source);
175-
176-
return id === identifier && (angularImports[moduleId + '.'] === module);
177-
}
178-
179-
return false;
180-
})
181-
.filter(expr => expr.arguments[0]
182-
&& (expr.arguments[0].kind == ts.SyntaxKind.ObjectLiteralExpression ||
183-
expr.arguments[0].kind == ts.SyntaxKind.Identifier))
184-
.map(expr => expr.arguments[0] as ts.Node);
185-
}
186-
187-
function _angularImportsFromNode(node: ts.ImportDeclaration,
188-
_sourceFile: ts.SourceFile): { [name: string]: string } {
189-
const ms = node.moduleSpecifier;
190-
let modulePath: string;
191-
switch (ms.kind) {
192-
case ts.SyntaxKind.StringLiteral:
193-
modulePath = (ms as ts.StringLiteral).text;
194-
break;
195-
default:
196-
return {};
197-
}
198-
199-
if (!modulePath.startsWith('@angular/')) {
200-
return {};
201-
}
202-
203-
if (node.importClause) {
204-
if (node.importClause.name) {
205-
// This is of the form `import Name from 'path'`. Ignore.
206-
return {};
207-
} else if (node.importClause.namedBindings) {
208-
const nb = node.importClause.namedBindings;
209-
if (nb.kind == ts.SyntaxKind.NamespaceImport) {
210-
// This is of the form `import * as name from 'path'`. Return `name.`.
211-
return {
212-
[(nb as ts.NamespaceImport).name.text + '.']: modulePath,
213-
};
214-
} else {
215-
// This is of the form `import {a,b,c} from 'path'`
216-
const namedImports = nb as ts.NamedImports;
217-
218-
return namedImports.elements
219-
.map((is: ts.ImportSpecifier) => is.propertyName ? is.propertyName.text : is.name.text)
220-
.reduce((acc: { [name: string]: string }, curr: string) => {
221-
acc[curr] = modulePath;
222-
223-
return acc;
224-
}, {});
225-
}
134+
return [
135+
new ReplaceNodeOperation(sourceFile, targetPropertyValuesNode, newTargetPropertyValuesNode),
136+
new AddNodeOperation(sourceFile, lastImport, undefined, ngLazyLoaderNode)
137+
];
226138
}
227-
228-
return {};
229-
} else {
230-
// This is of the form `import 'path';`. Nothing to do.
231-
return {};
232139
}
233140
}
234141

142+
// handles cases like @NgModule(myCoolConfig) by returning a code snippet for processing
143+
// the config object and configuring its {{targetPropertyName}} based on the specified arguments
144+
// e.g.
145+
// if (!myCoolConfig.providers) {
146+
// myCoolConfig.providers = [];
147+
// }
148+
// if (Array.isArray(myCoolConfig.providers)) {
149+
// var wholeWordPropertyRegex = new RegExp("\bNgModuleFactoryLoader\b");
150+
// if (!myCoolConfig.providers.some(function (property) { return wholeWordPropertyRegex.test(property); })) {
151+
// myCoolConfig.providers.push({ provide: nsNgCoreImport_Generated.NgModuleFactoryLoader, useClass: NSLazyModulesLoader_Generated });
152+
// }
153+
// }
235154
export function getConfigObjectSetupCode(configObjectName: string, targetPropertyName: string, newPropertyValueMatch: string, newPropertyValue: string) {
236155
return `
237156
if (!${configObjectName}.${targetPropertyName}) {
@@ -298,4 +217,4 @@ var NSLazyModulesLoader_Generated = /** @class */ (function () {
298217
], NSLazyModulesLoader_Generated);
299218
return NSLazyModulesLoader_Generated;
300219
}());
301-
`;
220+
`;

0 commit comments

Comments
 (0)