code-explore-by-sql 0.1.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.
@@ -0,0 +1,183 @@
1
+ """Strict edge extractor — only deterministic, unambiguous relationships.
2
+
3
+ Extracts exactly 4 edge types per plan.md:
4
+ - inheritance: class A : public B
5
+ - type_dependency: function signature types (excluding basic types)
6
+ - static_call: explicit scope calls (Super::BeginPlay, UGameplayStatics::...)
7
+ - rpc_routing: framework-determined implicit routing (Server -> _Implementation)
8
+
9
+ Anti-Cartesian-Product rules:
10
+ - NEVER extract generalized pointer calls (Comp->Init())
11
+ - Basic types (TArray, FString, int, FName) generate NO edges
12
+
13
+ Refactored to accept LanguageConfig + FrameworkConfig instead of hardcoded constants.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ from dataclasses import dataclass
19
+
20
+ from .configs import FrameworkConfig, LanguageConfig
21
+ from .symbol_analyzer import ExtraSymbol, SymbolDef
22
+
23
+
24
+ @dataclass
25
+ class StrictEdge:
26
+ source_qn: str
27
+ target_qn: str
28
+ edge_type: str # inheritance, type_dependency, static_call, rpc_routing
29
+ language: str = ""
30
+
31
+
32
+ def extract_edges(
33
+ symbols: list[SymbolDef],
34
+ extra_symbols: list[ExtraSymbol],
35
+ lines: list[str],
36
+ fw: FrameworkConfig,
37
+ lang: LanguageConfig,
38
+ ) -> list[StrictEdge]:
39
+ """Extract all deterministic edges for a file.
40
+
41
+ Uses both symbol metadata and source text to find strict edges.
42
+ All regex patterns come from LanguageConfig and FrameworkConfig.
43
+ """
44
+ language = lang.name
45
+ base_kw = lang.base_keyword
46
+ type_re = lang.type_re
47
+ static_call_re = lang.static_call_re
48
+ super_call_re = lang.super_call_re
49
+ param_type_re = lang.param_type_re
50
+ control_flow_names = lang.control_flow_names
51
+ access_spec_names = lang.access_spec_names
52
+
53
+ edges: list[StrictEdge] = []
54
+ seen: set[tuple[str, str, str]] = set()
55
+
56
+ all_skip = lang.basic_skip_types | fw.skip_types | fw.noise_type_names
57
+
58
+ def _add(src: str, tgt: str, etype: str) -> None:
59
+ if src == tgt:
60
+ return
61
+ key = (src, tgt, etype)
62
+ if key not in seen:
63
+ seen.add(key)
64
+ edges.append(StrictEdge(source_qn=src, target_qn=tgt, edge_type=etype, language=language))
65
+
66
+ # Build a lookup of QN -> SymbolDef for resolving static calls
67
+ qn_set: set[str] = set()
68
+ for s in symbols:
69
+ qn_set.add(s.qualified_name)
70
+
71
+ # --- Pass 1: Symbol metadata edges ---
72
+
73
+ for sym in symbols:
74
+ qn = sym.qualified_name
75
+
76
+ # 1. Inheritance
77
+ if sym.block_type == "class" and sym.inheritance_base:
78
+ base = sym.inheritance_base
79
+ if base not in all_skip and len(base) >= 3:
80
+ _add(qn, base, "inheritance")
81
+
82
+ # 2. Framework-specific edges from decoration metadata
83
+ if sym.decoration_meta and fw.extract_framework_edges:
84
+ for target_qn, edge_type in fw.extract_framework_edges(qn, sym.decoration_meta):
85
+ _add(qn, target_qn, edge_type)
86
+
87
+ # --- Pass 2: Source text scanning for static_call and type_dependency ---
88
+
89
+ # QN internal convention uses "::" as separator regardless of language.
90
+ # scope_operator is only used for source text regex matching above.
91
+ _QN_SEP = "::"
92
+
93
+ method_symbols = [
94
+ s for s in symbols
95
+ if s.block_type in ("method", "function")
96
+ and s.qualified_name.split(_QN_SEP)[-1].lower() not in control_flow_names
97
+ ]
98
+
99
+ for sym in method_symbols:
100
+ qn = sym.qualified_name
101
+ start = sym.start_line - 1
102
+ end = sym.end_line
103
+
104
+ for line_idx in range(start, min(end, len(lines))):
105
+ line = lines[line_idx].strip()
106
+
107
+ # Skip comments and preprocessor
108
+ if ((lang.line_comment and line.startswith(lang.line_comment)) or
109
+ (lang.block_comment_pair and line.startswith(lang.block_comment_pair[0])) or
110
+ (lang.preprocessor_prefix and line.startswith(lang.preprocessor_prefix))):
111
+ continue
112
+ # Skip framework decoration macro lines
113
+ if fw.decoration_macro_names and any(
114
+ line.startswith(m) for m in fw.decoration_macro_names
115
+ ):
116
+ continue
117
+ # Skip string literals (rough check)
118
+ if line.startswith('"') or (lang.raw_string_char and line.startswith(lang.raw_string_char + '"')):
119
+ continue
120
+
121
+ # 3. Static calls: ClassName.Method( or ClassName::Method(
122
+ if static_call_re:
123
+ for m in static_call_re.finditer(line):
124
+ cls_name = m.group(1)
125
+ method_name = m.group(2)
126
+ if cls_name == base_kw and sym.parent_class:
127
+ target = f"{sym.parent_class}::{method_name}"
128
+ _add(qn, target, "static_call")
129
+ elif cls_name not in all_skip and cls_name not in control_flow_names:
130
+ target = f"{cls_name}::{method_name}"
131
+ _add(qn, target, "static_call")
132
+
133
+ # Super/base calls
134
+ if super_call_re:
135
+ for m in super_call_re.finditer(line):
136
+ method_name = m.group(1)
137
+ if sym.parent_class:
138
+ target = f"{sym.parent_class}::{method_name}"
139
+ _add(qn, target, "static_call")
140
+
141
+ # 4. Type dependencies from function signature (only on declaration lines)
142
+ if line_idx == start and param_type_re:
143
+ for m in param_type_re.finditer(line):
144
+ tname = m.group(1)
145
+ if tname and tname not in all_skip and len(tname) >= 3:
146
+ _add(qn, tname, "type_dependency")
147
+
148
+ # --- Pass 3: Type dependencies from class member variables ---
149
+ class_symbols = [s for s in symbols if s.block_type == "class"]
150
+ for sym in class_symbols:
151
+ qn = sym.qualified_name
152
+ start = sym.start_line - 1
153
+ end = sym.end_line
154
+
155
+ for line_idx in range(start, min(end, len(lines))):
156
+ line = lines[line_idx].strip()
157
+ if not line:
158
+ continue
159
+ if ((lang.line_comment and line.startswith(lang.line_comment)) or
160
+ (lang.block_comment_pair and line.startswith(lang.block_comment_pair[0])) or
161
+ (lang.preprocessor_prefix and line.startswith(lang.preprocessor_prefix))):
162
+ continue
163
+ if line in access_spec_names:
164
+ continue
165
+ if fw.decoration_macro_names and any(
166
+ line.startswith(m) for m in fw.decoration_macro_names
167
+ ):
168
+ continue
169
+
170
+ # Member variable: Type* Name; or Type& Name; or Type Name;
171
+ if type_re:
172
+ for m in type_re.finditer(line):
173
+ tname = m.group(1)
174
+ if not tname or tname in all_skip:
175
+ continue
176
+ if len(tname) < 3:
177
+ continue
178
+ pos = m.end()
179
+ rest = line[pos:].lstrip() if pos < len(line) else ""
180
+ if rest and (rest[0] in lang.type_indicator_chars or (rest[0].isalpha() or rest[0] == "_")):
181
+ _add(qn, tname, "type_dependency")
182
+
183
+ return edges
@@ -0,0 +1,31 @@
1
+ """Language factory registry — imports all language factories and registers them."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from ..configs import register_language
6
+ from .c import make_c_language
7
+ from .cpp import make_cpp_language
8
+ from .csharp import make_csharp_language
9
+ from .glsl import make_glsl_language
10
+ from .go import make_go_language
11
+ from .hlsl import make_hlsl_language
12
+ from .java import make_java_language
13
+ from .javascript import make_javascript_language, make_typescript_language
14
+ from .kotlin import make_kotlin_language
15
+ from .python import make_python_language
16
+ from .rust import make_rust_language
17
+ from .swift import make_swift_language
18
+
19
+ register_language("cpp", make_cpp_language)
20
+ register_language("csharp", make_csharp_language)
21
+ register_language("c", make_c_language)
22
+ register_language("java", make_java_language)
23
+ register_language("glsl", make_glsl_language)
24
+ register_language("go", make_go_language)
25
+ register_language("hlsl", make_hlsl_language)
26
+ register_language("rust", make_rust_language)
27
+ register_language("javascript", make_javascript_language)
28
+ register_language("typescript", make_typescript_language)
29
+ register_language("kotlin", make_kotlin_language)
30
+ register_language("swift", make_swift_language)
31
+ register_language("python", make_python_language)
@@ -0,0 +1,118 @@
1
+ """C language configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ from ..configs import LanguageConfig
8
+
9
+ _NEVER_MATCH = re.compile(r"(?!x)x")
10
+
11
+
12
+ def make_c_language() -> LanguageConfig:
13
+ """C language configuration — similar to C++ but no templates, namespaces,
14
+ classes, lambdas, or export macros."""
15
+ return LanguageConfig(
16
+ name="c",
17
+ # C has struct/union (no class); enum same as C++
18
+ class_re=re.compile(
19
+ r"(?:^|\s)(struct|union)\s+"
20
+ r"(?:(?:[A-Z][A-Z0-9_]*_API|[A-Z][A-Z0-9_]*(?:\s*\([^)]*\))?)\s+)*"
21
+ r"(\w+)"
22
+ r"\s*",
23
+ ),
24
+ enum_re=re.compile(r"\benum\s+(\w+)"),
25
+ # No namespaces in C
26
+ namespace_re=_NEVER_MATCH,
27
+ func_name_re=re.compile(r"(\w+)\s*\([^)]*\)\s*$"),
28
+ # No export macros in plain C
29
+ export_macro_re=_NEVER_MATCH,
30
+ calling_conv_re=re.compile(
31
+ r"\b(?:__cdecl|__stdcall|__fastcall|__thiscall|__vectorcall|WINAPI|CALLBACK|"
32
+ r"STDMETHODCALLTYPE|FORCEINLINE|FORCENOINLINE|FORCEINLINE_DEBUGGABLE|inline)\b"
33
+ ),
34
+ attribute_re=re.compile(
35
+ r"\b(?:__declspec|__attribute__|alignas)\s*\([^)]*(?:\)[^)]*)?\)|\[\[[^\]]*\]\]"
36
+ ),
37
+ # No templates in C
38
+ template_re=_NEVER_MATCH,
39
+ # No destructors in C
40
+ dtor_re=_NEVER_MATCH,
41
+ control_flow_re=re.compile(r"\b(if|else\s+if|else|while|for|do|switch|catch|try)\b"),
42
+ control_flow_names=frozenset({
43
+ "if", "else", "while", "for", "do", "switch", "catch", "try",
44
+ "return", "delete", "goto", "break", "continue", "throw",
45
+ }),
46
+ trailing_mods_re=re.compile(
47
+ r"\s*(?:const|constexpr|inline|static)\s*[;{]*\s*$"
48
+ ),
49
+ access_spec_re=re.compile(r"^(?!x)x"), # C has no access specifiers
50
+ macro_like_re=re.compile(r"^[A-Z][A-Z0-9_]*\s*(?:\([^{};]*\))?\s*$"),
51
+ define_re=re.compile(r"#\s*define\s+"),
52
+ extern_c_re=re.compile(r'\bextern\s+"C"'),
53
+ operator_re=None,
54
+ uses_braces=True,
55
+ uses_namespaces=False,
56
+ uses_colon_inheritance=False,
57
+ # Edge extraction
58
+ scope_operator="::",
59
+ base_keyword="Super",
60
+ static_call_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)::([A-Za-z_][A-Za-z0-9_]*)\s*\("),
61
+ super_call_re=None,
62
+ type_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)\b"),
63
+ param_type_re=re.compile(
64
+ r"(?:const\s+)?([A-Z][A-Za-z0-9_]+)\s*(?:\*+|&)?\s+\w+"
65
+ ),
66
+ basic_skip_types=frozenset({
67
+ "int8", "int16", "int32", "int64",
68
+ "uint8", "uint16", "uint32", "uint64",
69
+ "float", "double", "bool", "void", "int", "char", "long", "short",
70
+ "unsigned", "size_t",
71
+ }),
72
+ # Block classification helpers
73
+ block_keyword_re=re.compile(r"\b(?:struct|enum|union)\b"),
74
+ # No lambdas in C
75
+ lambda_re=None,
76
+ # No namespaces in C
77
+ namespace_sig_re=_NEVER_MATCH,
78
+ init_list_re=None,
79
+ # View / summary helpers
80
+ access_spec_names=frozenset(),
81
+ view_structural_kws=("struct ", "enum ", "union "),
82
+ view_modifier_kws=("static ", "FORCEINLINE"),
83
+ local_var_modifiers="const|static|volatile",
84
+ # Bracket scanner hints
85
+ verbatim_string_prefix=None,
86
+ raw_string_char="R",
87
+ # Function body summary hints — C has no range-based for
88
+ range_for_re=None,
89
+ # Comment syntax
90
+ line_comment="//",
91
+ block_comment_pair=("/*", "*/"),
92
+ # String syntax
93
+ string_delimiters=frozenset({'"', "'"}),
94
+ string_escape_char="\\",
95
+ triple_quote_strings=(),
96
+ # Block style
97
+ uses_indent_blocks=False,
98
+ # Preprocessor
99
+ preprocessor_prefix="#",
100
+ has_preprocessor_macros=True,
101
+ # Statement / block close
102
+ statement_terminator=";",
103
+ block_close_suffix="};",
104
+ summary_comment_prefix="//",
105
+ # Config-driven control flow
106
+ control_flow_patterns=(
107
+ ("for", re.compile(r"^\s*for\s*\((.{1,80})\)\s*\{?\s*$")),
108
+ ("while", re.compile(r"^\s*while\s*\((.{1,80})\)\s*\{?\s*$")),
109
+ ("if", re.compile(r"^\s*(?:else\s+)?if\s*\((.{1,80})\)\s*\{?\s*$")),
110
+ ("switch", re.compile(r"^\s*switch\s*\((.{1,40})\)\s*\{?\s*$")),
111
+ ),
112
+ return_re=re.compile(r"^\s*return\s+(.{1,60});"),
113
+ # Extra syntax hints
114
+ type_indicator_chars="*&",
115
+ define_line_re=re.compile(r"#\s*define\s+(\w+)(\([^)]*\))?\s*(.*)"),
116
+ has_template_strings=False,
117
+ raw_string_style="cpp",
118
+ )
@@ -0,0 +1,106 @@
1
+ """C/C++ language configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ from ..configs import LanguageConfig
8
+
9
+
10
+ def make_cpp_language() -> LanguageConfig:
11
+ """C/C++ language configuration."""
12
+ return LanguageConfig(
13
+ name="cpp",
14
+ class_re=re.compile(
15
+ r"(?:^|\s)(class|struct)\s+"
16
+ r"(?:(?:[A-Z][A-Z0-9_]*_API|[A-Z][A-Z0-9_]*(?:\s*\([^)]*\))?)\s+)*"
17
+ r"(\w+)"
18
+ r"\s*(?::\s*(?:public|protected|private)\s+(\w+))?",
19
+ ),
20
+ enum_re=re.compile(r"\benum\s+(?:(?:class|struct)\s+)?(\w+)"),
21
+ namespace_re=re.compile(r"\bnamespace\s+(\w+)"),
22
+ func_name_re=re.compile(r"(\w+(?:\s*::\s*\w+)*)\s*\([^)]*\)\s*$"),
23
+ export_macro_re=re.compile(r"\b[A-Z][A-Z0-9_]*_API\b"),
24
+ calling_conv_re=re.compile(
25
+ r"\b(?:__cdecl|__stdcall|__fastcall|__thiscall|__vectorcall|WINAPI|CALLBACK|"
26
+ r"STDMETHODCALLTYPE|FORCEINLINE|FORCENOINLINE|FORCEINLINE_DEBUGGABLE|inline)\b"
27
+ ),
28
+ attribute_re=re.compile(
29
+ r"\b(?:__declspec|__attribute__|alignas)\s*\([^)]*(?:\)[^)]*)?\)|\[\[[^\]]*\]\]"
30
+ ),
31
+ template_re=re.compile(r"\btemplate\s*<[^<>]*>"),
32
+ dtor_re=re.compile(r"~(\w+)\s*\("),
33
+ control_flow_re=re.compile(r"\b(if|else\s+if|else|while|for|do|switch|catch|try)\b"),
34
+ control_flow_names=frozenset({
35
+ "if", "else", "while", "for", "do", "switch", "catch", "try",
36
+ "return", "delete", "goto", "break", "continue", "throw",
37
+ "co_await", "co_yield", "co_return",
38
+ }),
39
+ trailing_mods_re=re.compile(
40
+ r"\s*(?:const|override|final|noexcept|mutable|constexpr|inline|static)\s*[;{]*\s*$"
41
+ ),
42
+ access_spec_re=re.compile(r"^(?:public|private|protected)\s*:\s*(?://.*)?$"),
43
+ macro_like_re=re.compile(r"^[A-Z][A-Z0-9_]*\s*(?:\([^{};]*\))?\s*$"),
44
+ define_re=re.compile(r"#\s*define\s+"),
45
+ extern_c_re=re.compile(r'\bextern\s+"C"'),
46
+ operator_re=re.compile(r"\boperator\b"),
47
+ uses_braces=True,
48
+ uses_namespaces=True,
49
+ uses_colon_inheritance=True,
50
+ scope_operator="::",
51
+ base_keyword="Super",
52
+ static_call_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)::([A-Za-z_][A-Za-z0-9_]*)\s*\("),
53
+ super_call_re=re.compile(r"\bSuper::([A-Za-z_][A-Za-z0-9_]*)\s*\("),
54
+ type_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)\b"),
55
+ param_type_re=re.compile(
56
+ r"(?:const\s+)?([A-Z][A-Za-z0-9_]+)\s*(?:\*+|&)?\s+\w+"
57
+ ),
58
+ basic_skip_types=frozenset({
59
+ "int8", "int16", "int32", "int64",
60
+ "uint8", "uint16", "uint32", "uint64",
61
+ "float", "double", "bool", "void", "int", "char", "long", "short",
62
+ "unsigned", "size_t", "auto", "nullptr_t",
63
+ }),
64
+ block_keyword_re=re.compile(r"\b(?:namespace|class|struct|enum)\b"),
65
+ lambda_re=re.compile(r"\[.*\]\s*[\(]"),
66
+ namespace_sig_re=re.compile(r"(?:inline\s+)?namespace\s+(\w+)?\s*$"),
67
+ init_list_re=re.compile(r"\)\s*:"),
68
+ access_spec_names=frozenset({"public:", "protected:", "private:"}),
69
+ view_structural_kws=("class ", "struct ", "enum ", "namespace "),
70
+ view_modifier_kws=("virtual ", "static ", "override", "FORCEINLINE"),
71
+ local_var_modifiers="const|static|mutable|constexpr|volatile",
72
+ verbatim_string_prefix=None,
73
+ raw_string_char="R",
74
+ range_for_re=re.compile(
75
+ r"for\s*\(\s*(?:const\s+)?(\w+(?:\s*<[^>]*>)?)\s*[*&]?\s+(\w+)\s*:\s*(\w+)"
76
+ ),
77
+ # Comment syntax
78
+ line_comment="//",
79
+ block_comment_pair=("/*", "*/"),
80
+ # String syntax
81
+ string_delimiters=frozenset({'"', "'"}),
82
+ string_escape_char="\\",
83
+ triple_quote_strings=(),
84
+ # Block style
85
+ uses_indent_blocks=False,
86
+ # Preprocessor
87
+ preprocessor_prefix="#",
88
+ has_preprocessor_macros=True,
89
+ # Statement / block close
90
+ statement_terminator=";",
91
+ block_close_suffix="};",
92
+ summary_comment_prefix="//",
93
+ # Config-driven control flow
94
+ control_flow_patterns=(
95
+ ("for", re.compile(r"^\s*for\s*\((.{1,80})\)\s*\{?\s*$")),
96
+ ("while", re.compile(r"^\s*while\s*\((.{1,80})\)\s*\{?\s*$")),
97
+ ("if", re.compile(r"^\s*(?:else\s+)?if\s*\((.{1,80})\)\s*\{?\s*$")),
98
+ ("switch", re.compile(r"^\s*switch\s*\((.{1,40})\)\s*\{?\s*$")),
99
+ ),
100
+ return_re=re.compile(r"^\s*return\s+(.{1,60});"),
101
+ # Extra syntax hints
102
+ type_indicator_chars="*&",
103
+ define_line_re=re.compile(r"#\s*define\s+(\w+)(\([^)]*\))?\s*(.*)"),
104
+ has_template_strings=False,
105
+ raw_string_style="cpp",
106
+ )
@@ -0,0 +1,103 @@
1
+ """C# language configuration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+
7
+ from ..configs import LanguageConfig
8
+
9
+
10
+ def make_csharp_language() -> LanguageConfig:
11
+ """C# language configuration."""
12
+ return LanguageConfig(
13
+ name="csharp",
14
+ class_re=re.compile(
15
+ r"(?:^|\s)(class|struct|interface|record)"
16
+ r"(?:\s+(?:class|struct))?"
17
+ r"\s+"
18
+ r"(\w+)"
19
+ r"\s*(?::\s*(\w+))?",
20
+ ),
21
+ enum_re=re.compile(r"\benum\s+(\w+)"),
22
+ namespace_re=re.compile(r"\bnamespace\s+([\w.]+)"),
23
+ func_name_re=re.compile(r"(\w+)\s*\([^)]*\)\s*$"),
24
+ export_macro_re=re.compile(r"(?!x)x"),
25
+ calling_conv_re=re.compile(r"(?!x)x"),
26
+ attribute_re=re.compile(r"\[[^\]]*\]"),
27
+ template_re=re.compile(r"<[^<>]*>"),
28
+ dtor_re=re.compile(r"(?!x)x"),
29
+ control_flow_re=re.compile(r"\b(if|else\s+if|else|while|for|foreach|do|switch|catch|try|using|lock)\b"),
30
+ control_flow_names=frozenset({
31
+ "if", "else", "while", "for", "foreach", "do", "switch", "catch", "try",
32
+ "return", "break", "continue", "throw", "using", "lock", "yield",
33
+ "async", "await", "new", "this", "base", "typeof", "sizeof", "nameof",
34
+ "default", "checked", "unchecked", "delegate",
35
+ }),
36
+ trailing_mods_re=re.compile(r"\s*(?:override|virtual|abstract|sealed|static|async)\s*[;{]*\s*$"),
37
+ access_spec_re=re.compile(r"^(?!x)x"),
38
+ macro_like_re=re.compile(r"(?!x)x"),
39
+ define_re=re.compile(r"(?!x)x"),
40
+ extern_c_re=re.compile(r"(?!x)x"),
41
+ operator_re=None,
42
+ uses_braces=True,
43
+ uses_namespaces=True,
44
+ uses_colon_inheritance=True,
45
+ scope_operator=".",
46
+ base_keyword="base",
47
+ static_call_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)\.([A-Za-z_][A-Za-z0-9_]*)\s*\("),
48
+ super_call_re=re.compile(r"\bbase\.([A-Za-z_][A-Za-z0-9_]*)\s*\("),
49
+ type_re=re.compile(r"\b([A-Z][A-Za-z0-9_]+)\b"),
50
+ param_type_re=re.compile(r"([A-Z][A-Za-z0-9_]+)\s+\w+"),
51
+ basic_skip_types=frozenset({
52
+ "int", "uint", "long", "ulong", "short", "ushort",
53
+ "byte", "sbyte", "float", "double", "decimal",
54
+ "bool", "string", "object", "void", "char",
55
+ "var", "dynamic", "nint", "nuint",
56
+ }),
57
+ block_keyword_re=re.compile(r"\b(?:namespace|class|struct|interface|record|enum)\b"),
58
+ lambda_re=re.compile(r"(?:\w+\s*=>|delegate\s*\()"),
59
+ namespace_sig_re=re.compile(r"namespace\s+([\w.]+)\s*$"),
60
+ init_list_re=None,
61
+ access_spec_names=frozenset({
62
+ "public", "private", "protected", "internal",
63
+ "protected internal", "private protected",
64
+ }),
65
+ view_structural_kws=("class ", "struct ", "interface ", "record ", "enum ", "namespace "),
66
+ view_modifier_kws=("virtual ", "static ", "override", "abstract ", "sealed ", "async "),
67
+ local_var_modifiers="const|static|volatile|readonly|ref|out",
68
+ verbatim_string_prefix="@",
69
+ raw_string_char=None,
70
+ range_for_re=re.compile(
71
+ r"foreach\s*\(\s*(\w+(?:\s*<[^>]*>)?)\s+(\w+)\s+in\s+(\w+)"
72
+ ),
73
+ # Comment syntax
74
+ line_comment="//",
75
+ block_comment_pair=("/*", "*/"),
76
+ # String syntax
77
+ string_delimiters=frozenset({'"'}),
78
+ string_escape_char="\\",
79
+ triple_quote_strings=(),
80
+ # Block style
81
+ uses_indent_blocks=False,
82
+ # Preprocessor
83
+ preprocessor_prefix="",
84
+ has_preprocessor_macros=False,
85
+ # Statement / block close
86
+ statement_terminator=";",
87
+ block_close_suffix="}",
88
+ summary_comment_prefix="//",
89
+ # Config-driven control flow
90
+ control_flow_patterns=(
91
+ ("for", re.compile(r"^\s*for\s*\((.{1,80})\)\s*\{?\s*$")),
92
+ ("foreach", re.compile(r"^\s*foreach\s*\((.{1,80})\)\s*\{?\s*$")),
93
+ ("while", re.compile(r"^\s*while\s*\((.{1,80})\)\s*\{?\s*$")),
94
+ ("if", re.compile(r"^\s*(?:else\s+)?if\s*\((.{1,80})\)\s*\{?\s*$")),
95
+ ("switch", re.compile(r"^\s*switch\s*\((.{1,40})\)\s*\{?\s*$")),
96
+ ),
97
+ return_re=re.compile(r"^\s*return\s+(.{1,60});"),
98
+ # Extra syntax hints
99
+ type_indicator_chars="",
100
+ define_line_re=None,
101
+ has_template_strings=False,
102
+ raw_string_style="cpp",
103
+ )