tree-sitter-analyzer 0.6.2__py3-none-any.whl → 0.7.0__py3-none-any.whl

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.

Potentially problematic release.


This version of tree-sitter-analyzer might be problematic. Click here for more details.

@@ -53,25 +53,26 @@ class TableFormatter:
53
53
  return self._convert_to_platform_newlines(result)
54
54
 
55
55
  def _format_full_table(self, data: dict[str, Any]) -> str:
56
- """Full table format"""
56
+ """Full table format - organized by class"""
57
57
  lines = []
58
58
 
59
- # Header - use filename when multiple classes exist
59
+ # Header - use filename for multi-class files
60
60
  classes = data.get("classes", [])
61
61
  if classes is None:
62
62
  classes = []
63
- if len(classes) > 1:
64
- # Use file name when multiple classes exist
65
- file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
66
- lines.append(f"# {file_name}")
67
- else:
68
- # Use class name for single class as before
69
- class_name = classes[0].get("name", "Unknown") if classes else "Unknown"
70
- lines.append(
71
- f"# {(data.get('package') or {}).get('name', 'unknown')}.{class_name}"
72
- )
63
+
64
+ # Always use filename for header to be consistent
65
+ file_name = data.get("file_path", "Unknown").split("/")[-1].split("\\")[-1]
66
+ lines.append(f"# {file_name}")
73
67
  lines.append("")
74
68
 
69
+ # Package info
70
+ package_name = (data.get("package") or {}).get("name", "")
71
+ if package_name:
72
+ lines.append("## Package")
73
+ lines.append(f"`{package_name}`")
74
+ lines.append("")
75
+
75
76
  # Imports
76
77
  imports = data.get("imports", [])
77
78
  if imports:
@@ -82,12 +83,9 @@ class TableFormatter:
82
83
  lines.append("```")
83
84
  lines.append("")
84
85
 
85
- # Class Info - Support for multiple classes
86
- classes = data.get("classes", [])
87
- if classes is None:
88
- classes = []
86
+ # Classes Overview
89
87
  if len(classes) > 1:
90
- lines.append("## Classes")
88
+ lines.append("## Classes Overview")
91
89
  lines.append("| Class | Type | Visibility | Lines | Methods | Fields |")
92
90
  lines.append("|-------|------|------------|-------|---------|--------|")
93
91
 
@@ -99,51 +97,198 @@ class TableFormatter:
99
97
  lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
100
98
 
101
99
  # Calculate method and field counts for this class
102
- class_methods = [
103
- m
104
- for m in data.get("methods", [])
105
- if line_range.get("start", 0)
106
- <= m.get("line_range", {}).get("start", 0)
107
- <= line_range.get("end", 0)
108
- ]
109
- class_fields = [
110
- f
111
- for f in data.get("fields", [])
112
- if line_range.get("start", 0)
113
- <= f.get("line_range", {}).get("start", 0)
114
- <= line_range.get("end", 0)
115
- ]
100
+ class_methods = self._get_class_methods(data, line_range)
101
+ class_fields = self._get_class_fields(data, line_range)
116
102
 
117
103
  lines.append(
118
104
  f"| {name} | {class_type} | {visibility} | {lines_str} | {len(class_methods)} | {len(class_fields)} |"
119
105
  )
120
- else:
121
- # Use traditional format for single class
122
- lines.append("## Class Info")
123
- lines.append("| Property | Value |")
124
- lines.append("|----------|-------|")
125
-
126
- package_name = (data.get("package") or {}).get("name", "unknown")
127
- class_info = data.get("classes", [{}])[0] if data.get("classes") else {}
128
- stats = data.get("statistics") or {}
129
-
130
- lines.append(f"| Package | {package_name} |")
131
- lines.append(f"| Type | {str(class_info.get('type', 'class'))} |")
132
- lines.append(
133
- f"| Visibility | {str(class_info.get('visibility', 'public'))} |"
134
- )
135
- lines.append(
136
- f"| Lines | {class_info.get('line_range', {}).get('start', 0)}-{class_info.get('line_range', {}).get('end', 0)} |"
137
- )
138
- lines.append(f"| Total Methods | {stats.get('method_count', 0)} |")
139
- lines.append(f"| Total Fields | {stats.get('field_count', 0)} |")
106
+ lines.append("")
107
+
108
+ # Detailed class information - organized by class
109
+ for class_info in classes:
110
+ lines.extend(self._format_class_details(class_info, data))
111
+
112
+ # Remove trailing empty lines
113
+ while lines and lines[-1] == "":
114
+ lines.pop()
115
+
116
+ return "\n".join(lines)
117
+
118
+ def _get_class_methods(self, data: dict[str, Any], class_line_range: dict[str, int]) -> list[dict[str, Any]]:
119
+ """Get methods that belong to a specific class based on line range, excluding nested classes."""
120
+ methods = data.get("methods", [])
121
+ classes = data.get("classes", [])
122
+ class_methods = []
123
+
124
+ # Get nested class ranges to exclude their methods
125
+ nested_class_ranges = []
126
+ for cls in classes:
127
+ cls_range = cls.get("line_range", {})
128
+ cls_start = cls_range.get("start", 0)
129
+ cls_end = cls_range.get("end", 0)
130
+
131
+ # If this class is nested within the current class range
132
+ if (class_line_range.get("start", 0) < cls_start and
133
+ cls_end < class_line_range.get("end", 0)):
134
+ nested_class_ranges.append((cls_start, cls_end))
135
+
136
+ for method in methods:
137
+ method_line = method.get("line_range", {}).get("start", 0)
138
+
139
+ # Check if method is within the class range
140
+ if (class_line_range.get("start", 0) <= method_line <= class_line_range.get("end", 0)):
141
+ # Check if method is NOT within any nested class
142
+ in_nested_class = False
143
+ for nested_start, nested_end in nested_class_ranges:
144
+ if nested_start <= method_line <= nested_end:
145
+ in_nested_class = True
146
+ break
147
+
148
+ if not in_nested_class:
149
+ class_methods.append(method)
150
+
151
+ return class_methods
152
+
153
+ def _get_class_fields(self, data: dict[str, Any], class_line_range: dict[str, int]) -> list[dict[str, Any]]:
154
+ """Get fields that belong to a specific class based on line range, excluding nested classes."""
155
+ fields = data.get("fields", [])
156
+ classes = data.get("classes", [])
157
+ class_fields = []
158
+
159
+ # Get nested class ranges to exclude their fields
160
+ nested_class_ranges = []
161
+ for cls in classes:
162
+ cls_range = cls.get("line_range", {})
163
+ cls_start = cls_range.get("start", 0)
164
+ cls_end = cls_range.get("end", 0)
165
+
166
+ # If this class is nested within the current class range
167
+ if (class_line_range.get("start", 0) < cls_start and
168
+ cls_end < class_line_range.get("end", 0)):
169
+ nested_class_ranges.append((cls_start, cls_end))
170
+
171
+ for field in fields:
172
+ field_line = field.get("line_range", {}).get("start", 0)
173
+
174
+ # Check if field is within the class range
175
+ if (class_line_range.get("start", 0) <= field_line <= class_line_range.get("end", 0)):
176
+ # Check if field is NOT within any nested class
177
+ in_nested_class = False
178
+ for nested_start, nested_end in nested_class_ranges:
179
+ if nested_start <= field_line <= nested_end:
180
+ in_nested_class = True
181
+ break
182
+
183
+ if not in_nested_class:
184
+ class_fields.append(field)
185
+
186
+ return class_fields
187
+
188
+ def _format_class_details(self, class_info: dict[str, Any], data: dict[str, Any]) -> list[str]:
189
+ """Format detailed information for a single class."""
190
+ lines = []
191
+
192
+ name = str(class_info.get("name", "Unknown"))
193
+ line_range = class_info.get("line_range", {})
194
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
195
+
196
+ # Class header
197
+ lines.append(f"## {name} ({lines_str})")
198
+
199
+ # Get class-specific methods and fields
200
+ class_methods = self._get_class_methods(data, line_range)
201
+ class_fields = self._get_class_fields(data, line_range)
202
+
203
+ # Fields section
204
+ if class_fields:
205
+ lines.append("### Fields")
206
+ lines.append("| Name | Type | Vis | Modifiers | Line | Doc |")
207
+ lines.append("|------|------|-----|-----------|------|-----|")
208
+
209
+ for field in class_fields:
210
+ name_field = str(field.get("name", ""))
211
+ type_field = str(field.get("type", ""))
212
+ visibility = self._convert_visibility(str(field.get("visibility", "")))
213
+ modifiers = ",".join(field.get("modifiers", []))
214
+ line_num = field.get("line_range", {}).get("start", 0)
215
+ doc = self._extract_doc_summary(str(field.get("javadoc", ""))) if self.include_javadoc else "-"
216
+
217
+ lines.append(f"| {name_field} | {type_field} | {visibility} | {modifiers} | {line_num} | {doc} |")
218
+ lines.append("")
219
+
220
+ # Methods section - separate by type
221
+ constructors = [m for m in class_methods if m.get("is_constructor", False)]
222
+ regular_methods = [m for m in class_methods if not m.get("is_constructor", False)]
223
+
224
+ # Constructors
225
+ if constructors:
226
+ lines.append("### Constructors")
227
+ lines.append("| Constructor | Signature | Vis | Lines | Cx | Doc |")
228
+ lines.append("|-------------|-----------|-----|-------|----|----|")
140
229
 
230
+ for method in constructors:
231
+ lines.append(self._format_method_row_detailed(method))
232
+ lines.append("")
233
+
234
+ # Methods grouped by visibility
235
+ public_methods = [m for m in regular_methods if m.get("visibility", "") == "public"]
236
+ protected_methods = [m for m in regular_methods if m.get("visibility", "") == "protected"]
237
+ package_methods = [m for m in regular_methods if m.get("visibility", "") == "package"]
238
+ private_methods = [m for m in regular_methods if m.get("visibility", "") == "private"]
239
+
240
+ for method_group, title in [
241
+ (public_methods, "Public Methods"),
242
+ (protected_methods, "Protected Methods"),
243
+ (package_methods, "Package Methods"),
244
+ (private_methods, "Private Methods")
245
+ ]:
246
+ if method_group:
247
+ lines.append(f"### {title}")
248
+ lines.append("| Method | Signature | Vis | Lines | Cx | Doc |")
249
+ lines.append("|--------|-----------|-----|-------|----|----|")
250
+
251
+ for method in method_group:
252
+ lines.append(self._format_method_row_detailed(method))
253
+ lines.append("")
254
+
255
+ return lines
256
+
257
+ def _format_method_row_detailed(self, method: dict[str, Any]) -> str:
258
+ """Format method row for detailed class view."""
259
+ name = str(method.get("name", ""))
260
+ signature = self._create_full_signature(method)
261
+ visibility = self._convert_visibility(str(method.get("visibility", "")))
262
+ line_range = method.get("line_range", {})
263
+ lines_str = f"{line_range.get('start', 0)}-{line_range.get('end', 0)}"
264
+ complexity = method.get("complexity_score", 0)
265
+ doc = self._extract_doc_summary(str(method.get("javadoc", ""))) if self.include_javadoc else "-"
266
+
267
+ return f"| {name} | {signature} | {visibility} | {lines_str} | {complexity} | {doc} |"
268
+
269
+ def _format_traditional_sections(self, data: dict[str, Any]) -> list[str]:
270
+ """Format traditional sections when no classes are found."""
271
+ lines = []
272
+
273
+ # Traditional class info
274
+ lines.append("## Class Info")
275
+ lines.append("| Property | Value |")
276
+ lines.append("|----------|-------|")
277
+
278
+ package_name = (data.get("package") or {}).get("name", "unknown")
279
+ class_info = data.get("classes", [{}])[0] if data.get("classes") else {}
280
+ stats = data.get("statistics") or {}
281
+
282
+ lines.append(f"| Package | {package_name} |")
283
+ lines.append(f"| Type | {str(class_info.get('type', 'class'))} |")
284
+ lines.append(f"| Visibility | {str(class_info.get('visibility', 'public'))} |")
285
+ lines.append(f"| Lines | {class_info.get('line_range', {}).get('start', 0)}-{class_info.get('line_range', {}).get('end', 0)} |")
286
+ lines.append(f"| Total Methods | {stats.get('method_count', 0)} |")
287
+ lines.append(f"| Total Fields | {stats.get('field_count', 0)} |")
141
288
  lines.append("")
142
289
 
143
290
  # Fields
144
291
  fields = data.get("fields", [])
145
- if fields is None:
146
- fields = []
147
292
  if fields:
148
293
  lines.append("## Fields")
149
294
  lines.append("| Name | Type | Vis | Modifiers | Line | Doc |")
@@ -155,66 +300,37 @@ class TableFormatter:
155
300
  visibility = self._convert_visibility(str(field.get("visibility", "")))
156
301
  modifiers = ",".join([str(m) for m in field.get("modifiers", [])])
157
302
  line = field.get("line_range", {}).get("start", 0)
158
- if self.include_javadoc:
159
- doc = self._extract_doc_summary(str(field.get("javadoc", "")))
160
- else:
161
- doc = "-"
303
+ doc = self._extract_doc_summary(str(field.get("javadoc", ""))) if self.include_javadoc else "-"
162
304
 
163
- lines.append(
164
- f"| {name} | {field_type} | {visibility} | {modifiers} | {line} | {doc} |"
165
- )
305
+ lines.append(f"| {name} | {field_type} | {visibility} | {modifiers} | {line} | {doc} |")
166
306
  lines.append("")
167
307
 
168
- # Constructor
169
- constructors = [
170
- m for m in (data.get("methods") or []) if m.get("is_constructor", False)
171
- ]
308
+ # Methods by type
309
+ methods = data.get("methods", [])
310
+ constructors = [m for m in methods if m.get("is_constructor", False)]
311
+ regular_methods = [m for m in methods if not m.get("is_constructor", False)]
312
+
313
+ # Constructors
172
314
  if constructors:
173
315
  lines.append("## Constructor")
174
316
  lines.append("| Method | Signature | Vis | Lines | Cols | Cx | Doc |")
175
317
  lines.append("|--------|-----------|-----|-------|------|----|----|")
176
-
177
318
  for method in constructors:
178
319
  lines.append(self._format_method_row(method))
179
320
  lines.append("")
180
321
 
181
- # Public Methods
182
- public_methods = [
183
- m
184
- for m in (data.get("methods") or [])
185
- if not m.get("is_constructor", False)
186
- and str(m.get("visibility")) == "public"
187
- ]
188
- if public_methods:
189
- lines.append("## Public Methods")
190
- lines.append("| Method | Signature | Vis | Lines | Cols | Cx | Doc |")
191
- lines.append("|--------|-----------|-----|-------|------|----|----|")
192
-
193
- for method in public_methods:
194
- lines.append(self._format_method_row(method))
195
- lines.append("")
196
-
197
- # Private Methods
198
- private_methods = [
199
- m
200
- for m in (data.get("methods") or [])
201
- if not m.get("is_constructor", False)
202
- and str(m.get("visibility")) == "private"
203
- ]
204
- if private_methods:
205
- lines.append("## Private Methods")
206
- lines.append("| Method | Signature | Vis | Lines | Cols | Cx | Doc |")
207
- lines.append("|--------|-----------|-----|-------|------|----|----|")
208
-
209
- for method in private_methods:
210
- lines.append(self._format_method_row(method))
211
- lines.append("")
212
-
213
- # Remove trailing empty lines
214
- while lines and lines[-1] == "":
215
- lines.pop()
216
-
217
- return "\n".join(lines)
322
+ # Methods by visibility
323
+ for visibility, title in [("public", "Public Methods"), ("private", "Private Methods")]:
324
+ visibility_methods = [m for m in regular_methods if str(m.get("visibility")) == visibility]
325
+ if visibility_methods:
326
+ lines.append(f"## {title}")
327
+ lines.append("| Method | Signature | Vis | Lines | Cols | Cx | Doc |")
328
+ lines.append("|--------|-----------|-----|-------|------|----|----|")
329
+ for method in visibility_methods:
330
+ lines.append(self._format_method_row(method))
331
+ lines.append("")
332
+
333
+ return lines
218
334
 
219
335
  def _format_compact_table(self, data: dict[str, Any]) -> str:
220
336
  """Compact table format"""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tree-sitter-analyzer
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: Extensible multi-language code analyzer framework using Tree-sitter with dynamic plugin architecture
5
5
  Project-URL: Homepage, https://github.com/aimasteracc/tree-sitter-analyzer
6
6
  Project-URL: Documentation, https://github.com/aimasteracc/tree-sitter-analyzer#readme
@@ -10,7 +10,7 @@ tree_sitter_analyzer/language_loader.py,sha256=gdLxkSoajm-q7c1vcvFONtBf5XJRgasUV
10
10
  tree_sitter_analyzer/models.py,sha256=z0aqdZOVA8rYWF0143TSAUoCvncVRLZ1O70eAjV87gU,16564
11
11
  tree_sitter_analyzer/output_manager.py,sha256=saZ8Ss6PhUJgjjwviLgrePFL7CCLMixxdKtdrpuFgHM,8146
12
12
  tree_sitter_analyzer/query_loader.py,sha256=jcJc6_kIMeZINfTVGuiEmDii9LViP_pbJfg4A9phJY4,9863
13
- tree_sitter_analyzer/table_formatter.py,sha256=NS8nPrgi_tjlqksRXtoPCv6NAUD4scNPH_-MQAIdU1s,17798
13
+ tree_sitter_analyzer/table_formatter.py,sha256=6BsmXni1eiwGxLBF-nV1h8Nyya8T9bRP_obOpAE1Xic,23796
14
14
  tree_sitter_analyzer/utils.py,sha256=AarFoPxiU20y8U8ysy8G6JWK-XLMP3tUoySv6qc8nr8,7991
15
15
  tree_sitter_analyzer/cli/__init__.py,sha256=O_3URpbdu5Ilb2-r48LjbZuWtOWQu_BhL3pa6C0G3Bk,871
16
16
  tree_sitter_analyzer/cli/__main__.py,sha256=Xq8o8-0dPnMDU9WZqmqhzr98rx8rvoffTUHAkAwl-L8,218
@@ -66,7 +66,7 @@ tree_sitter_analyzer/queries/java.py,sha256=NZTSzFADlGrm3MD0oIkOdkN_6wP2pGZpNs0R
66
66
  tree_sitter_analyzer/queries/javascript.py,sha256=pnXrgISwDE5GhPHDbUKEGI3thyLmebTeQt-l_-x4qT8,3962
67
67
  tree_sitter_analyzer/queries/python.py,sha256=L33KRUyV3sAvA3_HFkPyGgtiq0ygSpNY_n2YojodPlc,7570
68
68
  tree_sitter_analyzer/queries/typescript.py,sha256=eersyAF7TladuCWa8WE_-cO9YTF1LUSjLIl-tk2fZDo,6708
69
- tree_sitter_analyzer-0.6.2.dist-info/METADATA,sha256=lkgv431sXkEnLiLoZuK47muCiKqmEJqYPySwZAXyA8E,13410
70
- tree_sitter_analyzer-0.6.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
71
- tree_sitter_analyzer-0.6.2.dist-info/entry_points.txt,sha256=EA0Ow27x2SqNt2300sv70RTWxKRIxJzOhNPIVlez4NM,417
72
- tree_sitter_analyzer-0.6.2.dist-info/RECORD,,
69
+ tree_sitter_analyzer-0.7.0.dist-info/METADATA,sha256=tw9dLVI_6-kKpiK_bzQ7Z-PW7XhoP9pTJpsHeq2AlUo,13410
70
+ tree_sitter_analyzer-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
71
+ tree_sitter_analyzer-0.7.0.dist-info/entry_points.txt,sha256=EA0Ow27x2SqNt2300sv70RTWxKRIxJzOhNPIVlez4NM,417
72
+ tree_sitter_analyzer-0.7.0.dist-info/RECORD,,