codegraph-py 1.0.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.
- codegraph/__init__.py +12 -0
- codegraph/__main__.py +6 -0
- codegraph/cli.py +911 -0
- codegraph/codegraph.py +618 -0
- codegraph/context/__init__.py +216 -0
- codegraph/db/__init__.py +11 -0
- codegraph/db/connection.py +163 -0
- codegraph/db/queries.py +752 -0
- codegraph/db/schema.sql +151 -0
- codegraph/directory.py +160 -0
- codegraph/errors.py +101 -0
- codegraph/extraction/__init__.py +956 -0
- codegraph/extraction/languages/__init__.py +64 -0
- codegraph/extraction/languages/base.py +132 -0
- codegraph/extraction/languages/c_cfg.py +53 -0
- codegraph/extraction/languages/cpp_cfg.py +60 -0
- codegraph/extraction/languages/dart_cfg.py +53 -0
- codegraph/extraction/languages/go_cfg.py +70 -0
- codegraph/extraction/languages/java_cfg.py +62 -0
- codegraph/extraction/languages/javascript_cfg.py +84 -0
- codegraph/extraction/languages/kotlin_cfg.py +52 -0
- codegraph/extraction/languages/lua_cfg.py +65 -0
- codegraph/extraction/languages/python_cfg.py +75 -0
- codegraph/extraction/languages/ruby_cfg.py +48 -0
- codegraph/extraction/languages/rust_cfg.py +68 -0
- codegraph/extraction/languages/scala_cfg.py +59 -0
- codegraph/extraction/languages/swift_cfg.py +64 -0
- codegraph/extraction/languages/typescript_cfg.py +89 -0
- codegraph/extraction/tree_sitter_extractor.py +689 -0
- codegraph/graph/__init__.py +685 -0
- codegraph/installer/__init__.py +6 -0
- codegraph/mcp/__init__.py +668 -0
- codegraph/project_config.py +191 -0
- codegraph/resolution/__init__.py +337 -0
- codegraph/search/__init__.py +653 -0
- codegraph/sync/__init__.py +204 -0
- codegraph/types.py +334 -0
- codegraph/ui/__init__.py +11 -0
- codegraph/utils.py +218 -0
- codegraph_py-1.0.0.dist-info/METADATA +238 -0
- codegraph_py-1.0.0.dist-info/RECORD +44 -0
- codegraph_py-1.0.0.dist-info/WHEEL +5 -0
- codegraph_py-1.0.0.dist-info/entry_points.txt +2 -0
- codegraph_py-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Lua language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LuaConfig(LanguageConfig):
|
|
9
|
+
"""Lua extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'lua'
|
|
12
|
+
|
|
13
|
+
function_types = ['function_declaration']
|
|
14
|
+
class_types = []
|
|
15
|
+
method_types = ['function_declaration'] # Methods using self syntax
|
|
16
|
+
interface_types = []
|
|
17
|
+
struct_types = []
|
|
18
|
+
enum_types = []
|
|
19
|
+
type_alias_types = []
|
|
20
|
+
import_types = ['require_statement']
|
|
21
|
+
call_types = ['function_call']
|
|
22
|
+
variable_types = ['variable_declaration', 'assignment_statement']
|
|
23
|
+
field_types = ['field']
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = None
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
if not params:
|
|
34
|
+
return None
|
|
35
|
+
return source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
36
|
+
|
|
37
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
38
|
+
if node.type == 'require_statement':
|
|
39
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
40
|
+
# require('module') or require "module"
|
|
41
|
+
arg = node.child_by_field_name('module') or node.child(1)
|
|
42
|
+
if arg:
|
|
43
|
+
module_name = source[arg.start_byte:arg.end_byte].decode('utf-8', errors='replace')
|
|
44
|
+
module_name = module_name.strip('\'"')
|
|
45
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
49
|
+
# Lua: functions in module scope, not starting with _
|
|
50
|
+
name_node = node.child_by_field_name('name')
|
|
51
|
+
if name_node:
|
|
52
|
+
try:
|
|
53
|
+
t = name_node.text
|
|
54
|
+
if isinstance(t, bytes):
|
|
55
|
+
name = t.decode('utf-8', errors='replace')
|
|
56
|
+
else:
|
|
57
|
+
name = str(t)
|
|
58
|
+
return not name.startswith('_')
|
|
59
|
+
except Exception:
|
|
60
|
+
pass
|
|
61
|
+
return True
|
|
62
|
+
|
|
63
|
+
def classify_class_node(self, node: TSNode) -> str:
|
|
64
|
+
# Lua uses metatables, treat function_declaration returning a table as class
|
|
65
|
+
return 'class'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Python language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class PythonConfig(LanguageConfig):
|
|
9
|
+
"""Python-specific extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'python'
|
|
12
|
+
|
|
13
|
+
function_types = ['function_definition']
|
|
14
|
+
class_types = ['class_definition']
|
|
15
|
+
method_types = ['function_definition'] # Methods are functions inside classes
|
|
16
|
+
interface_types = []
|
|
17
|
+
struct_types = []
|
|
18
|
+
enum_types = []
|
|
19
|
+
type_alias_types = []
|
|
20
|
+
import_types = ['import_statement', 'import_from_statement']
|
|
21
|
+
call_types = ['call']
|
|
22
|
+
variable_types = ['assignment']
|
|
23
|
+
field_types = []
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = 'return_type'
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
return_type = node.child_by_field_name('return_type')
|
|
34
|
+
if not params:
|
|
35
|
+
return None
|
|
36
|
+
sig = source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
37
|
+
if return_type:
|
|
38
|
+
sig += ' -> ' + source[return_type.start_byte:return_type.end_byte].decode('utf-8', errors='replace')
|
|
39
|
+
return sig
|
|
40
|
+
|
|
41
|
+
def is_async(self, node: TSNode) -> bool:
|
|
42
|
+
prev = node.prev_sibling
|
|
43
|
+
return prev is not None and prev.type == 'async'
|
|
44
|
+
|
|
45
|
+
def is_static(self, node: TSNode) -> bool:
|
|
46
|
+
prev = node.prev_named_sibling
|
|
47
|
+
if prev is not None and prev.type == 'decorator':
|
|
48
|
+
text = _node_text(prev)
|
|
49
|
+
return 'staticmethod' in text
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
53
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
54
|
+
if node.type == 'import_from_statement':
|
|
55
|
+
module_node = node.child_by_field_name('module_name')
|
|
56
|
+
if module_node:
|
|
57
|
+
module_name = source[module_node.start_byte:module_node.end_byte].decode('utf-8', errors='replace')
|
|
58
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
59
|
+
elif node.type == 'import_statement':
|
|
60
|
+
name_node = node.child_by_field_name('name')
|
|
61
|
+
if name_node:
|
|
62
|
+
module_name = source[name_node.start_byte:name_node.end_byte].decode('utf-8', errors='replace')
|
|
63
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
64
|
+
return None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _node_text(node: TSNode) -> str:
|
|
68
|
+
"""Get text from a tree-sitter node safely."""
|
|
69
|
+
try:
|
|
70
|
+
t = node.text
|
|
71
|
+
if isinstance(t, bytes):
|
|
72
|
+
return t.decode('utf-8', errors='replace')
|
|
73
|
+
return str(t)
|
|
74
|
+
except Exception:
|
|
75
|
+
return ''
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Ruby language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RubyConfig(LanguageConfig):
|
|
9
|
+
"""Ruby extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'ruby'
|
|
12
|
+
|
|
13
|
+
function_types = ['method']
|
|
14
|
+
class_types = ['class']
|
|
15
|
+
method_types = ['method'] # Methods inside class bodies
|
|
16
|
+
interface_types = []
|
|
17
|
+
struct_types = []
|
|
18
|
+
enum_types = []
|
|
19
|
+
type_alias_types = []
|
|
20
|
+
import_types = ['require', 'require_relative']
|
|
21
|
+
call_types = ['call', 'method_call']
|
|
22
|
+
variable_types = ['assignment']
|
|
23
|
+
field_types = []
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = None
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
if not params:
|
|
34
|
+
return None
|
|
35
|
+
return source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
36
|
+
|
|
37
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
38
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
39
|
+
if node.type in ('require', 'require_relative'):
|
|
40
|
+
arg = node.child_by_field_name('path') or node.child(1)
|
|
41
|
+
if arg:
|
|
42
|
+
module_name = source[arg.start_byte:arg.end_byte].decode('utf-8', errors='replace')
|
|
43
|
+
module_name = module_name.strip('\'"')
|
|
44
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
48
|
+
return not node.type.startswith('_')
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Rust language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class RustConfig(LanguageConfig):
|
|
9
|
+
"""Rust extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'rust'
|
|
12
|
+
|
|
13
|
+
function_types = ['function_item']
|
|
14
|
+
class_types = []
|
|
15
|
+
method_types = ['function_item'] # Methods in impl blocks
|
|
16
|
+
interface_types = []
|
|
17
|
+
struct_types = ['struct_item']
|
|
18
|
+
enum_types = ['enum_item']
|
|
19
|
+
type_alias_types = ['type_item']
|
|
20
|
+
import_types = ['use_declaration']
|
|
21
|
+
call_types = ['call_expression']
|
|
22
|
+
variable_types = ['let_declaration']
|
|
23
|
+
field_types = []
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = 'return_type'
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
if not params:
|
|
34
|
+
return None
|
|
35
|
+
sig = source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
36
|
+
return_type = node.child_by_field_name('return_type')
|
|
37
|
+
if return_type:
|
|
38
|
+
sig += ' -> ' + source[return_type.start_byte:return_type.end_byte].decode('utf-8', errors='replace')
|
|
39
|
+
return sig
|
|
40
|
+
|
|
41
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
42
|
+
if node.type == 'use_declaration':
|
|
43
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
44
|
+
# Extract the first path segment
|
|
45
|
+
arg = node.child_by_field_name('argument')
|
|
46
|
+
if arg:
|
|
47
|
+
module_name = source[arg.start_byte:arg.end_byte].decode('utf-8', errors='replace')
|
|
48
|
+
# Get the top-level crate/module name
|
|
49
|
+
top_level = module_name.split('::')[0]
|
|
50
|
+
return ImportInfo(module_name=top_level, signature=text)
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
54
|
+
# Check for 'pub' keyword
|
|
55
|
+
prev = node.prev_sibling
|
|
56
|
+
while prev is not None:
|
|
57
|
+
if prev.type == 'pub':
|
|
58
|
+
return True
|
|
59
|
+
if prev.is_named and prev.type != 'pub':
|
|
60
|
+
break
|
|
61
|
+
prev = prev.prev_sibling
|
|
62
|
+
return False
|
|
63
|
+
|
|
64
|
+
def classify_class_node(self, node: TSNode) -> str:
|
|
65
|
+
# Rust uses `impl` blocks for implementations
|
|
66
|
+
if node.type == 'impl_item':
|
|
67
|
+
return 'class' # Treat impl blocks as containers for methods
|
|
68
|
+
return 'class'
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Scala language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ScalaConfig(LanguageConfig):
|
|
9
|
+
"""Scala extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'scala'
|
|
12
|
+
|
|
13
|
+
function_types = ['function_definition']
|
|
14
|
+
class_types = ['class_definition']
|
|
15
|
+
method_types = ['function_definition'] # Functions inside class/object bodies
|
|
16
|
+
interface_types = ['trait_definition']
|
|
17
|
+
struct_types = []
|
|
18
|
+
enum_types = ['enum_definition']
|
|
19
|
+
type_alias_types = ['type_definition']
|
|
20
|
+
import_types = ['import_statement']
|
|
21
|
+
call_types = ['call_expression']
|
|
22
|
+
variable_types = ['val_definition', 'var_definition']
|
|
23
|
+
field_types = ['variable_definition']
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = 'return_type'
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
if not params:
|
|
34
|
+
return None
|
|
35
|
+
sig = source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
36
|
+
return_type = node.child_by_field_name('return_type')
|
|
37
|
+
if return_type:
|
|
38
|
+
ret = source[return_type.start_byte:return_type.end_byte].decode('utf-8', errors='replace')
|
|
39
|
+
sig += f': {ret}'
|
|
40
|
+
return sig
|
|
41
|
+
|
|
42
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
43
|
+
if node.type == 'import_statement':
|
|
44
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
45
|
+
path = node.child_by_field_name('path')
|
|
46
|
+
if path:
|
|
47
|
+
module_name = source[path.start_byte:path.end_byte].decode('utf-8', errors='replace')
|
|
48
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
52
|
+
return True # Scala defs at package level are public by default
|
|
53
|
+
|
|
54
|
+
def is_static(self, node: TSNode) -> bool:
|
|
55
|
+
# Check for 'static' modifier in Scala 3
|
|
56
|
+
for child in node.children:
|
|
57
|
+
if child.type == 'static':
|
|
58
|
+
return True
|
|
59
|
+
return False
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Swift language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class SwiftConfig(LanguageConfig):
|
|
9
|
+
"""Swift extraction configuration."""
|
|
10
|
+
|
|
11
|
+
language_id = 'swift'
|
|
12
|
+
|
|
13
|
+
function_types = ['function_declaration']
|
|
14
|
+
class_types = ['class_declaration']
|
|
15
|
+
method_types = ['function_declaration'] # Functions inside class bodies
|
|
16
|
+
interface_types = ['protocol_declaration']
|
|
17
|
+
struct_types = ['struct_declaration']
|
|
18
|
+
enum_types = ['enum_declaration']
|
|
19
|
+
type_alias_types = ['typealias_declaration']
|
|
20
|
+
import_types = ['import_declaration']
|
|
21
|
+
call_types = ['call_expression']
|
|
22
|
+
variable_types = ['variable_declaration']
|
|
23
|
+
field_types = ['property_declaration']
|
|
24
|
+
property_types = []
|
|
25
|
+
|
|
26
|
+
name_field = 'name'
|
|
27
|
+
body_field = 'body'
|
|
28
|
+
params_field = 'parameters'
|
|
29
|
+
return_field = 'return_type'
|
|
30
|
+
|
|
31
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
32
|
+
params = node.child_by_field_name('parameters')
|
|
33
|
+
if not params:
|
|
34
|
+
return None
|
|
35
|
+
sig = source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
36
|
+
return_type = node.child_by_field_name('return_type')
|
|
37
|
+
if return_type:
|
|
38
|
+
sig += ' -> ' + source[return_type.start_byte:return_type.end_byte].decode('utf-8', errors='replace')
|
|
39
|
+
return sig
|
|
40
|
+
|
|
41
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
42
|
+
if node.type == 'import_declaration':
|
|
43
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
44
|
+
# Get the module path (all children after 'import' keyword)
|
|
45
|
+
parts = []
|
|
46
|
+
for child in node.named_children:
|
|
47
|
+
t = source[child.start_byte:child.end_byte].decode('utf-8', errors='replace')
|
|
48
|
+
parts.append(t)
|
|
49
|
+
module_name = '.'.join(parts) if parts else ''
|
|
50
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
54
|
+
# Check for 'public' or 'open' modifiers
|
|
55
|
+
for child in node.children:
|
|
56
|
+
if child.type in ('public', 'open'):
|
|
57
|
+
return True
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
def is_static(self, node: TSNode) -> bool:
|
|
61
|
+
for child in node.children:
|
|
62
|
+
if child.type == 'static':
|
|
63
|
+
return True
|
|
64
|
+
return False
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TypeScript/TSX language extraction configuration.
|
|
3
|
+
"""
|
|
4
|
+
from tree_sitter import Node as TSNode
|
|
5
|
+
from .base import LanguageConfig, ImportInfo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _node_text(node: TSNode) -> str:
|
|
9
|
+
try:
|
|
10
|
+
t = node.text
|
|
11
|
+
if isinstance(t, bytes):
|
|
12
|
+
return t.decode('utf-8', errors='replace')
|
|
13
|
+
return str(t)
|
|
14
|
+
except Exception:
|
|
15
|
+
return ''
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TypeScriptConfig(LanguageConfig):
|
|
19
|
+
"""TypeScript/TSX extraction configuration."""
|
|
20
|
+
|
|
21
|
+
language_id = 'typescript'
|
|
22
|
+
|
|
23
|
+
# TS uses 'typescript' grammar, access specific dialects via 'typescript' or 'tsx'
|
|
24
|
+
_tsx = False
|
|
25
|
+
|
|
26
|
+
function_types = ['function_declaration', 'arrow_function', 'generator_function_declaration']
|
|
27
|
+
class_types = ['class_declaration']
|
|
28
|
+
method_types = ['method_definition']
|
|
29
|
+
interface_types = ['interface_declaration']
|
|
30
|
+
struct_types = []
|
|
31
|
+
enum_types = ['enum_declaration']
|
|
32
|
+
type_alias_types = ['type_alias_declaration']
|
|
33
|
+
import_types = ['import_statement']
|
|
34
|
+
call_types = ['call_expression']
|
|
35
|
+
variable_types = ['variable_declaration', 'lexical_declaration']
|
|
36
|
+
field_types = ['property_signature', 'public_field_definition']
|
|
37
|
+
property_types = ['property_identifier']
|
|
38
|
+
|
|
39
|
+
name_field = 'name'
|
|
40
|
+
body_field = 'body'
|
|
41
|
+
params_field = 'parameters'
|
|
42
|
+
return_field = 'type'
|
|
43
|
+
|
|
44
|
+
def get_signature(self, node: TSNode, source: bytes) -> str | None:
|
|
45
|
+
params = node.child_by_field_name('parameters')
|
|
46
|
+
if not params:
|
|
47
|
+
return None
|
|
48
|
+
sig = source[params.start_byte:params.end_byte].decode('utf-8', errors='replace')
|
|
49
|
+
return_type = node.child_by_field_name('return_type')
|
|
50
|
+
if return_type:
|
|
51
|
+
sig += ': ' + source[return_type.start_byte:return_type.end_byte].decode('utf-8', errors='replace')
|
|
52
|
+
return sig
|
|
53
|
+
|
|
54
|
+
def extract_import(self, node: TSNode, source: bytes) -> ImportInfo | None:
|
|
55
|
+
text = source[node.start_byte:node.end_byte].decode('utf-8', errors='replace').strip()
|
|
56
|
+
if node.type == 'import_statement':
|
|
57
|
+
source_node = node.child_by_field_name('source')
|
|
58
|
+
if source_node:
|
|
59
|
+
module_name = source[source_node.start_byte:source_node.end_byte].decode('utf-8', errors='replace')
|
|
60
|
+
module_name = module_name.strip('\'"')
|
|
61
|
+
return ImportInfo(module_name=module_name, signature=text)
|
|
62
|
+
return None
|
|
63
|
+
|
|
64
|
+
def is_exported(self, node: TSNode, source: bytes) -> bool:
|
|
65
|
+
prev = node.prev_sibling
|
|
66
|
+
while prev is not None:
|
|
67
|
+
if prev.type == 'export':
|
|
68
|
+
return True
|
|
69
|
+
if prev.is_named or prev.type in (';', '\n'):
|
|
70
|
+
break
|
|
71
|
+
prev = prev.prev_sibling
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
def is_async(self, node: TSNode) -> bool:
|
|
75
|
+
prev = node.prev_sibling
|
|
76
|
+
while prev is not None:
|
|
77
|
+
if prev.type == 'async':
|
|
78
|
+
return True
|
|
79
|
+
if prev.is_named:
|
|
80
|
+
break
|
|
81
|
+
prev = prev.prev_sibling
|
|
82
|
+
return False
|
|
83
|
+
|
|
84
|
+
def is_const(self, node: TSNode) -> bool:
|
|
85
|
+
parent = node.parent
|
|
86
|
+
if parent and parent.type == 'variable_declaration':
|
|
87
|
+
kind = _node_text(parent.child(0)) if parent.child(0) else ''
|
|
88
|
+
return kind == 'const'
|
|
89
|
+
return False
|