-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathastMerge.ts
76 lines (67 loc) · 2.4 KB
/
astMerge.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { AstRootNode, AstRootTypeNode, RootTypeNames, AstDirChildren } from './directoryToAst';
export function astMerge(...asts: Array<AstRootNode>): AstRootNode {
const mergedAST = {
kind: 'root',
name: 'merged',
absPath: 'merged',
children: {},
} as AstRootNode;
asts.forEach((ast) => {
mergedAST.name += `; ${ast.name}`;
mergedAST.absPath += `; ${ast.absPath}`;
// merge rootTypes
Object.keys(ast.children).forEach((key) => {
const rootName = key as RootTypeNames;
const rootTypeNode = ast.children[rootName] as AstRootTypeNode;
let mergedRootTypeAST = mergedAST.children[rootName];
if (!mergedRootTypeAST) {
mergedRootTypeAST = {
kind: 'rootType',
name: rootTypeNode.name,
absPath: 'merged',
children: {},
} as AstRootTypeNode;
mergedAST.children[rootName] = mergedRootTypeAST;
}
mergedRootTypeAST.absPath += `; ${rootTypeNode.absPath}`;
// maybe in future namespaceConfig will be refactored
// but now it just take last one
if (rootTypeNode.namespaceConfig) {
mergedRootTypeAST.namespaceConfig = rootTypeNode.namespaceConfig;
}
mergedRootTypeAST.children = mergeChildren(mergedRootTypeAST.children, rootTypeNode.children);
});
});
return mergedAST;
}
function mergeChildren(target: AstDirChildren, source: AstDirChildren): AstDirChildren {
const result = { ...target };
Object.keys(source).forEach((key) => {
const targetChild = target[key];
const sourceChild = source[key];
if (!targetChild) {
// add new key from source
result[key] = sourceChild;
} else if (targetChild.kind === 'dir') {
if (sourceChild.kind === 'dir') {
// merge dirs
const mergedDirNode = {
...targetChild,
absPath: `merged; ${targetChild.absPath}; ${sourceChild.absPath}`,
children: mergeChildren(targetChild.children, sourceChild.children),
};
if (sourceChild.namespaceConfig) {
mergedDirNode.namespaceConfig = sourceChild.namespaceConfig;
}
result[key] = mergedDirNode;
} else if (sourceChild.kind === 'file') {
// replace dir by file from source
result[key] = sourceChild;
}
} else if (targetChild.kind === 'file') {
// replace file by any source type
result[key] = sourceChild;
}
});
return result;
}