UNPKG

9.32 kBPlain TextView Raw
1import { cloneDeep, concat, find } from 'lodash';
2
3import { cleanLifecycleHooksFromMethods } from '.';
4import Configuration from '../app/configuration';
5
6export class ExtendsMerger {
7 private components;
8 private classes;
9 private injectables;
10 private directives;
11 private controllers;
12
13 private static instance: ExtendsMerger;
14 private constructor() {}
15 public static getInstance() {
16 if (!ExtendsMerger.instance) {
17 ExtendsMerger.instance = new ExtendsMerger();
18 }
19 return ExtendsMerger.instance;
20 }
21
22 public merge(deps) {
23 this.components = deps.components;
24 this.classes = deps.classes;
25 this.injectables = deps.injectables;
26 this.directives = deps.directives;
27 this.controllers = deps.controllers;
28
29 const mergeExtendedProperties = component => {
30 let ext;
31 if (typeof component.extends !== 'undefined') {
32 ext = this.findInDependencies(component.extends);
33
34 if (ext) {
35 const recursiveScanWithInheritance = cls => {
36 // From class to component
37 if (typeof cls.methods !== 'undefined' && cls.methods.length > 0) {
38 let newMethods = cloneDeep(cls.methods);
39 newMethods = this.markInheritance(newMethods, cls);
40 if (typeof component.methodsClass !== 'undefined') {
41 this.mergeInheritance(component, 'methodsClass', newMethods);
42 }
43 }
44 if (typeof cls.properties !== 'undefined' && cls.properties.length > 0) {
45 let newProperties = cloneDeep(cls.properties);
46 newProperties = this.markInheritance(newProperties, cls);
47 if (typeof component.propertiesClass !== 'undefined') {
48 this.mergeInheritance(component, 'propertiesClass', newProperties);
49 }
50 }
51 // From component to component or directive to component
52 if (typeof cls.inputsClass !== 'undefined' && cls.inputsClass.length > 0) {
53 let newInputs = cloneDeep(cls.inputsClass);
54 newInputs = this.markInheritance(newInputs, cls);
55 if (typeof component.inputsClass !== 'undefined') {
56 this.mergeInheritance(component, 'inputsClass', newInputs);
57 }
58 }
59 if (
60 typeof cls.outputsClass !== 'undefined' &&
61 cls.outputsClass.length > 0
62 ) {
63 let newOutputs = cloneDeep(cls.outputsClass);
64 newOutputs = this.markInheritance(newOutputs, cls);
65 if (typeof component.outputsClass !== 'undefined') {
66 this.mergeInheritance(component, 'outputsClass', newOutputs);
67 }
68 }
69 if (
70 typeof cls.methodsClass !== 'undefined' &&
71 cls.methodsClass.length > 0
72 ) {
73 let newMethods = cloneDeep(cls.methodsClass);
74 newMethods = this.markInheritance(newMethods, cls);
75 if (typeof component.methodsClass !== 'undefined') {
76 this.mergeInheritance(component, 'methodsClass', newMethods);
77 }
78 }
79 if (
80 typeof cls.propertiesClass !== 'undefined' &&
81 cls.propertiesClass.length > 0
82 ) {
83 let newProperties = cloneDeep(cls.propertiesClass);
84 newProperties = this.markInheritance(newProperties, cls);
85 if (typeof component.propertiesClass !== 'undefined') {
86 this.mergeInheritance(component, 'propertiesClass', newProperties);
87 }
88 }
89 if (
90 typeof cls.hostBindings !== 'undefined' &&
91 cls.hostBindings.length > 0
92 ) {
93 let newHostBindings = cloneDeep(cls.hostBindings);
94 newHostBindings = this.markInheritance(newHostBindings, cls);
95 if (typeof component.hostBindings !== 'undefined') {
96 this.mergeInheritance(component, 'hostBindings', newHostBindings);
97 }
98 }
99 if (
100 typeof cls.hostListeners !== 'undefined' &&
101 cls.hostListeners.length > 0
102 ) {
103 let newHostListeners = cloneDeep(cls.hostListeners);
104 newHostListeners = this.markInheritance(newHostListeners, cls);
105 if (typeof component.hostListeners !== 'undefined') {
106 this.mergeInheritance(component, 'hostListeners', newHostListeners);
107 }
108 }
109 if (Configuration.mainData.disableLifeCycleHooks) {
110 component.methodsClass = cleanLifecycleHooksFromMethods(
111 component.methodsClass
112 );
113 }
114 if (cls.extends) {
115 recursiveScanWithInheritance(this.findInDependencies(cls.extends));
116 }
117 };
118 // From class to class
119 recursiveScanWithInheritance(ext);
120 }
121 }
122 };
123
124 this.components.forEach(mergeExtendedProperties);
125 this.directives.forEach(mergeExtendedProperties);
126 this.controllers.forEach(mergeExtendedProperties);
127
128 const mergeExtendedClasses = el => {
129 let ext;
130 if (typeof el.extends !== 'undefined') {
131 ext = this.findInDependencies(el.extends);
132 if (ext) {
133 const recursiveScanWithInheritance = cls => {
134 if (typeof cls.methods !== 'undefined' && cls.methods.length > 0) {
135 let newMethods = cloneDeep(cls.methods);
136 newMethods = this.markInheritance(newMethods, cls);
137 if (typeof el.methods !== 'undefined') {
138 this.mergeInheritance(el, 'methods', newMethods);
139 }
140 }
141 if (typeof cls.properties !== 'undefined' && cls.properties.length > 0) {
142 let newProperties = cloneDeep(cls.properties);
143 newProperties = this.markInheritance(newProperties, cls);
144 if (typeof el.properties !== 'undefined') {
145 this.mergeInheritance(el, 'properties', newProperties);
146 }
147 }
148 if (cls.extends) {
149 recursiveScanWithInheritance(this.findInDependencies(cls.extends));
150 }
151 };
152 // From elss to elss
153 recursiveScanWithInheritance(ext);
154 }
155 }
156 };
157
158 this.classes.forEach(mergeExtendedClasses);
159 this.injectables.forEach(mergeExtendedClasses);
160 this.directives.forEach(mergeExtendedClasses);
161 this.controllers.forEach(mergeExtendedClasses);
162
163 return deps;
164 }
165
166 private markInheritance(data, originalource) {
167 return data.map(el => {
168 const newElement = el;
169 newElement.inheritance = {
170 file: originalource.name
171 };
172 return newElement;
173 });
174 }
175
176 private mergeInheritance(component: any, metaPropertyId: string, newMembers: any) {
177 newMembers.forEach(newMember => {
178 const overriddenMethod = component[metaPropertyId].find(
179 componentMember => componentMember.name === newMember.name
180 );
181
182 if (overriddenMethod) {
183 overriddenMethod.inheritance = newMember.inheritance;
184 } else {
185 component[metaPropertyId].push(newMember);
186 }
187 });
188 }
189
190 private findInDependencies(name: string) {
191 const mergedData = concat(
192 [],
193 this.components,
194 this.classes,
195 this.injectables,
196 this.directives,
197 this.controllers
198 );
199 const result = find(mergedData, { name: name } as any);
200 return result || false;
201 }
202}
203
204export default ExtendsMerger.getInstance();