tree-sitter-analyzer 0.3.0__py3-none-any.whl → 0.6.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.
- tree_sitter_analyzer/__init__.py +5 -6
- tree_sitter_analyzer/__main__.py +2 -2
- tree_sitter_analyzer/api.py +4 -2
- tree_sitter_analyzer/cli/__init__.py +3 -3
- tree_sitter_analyzer/cli/commands/advanced_command.py +1 -1
- tree_sitter_analyzer/cli/commands/base_command.py +1 -1
- tree_sitter_analyzer/cli/commands/default_command.py +1 -1
- tree_sitter_analyzer/cli/commands/partial_read_command.py +2 -2
- tree_sitter_analyzer/cli/commands/query_command.py +5 -5
- tree_sitter_analyzer/cli/commands/summary_command.py +2 -2
- tree_sitter_analyzer/cli/commands/table_command.py +14 -11
- tree_sitter_analyzer/cli/info_commands.py +14 -13
- tree_sitter_analyzer/cli_main.py +51 -31
- tree_sitter_analyzer/core/analysis_engine.py +54 -90
- tree_sitter_analyzer/core/cache_service.py +31 -31
- tree_sitter_analyzer/core/engine.py +6 -4
- tree_sitter_analyzer/core/parser.py +1 -1
- tree_sitter_analyzer/core/query.py +502 -494
- tree_sitter_analyzer/encoding_utils.py +3 -2
- tree_sitter_analyzer/exceptions.py +23 -23
- tree_sitter_analyzer/file_handler.py +7 -14
- tree_sitter_analyzer/formatters/base_formatter.py +18 -18
- tree_sitter_analyzer/formatters/formatter_factory.py +15 -15
- tree_sitter_analyzer/formatters/java_formatter.py +291 -287
- tree_sitter_analyzer/formatters/python_formatter.py +259 -255
- tree_sitter_analyzer/interfaces/cli.py +1 -1
- tree_sitter_analyzer/interfaces/cli_adapter.py +62 -41
- tree_sitter_analyzer/interfaces/mcp_adapter.py +43 -17
- tree_sitter_analyzer/interfaces/mcp_server.py +9 -9
- tree_sitter_analyzer/language_detector.py +398 -398
- tree_sitter_analyzer/language_loader.py +224 -224
- tree_sitter_analyzer/languages/java_plugin.py +1174 -1129
- tree_sitter_analyzer/{plugins → languages}/javascript_plugin.py +3 -3
- tree_sitter_analyzer/languages/python_plugin.py +26 -8
- tree_sitter_analyzer/mcp/resources/code_file_resource.py +0 -3
- tree_sitter_analyzer/mcp/resources/project_stats_resource.py +555 -560
- tree_sitter_analyzer/mcp/server.py +4 -4
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +63 -30
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +9 -4
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +2 -2
- tree_sitter_analyzer/mcp/utils/__init__.py +10 -8
- tree_sitter_analyzer/models.py +470 -470
- tree_sitter_analyzer/output_manager.py +12 -20
- tree_sitter_analyzer/plugins/__init__.py +9 -62
- tree_sitter_analyzer/plugins/base.py +53 -1
- tree_sitter_analyzer/plugins/manager.py +29 -12
- tree_sitter_analyzer/queries/java.py +78 -78
- tree_sitter_analyzer/queries/javascript.py +7 -7
- tree_sitter_analyzer/queries/python.py +18 -18
- tree_sitter_analyzer/queries/typescript.py +12 -12
- tree_sitter_analyzer/query_loader.py +17 -14
- tree_sitter_analyzer/table_formatter.py +24 -19
- tree_sitter_analyzer/utils.py +7 -7
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.6.0.dist-info}/METADATA +11 -11
- tree_sitter_analyzer-0.6.0.dist-info/RECORD +72 -0
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.6.0.dist-info}/entry_points.txt +2 -1
- tree_sitter_analyzer/java_analyzer.py +0 -218
- tree_sitter_analyzer/plugins/java_plugin.py +0 -608
- tree_sitter_analyzer/plugins/plugin_loader.py +0 -85
- tree_sitter_analyzer/plugins/python_plugin.py +0 -606
- tree_sitter_analyzer/plugins/registry.py +0 -374
- tree_sitter_analyzer-0.3.0.dist-info/RECORD +0 -77
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.6.0.dist-info}/WHEEL +0 -0
|
@@ -151,17 +151,18 @@ class EncodingManager:
|
|
|
151
151
|
FALLBACK_ENCODINGS = ["utf-8", "cp1252", "iso-8859-1", "shift_jis", "gbk"]
|
|
152
152
|
|
|
153
153
|
@classmethod
|
|
154
|
-
def safe_encode(cls, text: str, encoding: str | None = None) -> bytes:
|
|
154
|
+
def safe_encode(cls, text: str | None, encoding: str | None = None) -> bytes:
|
|
155
155
|
"""
|
|
156
156
|
Safely encode text to bytes with fallback handling
|
|
157
157
|
|
|
158
158
|
Args:
|
|
159
|
-
text: Text to encode
|
|
159
|
+
text: Text to encode (can be None)
|
|
160
160
|
encoding: Target encoding (defaults to UTF-8)
|
|
161
161
|
|
|
162
162
|
Returns:
|
|
163
163
|
Encoded bytes
|
|
164
164
|
"""
|
|
165
|
+
# Handle None input
|
|
165
166
|
if text is None:
|
|
166
167
|
return b""
|
|
167
168
|
|
|
@@ -42,7 +42,7 @@ class AnalysisError(TreeSitterAnalyzerError):
|
|
|
42
42
|
message: str,
|
|
43
43
|
file_path: str | Path | None = None,
|
|
44
44
|
language: str | None = None,
|
|
45
|
-
**kwargs,
|
|
45
|
+
**kwargs: Any,
|
|
46
46
|
) -> None:
|
|
47
47
|
context = kwargs.get("context", {})
|
|
48
48
|
if file_path:
|
|
@@ -60,7 +60,7 @@ class ParseError(TreeSitterAnalyzerError):
|
|
|
60
60
|
message: str,
|
|
61
61
|
language: str | None = None,
|
|
62
62
|
source_info: dict[str, Any] | None = None,
|
|
63
|
-
**kwargs,
|
|
63
|
+
**kwargs: Any,
|
|
64
64
|
) -> None:
|
|
65
65
|
context = kwargs.get("context", {})
|
|
66
66
|
if language:
|
|
@@ -74,7 +74,7 @@ class LanguageNotSupportedError(TreeSitterAnalyzerError):
|
|
|
74
74
|
"""Raised when a language is not supported."""
|
|
75
75
|
|
|
76
76
|
def __init__(
|
|
77
|
-
self, language: str, supported_languages: list | None = None, **kwargs
|
|
77
|
+
self, language: str, supported_languages: list[str] | None = None, **kwargs: Any
|
|
78
78
|
) -> None:
|
|
79
79
|
message = f"Language '{language}' is not supported"
|
|
80
80
|
context = kwargs.get("context", {})
|
|
@@ -93,7 +93,7 @@ class PluginError(TreeSitterAnalyzerError):
|
|
|
93
93
|
message: str,
|
|
94
94
|
plugin_name: str | None = None,
|
|
95
95
|
operation: str | None = None,
|
|
96
|
-
**kwargs,
|
|
96
|
+
**kwargs: Any,
|
|
97
97
|
) -> None:
|
|
98
98
|
context = kwargs.get("context", {})
|
|
99
99
|
if plugin_name:
|
|
@@ -112,7 +112,7 @@ class QueryError(TreeSitterAnalyzerError):
|
|
|
112
112
|
query_name: str | None = None,
|
|
113
113
|
query_string: str | None = None,
|
|
114
114
|
language: str | None = None,
|
|
115
|
-
**kwargs,
|
|
115
|
+
**kwargs: Any,
|
|
116
116
|
) -> None:
|
|
117
117
|
context = kwargs.get("context", {})
|
|
118
118
|
if query_name:
|
|
@@ -132,7 +132,7 @@ class FileHandlingError(TreeSitterAnalyzerError):
|
|
|
132
132
|
message: str,
|
|
133
133
|
file_path: str | Path | None = None,
|
|
134
134
|
operation: str | None = None,
|
|
135
|
-
**kwargs,
|
|
135
|
+
**kwargs: Any,
|
|
136
136
|
) -> None:
|
|
137
137
|
context = kwargs.get("context", {})
|
|
138
138
|
if file_path:
|
|
@@ -150,7 +150,7 @@ class ConfigurationError(TreeSitterAnalyzerError):
|
|
|
150
150
|
message: str,
|
|
151
151
|
config_key: str | None = None,
|
|
152
152
|
config_value: Any | None = None,
|
|
153
|
-
**kwargs,
|
|
153
|
+
**kwargs: Any,
|
|
154
154
|
) -> None:
|
|
155
155
|
context = kwargs.get("context", {})
|
|
156
156
|
if config_key:
|
|
@@ -168,7 +168,7 @@ class ValidationError(TreeSitterAnalyzerError):
|
|
|
168
168
|
message: str,
|
|
169
169
|
validation_type: str | None = None,
|
|
170
170
|
invalid_value: Any | None = None,
|
|
171
|
-
**kwargs,
|
|
171
|
+
**kwargs: Any,
|
|
172
172
|
) -> None:
|
|
173
173
|
context = kwargs.get("context", {})
|
|
174
174
|
if validation_type:
|
|
@@ -186,7 +186,7 @@ class MCPError(TreeSitterAnalyzerError):
|
|
|
186
186
|
message: str,
|
|
187
187
|
tool_name: str | None = None,
|
|
188
188
|
resource_uri: str | None = None,
|
|
189
|
-
**kwargs,
|
|
189
|
+
**kwargs: Any,
|
|
190
190
|
) -> None:
|
|
191
191
|
context = kwargs.get("context", {})
|
|
192
192
|
if tool_name:
|
|
@@ -200,7 +200,7 @@ class MCPError(TreeSitterAnalyzerError):
|
|
|
200
200
|
def handle_exception(
|
|
201
201
|
exception: Exception,
|
|
202
202
|
context: dict[str, Any] | None = None,
|
|
203
|
-
reraise_as: type | None = None,
|
|
203
|
+
reraise_as: type[Exception] | None = None,
|
|
204
204
|
) -> None:
|
|
205
205
|
"""
|
|
206
206
|
Handle exceptions with optional context and re-raising.
|
|
@@ -231,13 +231,13 @@ def handle_exception(
|
|
|
231
231
|
|
|
232
232
|
|
|
233
233
|
def safe_execute(
|
|
234
|
-
func,
|
|
235
|
-
*args,
|
|
236
|
-
default_return=None,
|
|
237
|
-
exception_types: tuple = (Exception,),
|
|
234
|
+
func: Any,
|
|
235
|
+
*args: Any,
|
|
236
|
+
default_return: Any = None,
|
|
237
|
+
exception_types: tuple[type[Exception], ...] = (Exception,),
|
|
238
238
|
log_errors: bool = True,
|
|
239
|
-
**kwargs,
|
|
240
|
-
):
|
|
239
|
+
**kwargs: Any,
|
|
240
|
+
) -> Any:
|
|
241
241
|
"""
|
|
242
242
|
Safely execute a function with exception handling.
|
|
243
243
|
|
|
@@ -277,7 +277,7 @@ def create_error_response(
|
|
|
277
277
|
"""
|
|
278
278
|
import traceback
|
|
279
279
|
|
|
280
|
-
response = {
|
|
280
|
+
response: dict[str, Any] = {
|
|
281
281
|
"success": False,
|
|
282
282
|
"error": {"type": exception.__class__.__name__, "message": str(exception)},
|
|
283
283
|
}
|
|
@@ -299,11 +299,11 @@ def create_error_response(
|
|
|
299
299
|
|
|
300
300
|
# Decorator for exception handling
|
|
301
301
|
def handle_exceptions(
|
|
302
|
-
default_return=None,
|
|
303
|
-
exception_types: tuple = (Exception,),
|
|
304
|
-
reraise_as: type | None = None,
|
|
302
|
+
default_return: Any = None,
|
|
303
|
+
exception_types: tuple[type[Exception], ...] = (Exception,),
|
|
304
|
+
reraise_as: type[Exception] | None = None,
|
|
305
305
|
log_errors: bool = True,
|
|
306
|
-
):
|
|
306
|
+
) -> Any:
|
|
307
307
|
"""
|
|
308
308
|
Decorator for automatic exception handling.
|
|
309
309
|
|
|
@@ -314,8 +314,8 @@ def handle_exceptions(
|
|
|
314
314
|
log_errors: Whether to log errors
|
|
315
315
|
"""
|
|
316
316
|
|
|
317
|
-
def decorator(func):
|
|
318
|
-
def wrapper(*args, **kwargs):
|
|
317
|
+
def decorator(func: Any) -> Any:
|
|
318
|
+
def wrapper(*args: Any, **kwargs: Any) -> Any:
|
|
319
319
|
try:
|
|
320
320
|
return func(*args, **kwargs)
|
|
321
321
|
except exception_types as e:
|
|
@@ -13,13 +13,13 @@ from .utils import log_error, log_info, log_warning
|
|
|
13
13
|
|
|
14
14
|
def detect_language_from_extension(file_path: str) -> str:
|
|
15
15
|
"""
|
|
16
|
-
|
|
16
|
+
Detect programming language from file extension
|
|
17
17
|
|
|
18
18
|
Args:
|
|
19
|
-
file_path:
|
|
19
|
+
file_path: File path to analyze
|
|
20
20
|
|
|
21
21
|
Returns:
|
|
22
|
-
|
|
22
|
+
Language name or 'unknown' if not recognized
|
|
23
23
|
"""
|
|
24
24
|
extension = os.path.splitext(file_path)[1].lower()
|
|
25
25
|
|
|
@@ -62,14 +62,10 @@ def read_file_with_fallback(file_path: str) -> bytes | None:
|
|
|
62
62
|
|
|
63
63
|
try:
|
|
64
64
|
content, detected_encoding = read_file_safe(file_path)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return content.encode("utf-8")
|
|
70
|
-
else:
|
|
71
|
-
log_warning(f"File {file_path} is empty or could not be read")
|
|
72
|
-
return b""
|
|
65
|
+
log_info(
|
|
66
|
+
f"Successfully read file {file_path} with encoding: {detected_encoding}"
|
|
67
|
+
)
|
|
68
|
+
return content.encode("utf-8")
|
|
73
69
|
|
|
74
70
|
except Exception as e:
|
|
75
71
|
log_error(f"Failed to read file {file_path}: {e}")
|
|
@@ -113,9 +109,6 @@ def read_file_partial(
|
|
|
113
109
|
try:
|
|
114
110
|
# ファイル全体を安全に読み込み
|
|
115
111
|
content, detected_encoding = read_file_safe(file_path)
|
|
116
|
-
if content is None:
|
|
117
|
-
log_error(f"Failed to read file: {file_path}")
|
|
118
|
-
return None
|
|
119
112
|
|
|
120
113
|
# 行に分割
|
|
121
114
|
lines = content.splitlines(keepends=True)
|
|
@@ -17,17 +17,17 @@ class BaseTableFormatter(ABC):
|
|
|
17
17
|
self.format_type = format_type
|
|
18
18
|
|
|
19
19
|
def _get_platform_newline(self) -> str:
|
|
20
|
-
"""
|
|
20
|
+
"""Get platform-specific newline code"""
|
|
21
21
|
return os.linesep
|
|
22
22
|
|
|
23
23
|
def _convert_to_platform_newlines(self, text: str) -> str:
|
|
24
|
-
"""
|
|
24
|
+
"""Convert regular \n to platform-specific newline code"""
|
|
25
25
|
if os.linesep != "\n":
|
|
26
26
|
return text.replace("\n", os.linesep)
|
|
27
27
|
return text
|
|
28
28
|
|
|
29
29
|
def format_structure(self, structure_data: dict[str, Any]) -> str:
|
|
30
|
-
"""
|
|
30
|
+
"""Format structure data in table format"""
|
|
31
31
|
if self.format_type == "full":
|
|
32
32
|
result = self._format_full_table(structure_data)
|
|
33
33
|
elif self.format_type == "compact":
|
|
@@ -37,7 +37,7 @@ class BaseTableFormatter(ABC):
|
|
|
37
37
|
else:
|
|
38
38
|
raise ValueError(f"Unsupported format type: {self.format_type}")
|
|
39
39
|
|
|
40
|
-
#
|
|
40
|
+
# Finally convert to platform-specific newline code
|
|
41
41
|
if self.format_type == "csv":
|
|
42
42
|
return result
|
|
43
43
|
|
|
@@ -45,25 +45,25 @@ class BaseTableFormatter(ABC):
|
|
|
45
45
|
|
|
46
46
|
@abstractmethod
|
|
47
47
|
def _format_full_table(self, data: dict[str, Any]) -> str:
|
|
48
|
-
"""
|
|
48
|
+
"""Full table format (language-specific implementation)"""
|
|
49
49
|
pass
|
|
50
50
|
|
|
51
51
|
@abstractmethod
|
|
52
52
|
def _format_compact_table(self, data: dict[str, Any]) -> str:
|
|
53
|
-
"""
|
|
53
|
+
"""Compact table format (language-specific implementation)"""
|
|
54
54
|
pass
|
|
55
55
|
|
|
56
56
|
def _format_csv(self, data: dict[str, Any]) -> str:
|
|
57
|
-
"""CSV
|
|
57
|
+
"""CSV format (common implementation)"""
|
|
58
58
|
output = io.StringIO()
|
|
59
59
|
writer = csv.writer(output, lineterminator="\n")
|
|
60
60
|
|
|
61
|
-
#
|
|
61
|
+
# Header
|
|
62
62
|
writer.writerow(
|
|
63
63
|
["Type", "Name", "Signature", "Visibility", "Lines", "Complexity", "Doc"]
|
|
64
64
|
)
|
|
65
65
|
|
|
66
|
-
#
|
|
66
|
+
# Fields
|
|
67
67
|
for field in data.get("fields", []):
|
|
68
68
|
writer.writerow(
|
|
69
69
|
[
|
|
@@ -79,7 +79,7 @@ class BaseTableFormatter(ABC):
|
|
|
79
79
|
]
|
|
80
80
|
)
|
|
81
81
|
|
|
82
|
-
#
|
|
82
|
+
# Methods
|
|
83
83
|
for method in data.get("methods", []):
|
|
84
84
|
writer.writerow(
|
|
85
85
|
[
|
|
@@ -102,9 +102,9 @@ class BaseTableFormatter(ABC):
|
|
|
102
102
|
|
|
103
103
|
return csv_content
|
|
104
104
|
|
|
105
|
-
#
|
|
105
|
+
# Common helper methods
|
|
106
106
|
def _create_full_signature(self, method: dict[str, Any]) -> str:
|
|
107
|
-
"""
|
|
107
|
+
"""Create complete method signature"""
|
|
108
108
|
params = method.get("parameters", [])
|
|
109
109
|
param_strs = []
|
|
110
110
|
for param in params:
|
|
@@ -131,32 +131,32 @@ class BaseTableFormatter(ABC):
|
|
|
131
131
|
return signature
|
|
132
132
|
|
|
133
133
|
def _convert_visibility(self, visibility: str) -> str:
|
|
134
|
-
"""
|
|
134
|
+
"""Convert visibility to symbol"""
|
|
135
135
|
mapping = {"public": "+", "private": "-", "protected": "#", "package": "~"}
|
|
136
136
|
return mapping.get(visibility, visibility)
|
|
137
137
|
|
|
138
138
|
def _extract_doc_summary(self, javadoc: str) -> str:
|
|
139
|
-
"""
|
|
139
|
+
"""Extract summary from documentation"""
|
|
140
140
|
if not javadoc:
|
|
141
141
|
return "-"
|
|
142
142
|
|
|
143
|
-
#
|
|
143
|
+
# Remove comment symbols
|
|
144
144
|
clean_doc = (
|
|
145
145
|
javadoc.replace("/**", "").replace("*/", "").replace("*", "").strip()
|
|
146
146
|
)
|
|
147
147
|
|
|
148
|
-
#
|
|
148
|
+
# Get first line
|
|
149
149
|
lines = clean_doc.split("\n")
|
|
150
150
|
first_line = lines[0].strip()
|
|
151
151
|
|
|
152
|
-
#
|
|
152
|
+
# Truncate if too long
|
|
153
153
|
if len(first_line) > 50:
|
|
154
154
|
first_line = first_line[:47] + "..."
|
|
155
155
|
|
|
156
156
|
return first_line.replace("|", "\\|").replace("\n", " ")
|
|
157
157
|
|
|
158
158
|
def _clean_csv_text(self, text: str) -> str:
|
|
159
|
-
"""CSV
|
|
159
|
+
"""Text cleaning for CSV format"""
|
|
160
160
|
if not text:
|
|
161
161
|
return ""
|
|
162
162
|
|
|
@@ -9,7 +9,7 @@ from .python_formatter import PythonTableFormatter
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class TableFormatterFactory:
|
|
12
|
-
"""
|
|
12
|
+
"""Factory for creating language-specific table formatters"""
|
|
13
13
|
|
|
14
14
|
_formatters: dict[str, type[BaseTableFormatter]] = {
|
|
15
15
|
"java": JavaTableFormatter,
|
|
@@ -21,19 +21,19 @@ class TableFormatterFactory:
|
|
|
21
21
|
cls, language: str, format_type: str = "full"
|
|
22
22
|
) -> BaseTableFormatter:
|
|
23
23
|
"""
|
|
24
|
-
|
|
24
|
+
Create table formatter for specified language
|
|
25
25
|
|
|
26
26
|
Args:
|
|
27
|
-
language:
|
|
28
|
-
format_type:
|
|
27
|
+
language: Programming language name
|
|
28
|
+
format_type: Format type (full, compact, csv)
|
|
29
29
|
|
|
30
30
|
Returns:
|
|
31
|
-
|
|
31
|
+
Language-specific table formatter
|
|
32
32
|
"""
|
|
33
33
|
formatter_class = cls._formatters.get(language.lower())
|
|
34
34
|
|
|
35
35
|
if formatter_class is None:
|
|
36
|
-
#
|
|
36
|
+
# Use Java formatter as default
|
|
37
37
|
formatter_class = JavaTableFormatter
|
|
38
38
|
|
|
39
39
|
return formatter_class(format_type)
|
|
@@ -43,21 +43,21 @@ class TableFormatterFactory:
|
|
|
43
43
|
cls, language: str, formatter_class: type[BaseTableFormatter]
|
|
44
44
|
) -> None:
|
|
45
45
|
"""
|
|
46
|
-
|
|
46
|
+
Register new language formatter
|
|
47
47
|
|
|
48
48
|
Args:
|
|
49
|
-
language:
|
|
50
|
-
formatter_class:
|
|
49
|
+
language: Programming language name
|
|
50
|
+
formatter_class: Formatter class
|
|
51
51
|
"""
|
|
52
52
|
cls._formatters[language.lower()] = formatter_class
|
|
53
53
|
|
|
54
54
|
@classmethod
|
|
55
55
|
def get_supported_languages(cls) -> list[str]:
|
|
56
56
|
"""
|
|
57
|
-
|
|
57
|
+
Get list of supported languages
|
|
58
58
|
|
|
59
59
|
Returns:
|
|
60
|
-
|
|
60
|
+
List of supported languages
|
|
61
61
|
"""
|
|
62
62
|
return list(cls._formatters.keys())
|
|
63
63
|
|
|
@@ -66,13 +66,13 @@ def create_table_formatter(
|
|
|
66
66
|
format_type: str, language: str = "java"
|
|
67
67
|
) -> BaseTableFormatter:
|
|
68
68
|
"""
|
|
69
|
-
|
|
69
|
+
Create table formatter (function for compatibility)
|
|
70
70
|
|
|
71
71
|
Args:
|
|
72
|
-
format_type:
|
|
73
|
-
language:
|
|
72
|
+
format_type: Format type
|
|
73
|
+
language: Programming language name
|
|
74
74
|
|
|
75
75
|
Returns:
|
|
76
|
-
|
|
76
|
+
Table formatter
|
|
77
77
|
"""
|
|
78
78
|
return TableFormatterFactory.create_formatter(language, format_type)
|