91 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
		
			Executable file
		
	
	
	
	
| "use strict";
 | |
| /**
 | |
|  * @license
 | |
|  * Copyright Google LLC All Rights Reserved.
 | |
|  *
 | |
|  * Use of this source code is governed by an MIT-style license that can be
 | |
|  * found in the LICENSE file at https://angular.dev/license
 | |
|  */
 | |
| var __importDefault = (this && this.__importDefault) || function (mod) {
 | |
|     return (mod && mod.__esModule) ? mod : { "default": mod };
 | |
| };
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.findAppConfig = findAppConfig;
 | |
| const path_1 = require("path");
 | |
| const typescript_1 = __importDefault(require("../../third_party/github.com/Microsoft/TypeScript/lib/typescript"));
 | |
| const util_1 = require("./util");
 | |
| /**
 | |
|  * Resolves the node that defines the app config from a bootstrap call.
 | |
|  * @param bootstrapCall Call for which to resolve the config.
 | |
|  * @param tree File tree of the project.
 | |
|  * @param filePath File path of the bootstrap call.
 | |
|  */
 | |
| function findAppConfig(bootstrapCall, tree, filePath) {
 | |
|     if (bootstrapCall.arguments.length > 1) {
 | |
|         const config = bootstrapCall.arguments[1];
 | |
|         if (typescript_1.default.isObjectLiteralExpression(config)) {
 | |
|             return { filePath, node: config };
 | |
|         }
 | |
|         if (typescript_1.default.isIdentifier(config)) {
 | |
|             return resolveAppConfigFromIdentifier(config, tree, filePath);
 | |
|         }
 | |
|     }
 | |
|     return null;
 | |
| }
 | |
| /**
 | |
|  * Resolves the app config from an identifier referring to it.
 | |
|  * @param identifier Identifier referring to the app config.
 | |
|  * @param tree File tree of the project.
 | |
|  * @param bootstapFilePath Path of the bootstrap call.
 | |
|  */
 | |
| function resolveAppConfigFromIdentifier(identifier, tree, bootstapFilePath) {
 | |
|     const sourceFile = identifier.getSourceFile();
 | |
|     for (const node of sourceFile.statements) {
 | |
|         // Only look at relative imports. This will break if the app uses a path
 | |
|         // mapping to refer to the import, but in order to resolve those, we would
 | |
|         // need knowledge about the entire program.
 | |
|         if (!typescript_1.default.isImportDeclaration(node) ||
 | |
|             !node.importClause?.namedBindings ||
 | |
|             !typescript_1.default.isNamedImports(node.importClause.namedBindings) ||
 | |
|             !typescript_1.default.isStringLiteralLike(node.moduleSpecifier) ||
 | |
|             !node.moduleSpecifier.text.startsWith('.')) {
 | |
|             continue;
 | |
|         }
 | |
|         for (const specifier of node.importClause.namedBindings.elements) {
 | |
|             if (specifier.name.text !== identifier.text) {
 | |
|                 continue;
 | |
|             }
 | |
|             // Look for a variable with the imported name in the file. Note that ideally we would use
 | |
|             // the type checker to resolve this, but we can't because these utilities are set up to
 | |
|             // operate on individual files, not the entire program.
 | |
|             const filePath = (0, path_1.join)((0, path_1.dirname)(bootstapFilePath), node.moduleSpecifier.text + '.ts');
 | |
|             const importedSourceFile = (0, util_1.getSourceFile)(tree, filePath);
 | |
|             const resolvedVariable = findAppConfigFromVariableName(importedSourceFile, (specifier.propertyName || specifier.name).text);
 | |
|             if (resolvedVariable) {
 | |
|                 return { filePath, node: resolvedVariable };
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     const variableInSameFile = findAppConfigFromVariableName(sourceFile, identifier.text);
 | |
|     return variableInSameFile ? { filePath: bootstapFilePath, node: variableInSameFile } : null;
 | |
| }
 | |
| /**
 | |
|  * Finds an app config within the top-level variables of a file.
 | |
|  * @param sourceFile File in which to search for the config.
 | |
|  * @param variableName Name of the variable containing the config.
 | |
|  */
 | |
| function findAppConfigFromVariableName(sourceFile, variableName) {
 | |
|     for (const node of sourceFile.statements) {
 | |
|         if (typescript_1.default.isVariableStatement(node)) {
 | |
|             for (const decl of node.declarationList.declarations) {
 | |
|                 if (typescript_1.default.isIdentifier(decl.name) &&
 | |
|                     decl.name.text === variableName &&
 | |
|                     decl.initializer &&
 | |
|                     typescript_1.default.isObjectLiteralExpression(decl.initializer)) {
 | |
|                     return decl.initializer;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     return null;
 | |
| }
 |