driftdetect-vscode 0.8.2

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.
Files changed (309) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test.log +138 -0
  3. package/.vscode/launch.json +17 -0
  4. package/.vscode/tasks.json +15 -0
  5. package/LICENSE +121 -0
  6. package/dist/activation/activation-controller.d.ts +61 -0
  7. package/dist/activation/activation-controller.d.ts.map +1 -0
  8. package/dist/activation/activation-controller.js +235 -0
  9. package/dist/activation/activation-controller.js.map +1 -0
  10. package/dist/activation/activation-phases.d.ts +28 -0
  11. package/dist/activation/activation-phases.d.ts.map +1 -0
  12. package/dist/activation/activation-phases.js +80 -0
  13. package/dist/activation/activation-phases.js.map +1 -0
  14. package/dist/activation/index.d.ts +6 -0
  15. package/dist/activation/index.d.ts.map +1 -0
  16. package/dist/activation/index.js +6 -0
  17. package/dist/activation/index.js.map +1 -0
  18. package/dist/client/connection-config.d.ts +50 -0
  19. package/dist/client/connection-config.d.ts.map +1 -0
  20. package/dist/client/connection-config.js +56 -0
  21. package/dist/client/connection-config.js.map +1 -0
  22. package/dist/client/connection-manager.d.ts +70 -0
  23. package/dist/client/connection-manager.d.ts.map +1 -0
  24. package/dist/client/connection-manager.js +214 -0
  25. package/dist/client/connection-manager.js.map +1 -0
  26. package/dist/client/index.d.ts +8 -0
  27. package/dist/client/index.d.ts.map +1 -0
  28. package/dist/client/index.js +8 -0
  29. package/dist/client/index.js.map +1 -0
  30. package/dist/client/language-client-factory.d.ts +29 -0
  31. package/dist/client/language-client-factory.d.ts.map +1 -0
  32. package/dist/client/language-client-factory.js +76 -0
  33. package/dist/client/language-client-factory.js.map +1 -0
  34. package/dist/client/request-middleware.d.ts +38 -0
  35. package/dist/client/request-middleware.d.ts.map +1 -0
  36. package/dist/client/request-middleware.js +85 -0
  37. package/dist/client/request-middleware.js.map +1 -0
  38. package/dist/commands/command-definitions.d.ts +53 -0
  39. package/dist/commands/command-definitions.d.ts.map +1 -0
  40. package/dist/commands/command-definitions.js +212 -0
  41. package/dist/commands/command-definitions.js.map +1 -0
  42. package/dist/commands/command-router.d.ts +80 -0
  43. package/dist/commands/command-router.d.ts.map +1 -0
  44. package/dist/commands/command-router.js +127 -0
  45. package/dist/commands/command-router.js.map +1 -0
  46. package/dist/commands/handlers/connection-handlers.d.ts +14 -0
  47. package/dist/commands/handlers/connection-handlers.d.ts.map +1 -0
  48. package/dist/commands/handlers/connection-handlers.js +57 -0
  49. package/dist/commands/handlers/connection-handlers.js.map +1 -0
  50. package/dist/commands/handlers/constants-handlers.d.ts +11 -0
  51. package/dist/commands/handlers/constants-handlers.d.ts.map +1 -0
  52. package/dist/commands/handlers/constants-handlers.js +84 -0
  53. package/dist/commands/handlers/constants-handlers.js.map +1 -0
  54. package/dist/commands/handlers/index.d.ts +10 -0
  55. package/dist/commands/handlers/index.d.ts.map +1 -0
  56. package/dist/commands/handlers/index.js +10 -0
  57. package/dist/commands/handlers/index.js.map +1 -0
  58. package/dist/commands/handlers/pattern-handlers.d.ts +13 -0
  59. package/dist/commands/handlers/pattern-handlers.d.ts.map +1 -0
  60. package/dist/commands/handlers/pattern-handlers.js +127 -0
  61. package/dist/commands/handlers/pattern-handlers.js.map +1 -0
  62. package/dist/commands/handlers/scan-handlers.d.ts +15 -0
  63. package/dist/commands/handlers/scan-handlers.d.ts.map +1 -0
  64. package/dist/commands/handlers/scan-handlers.js +74 -0
  65. package/dist/commands/handlers/scan-handlers.js.map +1 -0
  66. package/dist/commands/handlers/ui-handlers.d.ts +12 -0
  67. package/dist/commands/handlers/ui-handlers.d.ts.map +1 -0
  68. package/dist/commands/handlers/ui-handlers.js +74 -0
  69. package/dist/commands/handlers/ui-handlers.js.map +1 -0
  70. package/dist/commands/handlers/violation-handlers.d.ts +13 -0
  71. package/dist/commands/handlers/violation-handlers.d.ts.map +1 -0
  72. package/dist/commands/handlers/violation-handlers.js +76 -0
  73. package/dist/commands/handlers/violation-handlers.js.map +1 -0
  74. package/dist/commands/index.d.ts +7 -0
  75. package/dist/commands/index.d.ts.map +1 -0
  76. package/dist/commands/index.js +7 -0
  77. package/dist/commands/index.js.map +1 -0
  78. package/dist/commands/middleware/connection-check-middleware.d.ts +12 -0
  79. package/dist/commands/middleware/connection-check-middleware.d.ts.map +1 -0
  80. package/dist/commands/middleware/connection-check-middleware.js +34 -0
  81. package/dist/commands/middleware/connection-check-middleware.js.map +1 -0
  82. package/dist/commands/middleware/index.d.ts +7 -0
  83. package/dist/commands/middleware/index.d.ts.map +1 -0
  84. package/dist/commands/middleware/index.js +7 -0
  85. package/dist/commands/middleware/index.js.map +1 -0
  86. package/dist/commands/middleware/logging-middleware.d.ts +12 -0
  87. package/dist/commands/middleware/logging-middleware.d.ts.map +1 -0
  88. package/dist/commands/middleware/logging-middleware.js +24 -0
  89. package/dist/commands/middleware/logging-middleware.js.map +1 -0
  90. package/dist/commands/middleware/telemetry-middleware.d.ts +22 -0
  91. package/dist/commands/middleware/telemetry-middleware.d.ts.map +1 -0
  92. package/dist/commands/middleware/telemetry-middleware.js +30 -0
  93. package/dist/commands/middleware/telemetry-middleware.js.map +1 -0
  94. package/dist/config/config-manager.d.ts +53 -0
  95. package/dist/config/config-manager.d.ts.map +1 -0
  96. package/dist/config/config-manager.js +178 -0
  97. package/dist/config/config-manager.js.map +1 -0
  98. package/dist/config/defaults.d.ts +11 -0
  99. package/dist/config/defaults.d.ts.map +1 -0
  100. package/dist/config/defaults.js +43 -0
  101. package/dist/config/defaults.js.map +1 -0
  102. package/dist/config/index.d.ts +7 -0
  103. package/dist/config/index.d.ts.map +1 -0
  104. package/dist/config/index.js +7 -0
  105. package/dist/config/index.js.map +1 -0
  106. package/dist/config/validator.d.ts +22 -0
  107. package/dist/config/validator.d.ts.map +1 -0
  108. package/dist/config/validator.js +93 -0
  109. package/dist/config/validator.js.map +1 -0
  110. package/dist/extension.d.ts +32 -0
  111. package/dist/extension.d.ts.map +1 -0
  112. package/dist/extension.js +50 -0
  113. package/dist/extension.js.map +1 -0
  114. package/dist/infrastructure/disposable-manager.d.ts +43 -0
  115. package/dist/infrastructure/disposable-manager.d.ts.map +1 -0
  116. package/dist/infrastructure/disposable-manager.js +75 -0
  117. package/dist/infrastructure/disposable-manager.js.map +1 -0
  118. package/dist/infrastructure/event-bus.d.ts +85 -0
  119. package/dist/infrastructure/event-bus.d.ts.map +1 -0
  120. package/dist/infrastructure/event-bus.js +74 -0
  121. package/dist/infrastructure/event-bus.js.map +1 -0
  122. package/dist/infrastructure/index.d.ts +10 -0
  123. package/dist/infrastructure/index.d.ts.map +1 -0
  124. package/dist/infrastructure/index.js +10 -0
  125. package/dist/infrastructure/index.js.map +1 -0
  126. package/dist/infrastructure/logger.d.ts +37 -0
  127. package/dist/infrastructure/logger.d.ts.map +1 -0
  128. package/dist/infrastructure/logger.js +86 -0
  129. package/dist/infrastructure/logger.js.map +1 -0
  130. package/dist/infrastructure/service-container.d.ts +68 -0
  131. package/dist/infrastructure/service-container.d.ts.map +1 -0
  132. package/dist/infrastructure/service-container.js +94 -0
  133. package/dist/infrastructure/service-container.js.map +1 -0
  134. package/dist/state/index.d.ts +7 -0
  135. package/dist/state/index.d.ts.map +1 -0
  136. package/dist/state/index.js +7 -0
  137. package/dist/state/index.js.map +1 -0
  138. package/dist/state/initial-state.d.ts +11 -0
  139. package/dist/state/initial-state.d.ts.map +1 -0
  140. package/dist/state/initial-state.js +58 -0
  141. package/dist/state/initial-state.js.map +1 -0
  142. package/dist/state/selectors.d.ts +41 -0
  143. package/dist/state/selectors.d.ts.map +1 -0
  144. package/dist/state/selectors.js +61 -0
  145. package/dist/state/selectors.js.map +1 -0
  146. package/dist/state/state-manager.d.ts +54 -0
  147. package/dist/state/state-manager.d.ts.map +1 -0
  148. package/dist/state/state-manager.js +166 -0
  149. package/dist/state/state-manager.js.map +1 -0
  150. package/dist/types/config-types.d.ts +69 -0
  151. package/dist/types/config-types.d.ts.map +1 -0
  152. package/dist/types/config-types.js +5 -0
  153. package/dist/types/config-types.js.map +1 -0
  154. package/dist/types/extension-types.d.ts +45 -0
  155. package/dist/types/extension-types.d.ts.map +1 -0
  156. package/dist/types/extension-types.js +5 -0
  157. package/dist/types/extension-types.js.map +1 -0
  158. package/dist/types/index.d.ts +12 -0
  159. package/dist/types/index.d.ts.map +1 -0
  160. package/dist/types/index.js +12 -0
  161. package/dist/types/index.js.map +1 -0
  162. package/dist/types/lsp-types.d.ts +70 -0
  163. package/dist/types/lsp-types.d.ts.map +1 -0
  164. package/dist/types/lsp-types.js +5 -0
  165. package/dist/types/lsp-types.js.map +1 -0
  166. package/dist/types/state-types.d.ts +82 -0
  167. package/dist/types/state-types.d.ts.map +1 -0
  168. package/dist/types/state-types.js +5 -0
  169. package/dist/types/state-types.js.map +1 -0
  170. package/dist/types/vscode-types.d.ts +36 -0
  171. package/dist/types/vscode-types.d.ts.map +1 -0
  172. package/dist/types/vscode-types.js +7 -0
  173. package/dist/types/vscode-types.js.map +1 -0
  174. package/dist/ui/decorations/decoration-controller.d.ts +45 -0
  175. package/dist/ui/decorations/decoration-controller.d.ts.map +1 -0
  176. package/dist/ui/decorations/decoration-controller.js +198 -0
  177. package/dist/ui/decorations/decoration-controller.js.map +1 -0
  178. package/dist/ui/decorations/decoration-types.d.ts +28 -0
  179. package/dist/ui/decorations/decoration-types.d.ts.map +1 -0
  180. package/dist/ui/decorations/decoration-types.js +98 -0
  181. package/dist/ui/decorations/decoration-types.js.map +1 -0
  182. package/dist/ui/decorations/index.d.ts +7 -0
  183. package/dist/ui/decorations/index.d.ts.map +1 -0
  184. package/dist/ui/decorations/index.js +6 -0
  185. package/dist/ui/decorations/index.js.map +1 -0
  186. package/dist/ui/index.d.ts +7 -0
  187. package/dist/ui/index.d.ts.map +1 -0
  188. package/dist/ui/index.js +7 -0
  189. package/dist/ui/index.js.map +1 -0
  190. package/dist/ui/notifications/index.d.ts +5 -0
  191. package/dist/ui/notifications/index.d.ts.map +1 -0
  192. package/dist/ui/notifications/index.js +5 -0
  193. package/dist/ui/notifications/index.js.map +1 -0
  194. package/dist/ui/notifications/notification-service.d.ts +66 -0
  195. package/dist/ui/notifications/notification-service.d.ts.map +1 -0
  196. package/dist/ui/notifications/notification-service.js +103 -0
  197. package/dist/ui/notifications/notification-service.js.map +1 -0
  198. package/dist/ui/status-bar/index.d.ts +6 -0
  199. package/dist/ui/status-bar/index.d.ts.map +1 -0
  200. package/dist/ui/status-bar/index.js +6 -0
  201. package/dist/ui/status-bar/index.js.map +1 -0
  202. package/dist/ui/status-bar/status-bar-controller.d.ts +37 -0
  203. package/dist/ui/status-bar/status-bar-controller.d.ts.map +1 -0
  204. package/dist/ui/status-bar/status-bar-controller.js +111 -0
  205. package/dist/ui/status-bar/status-bar-controller.js.map +1 -0
  206. package/dist/ui/status-bar/status-bar-modes.d.ts +26 -0
  207. package/dist/ui/status-bar/status-bar-modes.d.ts.map +1 -0
  208. package/dist/ui/status-bar/status-bar-modes.js +97 -0
  209. package/dist/ui/status-bar/status-bar-modes.js.map +1 -0
  210. package/dist/views/base-tree-provider.d.ts +74 -0
  211. package/dist/views/base-tree-provider.d.ts.map +1 -0
  212. package/dist/views/base-tree-provider.js +95 -0
  213. package/dist/views/base-tree-provider.js.map +1 -0
  214. package/dist/views/constants-tree-provider.d.ts +112 -0
  215. package/dist/views/constants-tree-provider.d.ts.map +1 -0
  216. package/dist/views/constants-tree-provider.js +344 -0
  217. package/dist/views/constants-tree-provider.js.map +1 -0
  218. package/dist/views/files-tree-provider.d.ts +37 -0
  219. package/dist/views/files-tree-provider.d.ts.map +1 -0
  220. package/dist/views/files-tree-provider.js +98 -0
  221. package/dist/views/files-tree-provider.js.map +1 -0
  222. package/dist/views/index.d.ts +10 -0
  223. package/dist/views/index.d.ts.map +1 -0
  224. package/dist/views/index.js +10 -0
  225. package/dist/views/index.js.map +1 -0
  226. package/dist/views/patterns-tree-provider.d.ts +39 -0
  227. package/dist/views/patterns-tree-provider.d.ts.map +1 -0
  228. package/dist/views/patterns-tree-provider.js +139 -0
  229. package/dist/views/patterns-tree-provider.js.map +1 -0
  230. package/dist/views/violations-tree-provider.d.ts +46 -0
  231. package/dist/views/violations-tree-provider.d.ts.map +1 -0
  232. package/dist/views/violations-tree-provider.js +158 -0
  233. package/dist/views/violations-tree-provider.js.map +1 -0
  234. package/dist/webview/index.d.ts +7 -0
  235. package/dist/webview/index.d.ts.map +1 -0
  236. package/dist/webview/index.js +7 -0
  237. package/dist/webview/index.js.map +1 -0
  238. package/dist/webview/webview-manager.d.ts +57 -0
  239. package/dist/webview/webview-manager.d.ts.map +1 -0
  240. package/dist/webview/webview-manager.js +167 -0
  241. package/dist/webview/webview-manager.js.map +1 -0
  242. package/package.json +405 -0
  243. package/resources/drift-icon.png +0 -0
  244. package/resources/drift-icon.svg +5 -0
  245. package/resources/icons/error.svg +4 -0
  246. package/resources/icons/info.svg +4 -0
  247. package/resources/icons/lightbulb.svg +4 -0
  248. package/resources/icons/warning.svg +4 -0
  249. package/src/activation/activation-controller.ts +320 -0
  250. package/src/activation/activation-phases.ts +96 -0
  251. package/src/activation/index.ts +6 -0
  252. package/src/client/connection-config.ts +64 -0
  253. package/src/client/connection-manager.ts +263 -0
  254. package/src/client/index.ts +8 -0
  255. package/src/client/language-client-factory.ts +111 -0
  256. package/src/client/request-middleware.ts +117 -0
  257. package/src/commands/command-definitions.ts +243 -0
  258. package/src/commands/command-router.ts +194 -0
  259. package/src/commands/handlers/connection-handlers.ts +74 -0
  260. package/src/commands/handlers/constants-handlers.ts +99 -0
  261. package/src/commands/handlers/index.ts +10 -0
  262. package/src/commands/handlers/pattern-handlers.ts +167 -0
  263. package/src/commands/handlers/scan-handlers.ts +107 -0
  264. package/src/commands/handlers/ui-handlers.ts +88 -0
  265. package/src/commands/handlers/violation-handlers.ts +97 -0
  266. package/src/commands/index.ts +7 -0
  267. package/src/commands/middleware/connection-check-middleware.ts +46 -0
  268. package/src/commands/middleware/index.ts +7 -0
  269. package/src/commands/middleware/logging-middleware.ts +28 -0
  270. package/src/commands/middleware/telemetry-middleware.ts +46 -0
  271. package/src/config/config-manager.ts +213 -0
  272. package/src/config/defaults.ts +45 -0
  273. package/src/config/index.ts +7 -0
  274. package/src/config/validator.ts +118 -0
  275. package/src/extension.ts +57 -0
  276. package/src/infrastructure/disposable-manager.ts +87 -0
  277. package/src/infrastructure/event-bus.ts +121 -0
  278. package/src/infrastructure/index.ts +10 -0
  279. package/src/infrastructure/logger.ts +108 -0
  280. package/src/infrastructure/service-container.ts +123 -0
  281. package/src/state/index.ts +7 -0
  282. package/src/state/initial-state.ts +60 -0
  283. package/src/state/selectors.ts +126 -0
  284. package/src/state/state-manager.ts +198 -0
  285. package/src/types/config-types.ts +77 -0
  286. package/src/types/extension-types.ts +58 -0
  287. package/src/types/index.ts +12 -0
  288. package/src/types/lsp-types.ts +77 -0
  289. package/src/types/state-types.ts +92 -0
  290. package/src/types/vscode-types.ts +40 -0
  291. package/src/ui/decorations/decoration-controller.ts +252 -0
  292. package/src/ui/decorations/decoration-types.ts +129 -0
  293. package/src/ui/decorations/index.ts +7 -0
  294. package/src/ui/index.ts +7 -0
  295. package/src/ui/notifications/index.ts +5 -0
  296. package/src/ui/notifications/notification-service.ts +167 -0
  297. package/src/ui/status-bar/index.ts +6 -0
  298. package/src/ui/status-bar/status-bar-controller.ts +135 -0
  299. package/src/ui/status-bar/status-bar-modes.ts +119 -0
  300. package/src/views/base-tree-provider.ts +127 -0
  301. package/src/views/constants-tree-provider.ts +525 -0
  302. package/src/views/files-tree-provider.ts +140 -0
  303. package/src/views/index.ts +10 -0
  304. package/src/views/patterns-tree-provider.ts +179 -0
  305. package/src/views/violations-tree-provider.ts +210 -0
  306. package/src/webview/index.ts +7 -0
  307. package/src/webview/webview-manager.ts +238 -0
  308. package/tsconfig.json +22 -0
  309. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,525 @@
1
+ /**
2
+ * ConstantsTreeProvider - Constants and Enums tree view
3
+ *
4
+ * Single responsibility: Display constants, enums, and related issues in a tree view.
5
+ */
6
+
7
+ import * as vscode from 'vscode';
8
+
9
+ import { BaseTreeProvider, type BaseTreeItem } from './base-tree-provider.js';
10
+
11
+ import type { LanguageClient } from 'vscode-languageclient/node';
12
+
13
+ /**
14
+ * Tree item types
15
+ */
16
+ type ConstantTreeItemType =
17
+ | 'category'
18
+ | 'language'
19
+ | 'constant'
20
+ | 'enum'
21
+ | 'issue-group'
22
+ | 'secret'
23
+ | 'inconsistent'
24
+ | 'dead';
25
+
26
+ /**
27
+ * Constant data from server
28
+ */
29
+ export interface ConstantData {
30
+ id: string;
31
+ name: string;
32
+ qualifiedName: string;
33
+ file: string;
34
+ line: number;
35
+ language: string;
36
+ kind: string;
37
+ category: string;
38
+ value?: string | number | boolean | null;
39
+ isExported: boolean;
40
+ }
41
+
42
+ /**
43
+ * Enum data from server
44
+ */
45
+ export interface EnumData {
46
+ id: string;
47
+ name: string;
48
+ file: string;
49
+ line: number;
50
+ memberCount: number;
51
+ language: string;
52
+ }
53
+
54
+ /**
55
+ * Category summary
56
+ */
57
+ export interface CategorySummary {
58
+ name: string;
59
+ count: number;
60
+ }
61
+
62
+ /**
63
+ * Language summary
64
+ */
65
+ export interface LanguageSummary {
66
+ name: string;
67
+ count: number;
68
+ }
69
+
70
+ /**
71
+ * Secret issue
72
+ */
73
+ export interface SecretIssue {
74
+ name: string;
75
+ file: string;
76
+ line: number;
77
+ severity: string;
78
+ secretType: string;
79
+ }
80
+
81
+ /**
82
+ * Inconsistent constant issue
83
+ */
84
+ export interface InconsistentIssue {
85
+ name: string;
86
+ instanceCount: number;
87
+ }
88
+
89
+ /**
90
+ * Constants tree item
91
+ */
92
+ export interface ConstantTreeItem extends BaseTreeItem {
93
+ type: ConstantTreeItemType;
94
+ data?: ConstantData | EnumData | CategorySummary | LanguageSummary | SecretIssue | InconsistentIssue;
95
+ category?: string;
96
+ language?: string;
97
+ }
98
+
99
+ /**
100
+ * Constants tree provider
101
+ */
102
+ export class ConstantsTreeProvider extends BaseTreeProvider<ConstantTreeItem> {
103
+ private viewMode: 'category' | 'language' | 'issues' = 'category';
104
+
105
+ constructor(client: LanguageClient | null) {
106
+ super(client);
107
+ }
108
+
109
+ /**
110
+ * Set the view mode
111
+ */
112
+ setViewMode(mode: 'category' | 'language' | 'issues'): void {
113
+ this.viewMode = mode;
114
+ this.refresh();
115
+ }
116
+
117
+ async getChildren(element?: ConstantTreeItem): Promise<ConstantTreeItem[]> {
118
+ if (!this.client) {
119
+ return [];
120
+ }
121
+
122
+ const cacheKey = this.getCacheKey(element);
123
+ const cached = this.getCached(cacheKey);
124
+ if (cached) {
125
+ return cached;
126
+ }
127
+
128
+ let items: ConstantTreeItem[];
129
+
130
+ if (!element) {
131
+ // Root level: show based on view mode
132
+ switch (this.viewMode) {
133
+ case 'category':
134
+ items = await this.getCategories();
135
+ break;
136
+ case 'language':
137
+ items = await this.getLanguages();
138
+ break;
139
+ case 'issues':
140
+ items = await this.getIssueGroups();
141
+ break;
142
+ default:
143
+ items = [];
144
+ }
145
+ } else if (element.type === 'category') {
146
+ items = await this.getConstantsByCategory(element.label as string);
147
+ } else if (element.type === 'language') {
148
+ items = await this.getConstantsByLanguage(element.label as string);
149
+ } else if (element.type === 'issue-group') {
150
+ items = await this.getIssuesByType(element.label as string);
151
+ } else {
152
+ items = [];
153
+ }
154
+
155
+ this.setCache(cacheKey, items);
156
+ return items;
157
+ }
158
+
159
+ private async getCategories(): Promise<ConstantTreeItem[]> {
160
+ try {
161
+ const response = await this.sendRequest<{
162
+ data: { byCategory: Record<string, number> };
163
+ }>('drift/constants', { action: 'status' });
164
+
165
+ const categories = Object.entries(response.data.byCategory || {})
166
+ .filter(([, count]) => count > 0)
167
+ .sort(([, a], [, b]) => b - a);
168
+
169
+ return categories.map(([name, count]) =>
170
+ this.createCategoryItem({ name, count })
171
+ );
172
+ } catch {
173
+ return [];
174
+ }
175
+ }
176
+
177
+ private async getLanguages(): Promise<ConstantTreeItem[]> {
178
+ try {
179
+ const response = await this.sendRequest<{
180
+ data: { byLanguage: Record<string, number> };
181
+ }>('drift/constants', { action: 'status' });
182
+
183
+ const languages = Object.entries(response.data.byLanguage || {})
184
+ .filter(([, count]) => count > 0)
185
+ .sort(([, a], [, b]) => b - a);
186
+
187
+ return languages.map(([name, count]) =>
188
+ this.createLanguageItem({ name, count })
189
+ );
190
+ } catch {
191
+ return [];
192
+ }
193
+ }
194
+
195
+ private async getIssueGroups(): Promise<ConstantTreeItem[]> {
196
+ try {
197
+ const response = await this.sendRequest<{
198
+ data: {
199
+ issues: {
200
+ potentialSecrets: number;
201
+ inconsistentValues: number;
202
+ deadConstants: number;
203
+ };
204
+ };
205
+ }>('drift/constants', { action: 'status' });
206
+
207
+ const issues = response.data.issues || {
208
+ potentialSecrets: 0,
209
+ inconsistentValues: 0,
210
+ deadConstants: 0,
211
+ };
212
+
213
+ const items: ConstantTreeItem[] = [];
214
+
215
+ if (issues.potentialSecrets > 0) {
216
+ items.push(this.createIssueGroupItem('Secrets', issues.potentialSecrets, 'shield'));
217
+ }
218
+ if (issues.inconsistentValues > 0) {
219
+ items.push(this.createIssueGroupItem('Inconsistent', issues.inconsistentValues, 'warning'));
220
+ }
221
+ if (issues.deadConstants > 0) {
222
+ items.push(this.createIssueGroupItem('Unused', issues.deadConstants, 'trash'));
223
+ }
224
+
225
+ if (items.length === 0) {
226
+ items.push({
227
+ type: 'issue-group',
228
+ label: 'No issues found',
229
+ iconPath: new vscode.ThemeIcon('check', new vscode.ThemeColor('charts.green')),
230
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
231
+ contextValue: 'no-issues',
232
+ });
233
+ }
234
+
235
+ return items;
236
+ } catch {
237
+ return [];
238
+ }
239
+ }
240
+
241
+ private async getConstantsByCategory(category: string): Promise<ConstantTreeItem[]> {
242
+ try {
243
+ const response = await this.sendRequest<{
244
+ data: { constants: ConstantData[]; enums: EnumData[] };
245
+ }>('drift/constants', { action: 'list', category, limit: 50 });
246
+
247
+ const items: ConstantTreeItem[] = [];
248
+
249
+ for (const constant of response.data.constants || []) {
250
+ items.push(this.createConstantItem(constant));
251
+ }
252
+
253
+ for (const enumDef of response.data.enums || []) {
254
+ items.push(this.createEnumItem(enumDef));
255
+ }
256
+
257
+ return items;
258
+ } catch {
259
+ return [];
260
+ }
261
+ }
262
+
263
+ private async getConstantsByLanguage(language: string): Promise<ConstantTreeItem[]> {
264
+ try {
265
+ const response = await this.sendRequest<{
266
+ data: { constants: ConstantData[]; enums: EnumData[] };
267
+ }>('drift/constants', { action: 'list', language, limit: 50 });
268
+
269
+ const items: ConstantTreeItem[] = [];
270
+
271
+ for (const constant of response.data.constants || []) {
272
+ items.push(this.createConstantItem(constant));
273
+ }
274
+
275
+ for (const enumDef of response.data.enums || []) {
276
+ items.push(this.createEnumItem(enumDef));
277
+ }
278
+
279
+ return items;
280
+ } catch {
281
+ return [];
282
+ }
283
+ }
284
+
285
+ private async getIssuesByType(issueType: string): Promise<ConstantTreeItem[]> {
286
+ try {
287
+ if (issueType === 'Secrets') {
288
+ const response = await this.sendRequest<{
289
+ data: { potentialSecrets: SecretIssue[] };
290
+ }>('drift/constants', { action: 'secrets', limit: 50 });
291
+
292
+ return (response.data.potentialSecrets || []).map((secret) =>
293
+ this.createSecretItem(secret)
294
+ );
295
+ }
296
+
297
+ if (issueType === 'Inconsistent') {
298
+ const response = await this.sendRequest<{
299
+ data: { inconsistencies: InconsistentIssue[] };
300
+ }>('drift/constants', { action: 'inconsistent', limit: 50 });
301
+
302
+ return (response.data.inconsistencies || []).map((inc) =>
303
+ this.createInconsistentItem(inc)
304
+ );
305
+ }
306
+
307
+ if (issueType === 'Unused') {
308
+ const response = await this.sendRequest<{
309
+ data: { deadConstants: Array<{ id: string; name: string; file: string; line: number }> };
310
+ }>('drift/constants', { action: 'dead', limit: 50 });
311
+
312
+ return (response.data.deadConstants || []).map((dead) =>
313
+ this.createDeadItem(dead)
314
+ );
315
+ }
316
+
317
+ return [];
318
+ } catch {
319
+ return [];
320
+ }
321
+ }
322
+
323
+ private createCategoryItem(category: CategorySummary): ConstantTreeItem {
324
+ return {
325
+ type: 'category',
326
+ label: category.name,
327
+ description: `${category.count} constants`,
328
+ iconPath: this.getCategoryIcon(category.name),
329
+ collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
330
+ contextValue: 'constant-category',
331
+ data: category,
332
+ };
333
+ }
334
+
335
+ private createLanguageItem(language: LanguageSummary): ConstantTreeItem {
336
+ return {
337
+ type: 'language',
338
+ label: language.name,
339
+ description: `${language.count} constants`,
340
+ iconPath: this.getLanguageIcon(language.name),
341
+ collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
342
+ contextValue: 'constant-language',
343
+ data: language,
344
+ };
345
+ }
346
+
347
+ private createIssueGroupItem(
348
+ name: string,
349
+ count: number,
350
+ icon: string
351
+ ): ConstantTreeItem {
352
+ const color =
353
+ name === 'Secrets'
354
+ ? 'charts.red'
355
+ : name === 'Inconsistent'
356
+ ? 'charts.yellow'
357
+ : 'charts.gray';
358
+
359
+ return {
360
+ type: 'issue-group',
361
+ label: name,
362
+ description: `${count} issues`,
363
+ iconPath: new vscode.ThemeIcon(icon, new vscode.ThemeColor(color)),
364
+ collapsibleState: vscode.TreeItemCollapsibleState.Collapsed,
365
+ contextValue: 'constant-issue-group',
366
+ };
367
+ }
368
+
369
+ private createConstantItem(constant: ConstantData): ConstantTreeItem {
370
+ const valueStr = constant.value !== undefined ? ` = ${String(constant.value).slice(0, 30)}` : '';
371
+
372
+ return {
373
+ type: 'constant',
374
+ id: constant.id,
375
+ label: constant.name,
376
+ description: `${constant.kind}${valueStr}`,
377
+ iconPath: constant.isExported
378
+ ? new vscode.ThemeIcon('symbol-constant', new vscode.ThemeColor('charts.blue'))
379
+ : new vscode.ThemeIcon('symbol-constant'),
380
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
381
+ contextValue: 'constant',
382
+ tooltip: this.createConstantTooltip(constant),
383
+ command: {
384
+ command: 'drift.goToConstant',
385
+ title: 'Go to Constant',
386
+ arguments: [constant.file, constant.line],
387
+ },
388
+ data: constant,
389
+ };
390
+ }
391
+
392
+ private createEnumItem(enumDef: EnumData): ConstantTreeItem {
393
+ return {
394
+ type: 'enum',
395
+ id: enumDef.id,
396
+ label: enumDef.name,
397
+ description: `enum (${enumDef.memberCount} members)`,
398
+ iconPath: new vscode.ThemeIcon('symbol-enum'),
399
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
400
+ contextValue: 'enum',
401
+ command: {
402
+ command: 'drift.goToConstant',
403
+ title: 'Go to Enum',
404
+ arguments: [enumDef.file, enumDef.line],
405
+ },
406
+ data: enumDef,
407
+ };
408
+ }
409
+
410
+ private createSecretItem(secret: SecretIssue): ConstantTreeItem {
411
+ const severityColor =
412
+ secret.severity === 'critical' || secret.severity === 'high'
413
+ ? 'charts.red'
414
+ : 'charts.yellow';
415
+
416
+ return {
417
+ type: 'secret',
418
+ label: secret.name,
419
+ description: `${secret.severity} - ${secret.secretType}`,
420
+ iconPath: new vscode.ThemeIcon('shield', new vscode.ThemeColor(severityColor)),
421
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
422
+ contextValue: 'constant-secret',
423
+ command: {
424
+ command: 'drift.goToConstant',
425
+ title: 'Go to Secret',
426
+ arguments: [secret.file, secret.line],
427
+ },
428
+ data: secret,
429
+ };
430
+ }
431
+
432
+ private createInconsistentItem(inc: InconsistentIssue): ConstantTreeItem {
433
+ return {
434
+ type: 'inconsistent',
435
+ label: inc.name,
436
+ description: `${inc.instanceCount} different values`,
437
+ iconPath: new vscode.ThemeIcon('warning', new vscode.ThemeColor('charts.yellow')),
438
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
439
+ contextValue: 'constant-inconsistent',
440
+ data: inc,
441
+ };
442
+ }
443
+
444
+ private createDeadItem(dead: {
445
+ id: string;
446
+ name: string;
447
+ file: string;
448
+ line: number;
449
+ }): ConstantTreeItem {
450
+ return {
451
+ type: 'dead',
452
+ id: dead.id,
453
+ label: dead.name,
454
+ description: 'potentially unused',
455
+ iconPath: new vscode.ThemeIcon('trash', new vscode.ThemeColor('charts.gray')),
456
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
457
+ contextValue: 'constant-dead',
458
+ command: {
459
+ command: 'drift.goToConstant',
460
+ title: 'Go to Constant',
461
+ arguments: [dead.file, dead.line],
462
+ },
463
+ };
464
+ }
465
+
466
+ private getCategoryIcon(category: string): vscode.ThemeIcon {
467
+ const iconMap: Record<string, string> = {
468
+ config: 'gear',
469
+ api: 'globe',
470
+ status: 'pulse',
471
+ error: 'error',
472
+ feature_flag: 'toggle-on',
473
+ limit: 'dashboard',
474
+ regex: 'regex',
475
+ path: 'folder',
476
+ env: 'server-environment',
477
+ security: 'shield',
478
+ uncategorized: 'symbol-misc',
479
+ };
480
+
481
+ return new vscode.ThemeIcon(iconMap[category] || 'symbol-constant');
482
+ }
483
+
484
+ private getLanguageIcon(language: string): vscode.ThemeIcon {
485
+ const iconMap: Record<string, string> = {
486
+ typescript: 'symbol-class',
487
+ javascript: 'symbol-class',
488
+ python: 'symbol-class',
489
+ java: 'symbol-class',
490
+ csharp: 'symbol-class',
491
+ php: 'symbol-class',
492
+ go: 'symbol-class',
493
+ };
494
+
495
+ return new vscode.ThemeIcon(iconMap[language] || 'file-code');
496
+ }
497
+
498
+ private createConstantTooltip(constant: ConstantData): vscode.MarkdownString {
499
+ const md = new vscode.MarkdownString();
500
+ md.isTrusted = true;
501
+
502
+ md.appendMarkdown(`### ${constant.name}\n\n`);
503
+ md.appendMarkdown(`**Qualified Name:** \`${constant.qualifiedName}\`\n\n`);
504
+ md.appendMarkdown(`**File:** ${constant.file}:${constant.line}\n\n`);
505
+ md.appendMarkdown(`**Language:** ${constant.language}\n\n`);
506
+ md.appendMarkdown(`**Kind:** ${constant.kind}\n\n`);
507
+ md.appendMarkdown(`**Category:** ${constant.category}\n\n`);
508
+ md.appendMarkdown(`**Exported:** ${constant.isExported ? 'Yes' : 'No'}\n\n`);
509
+
510
+ if (constant.value !== undefined) {
511
+ md.appendMarkdown(`---\n\n**Value:**\n\`\`\`\n${String(constant.value)}\n\`\`\`\n`);
512
+ }
513
+
514
+ return md;
515
+ }
516
+ }
517
+
518
+ /**
519
+ * Factory function for creating constants tree provider
520
+ */
521
+ export function createConstantsTreeProvider(
522
+ client: LanguageClient | null
523
+ ): ConstantsTreeProvider {
524
+ return new ConstantsTreeProvider(client);
525
+ }
@@ -0,0 +1,140 @@
1
+ /**
2
+ * FilesTreeProvider - Files tree view
3
+ *
4
+ * Single responsibility: Display files with patterns in a tree view.
5
+ */
6
+
7
+ import * as vscode from 'vscode';
8
+
9
+ import { BaseTreeProvider, type BaseTreeItem } from './base-tree-provider.js';
10
+
11
+ import type { FilePatternData } from '../types/index.js';
12
+ import type { LanguageClient } from 'vscode-languageclient/node';
13
+
14
+ /**
15
+ * Tree item types
16
+ */
17
+ type FileTreeItemType = 'folder' | 'file';
18
+
19
+ /**
20
+ * File tree item
21
+ */
22
+ export interface FileTreeItem extends BaseTreeItem {
23
+ type: FileTreeItemType;
24
+ path: string;
25
+ data?: FilePatternData;
26
+ }
27
+
28
+ /**
29
+ * Files tree provider
30
+ */
31
+ export class FilesTreeProvider extends BaseTreeProvider<FileTreeItem> {
32
+ constructor(client: LanguageClient | null) {
33
+ super(client);
34
+ }
35
+
36
+ async getChildren(element?: FileTreeItem): Promise<FileTreeItem[]> {
37
+ if (!this.client) {
38
+ return [];
39
+ }
40
+
41
+ const cacheKey = this.getCacheKey(element);
42
+ const cached = this.getCached(cacheKey);
43
+ if (cached) {
44
+ return cached;
45
+ }
46
+
47
+ let items: FileTreeItem[];
48
+
49
+ if (!element) {
50
+ // Root level: get all files with patterns
51
+ items = await this.getFilesWithPatterns();
52
+ } else {
53
+ // No nested children for now
54
+ items = [];
55
+ }
56
+
57
+ this.setCache(cacheKey, items);
58
+ return items;
59
+ }
60
+
61
+ private async getFilesWithPatterns(): Promise<FileTreeItem[]> {
62
+ try {
63
+ const response = await this.sendRequest<{ files: FilePatternData[] }>(
64
+ 'drift/files/list',
65
+ { minPatterns: 1 }
66
+ );
67
+
68
+ // Sort by pattern count descending
69
+ const sorted = response.files.sort((a, b) => b.patternCount - a.patternCount);
70
+
71
+ return sorted.map((file) => this.createFileItem(file));
72
+ } catch {
73
+ return [];
74
+ }
75
+ }
76
+
77
+ private createFileItem(file: FilePatternData): FileTreeItem {
78
+ const fileName = file.path.split('/').pop() || file.path;
79
+ const hasViolations = file.violationCount > 0;
80
+
81
+ return {
82
+ type: 'file',
83
+ path: file.path,
84
+ label: fileName,
85
+ description: this.createDescription(file),
86
+ iconPath: hasViolations
87
+ ? new vscode.ThemeIcon('warning', new vscode.ThemeColor('editorWarning.foreground'))
88
+ : vscode.ThemeIcon.File,
89
+ collapsibleState: vscode.TreeItemCollapsibleState.None,
90
+ contextValue: 'file',
91
+ resourceUri: vscode.Uri.file(file.path),
92
+ tooltip: this.createFileTooltip(file),
93
+ command: {
94
+ command: 'vscode.open',
95
+ title: 'Open File',
96
+ arguments: [vscode.Uri.file(file.path)],
97
+ },
98
+ data: file,
99
+ };
100
+ }
101
+
102
+ private createDescription(file: FilePatternData): string {
103
+ const parts: string[] = [];
104
+
105
+ parts.push(`${file.patternCount} pattern${file.patternCount === 1 ? '' : 's'}`);
106
+
107
+ if (file.violationCount > 0) {
108
+ parts.push(`${file.violationCount} violation${file.violationCount === 1 ? '' : 's'}`);
109
+ }
110
+
111
+ return parts.join(' • ');
112
+ }
113
+
114
+ private createFileTooltip(file: FilePatternData): vscode.MarkdownString {
115
+ const md = new vscode.MarkdownString();
116
+ md.isTrusted = true;
117
+
118
+ md.appendMarkdown(`### ${file.path}\n\n`);
119
+ md.appendMarkdown(`**Patterns:** ${file.patternCount}\n\n`);
120
+ md.appendMarkdown(`**Violations:** ${file.violationCount}\n\n`);
121
+
122
+ if (file.categories.length > 0) {
123
+ md.appendMarkdown(`**Categories:** ${file.categories.join(', ')}\n\n`);
124
+ }
125
+
126
+ md.appendMarkdown(`---\n\n`);
127
+ md.appendMarkdown(`[View Patterns](command:drift.showFilePatterns?${encodeURIComponent(JSON.stringify({ path: file.path }))})`);
128
+
129
+ return md;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Factory function for creating files tree provider
135
+ */
136
+ export function createFilesTreeProvider(
137
+ client: LanguageClient | null
138
+ ): FilesTreeProvider {
139
+ return new FilesTreeProvider(client);
140
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Views module exports
3
+ *
4
+ * Tree view providers for the sidebar.
5
+ */
6
+
7
+ export { PatternsTreeProvider, createPatternsTreeProvider } from './patterns-tree-provider.js';
8
+ export { ViolationsTreeProvider, createViolationsTreeProvider } from './violations-tree-provider.js';
9
+ export { FilesTreeProvider, createFilesTreeProvider } from './files-tree-provider.js';
10
+ export { ConstantsTreeProvider, createConstantsTreeProvider } from './constants-tree-provider.js';