ngrx-uml
Version:
NGRX to Plant UML diagram
260 lines (259 loc) • 12.3 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RegisterReducerCallConverter = void 0;
const chalk_1 = __importDefault(require("chalk"));
const loglevel_1 = __importDefault(require("loglevel"));
const os_1 = require("os");
const typescript_1 = __importDefault(require("typescript"));
const node_converter_1 = require("../../../core/converters/node.converter");
const utils_1 = require("../../../utils");
const preparet_to_print_1 = require("../../../utils/preparet-to-print");
const registered_reducer_model_1 = require("../models/registered-reducer.model");
var ReducerFunctions;
(function (ReducerFunctions) {
ReducerFunctions["createReducer"] = "createReducer";
ReducerFunctions["combineReducers"] = "combineReducers";
})(ReducerFunctions || (ReducerFunctions = {}));
class RegisterReducerCallConverter extends node_converter_1.NodeConverter {
convert(context, storeModuleCall) {
let callName;
const callSymbol = context.typeChecker.getSymbolAtLocation(storeModuleCall.expression);
if (callSymbol) {
callName = callSymbol.getName();
}
else {
callName = storeModuleCall.expression.getText();
loglevel_1.default.debug('no call symbol for callName:', callName);
}
let name;
let reducerSearchItem;
switch (callName) {
case 'StoreModule.forFeature':
case 'forFeature': {
name = this.getStringValue(context, storeModuleCall.arguments[0]) || 'noForFeatureKey';
reducerSearchItem = this.getReducer(context, storeModuleCall.arguments[1]);
break;
}
case 'StoreModule.forRoot':
name = 'root';
break;
default:
// log.warn('StoreModule not supported call:', callName);
return;
}
// log.info(`registeredReducer [${name}]:`, reducerSearchItem);
const registeredReducer = this.createRegisteredReducer(name, storeModuleCall, reducerSearchItem);
return registeredReducer;
}
createRegisteredReducer(name, srcNode, reducer) {
const registeredReducer = new registered_reducer_model_1.RegisteredReducerItem(name || 'noName', srcNode.getSourceFile().fileName, srcNode.getStart(), srcNode.getEnd());
if (reducer) {
registeredReducer.reducerItems = reducer.registered;
registeredReducer.reducerSymbol = reducer.symbol;
}
return registeredReducer;
}
symbolFlagsToString(flags) {
let i = 0;
let flag;
let resultText = '';
while (typescript_1.default.SymbolFlags[flag = 1 << i++]) {
if (flags & flag) {
resultText += typescript_1.default.SymbolFlags[flag];
}
}
return resultText;
}
getReducer(context, exp) {
var _a;
const foundReducer = this.getReducerRecursive(context, exp);
loglevel_1.default.debug('getReducer:', preparet_to_print_1.prepareToPrint(foundReducer));
if (foundReducer) {
if ((_a = foundReducer.symbol) === null || _a === void 0 ? void 0 : _a.flags) {
loglevel_1.default.debug('reducer symbol flags:', this.symbolFlagsToString(foundReducer.symbol.flags));
}
}
return foundReducer;
}
getReducerRecursive(context, exp) {
loglevel_1.default.trace('getReducerRecursive:', utils_1.syntaxKindText(exp));
switch (exp.kind) {
case typescript_1.default.SyntaxKind.PropertyAccessExpression: {
const propertyExp = exp;
const symbol = context.typeChecker.getSymbolAtLocation(propertyExp);
if (symbol) {
return this.getReducerRecursive(context, symbol.valueDeclaration);
}
else {
loglevel_1.default.warn('no symbol for PropertyAccessExpression');
}
return;
}
case typescript_1.default.SyntaxKind.ShorthandPropertyAssignment: {
const assigment = exp;
if (assigment.objectAssignmentInitializer) {
const result = this.getReducerRecursive(context, assigment.objectAssignmentInitializer);
if ((result === null || result === void 0 ? void 0 : result.callName) === ReducerFunctions.createReducer) {
const symbol = context.typeChecker.getSymbolAtLocation(assigment.name);
return symbol && { symbol };
}
return result;
}
return;
}
case typescript_1.default.SyntaxKind.VariableDeclaration: {
const declaration = exp;
if (declaration.initializer) {
const result = this.getReducerRecursive(context, declaration.initializer);
if ((result === null || result === void 0 ? void 0 : result.callName) === ReducerFunctions.createReducer) {
const symbol = context.typeChecker.getSymbolAtLocation(declaration.name);
return symbol && { symbol };
}
return result;
}
return;
}
case typescript_1.default.SyntaxKind.CallExpression: {
const callExp = exp;
if (typescript_1.default.isIdentifier(callExp.expression)) {
const callName = callExp.expression.getText();
switch (callName) {
case ReducerFunctions.createReducer:
return { callName };
case ReducerFunctions.combineReducers: {
const reducerItems = this.extractCombineReducers(context, callExp);
return reducerItems && { registered: reducerItems };
}
default: {
const symbol = context.typeChecker.getSymbolAtLocation(callExp.expression);
if (symbol) {
return this.getReducerRecursive(context, symbol.valueDeclaration);
}
else {
loglevel_1.default.warn('no symbol for callExpression:', callName);
return;
}
}
}
}
return this.getReducerRecursive(context, callExp.expression);
}
case typescript_1.default.SyntaxKind.ArrowFunction: {
const arrowFunction = exp;
return this.getReducerRecursive(context, arrowFunction.body);
}
case typescript_1.default.SyntaxKind.Block: {
const block = exp;
for (const statement of block.statements) {
const reducer = this.getReducerRecursive(context, statement);
if (reducer) {
return reducer;
}
}
return;
}
case typescript_1.default.SyntaxKind.ReturnStatement: {
const returnStatement = exp;
if (returnStatement.expression) {
return this.getReducerRecursive(context, returnStatement.expression);
}
return;
}
case typescript_1.default.SyntaxKind.FunctionDeclaration: {
const declaration = exp;
if (declaration.body) {
return this.getReducerRecursive(context, declaration.body);
}
return;
}
default:
loglevel_1.default.info(`getReducerRecursive - Unknown argument kind [${utils_1.syntaxKindText(exp)}] [${chalk_1.default.gray(exp.getSourceFile().fileName)}]`, os_1.EOL, chalk_1.default.gray(exp.getText()));
return;
}
}
extractPropertyName(context, node) {
switch (node.kind) {
case typescript_1.default.SyntaxKind.StringLiteral:
return node.text;
case typescript_1.default.SyntaxKind.ComputedPropertyName:
{
const symbol = context.typeChecker.getSymbolAtLocation(node.expression);
if (symbol) {
return this.getStringValue(context, symbol.valueDeclaration);
}
loglevel_1.default.warn('extractPropertyName symbol:', preparet_to_print_1.prepareToPrint(symbol), '\r\n', node.expression.getText());
}
break;
default:
loglevel_1.default.warn('extractPropertyName:', utils_1.syntaxKindText(node), preparet_to_print_1.prepareToPrint(node));
break;
}
return;
}
extractCombineReducers(context, callExp) {
if (callExp.arguments.length > 0) {
const [reducers] = callExp.arguments;
if (typescript_1.default.isObjectLiteralExpression(reducers)) {
const registeredReducerItems = [];
for (const property of reducers.properties) {
if (typescript_1.default.isPropertyAssignment(property)) {
loglevel_1.default.debug('combineReducers:', preparet_to_print_1.printNode(property, 5));
if (property.name) {
const name = this.extractPropertyName(context, property.name);
loglevel_1.default.trace('extractCombineReducers propertyName:', name);
const reducer = this.getReducer(context, property.initializer);
if (reducer === null || reducer === void 0 ? void 0 : reducer.symbol) {
registeredReducerItems.push(this.createRegisteredReducer(name, reducer.symbol.valueDeclaration, reducer));
}
// log.info('extractCombineReducers reducer:', prepareToPrint(reducer));
}
}
}
if (registeredReducerItems.length) {
return registeredReducerItems;
}
// reducers.
}
}
return;
}
getStringValue(context, exp) {
switch (exp.kind) {
case typescript_1.default.SyntaxKind.PropertyAccessExpression:
{
const propertyExp = exp;
const symbol = context.typeChecker.getSymbolAtLocation(propertyExp);
if (symbol) {
return this.getStringValue(context, symbol.valueDeclaration);
}
else {
loglevel_1.default.warn('no symbol for PropertyAccessExpression');
}
}
return;
case typescript_1.default.SyntaxKind.ShorthandPropertyAssignment: {
const assigment = exp;
if (assigment.objectAssignmentInitializer) {
return this.getStringValue(context, assigment.objectAssignmentInitializer);
}
return;
}
case typescript_1.default.SyntaxKind.VariableDeclaration: {
const declaration = exp;
if (declaration.initializer) {
return this.getStringValue(context, declaration.initializer);
}
return;
}
case typescript_1.default.SyntaxKind.StringLiteral:
return exp.text;
default:
loglevel_1.default.info('arg kind', utils_1.syntaxKindText(exp));
return;
}
}
}
exports.RegisterReducerCallConverter = RegisterReducerCallConverter;