-
Notifications
You must be signed in to change notification settings - Fork 1
/
extension.js
160 lines (139 loc) · 4.53 KB
/
extension.js
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
const vscode = require('vscode');
const {
exec
} = require('child_process');
const path = require('path');
const fs = require('fs');
const getGoFiles = (dirPath) => {
let results = [];
const list = fs.readdirSync(dirPath);
list.forEach(file => {
const filePath = path.join(dirPath, file);
const stat = fs.statSync(filePath);
if (stat && stat.isDirectory()) {
results = results.concat(getGoFiles(filePath));
} else if (file.endsWith('.go')) {
results.push(filePath);
}
});
return results;
};
function activate(context) {
let disposable = vscode.commands.registerCommand('callgraph.analyze', async () => {
const options = ['Active File', 'All Files in Project'];
const selectedOption = await vscode.window.showQuickPick(options, {
placeHolder: 'Select an analysis option'
});
if (!selectedOption) {
return;
}
const editor = vscode.window.activeTextEditor;
let filePath = editor.document.uri.fsPath;
const workspaceFolders = vscode.workspace.workspaceFolders;
let rootPath = workspaceFolders && workspaceFolders.length > 0 ? workspaceFolders[0].uri.fsPath : '';
//vscode.window.showInformationMessage(`File Path: ${filePath}`);
//vscode.window.showInformationMessage(`Root Path: ${rootPath}`);
if (selectedOption === 'Active File') {
try {
const analysisData = await analyzeGoFile(filePath, selectedOption);
createVisualization(context, analysisData);
} catch (err) {
vscode.window.showErrorMessage(`Analysis failed: ${err.message}`);
}
} else if (selectedOption === 'All Files in Project') {
const dirPath = rootPath;
//vscode.window.showInformationMessage(`Root Path: ${dirPath}`);
try {
const files = getGoFiles(dirPath);
if (files.length === 0) {
vscode.window.showWarningMessage('No Go files found in the directory.');
} else {
//vscode.window.showInformationMessage(`Found Go files: ${files.join(', ')}`);
const analysisData = await analyzeGoFile(files, selectedOption);
createVisualization(context, analysisData);
}
} catch (err) {
vscode.window.showErrorMessage(`Error reading directory: ${err.message}`);
}
}
});
context.subscriptions.push(disposable);
}
async function analyzeGoFile(filePaths, option) {
return new Promise((resolve, reject) => {
const analyzerPath = path.join(__dirname, 'tools/golang', 'analyzer');
// TODO: Is it necessary to build the analyzer every time?
exec(`cd ${path.join(__dirname, 'tools/golang')} && go build -o analyzer analyzer.go`, (buildErr) => {
if (buildErr) {
reject(buildErr);
return;
}
if (option === 'All Files in Project') {
let command = `${analyzerPath} ${filePaths.join(' ')}`;
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
return;
}
try {
const data = JSON.parse(stdout);
//vscode.window.showInformationMessage(`Analyzer Output: ${stdout}`);
resolve(data);
} catch (err) {
reject(new Error('Failed to parse analyzer output'));
}
});
} else if (option === 'Active File') {
let command = `${analyzerPath} ${filePaths}`;
exec(command, (error, stdout, stderr) => {
if (error) {
reject(error);
return;
}
try {
const data = JSON.parse(stdout);
//vscode.window.showInformationMessage(`Analyzer Output: ${stdout}`);
resolve(data);
} catch (err) {
reject(new Error('Failed to parse analyzer output'));
}
});
} else {
reject(new Error('Invalid option selected.'));
}
});
});
}
function createVisualization(context, analysisData) {
const panel = vscode.window.createWebviewPanel(
'goCallGraph',
'Go Call Graph',
vscode.ViewColumn.One, {
enableScripts: true
}
);
panel.webview.onDidReceiveMessage(async message => {
if (message.command === 'openFile') {
//console.log("Received file path:", message);
const absoluteFilePath = vscode.Uri.file(path.resolve(__dirname, message.file));
vscode.workspace.openTextDocument(absoluteFilePath).then(doc => {
vscode.window.showTextDocument(doc, {
selection: new vscode.Range(message.line - 1, 0, message.line - 1, 0)
});
});
}
});
const htmlPath = vscode.Uri.file(path.join(__dirname, 'media', 'graph.html'));
fs.readFile(htmlPath.fsPath, 'utf8', (err, htmlContent) => {
if (err) {
console.error("Error reading HTML file:", err);
return;
}
const updatedHtmlContent = htmlContent.replace("{{data}}", JSON.stringify(analysisData));
panel.webview.html = updatedHtmlContent;
});
}
module.exports = {
activate,
deactivate: () => {}
};