route-intelligence-vscode 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/extension.d.ts +6 -0
- package/dist/extension.js +186 -0
- package/package.json +56 -0
- package/src/extension.ts +222 -0
- package/tsconfig.json +5 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# route-intelligence-vscode
|
|
2
|
+
|
|
3
|
+
## 1.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- start of my project
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- Updated dependencies
|
|
13
|
+
- Updated dependencies
|
|
14
|
+
- @route-intelligence/core@2.0.0
|
|
15
|
+
- @route-intelligence/next@2.0.0
|
|
16
|
+
- @route-intelligence/shared@2.0.0
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
// src/extension.ts
|
|
2
|
+
import { createAnalyzer, exportJson } from "@route-intelligence/core";
|
|
3
|
+
import { NextPlugin } from "@route-intelligence/next";
|
|
4
|
+
import * as vscode from "vscode";
|
|
5
|
+
var cachedGraph = null;
|
|
6
|
+
var diagnosticCollection = vscode.languages.createDiagnosticCollection("route-intelligence");
|
|
7
|
+
async function analyzeWorkspace() {
|
|
8
|
+
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
|
9
|
+
if (!workspaceRoot) return null;
|
|
10
|
+
const analyzer = createAnalyzer({
|
|
11
|
+
root: workspaceRoot,
|
|
12
|
+
plugins: [NextPlugin()],
|
|
13
|
+
include: ["app/**", "pages/**", "src/**", "middleware.ts"],
|
|
14
|
+
exclude: ["**/node_modules/**", "**/.next/**"]
|
|
15
|
+
});
|
|
16
|
+
const result = await analyzer.analyze();
|
|
17
|
+
cachedGraph = JSON.parse(
|
|
18
|
+
exportJson(result.graph, workspaceRoot)
|
|
19
|
+
);
|
|
20
|
+
updateDiagnostics(result.diagnostics);
|
|
21
|
+
return cachedGraph;
|
|
22
|
+
}
|
|
23
|
+
function updateDiagnostics(diagnostics) {
|
|
24
|
+
diagnosticCollection.clear();
|
|
25
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
26
|
+
for (const d of diagnostics) {
|
|
27
|
+
if (!d.loc?.filePath) continue;
|
|
28
|
+
const diags = byFile.get(d.loc.filePath) ?? [];
|
|
29
|
+
diags.push(
|
|
30
|
+
new vscode.Diagnostic(
|
|
31
|
+
new vscode.Range(
|
|
32
|
+
Math.max(0, d.loc.line - 1),
|
|
33
|
+
d.loc.column,
|
|
34
|
+
Math.max(0, d.loc.line - 1),
|
|
35
|
+
d.loc.column + 1
|
|
36
|
+
),
|
|
37
|
+
d.message,
|
|
38
|
+
d.severity === "error" ? vscode.DiagnosticSeverity.Error : vscode.DiagnosticSeverity.Warning
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
byFile.set(d.loc.filePath, diags);
|
|
42
|
+
}
|
|
43
|
+
for (const [file, diags] of byFile) {
|
|
44
|
+
diagnosticCollection.set(vscode.Uri.file(file), diags);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
var RouteTreeProvider = class {
|
|
48
|
+
_onDidChangeTreeData = new vscode.EventEmitter();
|
|
49
|
+
onDidChangeTreeData = this._onDidChangeTreeData.event;
|
|
50
|
+
refresh() {
|
|
51
|
+
this._onDidChangeTreeData.fire(void 0);
|
|
52
|
+
}
|
|
53
|
+
getTreeItem(element) {
|
|
54
|
+
return element;
|
|
55
|
+
}
|
|
56
|
+
getChildren(element) {
|
|
57
|
+
if (!cachedGraph) return [];
|
|
58
|
+
const graph = cachedGraph;
|
|
59
|
+
if (!element) {
|
|
60
|
+
return graph.nodes.filter((n) => n.attributes.type === "route").map(
|
|
61
|
+
(n) => new RouteTreeItem(n.attributes.path, n.id, vscode.TreeItemCollapsibleState.Collapsed)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
const incoming = graph.edges.filter(
|
|
65
|
+
(e) => e.target === element.id && e.attributes.type === "navigation"
|
|
66
|
+
);
|
|
67
|
+
const outgoing = graph.edges.filter(
|
|
68
|
+
(e) => e.source === element.id && e.attributes.type === "navigation"
|
|
69
|
+
);
|
|
70
|
+
return [
|
|
71
|
+
...incoming.map((e) => {
|
|
72
|
+
const source = graph.nodes.find((n) => n.id === e.source);
|
|
73
|
+
return new RouteTreeItem(
|
|
74
|
+
`\u2190 ${source?.attributes.path ?? e.source}`,
|
|
75
|
+
e.source,
|
|
76
|
+
vscode.TreeItemCollapsibleState.None
|
|
77
|
+
);
|
|
78
|
+
}),
|
|
79
|
+
...outgoing.map((e) => {
|
|
80
|
+
const target = graph.nodes.find((n) => n.id === e.target);
|
|
81
|
+
return new RouteTreeItem(
|
|
82
|
+
`\u2192 ${target?.attributes.path ?? e.target}`,
|
|
83
|
+
e.target,
|
|
84
|
+
vscode.TreeItemCollapsibleState.None
|
|
85
|
+
);
|
|
86
|
+
})
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
var RouteTreeItem = class extends vscode.TreeItem {
|
|
91
|
+
constructor(label, id, collapsibleState) {
|
|
92
|
+
super(label, collapsibleState);
|
|
93
|
+
this.id = id;
|
|
94
|
+
}
|
|
95
|
+
id;
|
|
96
|
+
};
|
|
97
|
+
function activate(context) {
|
|
98
|
+
const treeProvider = new RouteTreeProvider();
|
|
99
|
+
vscode.window.registerTreeDataProvider("routeIntelligenceRoutes", treeProvider);
|
|
100
|
+
const hoverProvider = vscode.languages.registerHoverProvider(
|
|
101
|
+
["typescript", "typescriptreact", "javascript", "javascriptreact"],
|
|
102
|
+
{
|
|
103
|
+
provideHover(document, position) {
|
|
104
|
+
if (!cachedGraph) return null;
|
|
105
|
+
const line = document.lineAt(position.line).text;
|
|
106
|
+
const hrefMatch = line.match(/href=["']([^"']+)["']/);
|
|
107
|
+
if (hrefMatch?.[1]) {
|
|
108
|
+
const path = hrefMatch[1];
|
|
109
|
+
const node = cachedGraph.nodes.find((n) => n.attributes.path === path);
|
|
110
|
+
if (node) {
|
|
111
|
+
return new vscode.Hover(
|
|
112
|
+
[
|
|
113
|
+
`**Route:** ${node.attributes.path}`,
|
|
114
|
+
`Type: ${node.attributes.type}`,
|
|
115
|
+
`File: ${node.attributes.filePath}`,
|
|
116
|
+
node.attributes.isDead ? "\u26A0 Dead route" : ""
|
|
117
|
+
].filter(Boolean).join("\n\n")
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
return new vscode.Hover(`\u26A0 Unknown route: ${path}`);
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
const definitionProvider = vscode.languages.registerDefinitionProvider(
|
|
127
|
+
["typescript", "typescriptreact", "javascript", "javascriptreact"],
|
|
128
|
+
{
|
|
129
|
+
provideDefinition(document, position) {
|
|
130
|
+
if (!cachedGraph) return null;
|
|
131
|
+
const line = document.lineAt(position.line).text;
|
|
132
|
+
const hrefMatch = line.match(/href=["']([^"']+)["']/);
|
|
133
|
+
if (!hrefMatch?.[1]) return null;
|
|
134
|
+
const node = cachedGraph.nodes.find((n) => n.attributes.path === hrefMatch[1]);
|
|
135
|
+
if (node) {
|
|
136
|
+
return new vscode.Location(
|
|
137
|
+
vscode.Uri.file(node.attributes.filePath),
|
|
138
|
+
new vscode.Position(0, 0)
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
context.subscriptions.push(
|
|
146
|
+
vscode.commands.registerCommand("route-intelligence.analyze", async () => {
|
|
147
|
+
await vscode.window.withProgress(
|
|
148
|
+
{ location: vscode.ProgressLocation.Notification, title: "Analyzing routes..." },
|
|
149
|
+
async () => {
|
|
150
|
+
await analyzeWorkspace();
|
|
151
|
+
treeProvider.refresh();
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
vscode.window.showInformationMessage("Route analysis complete");
|
|
155
|
+
}),
|
|
156
|
+
vscode.commands.registerCommand("route-intelligence.showGraph", () => {
|
|
157
|
+
const panel = vscode.window.createWebviewPanel(
|
|
158
|
+
"routeGraph",
|
|
159
|
+
"Route Graph",
|
|
160
|
+
vscode.ViewColumn.One,
|
|
161
|
+
{ enableScripts: true }
|
|
162
|
+
);
|
|
163
|
+
panel.webview.html = getWebviewContent();
|
|
164
|
+
}),
|
|
165
|
+
hoverProvider,
|
|
166
|
+
definitionProvider,
|
|
167
|
+
diagnosticCollection
|
|
168
|
+
);
|
|
169
|
+
void analyzeWorkspace().then(() => treeProvider.refresh());
|
|
170
|
+
vscode.workspace.onDidSaveTextDocument(async (doc) => {
|
|
171
|
+
if (/\.(tsx?|jsx?)$/.test(doc.fileName)) {
|
|
172
|
+
await analyzeWorkspace();
|
|
173
|
+
treeProvider.refresh();
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function getWebviewContent() {
|
|
178
|
+
return "<!DOCTYPE html><html><body><h1>Route Graph</h1><p>Run route-intelligence graph for full visualization</p></body></html>";
|
|
179
|
+
}
|
|
180
|
+
function deactivate() {
|
|
181
|
+
diagnosticCollection.dispose();
|
|
182
|
+
}
|
|
183
|
+
export {
|
|
184
|
+
activate,
|
|
185
|
+
deactivate
|
|
186
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "route-intelligence-vscode",
|
|
3
|
+
"displayName": "Route Intelligence",
|
|
4
|
+
"description": "Routing intelligence for React and Next.js applications",
|
|
5
|
+
"version": "1.1.0",
|
|
6
|
+
"publisher": "route-intelligence",
|
|
7
|
+
"engines": {
|
|
8
|
+
"vscode": "^1.90.0"
|
|
9
|
+
},
|
|
10
|
+
"categories": ["Other", "Linters"],
|
|
11
|
+
"activationEvents": [
|
|
12
|
+
"onLanguage:typescript",
|
|
13
|
+
"onLanguage:typescriptreact",
|
|
14
|
+
"onLanguage:javascript",
|
|
15
|
+
"onLanguage:javascriptreact"
|
|
16
|
+
],
|
|
17
|
+
"type": "module",
|
|
18
|
+
"main": "./dist/extension.js",
|
|
19
|
+
"contributes": {
|
|
20
|
+
"commands": [
|
|
21
|
+
{
|
|
22
|
+
"command": "route-intelligence.analyze",
|
|
23
|
+
"title": "Route Intelligence: Analyze Project"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"command": "route-intelligence.showGraph",
|
|
27
|
+
"title": "Route Intelligence: Show Route Graph"
|
|
28
|
+
}
|
|
29
|
+
],
|
|
30
|
+
"views": {
|
|
31
|
+
"explorer": [
|
|
32
|
+
{
|
|
33
|
+
"id": "routeIntelligenceRoutes",
|
|
34
|
+
"name": "Route Intelligence"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup src/extension.ts --format esm --dts --clean --external vscode",
|
|
41
|
+
"typecheck": "tsc --noEmit"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@route-intelligence/core": "*",
|
|
45
|
+
"@route-intelligence/next": "*",
|
|
46
|
+
"@route-intelligence/shared": "*"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@route-intelligence/tsconfig": "*",
|
|
50
|
+
"@types/node": "^22.15.32",
|
|
51
|
+
"@types/vscode": "^1.90.0",
|
|
52
|
+
"tsup": "^8.4.0",
|
|
53
|
+
"typescript": "^5.8.3"
|
|
54
|
+
},
|
|
55
|
+
"license": "MIT"
|
|
56
|
+
}
|
package/src/extension.ts
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { type RouteGraph, createAnalyzer, exportJson } from '@route-intelligence/core';
|
|
2
|
+
import { NextPlugin } from '@route-intelligence/next';
|
|
3
|
+
import type { SerializedGraph } from '@route-intelligence/shared';
|
|
4
|
+
import * as vscode from 'vscode';
|
|
5
|
+
|
|
6
|
+
let cachedGraph: SerializedGraph | null = null;
|
|
7
|
+
const diagnosticCollection = vscode.languages.createDiagnosticCollection('route-intelligence');
|
|
8
|
+
|
|
9
|
+
async function analyzeWorkspace(): Promise<SerializedGraph | null> {
|
|
10
|
+
const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
|
|
11
|
+
if (!workspaceRoot) return null;
|
|
12
|
+
|
|
13
|
+
const analyzer = createAnalyzer({
|
|
14
|
+
root: workspaceRoot,
|
|
15
|
+
plugins: [NextPlugin()],
|
|
16
|
+
include: ['app/**', 'pages/**', 'src/**', 'middleware.ts'],
|
|
17
|
+
exclude: ['**/node_modules/**', '**/.next/**'],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const result = await analyzer.analyze();
|
|
21
|
+
cachedGraph = JSON.parse(
|
|
22
|
+
exportJson(result.graph as RouteGraph, workspaceRoot),
|
|
23
|
+
) as SerializedGraph;
|
|
24
|
+
|
|
25
|
+
updateDiagnostics(result.diagnostics);
|
|
26
|
+
return cachedGraph;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function updateDiagnostics(
|
|
30
|
+
diagnostics: Array<{
|
|
31
|
+
severity: string;
|
|
32
|
+
message: string;
|
|
33
|
+
loc?: { filePath: string; line: number; column: number };
|
|
34
|
+
}>,
|
|
35
|
+
) {
|
|
36
|
+
diagnosticCollection.clear();
|
|
37
|
+
const byFile = new Map<string, vscode.Diagnostic[]>();
|
|
38
|
+
|
|
39
|
+
for (const d of diagnostics) {
|
|
40
|
+
if (!d.loc?.filePath) continue;
|
|
41
|
+
const diags = byFile.get(d.loc.filePath) ?? [];
|
|
42
|
+
diags.push(
|
|
43
|
+
new vscode.Diagnostic(
|
|
44
|
+
new vscode.Range(
|
|
45
|
+
Math.max(0, d.loc.line - 1),
|
|
46
|
+
d.loc.column,
|
|
47
|
+
Math.max(0, d.loc.line - 1),
|
|
48
|
+
d.loc.column + 1,
|
|
49
|
+
),
|
|
50
|
+
d.message,
|
|
51
|
+
d.severity === 'error'
|
|
52
|
+
? vscode.DiagnosticSeverity.Error
|
|
53
|
+
: vscode.DiagnosticSeverity.Warning,
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
byFile.set(d.loc.filePath, diags);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
for (const [file, diags] of byFile) {
|
|
60
|
+
diagnosticCollection.set(vscode.Uri.file(file), diags);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
class RouteTreeProvider implements vscode.TreeDataProvider<RouteTreeItem> {
|
|
65
|
+
private _onDidChangeTreeData = new vscode.EventEmitter<RouteTreeItem | undefined>();
|
|
66
|
+
readonly onDidChangeTreeData = this._onDidChangeTreeData.event;
|
|
67
|
+
|
|
68
|
+
refresh(): void {
|
|
69
|
+
this._onDidChangeTreeData.fire(undefined);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
getTreeItem(element: RouteTreeItem): vscode.TreeItem {
|
|
73
|
+
return element;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
getChildren(element?: RouteTreeItem): RouteTreeItem[] {
|
|
77
|
+
if (!cachedGraph) return [];
|
|
78
|
+
const graph = cachedGraph;
|
|
79
|
+
if (!element) {
|
|
80
|
+
return graph.nodes
|
|
81
|
+
.filter((n) => n.attributes.type === 'route')
|
|
82
|
+
.map(
|
|
83
|
+
(n) =>
|
|
84
|
+
new RouteTreeItem(n.attributes.path, n.id, vscode.TreeItemCollapsibleState.Collapsed),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const incoming = graph.edges.filter(
|
|
89
|
+
(e) => e.target === element.id && e.attributes.type === 'navigation',
|
|
90
|
+
);
|
|
91
|
+
const outgoing = graph.edges.filter(
|
|
92
|
+
(e) => e.source === element.id && e.attributes.type === 'navigation',
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
return [
|
|
96
|
+
...incoming.map((e) => {
|
|
97
|
+
const source = graph.nodes.find((n) => n.id === e.source);
|
|
98
|
+
return new RouteTreeItem(
|
|
99
|
+
`← ${source?.attributes.path ?? e.source}`,
|
|
100
|
+
e.source,
|
|
101
|
+
vscode.TreeItemCollapsibleState.None,
|
|
102
|
+
);
|
|
103
|
+
}),
|
|
104
|
+
...outgoing.map((e) => {
|
|
105
|
+
const target = graph.nodes.find((n) => n.id === e.target);
|
|
106
|
+
return new RouteTreeItem(
|
|
107
|
+
`→ ${target?.attributes.path ?? e.target}`,
|
|
108
|
+
e.target,
|
|
109
|
+
vscode.TreeItemCollapsibleState.None,
|
|
110
|
+
);
|
|
111
|
+
}),
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class RouteTreeItem extends vscode.TreeItem {
|
|
117
|
+
constructor(
|
|
118
|
+
label: string,
|
|
119
|
+
public readonly id: string,
|
|
120
|
+
collapsibleState: vscode.TreeItemCollapsibleState,
|
|
121
|
+
) {
|
|
122
|
+
super(label, collapsibleState);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function activate(context: vscode.ExtensionContext) {
|
|
127
|
+
const treeProvider = new RouteTreeProvider();
|
|
128
|
+
vscode.window.registerTreeDataProvider('routeIntelligenceRoutes', treeProvider);
|
|
129
|
+
|
|
130
|
+
const hoverProvider = vscode.languages.registerHoverProvider(
|
|
131
|
+
['typescript', 'typescriptreact', 'javascript', 'javascriptreact'],
|
|
132
|
+
{
|
|
133
|
+
provideHover(document, position) {
|
|
134
|
+
if (!cachedGraph) return null;
|
|
135
|
+
const line = document.lineAt(position.line).text;
|
|
136
|
+
|
|
137
|
+
const hrefMatch = line.match(/href=["']([^"']+)["']/);
|
|
138
|
+
if (hrefMatch?.[1]) {
|
|
139
|
+
const path = hrefMatch[1];
|
|
140
|
+
const node = cachedGraph.nodes.find((n) => n.attributes.path === path);
|
|
141
|
+
if (node) {
|
|
142
|
+
return new vscode.Hover(
|
|
143
|
+
[
|
|
144
|
+
`**Route:** ${node.attributes.path}`,
|
|
145
|
+
`Type: ${node.attributes.type}`,
|
|
146
|
+
`File: ${node.attributes.filePath}`,
|
|
147
|
+
node.attributes.isDead ? '⚠ Dead route' : '',
|
|
148
|
+
]
|
|
149
|
+
.filter(Boolean)
|
|
150
|
+
.join('\n\n'),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
return new vscode.Hover(`⚠ Unknown route: ${path}`);
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const definitionProvider = vscode.languages.registerDefinitionProvider(
|
|
161
|
+
['typescript', 'typescriptreact', 'javascript', 'javascriptreact'],
|
|
162
|
+
{
|
|
163
|
+
provideDefinition(document, position) {
|
|
164
|
+
if (!cachedGraph) return null;
|
|
165
|
+
const line = document.lineAt(position.line).text;
|
|
166
|
+
const hrefMatch = line.match(/href=["']([^"']+)["']/);
|
|
167
|
+
if (!hrefMatch?.[1]) return null;
|
|
168
|
+
|
|
169
|
+
const node = cachedGraph.nodes.find((n) => n.attributes.path === hrefMatch[1]);
|
|
170
|
+
if (node) {
|
|
171
|
+
return new vscode.Location(
|
|
172
|
+
vscode.Uri.file(node.attributes.filePath),
|
|
173
|
+
new vscode.Position(0, 0),
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
return null;
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
context.subscriptions.push(
|
|
182
|
+
vscode.commands.registerCommand('route-intelligence.analyze', async () => {
|
|
183
|
+
await vscode.window.withProgress(
|
|
184
|
+
{ location: vscode.ProgressLocation.Notification, title: 'Analyzing routes...' },
|
|
185
|
+
async () => {
|
|
186
|
+
await analyzeWorkspace();
|
|
187
|
+
treeProvider.refresh();
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
vscode.window.showInformationMessage('Route analysis complete');
|
|
191
|
+
}),
|
|
192
|
+
vscode.commands.registerCommand('route-intelligence.showGraph', () => {
|
|
193
|
+
const panel = vscode.window.createWebviewPanel(
|
|
194
|
+
'routeGraph',
|
|
195
|
+
'Route Graph',
|
|
196
|
+
vscode.ViewColumn.One,
|
|
197
|
+
{ enableScripts: true },
|
|
198
|
+
);
|
|
199
|
+
panel.webview.html = getWebviewContent();
|
|
200
|
+
}),
|
|
201
|
+
hoverProvider,
|
|
202
|
+
definitionProvider,
|
|
203
|
+
diagnosticCollection,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
void analyzeWorkspace().then(() => treeProvider.refresh());
|
|
207
|
+
|
|
208
|
+
vscode.workspace.onDidSaveTextDocument(async (doc) => {
|
|
209
|
+
if (/\.(tsx?|jsx?)$/.test(doc.fileName)) {
|
|
210
|
+
await analyzeWorkspace();
|
|
211
|
+
treeProvider.refresh();
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function getWebviewContent(): string {
|
|
217
|
+
return '<!DOCTYPE html><html><body><h1>Route Graph</h1><p>Run route-intelligence graph for full visualization</p></body></html>';
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function deactivate() {
|
|
221
|
+
diagnosticCollection.dispose();
|
|
222
|
+
}
|