@wtdlee/repomap 0.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.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +527 -0
  3. package/dist/analyzers/base-analyzer.d.ts +46 -0
  4. package/dist/analyzers/base-analyzer.d.ts.map +1 -0
  5. package/dist/analyzers/base-analyzer.js +48 -0
  6. package/dist/analyzers/base-analyzer.js.map +1 -0
  7. package/dist/analyzers/dataflow-analyzer.d.ts +30 -0
  8. package/dist/analyzers/dataflow-analyzer.d.ts.map +1 -0
  9. package/dist/analyzers/dataflow-analyzer.js +426 -0
  10. package/dist/analyzers/dataflow-analyzer.js.map +1 -0
  11. package/dist/analyzers/graphql-analyzer.d.ts +23 -0
  12. package/dist/analyzers/graphql-analyzer.d.ts.map +1 -0
  13. package/dist/analyzers/graphql-analyzer.js +387 -0
  14. package/dist/analyzers/graphql-analyzer.js.map +1 -0
  15. package/dist/analyzers/index.d.ts +6 -0
  16. package/dist/analyzers/index.d.ts.map +1 -0
  17. package/dist/analyzers/index.js +6 -0
  18. package/dist/analyzers/index.js.map +1 -0
  19. package/dist/analyzers/pages-analyzer.d.ts +85 -0
  20. package/dist/analyzers/pages-analyzer.d.ts.map +1 -0
  21. package/dist/analyzers/pages-analyzer.js +1696 -0
  22. package/dist/analyzers/pages-analyzer.js.map +1 -0
  23. package/dist/analyzers/rails/index.d.ts +47 -0
  24. package/dist/analyzers/rails/index.d.ts.map +1 -0
  25. package/dist/analyzers/rails/index.js +146 -0
  26. package/dist/analyzers/rails/index.js.map +1 -0
  27. package/dist/analyzers/rails/rails-controller-analyzer.d.ts +83 -0
  28. package/dist/analyzers/rails/rails-controller-analyzer.d.ts.map +1 -0
  29. package/dist/analyzers/rails/rails-controller-analyzer.js +479 -0
  30. package/dist/analyzers/rails/rails-controller-analyzer.js.map +1 -0
  31. package/dist/analyzers/rails/rails-grpc-analyzer.d.ts +45 -0
  32. package/dist/analyzers/rails/rails-grpc-analyzer.d.ts.map +1 -0
  33. package/dist/analyzers/rails/rails-grpc-analyzer.js +263 -0
  34. package/dist/analyzers/rails/rails-grpc-analyzer.js.map +1 -0
  35. package/dist/analyzers/rails/rails-model-analyzer.d.ts +89 -0
  36. package/dist/analyzers/rails/rails-model-analyzer.d.ts.map +1 -0
  37. package/dist/analyzers/rails/rails-model-analyzer.js +494 -0
  38. package/dist/analyzers/rails/rails-model-analyzer.js.map +1 -0
  39. package/dist/analyzers/rails/rails-react-analyzer.d.ts +42 -0
  40. package/dist/analyzers/rails/rails-react-analyzer.d.ts.map +1 -0
  41. package/dist/analyzers/rails/rails-react-analyzer.js +530 -0
  42. package/dist/analyzers/rails/rails-react-analyzer.js.map +1 -0
  43. package/dist/analyzers/rails/rails-routes-analyzer.d.ts +63 -0
  44. package/dist/analyzers/rails/rails-routes-analyzer.d.ts.map +1 -0
  45. package/dist/analyzers/rails/rails-routes-analyzer.js +541 -0
  46. package/dist/analyzers/rails/rails-routes-analyzer.js.map +1 -0
  47. package/dist/analyzers/rails/rails-view-analyzer.d.ts +50 -0
  48. package/dist/analyzers/rails/rails-view-analyzer.d.ts.map +1 -0
  49. package/dist/analyzers/rails/rails-view-analyzer.js +387 -0
  50. package/dist/analyzers/rails/rails-view-analyzer.js.map +1 -0
  51. package/dist/analyzers/rails/ruby-parser.d.ts +64 -0
  52. package/dist/analyzers/rails/ruby-parser.d.ts.map +1 -0
  53. package/dist/analyzers/rails/ruby-parser.js +213 -0
  54. package/dist/analyzers/rails/ruby-parser.js.map +1 -0
  55. package/dist/analyzers/rest-api-analyzer.d.ts +66 -0
  56. package/dist/analyzers/rest-api-analyzer.d.ts.map +1 -0
  57. package/dist/analyzers/rest-api-analyzer.js +480 -0
  58. package/dist/analyzers/rest-api-analyzer.js.map +1 -0
  59. package/dist/cli.d.ts +3 -0
  60. package/dist/cli.d.ts.map +1 -0
  61. package/dist/cli.js +550 -0
  62. package/dist/cli.js.map +1 -0
  63. package/dist/core/cache.d.ts +48 -0
  64. package/dist/core/cache.d.ts.map +1 -0
  65. package/dist/core/cache.js +152 -0
  66. package/dist/core/cache.js.map +1 -0
  67. package/dist/core/engine.d.ts +47 -0
  68. package/dist/core/engine.d.ts.map +1 -0
  69. package/dist/core/engine.js +320 -0
  70. package/dist/core/engine.js.map +1 -0
  71. package/dist/core/index.d.ts +3 -0
  72. package/dist/core/index.d.ts.map +1 -0
  73. package/dist/core/index.js +3 -0
  74. package/dist/core/index.js.map +1 -0
  75. package/dist/generators/assets/common.css +187 -0
  76. package/dist/generators/assets/docs.css +363 -0
  77. package/dist/generators/assets/page-map.css +305 -0
  78. package/dist/generators/assets/rails-map.css +473 -0
  79. package/dist/generators/index.d.ts +4 -0
  80. package/dist/generators/index.d.ts.map +1 -0
  81. package/dist/generators/index.js +4 -0
  82. package/dist/generators/index.js.map +1 -0
  83. package/dist/generators/markdown-generator.d.ts +26 -0
  84. package/dist/generators/markdown-generator.d.ts.map +1 -0
  85. package/dist/generators/markdown-generator.js +783 -0
  86. package/dist/generators/markdown-generator.js.map +1 -0
  87. package/dist/generators/mermaid-generator.d.ts +36 -0
  88. package/dist/generators/mermaid-generator.d.ts.map +1 -0
  89. package/dist/generators/mermaid-generator.js +365 -0
  90. package/dist/generators/mermaid-generator.js.map +1 -0
  91. package/dist/generators/page-map-generator.d.ts +23 -0
  92. package/dist/generators/page-map-generator.d.ts.map +1 -0
  93. package/dist/generators/page-map-generator.js +3563 -0
  94. package/dist/generators/page-map-generator.js.map +1 -0
  95. package/dist/generators/rails-map-generator.d.ts +22 -0
  96. package/dist/generators/rails-map-generator.d.ts.map +1 -0
  97. package/dist/generators/rails-map-generator.js +909 -0
  98. package/dist/generators/rails-map-generator.js.map +1 -0
  99. package/dist/index.d.ts +11 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +12 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/server/doc-server.d.ts +31 -0
  104. package/dist/server/doc-server.d.ts.map +1 -0
  105. package/dist/server/doc-server.js +1233 -0
  106. package/dist/server/doc-server.js.map +1 -0
  107. package/dist/server/index.d.ts +2 -0
  108. package/dist/server/index.d.ts.map +1 -0
  109. package/dist/server/index.js +2 -0
  110. package/dist/server/index.js.map +1 -0
  111. package/dist/types.d.ts +294 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +6 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/utils/env-detector.d.ts +32 -0
  116. package/dist/utils/env-detector.d.ts.map +1 -0
  117. package/dist/utils/env-detector.js +189 -0
  118. package/dist/utils/env-detector.js.map +1 -0
  119. package/dist/utils/parallel.d.ts +24 -0
  120. package/dist/utils/parallel.d.ts.map +1 -0
  121. package/dist/utils/parallel.js +71 -0
  122. package/dist/utils/parallel.js.map +1 -0
  123. package/package.json +131 -0
@@ -0,0 +1,387 @@
1
+ /**
2
+ * Rails View Analyzer
3
+ * Analyzes HAML/ERB views and their connections to controllers and APIs
4
+ */
5
+ import * as path from 'path';
6
+ import * as fs from 'fs/promises';
7
+ import { glob } from 'glob';
8
+ export async function analyzeRailsViews(rootPath) {
9
+ const viewsPath = path.join(rootPath, 'app/views');
10
+ const controllersPath = path.join(rootPath, 'app/controllers');
11
+ // Check if views directory exists
12
+ try {
13
+ await fs.access(viewsPath);
14
+ }
15
+ catch {
16
+ return {
17
+ views: [],
18
+ pages: [],
19
+ summary: { totalViews: 0, totalPages: 0, byController: {}, byTemplate: {} },
20
+ };
21
+ }
22
+ // Find all view files (including .yml for SSR React pages)
23
+ const viewFiles = await glob('**/*.{haml,erb,html.haml,html.erb,yml}', {
24
+ cwd: viewsPath,
25
+ nodir: true,
26
+ });
27
+ const views = [];
28
+ const byController = {};
29
+ const byTemplate = {};
30
+ for (const file of viewFiles) {
31
+ const view = await parseViewFile(viewsPath, file);
32
+ if (view) {
33
+ views.push(view);
34
+ // Count by controller
35
+ byController[view.controller] = (byController[view.controller] || 0) + 1;
36
+ // Count by template
37
+ byTemplate[view.template] = (byTemplate[view.template] || 0) + 1;
38
+ }
39
+ }
40
+ // Analyze controllers and map to pages
41
+ const pages = await analyzeControllersForPages(controllersPath, views, rootPath);
42
+ return {
43
+ views,
44
+ pages,
45
+ summary: {
46
+ totalViews: views.length,
47
+ totalPages: pages.length,
48
+ byController,
49
+ byTemplate,
50
+ },
51
+ };
52
+ }
53
+ async function parseViewFile(viewsPath, relativePath) {
54
+ const fullPath = path.join(viewsPath, relativePath);
55
+ try {
56
+ const content = await fs.readFile(fullPath, 'utf-8');
57
+ const parts = relativePath.split('/');
58
+ // Skip mailer views, layouts, shared
59
+ if (parts.some((p) => p.endsWith('_mailer') || p === 'layouts' || p === 'shared' || p === 'devise')) {
60
+ return null;
61
+ }
62
+ // Parse controller and action from path
63
+ // e.g., users/show.html.haml -> controller: users, action: show
64
+ const fileName = parts.pop() || '';
65
+ const controller = parts.join('/') || 'application';
66
+ // Parse filename: action.format.template
67
+ const nameParts = fileName.split('.');
68
+ const action = nameParts[0].replace(/^_/, ''); // Remove leading underscore for partials
69
+ const isPartial = fileName.startsWith('_');
70
+ // Detect template type
71
+ let template;
72
+ if (fileName.endsWith('.yml')) {
73
+ template = 'yml';
74
+ }
75
+ else if (fileName.endsWith('.haml')) {
76
+ template = 'haml';
77
+ }
78
+ else if (fileName.endsWith('.erb')) {
79
+ template = 'erb';
80
+ }
81
+ else {
82
+ template = 'other';
83
+ }
84
+ const format = nameParts.length > 2 ? nameParts[1] : 'html';
85
+ // Skip partials for main page list
86
+ if (isPartial)
87
+ return null;
88
+ // Extract information from content
89
+ let partials = [];
90
+ let helpers = [];
91
+ let instanceVars = [];
92
+ let reactComponents = [];
93
+ if (template === 'yml') {
94
+ // YML files are SSR React pages - extract data fields as "instance vars"
95
+ instanceVars = extractYmlFields(content);
96
+ // Mark as SSR React page
97
+ reactComponents = [{ name: 'App', ssr: true, propsVar: '@yml_data' }];
98
+ }
99
+ else {
100
+ partials = extractPartials(content, template);
101
+ helpers = extractHelpers(content, template);
102
+ instanceVars = extractInstanceVars(content);
103
+ reactComponents = extractReactComponents(content, template);
104
+ }
105
+ return {
106
+ name: action,
107
+ path: relativePath,
108
+ controller,
109
+ action,
110
+ format,
111
+ template,
112
+ partials,
113
+ helpers,
114
+ instanceVars,
115
+ reactComponents,
116
+ };
117
+ }
118
+ catch {
119
+ return null;
120
+ }
121
+ }
122
+ function extractPartials(content, template) {
123
+ const partials = [];
124
+ if (template === 'haml') {
125
+ // HAML: = render 'partial' or = render partial: 'name'
126
+ const matches = content.matchAll(/=\s*render\s+(?:partial:\s*)?['"]([^'"]+)['"]/g);
127
+ for (const match of matches) {
128
+ partials.push(match[1]);
129
+ }
130
+ }
131
+ else if (template === 'erb') {
132
+ // ERB: <%= render 'partial' %>
133
+ const matches = content.matchAll(/<%=?\s*render\s+(?:partial:\s*)?['"]([^'"]+)['"]/g);
134
+ for (const match of matches) {
135
+ partials.push(match[1]);
136
+ }
137
+ }
138
+ return [...new Set(partials)];
139
+ }
140
+ function extractHelpers(content, _template) {
141
+ const helpers = [];
142
+ // Common helpers: link_to, form_for, image_tag, etc.
143
+ const helperPattern = /\b(link_to|form_for|form_with|image_tag|content_for|yield|render|t|l|raw|html_safe|simple_form_for)\b/g;
144
+ const matches = content.matchAll(helperPattern);
145
+ for (const match of matches) {
146
+ helpers.push(match[1]);
147
+ }
148
+ return [...new Set(helpers)];
149
+ }
150
+ function extractReactComponents(content, _template) {
151
+ const components = [];
152
+ // Pattern 1: render_react_component "ComponentName", {}, ssr: true/false
153
+ // e.g., = render_react_component("App", {}, ssr: true)
154
+ const renderReactPattern = /render_react_component\s*\(?\s*["']([^"']+)["'](?:,\s*\{[^}]*\})?\s*(?:,\s*ssr:\s*(true|false))?\)?/g;
155
+ let match;
156
+ while ((match = renderReactPattern.exec(content)) !== null) {
157
+ components.push({
158
+ name: match[1],
159
+ ssr: match[2] === 'true',
160
+ });
161
+ }
162
+ // Pattern 2: data: { react_component: "ComponentName", react_component_props: props.to_json }
163
+ // e.g., %div{ data: { react_component: "OrgPage", react_component_props: @react_state.to_json } }
164
+ const dataReactPattern = /data:\s*\{\s*react_component:\s*["']([^"']+)["'](?:,\s*react_component_props:\s*(@?\w+)(?:\.to_json)?)?/g;
165
+ while ((match = dataReactPattern.exec(content)) !== null) {
166
+ components.push({
167
+ name: match[1],
168
+ propsVar: match[2],
169
+ ssr: false,
170
+ });
171
+ }
172
+ // Pattern 3: ReactComponent name="ComponentName" (ERB style)
173
+ const reactComponentPattern = /ReactComponent\s+name=["']([^"']+)["']/g;
174
+ while ((match = reactComponentPattern.exec(content)) !== null) {
175
+ components.push({
176
+ name: match[1],
177
+ ssr: false,
178
+ });
179
+ }
180
+ // Deduplicate by name
181
+ const seen = new Set();
182
+ return components.filter((c) => {
183
+ if (seen.has(c.name))
184
+ return false;
185
+ seen.add(c.name);
186
+ return true;
187
+ });
188
+ }
189
+ function extractYmlFields(content) {
190
+ // Extract top-level keys from YML file as "data fields"
191
+ const fields = [];
192
+ const lines = content.split('\n');
193
+ for (const line of lines) {
194
+ // Top-level keys (not indented)
195
+ const topMatch = line.match(/^([a-z_]+):/);
196
+ if (topMatch && !topMatch[1].startsWith('_')) {
197
+ fields.push(topMatch[1]);
198
+ }
199
+ // _fields array items
200
+ const fieldMatch = line.match(/^\s+-\s+(\w+)/);
201
+ if (fieldMatch) {
202
+ fields.push(fieldMatch[1]);
203
+ }
204
+ }
205
+ return [...new Set(fields)].slice(0, 50); // Limit to 50 fields
206
+ }
207
+ function extractInstanceVars(content) {
208
+ const vars = [];
209
+ const matches = content.matchAll(/@(\w+)/g);
210
+ for (const match of matches) {
211
+ if (!['import', 'media', 'keyframes', 'charset'].includes(match[1])) {
212
+ vars.push(match[1]);
213
+ }
214
+ }
215
+ return [...new Set(vars)];
216
+ }
217
+ async function analyzeControllersForPages(controllersPath, views, rootPath) {
218
+ const pages = [];
219
+ try {
220
+ await fs.access(controllersPath);
221
+ }
222
+ catch {
223
+ return pages;
224
+ }
225
+ const controllerFiles = await glob('**/*_controller.rb', {
226
+ cwd: controllersPath,
227
+ nodir: true,
228
+ });
229
+ // Load routes if available
230
+ const routesMap = await loadRoutesMap(rootPath);
231
+ for (const file of controllerFiles) {
232
+ const fullPath = path.join(controllersPath, file);
233
+ const content = await fs.readFile(fullPath, 'utf-8');
234
+ // Parse controller name from filename
235
+ // e.g., users_controller.rb -> users
236
+ const controllerName = file.replace(/_controller\.rb$/, '').replace(/\//g, '/');
237
+ // Extract actions and their API calls
238
+ const controllerPages = parseControllerActions(content, controllerName, file, views, routesMap);
239
+ pages.push(...controllerPages);
240
+ }
241
+ return pages;
242
+ }
243
+ async function loadRoutesMap(rootPath) {
244
+ const routesMap = new Map();
245
+ try {
246
+ // Try to load from previously analyzed routes
247
+ const railsDataPath = path.join(rootPath, '.repomap', 'rails-routes.json');
248
+ const data = await fs.readFile(railsDataPath, 'utf-8');
249
+ const routes = JSON.parse(data);
250
+ for (const route of routes) {
251
+ const key = `${route.controller}#${route.action}`;
252
+ routesMap.set(key, { path: route.path, method: route.method });
253
+ }
254
+ }
255
+ catch {
256
+ // Routes not available
257
+ }
258
+ return routesMap;
259
+ }
260
+ function parseControllerActions(content, controllerName, sourceFile, views, routesMap) {
261
+ const pages = [];
262
+ // Extract public actions (methods before private/protected)
263
+ const publicSection = content.split(/\n\s*(private|protected)\b/)[0];
264
+ // Match action definitions
265
+ const actionPattern = /def\s+(\w+)/g;
266
+ let match;
267
+ while ((match = actionPattern.exec(publicSection)) !== null) {
268
+ const action = match[1];
269
+ // Skip common non-action methods
270
+ if (['initialize', 'new', 'create', 'update', 'destroy', 'index', 'show', 'edit'].includes(action) ||
271
+ action.startsWith('set_') ||
272
+ action.startsWith('_')) {
273
+ // These ARE valid actions, don't skip
274
+ }
275
+ // Find the action body
276
+ const actionStart = match.index;
277
+ const actionBody = extractActionBody(publicSection, actionStart);
278
+ // Extract API calls from action
279
+ const apis = extractApiCalls(actionBody, sourceFile);
280
+ const services = extractServiceCalls(actionBody);
281
+ const grpcCalls = extractGrpcCalls(actionBody);
282
+ const modelAccess = extractModelAccess(actionBody);
283
+ // Find matching view
284
+ const view = views.find((v) => v.controller === controllerName && v.action === action);
285
+ // Get route info
286
+ const routeKey = `${controllerName}#${action}`;
287
+ const routeInfo = routesMap.get(routeKey);
288
+ pages.push({
289
+ route: routeInfo?.path || `/${controllerName}/${action}`,
290
+ method: routeInfo?.method || 'GET',
291
+ controller: controllerName,
292
+ action,
293
+ view,
294
+ apis,
295
+ services,
296
+ grpcCalls,
297
+ modelAccess,
298
+ });
299
+ }
300
+ return pages;
301
+ }
302
+ function extractActionBody(content, startIndex) {
303
+ // Simple extraction - find matching 'end'
304
+ let depth = 0;
305
+ let started = false;
306
+ let body = '';
307
+ for (let i = startIndex; i < content.length; i++) {
308
+ const line = content.slice(i, content.indexOf('\n', i) + 1 || content.length);
309
+ if (line.match(/^\s*(def|class|module|if|unless|case|while|until|for|begin|do)\b/)) {
310
+ depth++;
311
+ started = true;
312
+ }
313
+ if (line.match(/^\s*end\b/)) {
314
+ depth--;
315
+ if (started && depth === 0) {
316
+ break;
317
+ }
318
+ }
319
+ body += line;
320
+ i = content.indexOf('\n', i);
321
+ if (i === -1)
322
+ break;
323
+ }
324
+ return body;
325
+ }
326
+ function extractApiCalls(content, sourceFile) {
327
+ const apis = [];
328
+ // HTTP client calls
329
+ const httpPatterns = [
330
+ /HTTPClient\.(get|post|put|patch|delete)\s*\(\s*['"]([^'"]+)['"]/gi,
331
+ /RestClient\.(get|post|put|patch|delete)\s*\(\s*['"]([^'"]+)['"]/gi,
332
+ /Faraday\.(get|post|put|patch|delete)\s*\(\s*['"]([^'"]+)['"]/gi,
333
+ /Net::HTTP\.(get|post)\s*\(/gi,
334
+ ];
335
+ for (const pattern of httpPatterns) {
336
+ let match;
337
+ while ((match = pattern.exec(content)) !== null) {
338
+ apis.push({
339
+ type: 'http',
340
+ name: match[2] || 'HTTP call',
341
+ method: match[1]?.toUpperCase(),
342
+ source: sourceFile,
343
+ });
344
+ }
345
+ }
346
+ return apis;
347
+ }
348
+ function extractServiceCalls(content) {
349
+ const services = [];
350
+ // Match Service.call or Service.call! or Service.new.call
351
+ const pattern = /(\w+(?:::\w+)*Service)\.(?:call!?|new)/g;
352
+ let match;
353
+ while ((match = pattern.exec(content)) !== null) {
354
+ services.push(match[1]);
355
+ }
356
+ return [...new Set(services)];
357
+ }
358
+ function extractGrpcCalls(content) {
359
+ const grpcCalls = [];
360
+ // Match gRPC calls: Grpc::XxxService or XxxGrpcService
361
+ const patterns = [
362
+ /(\w+(?:::\w+)*Grpc(?:::\w+)?)\./g,
363
+ /Grpc::(\w+(?:::\w+)*)/g,
364
+ /(\w+GrpcService)\./g,
365
+ ];
366
+ for (const pattern of patterns) {
367
+ let match;
368
+ while ((match = pattern.exec(content)) !== null) {
369
+ grpcCalls.push(match[1]);
370
+ }
371
+ }
372
+ return [...new Set(grpcCalls)];
373
+ }
374
+ function extractModelAccess(content) {
375
+ const models = [];
376
+ // Match model access: ModelName.find, ModelName.where, etc.
377
+ const pattern = /([A-Z][a-zA-Z0-9]+)\.(?:find|where|find_by|first|last|all|create|update|destroy|new)/g;
378
+ let match;
379
+ while ((match = pattern.exec(content)) !== null) {
380
+ // Skip common non-model classes
381
+ if (!['File', 'Dir', 'Time', 'Date', 'DateTime', 'JSON', 'YAML', 'CSV', 'Logger'].includes(match[1])) {
382
+ models.push(match[1]);
383
+ }
384
+ }
385
+ return [...new Set(models)];
386
+ }
387
+ //# sourceMappingURL=rails-view-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails-view-analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/rails/rails-view-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Ruby Parser using web-tree-sitter
3
+ * web-tree-sitterを使用したRubyパーサー
4
+ */
5
+ import { Parser, Node, Tree } from 'web-tree-sitter';
6
+ export type SyntaxNode = Node;
7
+ export { Tree };
8
+ /**
9
+ * Initialize the Ruby parser
10
+ */
11
+ export declare function initRubyParser(): Promise<Parser>;
12
+ /**
13
+ * Parse Ruby code
14
+ */
15
+ export declare function parseRuby(code: string): Promise<Tree>;
16
+ /**
17
+ * Parse Ruby file
18
+ */
19
+ export declare function parseRubyFile(filePath: string): Promise<Tree>;
20
+ /**
21
+ * Find all nodes of a specific type
22
+ */
23
+ export declare function findNodes(node: SyntaxNode, type: string): SyntaxNode[];
24
+ /**
25
+ * Find all nodes matching multiple types
26
+ */
27
+ export declare function findNodesByTypes(node: SyntaxNode, types: string[]): SyntaxNode[];
28
+ /**
29
+ * Get the text of a named child
30
+ */
31
+ export declare function getChildText(node: SyntaxNode, fieldName: string): string | null;
32
+ /**
33
+ * Get the first child of a specific type
34
+ */
35
+ export declare function getChildByType(node: SyntaxNode, type: string): SyntaxNode | null;
36
+ /**
37
+ * Get all children of a specific type
38
+ */
39
+ export declare function getChildrenByType(node: SyntaxNode, type: string): SyntaxNode[];
40
+ /**
41
+ * Extract method call arguments
42
+ */
43
+ export declare function getCallArguments(callNode: SyntaxNode): SyntaxNode[];
44
+ /**
45
+ * Check if node is inside a specific block type
46
+ */
47
+ export declare function isInsideBlock(node: SyntaxNode, blockType: string): boolean;
48
+ /**
49
+ * Get the class name from a class node
50
+ */
51
+ export declare function getClassName(classNode: SyntaxNode): string | null;
52
+ /**
53
+ * Get the superclass from a class node
54
+ */
55
+ export declare function getSuperclass(classNode: SyntaxNode): string | null;
56
+ /**
57
+ * Get method name from a method node
58
+ */
59
+ export declare function getMethodName(methodNode: SyntaxNode): string | null;
60
+ /**
61
+ * Get method parameters
62
+ */
63
+ export declare function getMethodParameters(methodNode: SyntaxNode): string[];
64
+ //# sourceMappingURL=ruby-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruby-parser.d.ts","sourceRoot":"","sources":["../../../src/analyzers/rails/ruby-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAY,MAAM,iBAAiB,CAAC;AAM/D,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC;AAC9B,OAAO,EAAE,IAAI,EAAE,CAAC;AAShB;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAqCtD;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAO3D;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGnE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAetE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAehF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAQhF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,EAAE,CAS9E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,EAAE,CAYnE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAS1E;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGjE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CASlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGnE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,CAwBpE"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Ruby Parser using web-tree-sitter
3
+ * web-tree-sitterを使用したRubyパーサー
4
+ */
5
+ import { Parser, Tree, Language } from 'web-tree-sitter';
6
+ import * as path from 'path';
7
+ import * as fs from 'fs';
8
+ import { fileURLToPath } from 'url';
9
+ export { Tree };
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+ let parserInitialized = false;
13
+ let rubyLanguage = null;
14
+ let parser = null;
15
+ /**
16
+ * Initialize the Ruby parser
17
+ */
18
+ export async function initRubyParser() {
19
+ if (parser && rubyLanguage) {
20
+ return parser;
21
+ }
22
+ if (!parserInitialized) {
23
+ await Parser.init();
24
+ parserInitialized = true;
25
+ }
26
+ parser = new Parser();
27
+ // Find WASM file - try multiple locations
28
+ const possiblePaths = [
29
+ // When running from source
30
+ path.join(process.cwd(), 'node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm'),
31
+ // When installed as dependency
32
+ path.join(__dirname, '../../../node_modules/tree-sitter-wasms/out/tree-sitter-ruby.wasm'),
33
+ path.join(__dirname, '../../../../tree-sitter-wasms/out/tree-sitter-ruby.wasm'),
34
+ ];
35
+ let wasmPath = null;
36
+ for (const p of possiblePaths) {
37
+ if (fs.existsSync(p)) {
38
+ wasmPath = p;
39
+ break;
40
+ }
41
+ }
42
+ if (!wasmPath) {
43
+ throw new Error('tree-sitter-ruby.wasm not found. Please install tree-sitter-wasms package.');
44
+ }
45
+ rubyLanguage = await Language.load(wasmPath);
46
+ parser.setLanguage(rubyLanguage);
47
+ return parser;
48
+ }
49
+ /**
50
+ * Parse Ruby code
51
+ */
52
+ export async function parseRuby(code) {
53
+ const p = await initRubyParser();
54
+ const tree = p.parse(code);
55
+ if (!tree) {
56
+ throw new Error('Failed to parse Ruby code');
57
+ }
58
+ return tree;
59
+ }
60
+ /**
61
+ * Parse Ruby file
62
+ */
63
+ export async function parseRubyFile(filePath) {
64
+ const code = fs.readFileSync(filePath, 'utf-8');
65
+ return parseRuby(code);
66
+ }
67
+ /**
68
+ * Find all nodes of a specific type
69
+ */
70
+ export function findNodes(node, type) {
71
+ const results = [];
72
+ if (node.type === type) {
73
+ results.push(node);
74
+ }
75
+ for (let i = 0; i < node.childCount; i++) {
76
+ const child = node.child(i);
77
+ if (child) {
78
+ results.push(...findNodes(child, type));
79
+ }
80
+ }
81
+ return results;
82
+ }
83
+ /**
84
+ * Find all nodes matching multiple types
85
+ */
86
+ export function findNodesByTypes(node, types) {
87
+ const results = [];
88
+ if (types.includes(node.type)) {
89
+ results.push(node);
90
+ }
91
+ for (let i = 0; i < node.childCount; i++) {
92
+ const child = node.child(i);
93
+ if (child) {
94
+ results.push(...findNodesByTypes(child, types));
95
+ }
96
+ }
97
+ return results;
98
+ }
99
+ /**
100
+ * Get the text of a named child
101
+ */
102
+ export function getChildText(node, fieldName) {
103
+ const child = node.childForFieldName(fieldName);
104
+ return child ? child.text : null;
105
+ }
106
+ /**
107
+ * Get the first child of a specific type
108
+ */
109
+ export function getChildByType(node, type) {
110
+ for (let i = 0; i < node.childCount; i++) {
111
+ const child = node.child(i);
112
+ if (child && child.type === type) {
113
+ return child;
114
+ }
115
+ }
116
+ return null;
117
+ }
118
+ /**
119
+ * Get all children of a specific type
120
+ */
121
+ export function getChildrenByType(node, type) {
122
+ const results = [];
123
+ for (let i = 0; i < node.childCount; i++) {
124
+ const child = node.child(i);
125
+ if (child && child.type === type) {
126
+ results.push(child);
127
+ }
128
+ }
129
+ return results;
130
+ }
131
+ /**
132
+ * Extract method call arguments
133
+ */
134
+ export function getCallArguments(callNode) {
135
+ const args = callNode.childForFieldName('arguments');
136
+ if (!args)
137
+ return [];
138
+ const results = [];
139
+ for (let i = 0; i < args.childCount; i++) {
140
+ const child = args.child(i);
141
+ if (child && child.type !== '(' && child.type !== ')' && child.type !== ',') {
142
+ results.push(child);
143
+ }
144
+ }
145
+ return results;
146
+ }
147
+ /**
148
+ * Check if node is inside a specific block type
149
+ */
150
+ export function isInsideBlock(node, blockType) {
151
+ let current = node.parent;
152
+ while (current) {
153
+ if (current.type === blockType) {
154
+ return true;
155
+ }
156
+ current = current.parent;
157
+ }
158
+ return false;
159
+ }
160
+ /**
161
+ * Get the class name from a class node
162
+ */
163
+ export function getClassName(classNode) {
164
+ const nameNode = classNode.childForFieldName('name');
165
+ return nameNode ? nameNode.text : null;
166
+ }
167
+ /**
168
+ * Get the superclass from a class node
169
+ */
170
+ export function getSuperclass(classNode) {
171
+ const superclassNode = classNode.childForFieldName('superclass');
172
+ if (!superclassNode)
173
+ return null;
174
+ // superclass node contains "< ClassName", extract just the class name
175
+ const constantNode = getChildByType(superclassNode, 'constant') ||
176
+ getChildByType(superclassNode, 'scope_resolution');
177
+ return constantNode ? constantNode.text : null;
178
+ }
179
+ /**
180
+ * Get method name from a method node
181
+ */
182
+ export function getMethodName(methodNode) {
183
+ const nameNode = methodNode.childForFieldName('name');
184
+ return nameNode ? nameNode.text : null;
185
+ }
186
+ /**
187
+ * Get method parameters
188
+ */
189
+ export function getMethodParameters(methodNode) {
190
+ const paramsNode = methodNode.childForFieldName('parameters');
191
+ if (!paramsNode)
192
+ return [];
193
+ const params = [];
194
+ for (let i = 0; i < paramsNode.childCount; i++) {
195
+ const child = paramsNode.child(i);
196
+ if (child &&
197
+ (child.type === 'identifier' ||
198
+ child.type === 'keyword_parameter' ||
199
+ child.type === 'optional_parameter' ||
200
+ child.type === 'splat_parameter')) {
201
+ // Extract the parameter name
202
+ const nameNode = child.childForFieldName('name') || child;
203
+ if (nameNode.type === 'identifier') {
204
+ params.push(nameNode.text);
205
+ }
206
+ else {
207
+ params.push(child.text);
208
+ }
209
+ }
210
+ }
211
+ return params;
212
+ }
213
+ //# sourceMappingURL=ruby-parser.js.map