Skip to content

Commit 800277d

Browse files
committed
refactor(creategraph): ソースファイルをグラフにする部分を関数化
1 parent b946f34 commit 800277d

File tree

1 file changed

+97
-73
lines changed

1 file changed

+97
-73
lines changed

src/graph/createGraph.ts

Lines changed: 97 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import path from 'path';
22
import * as ts from 'typescript';
33
import { Graph, Meta, Node, OptionValues, Relation } from '../models';
44
import { pipe, piped } from 'remeda';
5+
import { mergeGraph } from './utils';
56

67
export function createGraph(
78
/**
@@ -30,90 +31,23 @@ export function createGraph(
3031
);
3132
options.rootDir = rootDir;
3233
const program = ts.createProgram(fileNames, options);
33-
const nodes: Node[] = [];
34-
const relations: Relation[] = [];
34+
3535
const bindWords_isFileNameMatchSomeWords =
3636
(array: string[]) => (filename: string) =>
3737
array.some(word => filename.includes(word));
38-
3938
const isMatchSomeExclude = opt.exclude
4039
? bindWords_isFileNameMatchSomeWords(opt.exclude)
4140
: () => false;
4241
const isNotMatchSomeExclude = (filename: string) =>
4342
!isMatchSomeExclude(filename);
44-
function getFilePath(sourceFile: ts.SourceFile) {
45-
return options.rootDir
46-
? sourceFile.fileName.replace(options.rootDir + '/', '')
47-
: sourceFile.fileName;
48-
}
4943

50-
program
44+
const graphs = program
5145
.getSourceFiles()
52-
.filter(sourceFile => !sourceFile.fileName.includes('node_modules'))
53-
.filter(piped(getFilePath, removeSlash, isNotMatchSomeExclude))
54-
.forEach(sourceFile => {
55-
const filePath = pipe(sourceFile, getFilePath, removeSlash);
56-
const fileName = getName(filePath);
57-
const fromNode: Node = {
58-
path: filePath,
59-
name: fileName,
60-
changeStatus: 'not_modified',
61-
};
62-
nodes.push(fromNode);
63-
64-
ts.forEachChild(sourceFile, node => {
65-
const importPaths: (string | undefined)[] = [];
66-
function getModuleNameText(node: ts.Node) {
67-
if (ts.isImportDeclaration(node)) {
68-
importPaths.push(node.moduleSpecifier?.getText(sourceFile));
69-
} else if (ts.isCallExpression(node)) {
70-
const text = node.getText(sourceFile);
71-
if (text.includes('require') || text.includes('import')) {
72-
importPaths.push(node.arguments[0]?.getText(sourceFile));
73-
}
74-
} else if (ts.isExportDeclaration(node)) {
75-
importPaths.push(node.moduleSpecifier?.getText(sourceFile));
76-
}
77-
ts.forEachChild(node, getModuleNameText);
78-
}
79-
getModuleNameText(node);
46+
.filter(sourceFile => !sourceFile.fileName.includes('node_modules')) // node_modules 配下のファイルは除外
47+
.filter(piped(getFilePath(options), removeSlash, isNotMatchSomeExclude))
48+
.map(analyzeSoucreFile(options));
8049

81-
importPaths.forEach(moduleNameText => {
82-
if (!moduleNameText) return;
83-
const moduleName = moduleNameText.slice(1, moduleNameText.length - 1); // import 文のクォート及びダブルクォートを除去
84-
const moduleFileFullName =
85-
ts.resolveModuleName(
86-
moduleName,
87-
sourceFile.fileName,
88-
options,
89-
ts.sys,
90-
).resolvedModule?.resolvedFileName ?? '';
91-
const moduleFilePath = removeSlash(
92-
options.rootDir
93-
? moduleFileFullName.replace(options.rootDir, '')
94-
: moduleFileFullName,
95-
);
96-
if (!moduleFilePath) return;
97-
const toNode: Node = {
98-
path: moduleFilePath,
99-
name: getName(moduleFilePath),
100-
changeStatus: 'not_modified',
101-
};
102-
if (!findNode(nodes, moduleFilePath)) {
103-
nodes.push(toNode);
104-
}
105-
relations.push({
106-
kind: 'depends_on',
107-
from: fromNode,
108-
to: toNode,
109-
fullText: node.getChildAt(1, sourceFile)?.getText(sourceFile) ?? '',
110-
changeStatus: 'not_modified',
111-
});
112-
});
113-
});
114-
});
115-
116-
return { graph: { nodes, relations }, meta: { rootDir } };
50+
return { graph: mergeGraph(...graphs), meta: { rootDir } };
11751
}
11852

11953
function getName(filePath: string) {
@@ -141,3 +75,93 @@ function findNode(nodes: Node[], filePath: string): Node | undefined {
14175
function removeSlash(pathName: string): string {
14276
return pathName.startsWith('/') ? pathName.replace('/', '') : pathName;
14377
}
78+
79+
function getFilePath(
80+
options: ts.CompilerOptions,
81+
): (sourceFile: ts.SourceFile) => string {
82+
return (sourceFile: ts.SourceFile) =>
83+
options.rootDir
84+
? sourceFile.fileName.replace(options.rootDir + '/', '')
85+
: sourceFile.fileName;
86+
}
87+
88+
function analyzeSoucreFile(
89+
options: ts.CompilerOptions,
90+
): (sourceFile: ts.SourceFile) => Graph {
91+
return (sourceFile: ts.SourceFile) => {
92+
const nodes: Node[] = [];
93+
const relations: Relation[] = [];
94+
const filePath = pipe(sourceFile, getFilePath(options), removeSlash);
95+
const fileName = getName(filePath);
96+
const fromNode: Node = {
97+
path: filePath,
98+
name: fileName,
99+
changeStatus: 'not_modified',
100+
};
101+
nodes.push(fromNode);
102+
103+
ts.forEachChild(sourceFile, node => {
104+
const importPaths: (string | undefined)[] = [];
105+
function getModuleNameText(node: ts.Node) {
106+
if (ts.isImportDeclaration(node)) {
107+
console.log(
108+
'isImportDeclaration',
109+
node.moduleSpecifier?.getText(sourceFile),
110+
);
111+
importPaths.push(node.moduleSpecifier?.getText(sourceFile));
112+
} else if (ts.isCallExpression(node)) {
113+
const text = node.getText(sourceFile);
114+
if (text.includes('require') || text.includes('import')) {
115+
importPaths.push(node.arguments[0]?.getText(sourceFile));
116+
}
117+
} else if (ts.isExportDeclaration(node)) {
118+
importPaths.push(node.moduleSpecifier?.getText(sourceFile));
119+
}
120+
ts.forEachChild(node, getModuleNameText);
121+
}
122+
getModuleNameText(node);
123+
console.log(importPaths);
124+
125+
importPaths.forEach(moduleNameText => {
126+
if (!moduleNameText) {
127+
console.log('moduleNameText is empty');
128+
return;
129+
}
130+
const moduleName = moduleNameText.slice(1, moduleNameText.length - 1); // import 文のクォート及びダブルクォートを除去
131+
console.log(
132+
'ts.resolveModuleName(moduleName, sourceFile.fileName, options, ts.sys).resolvedModule?.resolvedFileName = ',
133+
ts.resolveModuleName(moduleName, sourceFile.fileName, options, ts.sys)
134+
.resolvedModule?.resolvedFileName,
135+
);
136+
const moduleFileFullName =
137+
ts.resolveModuleName(moduleName, sourceFile.fileName, options, ts.sys)
138+
.resolvedModule?.resolvedFileName ?? '';
139+
const moduleFilePath = removeSlash(
140+
options.rootDir
141+
? moduleFileFullName.replace(options.rootDir, '')
142+
: moduleFileFullName,
143+
);
144+
if (!moduleFilePath) {
145+
console.log('moduleFilePath is empty');
146+
return;
147+
}
148+
const toNode: Node = {
149+
path: moduleFilePath,
150+
name: getName(moduleFilePath),
151+
changeStatus: 'not_modified',
152+
};
153+
if (!findNode(nodes, moduleFilePath)) {
154+
nodes.push(toNode);
155+
}
156+
relations.push({
157+
kind: 'depends_on',
158+
from: fromNode,
159+
to: toNode,
160+
fullText: node.getChildAt(1, sourceFile)?.getText(sourceFile) ?? '',
161+
changeStatus: 'not_modified',
162+
});
163+
});
164+
});
165+
return { nodes, relations };
166+
};
167+
}

0 commit comments

Comments
 (0)