code2logic 1.0.35__tar.gz → 1.0.37__tar.gz
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.
- {code2logic-1.0.35 → code2logic-1.0.37}/PKG-INFO +1 -1
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/__init__.py +1 -1
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/cli.py +42 -2
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/function_logic.py +114 -21
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/toon_format.py +64 -6
- {code2logic-1.0.35 → code2logic-1.0.37}/pyproject.toml +1 -1
- {code2logic-1.0.35 → code2logic-1.0.37}/LICENSE +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/README.md +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/__main__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/adaptive.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/analyzer.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/base.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/benchmark.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/benchmarks/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/benchmarks/common.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/benchmarks/results.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/benchmarks/runner.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/chunked_reproduction.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/code_review.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/config.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/core/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/dependency.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/errors.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/file_formats.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/formats/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/generators.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/gherkin.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/integrations/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/intent.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/llm/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/llm.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/llm_clients.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/llm_clients_new.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/llm_profiler.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/logicml.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/markdown_format.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/mcp_server.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/metrics.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/models.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/parsers.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/project_comparison.md +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/project_reproducer.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/prompts.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/py.typed +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/quality.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/refactor.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/reproducer.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/reproduction.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/schemas/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/schemas/json_schema.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/schemas/logicml_schema.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/schemas/markdown_schema.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/schemas/yaml_schema.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/shared_utils.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/similarity.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/terminal.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/tools/__init__.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/universal.py +0 -0
- {code2logic-1.0.35 → code2logic-1.0.37}/code2logic/utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2logic
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.37
|
|
4
4
|
Summary: Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support.
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
License-File: LICENSE
|
|
@@ -651,6 +651,23 @@ code2logic [path] [options]
|
|
|
651
651
|
action='store_true',
|
|
652
652
|
help='Write all output to stdout instead of files (including schema and function-logic). Useful for piping.'
|
|
653
653
|
)
|
|
654
|
+
parser.add_argument(
|
|
655
|
+
'--no-repeat-module',
|
|
656
|
+
action='store_true',
|
|
657
|
+
dest='no_repeat_module',
|
|
658
|
+
help='Reduce repeated directory prefixes in TOON outputs by using ./file for consecutive entries in the same folder (applies to function-logic TOON and TOON module lists).'
|
|
659
|
+
)
|
|
660
|
+
parser.add_argument(
|
|
661
|
+
'--no-repeat-name',
|
|
662
|
+
action='store_true',
|
|
663
|
+
dest='no_repeat_module',
|
|
664
|
+
help=argparse.SUPPRESS
|
|
665
|
+
)
|
|
666
|
+
parser.add_argument(
|
|
667
|
+
'--no-repeat-details',
|
|
668
|
+
action='store_true',
|
|
669
|
+
help='Reduce repeated directory prefixes in function-logic TOON section function_details by using ./file for consecutive entries in the same folder.'
|
|
670
|
+
)
|
|
654
671
|
parser.add_argument(
|
|
655
672
|
'--no-install',
|
|
656
673
|
action='store_true',
|
|
@@ -961,7 +978,11 @@ code2logic [path] [options]
|
|
|
961
978
|
'standard': 'standard',
|
|
962
979
|
'full': 'full',
|
|
963
980
|
}
|
|
964
|
-
output = generator.generate(
|
|
981
|
+
output = generator.generate(
|
|
982
|
+
project,
|
|
983
|
+
detail=detail_map.get(args.detail, 'standard'),
|
|
984
|
+
no_repeat_name=args.no_repeat_module,
|
|
985
|
+
)
|
|
965
986
|
|
|
966
987
|
# Generate schema if requested
|
|
967
988
|
if args.with_schema:
|
|
@@ -1012,14 +1033,27 @@ code2logic [path] [options]
|
|
|
1012
1033
|
elif lower.endswith(('.yaml', '.yml')):
|
|
1013
1034
|
logic_out = logic_gen.generate_yaml(project, detail=args.detail)
|
|
1014
1035
|
elif lower.endswith('.toon'):
|
|
1015
|
-
logic_out = logic_gen.generate_toon(
|
|
1036
|
+
logic_out = logic_gen.generate_toon(
|
|
1037
|
+
project,
|
|
1038
|
+
detail=args.detail,
|
|
1039
|
+
no_repeat_name=args.no_repeat_module,
|
|
1040
|
+
no_repeat_details=args.no_repeat_details,
|
|
1041
|
+
)
|
|
1016
1042
|
else:
|
|
1017
1043
|
logic_out = logic_gen.generate(project, detail=args.detail)
|
|
1018
1044
|
|
|
1045
|
+
# Generate function-logic schema if requested and format is TOON
|
|
1046
|
+
func_schema = None
|
|
1047
|
+
if args.with_schema and lower.endswith('.toon'):
|
|
1048
|
+
func_schema = logic_gen.generate_toon_schema()
|
|
1049
|
+
|
|
1019
1050
|
if use_stdout:
|
|
1020
1051
|
# Write to stdout with section marker
|
|
1021
1052
|
print(f"\n=== FUNCTION_LOGIC ===")
|
|
1022
1053
|
print(logic_out)
|
|
1054
|
+
if func_schema:
|
|
1055
|
+
print(f"\n=== FUNCTION_LOGIC_SCHEMA ===")
|
|
1056
|
+
print(func_schema)
|
|
1023
1057
|
elif output_dir:
|
|
1024
1058
|
# Write to file in output directory
|
|
1025
1059
|
os.makedirs(output_dir, exist_ok=True)
|
|
@@ -1027,6 +1061,12 @@ code2logic [path] [options]
|
|
|
1027
1061
|
f.write(logic_out)
|
|
1028
1062
|
if args.verbose:
|
|
1029
1063
|
log.success(f"Function logic written to: {logic_path}")
|
|
1064
|
+
if func_schema:
|
|
1065
|
+
schema_path = logic_path.replace('.toon', '-schema.json')
|
|
1066
|
+
with open(schema_path, 'w', encoding='utf-8') as f:
|
|
1067
|
+
f.write(func_schema)
|
|
1068
|
+
if args.verbose:
|
|
1069
|
+
log.success(f"Function logic schema written to: {schema_path}")
|
|
1030
1070
|
|
|
1031
1071
|
gen_time = time.time() - gen_start
|
|
1032
1072
|
|
|
@@ -59,35 +59,57 @@ class FunctionLogicGenerator:
|
|
|
59
59
|
return self.generate(project, detail)
|
|
60
60
|
return yaml.dump(data, default_flow_style=False, allow_unicode=True, sort_keys=False, width=120)
|
|
61
61
|
|
|
62
|
-
def generate_toon(
|
|
62
|
+
def generate_toon(
|
|
63
|
+
self,
|
|
64
|
+
project: ProjectInfo,
|
|
65
|
+
detail: str = 'full',
|
|
66
|
+
no_repeat_name: bool = False,
|
|
67
|
+
no_repeat_details: bool = False,
|
|
68
|
+
) -> str:
|
|
63
69
|
if detail == 'detailed':
|
|
64
70
|
detail = 'full'
|
|
65
71
|
toon = TOONGenerator()
|
|
66
72
|
delim = toon.delimiter
|
|
67
73
|
dm = toon.delim_marker
|
|
68
74
|
|
|
75
|
+
# Pre-filter: only modules with at least one function/method
|
|
76
|
+
all_modules = list(project.modules or [])
|
|
77
|
+
modules_with_items = [(m, self._module_items(m)) for m in all_modules]
|
|
78
|
+
modules_with_items = [(m, items) for m, items in modules_with_items if items]
|
|
79
|
+
|
|
69
80
|
lines: List[str] = []
|
|
81
|
+
|
|
82
|
+
# Format header — helps LLM understand the structure
|
|
83
|
+
lines.append(f"# {project.name} function-logic | {len(modules_with_items)} modules")
|
|
84
|
+
lines.append("# Convention: name with . = method, ~name = async, cc:N shown only when >1")
|
|
85
|
+
|
|
70
86
|
lines.append(f"project: {toon._quote(project.name)}")
|
|
71
87
|
if getattr(project, 'generated_at', None):
|
|
72
88
|
lines.append(f"generated: {toon._quote(project.generated_at)}")
|
|
73
89
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
for m in
|
|
77
|
-
|
|
78
|
-
|
|
90
|
+
lines.append(f"modules[{len(modules_with_items)}]{{path{dm}lang{dm}items}}:")
|
|
91
|
+
prev_dir: str | None = None
|
|
92
|
+
for m, items in modules_with_items:
|
|
93
|
+
if no_repeat_name:
|
|
94
|
+
compressed_path, prev_dir = toon._compress_module_path(m.path, prev_dir)
|
|
95
|
+
path_out = compressed_path
|
|
96
|
+
else:
|
|
97
|
+
path_out = m.path
|
|
98
|
+
lines.append(f" {toon._quote(path_out)}{delim}{toon._short_lang(m.language)}{delim}{len(items)}")
|
|
79
99
|
|
|
80
100
|
lines.append("")
|
|
81
101
|
lines.append("function_details:")
|
|
82
102
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if
|
|
86
|
-
|
|
103
|
+
prev_dir = None
|
|
104
|
+
for m, items in modules_with_items:
|
|
105
|
+
if no_repeat_details:
|
|
106
|
+
compressed_path, prev_dir = toon._compress_module_path(m.path, prev_dir)
|
|
107
|
+
details_key = compressed_path
|
|
108
|
+
else:
|
|
109
|
+
details_key = m.path
|
|
110
|
+
lines.append(f" {toon._quote(details_key)}:")
|
|
87
111
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
header = f"name{dm}kind{dm}sig{dm}loc{dm}async{dm}lines{dm}cc"
|
|
112
|
+
header = f"line{dm}name{dm}sig"
|
|
91
113
|
if detail in ('standard', 'full'):
|
|
92
114
|
header += f"{dm}does"
|
|
93
115
|
if detail == 'full':
|
|
@@ -97,16 +119,20 @@ class FunctionLogicGenerator:
|
|
|
97
119
|
|
|
98
120
|
for kind, qname, func in items:
|
|
99
121
|
sig = self._build_sig(func, include_async_prefix=False, language=m.language)
|
|
100
|
-
|
|
101
|
-
|
|
122
|
+
start_line = str(getattr(func, 'start_line', 0) or 0)
|
|
123
|
+
|
|
124
|
+
# Encode async as ~ prefix, cc as suffix (only when >1)
|
|
125
|
+
display_name = qname
|
|
126
|
+
if getattr(func, 'is_async', False):
|
|
127
|
+
display_name = f"~{qname}"
|
|
128
|
+
cc = getattr(func, 'complexity', 1) or 1
|
|
129
|
+
if cc > 1:
|
|
130
|
+
display_name = f"{display_name} cc:{cc}"
|
|
131
|
+
|
|
102
132
|
row = [
|
|
103
|
-
|
|
104
|
-
toon._quote(
|
|
133
|
+
start_line,
|
|
134
|
+
toon._quote(display_name),
|
|
105
135
|
toon._quote(sig),
|
|
106
|
-
toon._quote(loc),
|
|
107
|
-
is_async,
|
|
108
|
-
str(getattr(func, 'lines', 0) or 0),
|
|
109
|
-
str(getattr(func, 'complexity', 1) or 1),
|
|
110
136
|
]
|
|
111
137
|
|
|
112
138
|
if detail in ('standard', 'full'):
|
|
@@ -125,6 +151,73 @@ class FunctionLogicGenerator:
|
|
|
125
151
|
|
|
126
152
|
return "\n".join(lines).rstrip() + "\n"
|
|
127
153
|
|
|
154
|
+
def generate_toon_schema(self) -> str:
|
|
155
|
+
"""Generate JSON Schema describing the function-logic TOON format."""
|
|
156
|
+
import json
|
|
157
|
+
|
|
158
|
+
schema = {
|
|
159
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
160
|
+
"title": "Code2Logic Function-Logic TOON Schema",
|
|
161
|
+
"description": (
|
|
162
|
+
"Schema for project.functions.toon — compact function/method index. "
|
|
163
|
+
"Conventions: name containing '.' = method (Class.method), "
|
|
164
|
+
"~prefix = async, 'cc:N' suffix = cyclomatic complexity (only when >1)."
|
|
165
|
+
),
|
|
166
|
+
"type": "object",
|
|
167
|
+
"properties": {
|
|
168
|
+
"project": {"type": "string", "description": "Project name"},
|
|
169
|
+
"generated": {"type": "string", "description": "ISO timestamp"},
|
|
170
|
+
"modules": {
|
|
171
|
+
"type": "array",
|
|
172
|
+
"description": "Modules with at least one function/method. Rows: path,lang,items. Use ./file for same-dir compression (--no-repeat-module).",
|
|
173
|
+
"items": {
|
|
174
|
+
"type": "object",
|
|
175
|
+
"properties": {
|
|
176
|
+
"path": {"type": "string", "description": "Relative path or ./basename if same dir as previous"},
|
|
177
|
+
"lang": {"type": "string", "description": "Short language code (py, js, ts, ...)"},
|
|
178
|
+
"items": {"type": "integer", "description": "Number of functions+methods in module"}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
"function_details": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"description": "Per-module function tables. Keys are module paths (or ./basename with --no-repeat-details).",
|
|
185
|
+
"patternProperties": {
|
|
186
|
+
".*": {
|
|
187
|
+
"type": "object",
|
|
188
|
+
"properties": {
|
|
189
|
+
"functions": {
|
|
190
|
+
"type": "array",
|
|
191
|
+
"description": "Tabular rows: line,name,sig[,does][,decorators,calls,raises]",
|
|
192
|
+
"items": {
|
|
193
|
+
"type": "object",
|
|
194
|
+
"properties": {
|
|
195
|
+
"line": {"type": "integer", "description": "Start line number"},
|
|
196
|
+
"name": {
|
|
197
|
+
"type": "string",
|
|
198
|
+
"description": (
|
|
199
|
+
"Function or method name. "
|
|
200
|
+
"Contains '.' if method (e.g. Class.method). "
|
|
201
|
+
"Prefixed with ~ if async. "
|
|
202
|
+
"Suffixed with ' cc:N' if cyclomatic complexity > 1."
|
|
203
|
+
)
|
|
204
|
+
},
|
|
205
|
+
"sig": {"type": "string", "description": "Signature: (params) [-> return_type]"},
|
|
206
|
+
"does": {"type": "string", "description": "Intent/purpose (standard+full detail)"},
|
|
207
|
+
"decorators": {"type": "string", "description": "Pipe-separated decorators (full detail)"},
|
|
208
|
+
"calls": {"type": "string", "description": "Pipe-separated function calls (full detail)"},
|
|
209
|
+
"raises": {"type": "string", "description": "Pipe-separated exceptions (full detail)"}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return json.dumps(schema, indent=2, ensure_ascii=False)
|
|
220
|
+
|
|
128
221
|
def _build_data(self, project: ProjectInfo, detail: str) -> dict:
|
|
129
222
|
modules_data = []
|
|
130
223
|
for m in project.modules or []:
|
|
@@ -33,6 +33,37 @@ class TOONGenerator:
|
|
|
33
33
|
SPECIAL_CHARS = re.compile(r'[:\"\\\[\]\{\}\n\t\r,]')
|
|
34
34
|
LOOKS_LIKE_LITERAL = re.compile(r'^(true|false|null|-?\d+\.?\d*([eE][+-]?\d+)?|-)$')
|
|
35
35
|
|
|
36
|
+
LANGUAGE_ABBREVIATIONS = {
|
|
37
|
+
'python': 'py',
|
|
38
|
+
'javascript': 'js',
|
|
39
|
+
'typescript': 'ts',
|
|
40
|
+
'tsx': 'tsx',
|
|
41
|
+
'jsx': 'jsx',
|
|
42
|
+
'java': 'java',
|
|
43
|
+
'kotlin': 'kt',
|
|
44
|
+
'go': 'go',
|
|
45
|
+
'rust': 'rs',
|
|
46
|
+
'c': 'c',
|
|
47
|
+
'cpp': 'cpp',
|
|
48
|
+
'c++': 'cpp',
|
|
49
|
+
'csharp': 'cs',
|
|
50
|
+
'c#': 'cs',
|
|
51
|
+
'php': 'php',
|
|
52
|
+
'ruby': 'rb',
|
|
53
|
+
'swift': 'swift',
|
|
54
|
+
'scala': 'scala',
|
|
55
|
+
'bash': 'sh',
|
|
56
|
+
'shell': 'sh',
|
|
57
|
+
'sql': 'sql',
|
|
58
|
+
'yaml': 'yaml',
|
|
59
|
+
'json': 'json',
|
|
60
|
+
'toml': 'toml',
|
|
61
|
+
'markdown': 'md',
|
|
62
|
+
'html': 'html',
|
|
63
|
+
'css': 'css',
|
|
64
|
+
'dockerfile': 'docker',
|
|
65
|
+
}
|
|
66
|
+
|
|
36
67
|
def __init__(self, delimiter: str = ',', use_tabs: bool = False):
|
|
37
68
|
"""
|
|
38
69
|
Initialize TOON generator.
|
|
@@ -46,7 +77,27 @@ class TOONGenerator:
|
|
|
46
77
|
# parsers/LLMs can read them. Use comma-separated headers regardless of row delimiter.
|
|
47
78
|
self.delim_marker = ','
|
|
48
79
|
|
|
49
|
-
def
|
|
80
|
+
def _short_lang(self, lang: str) -> str:
|
|
81
|
+
lang_norm = (lang or '').strip().lower()
|
|
82
|
+
return self.LANGUAGE_ABBREVIATIONS.get(lang_norm, lang)
|
|
83
|
+
|
|
84
|
+
def _compress_module_path(self, path: str, prev_dir: str | None) -> tuple[str, str]:
|
|
85
|
+
"""Compress repeated directory prefixes for module summary tables.
|
|
86
|
+
|
|
87
|
+
If consecutive modules are in the same directory, emit './<basename>' instead
|
|
88
|
+
of repeating '<dir>/<basename>'. The first entry for a directory stays as the
|
|
89
|
+
full path.
|
|
90
|
+
"""
|
|
91
|
+
p = (path or '')
|
|
92
|
+
if '/' not in p:
|
|
93
|
+
return p, ''
|
|
94
|
+
|
|
95
|
+
cur_dir, base = p.rsplit('/', 1)
|
|
96
|
+
if prev_dir is not None and cur_dir == prev_dir:
|
|
97
|
+
return f"./{base}", cur_dir
|
|
98
|
+
return p, cur_dir
|
|
99
|
+
|
|
100
|
+
def generate(self, project: ProjectInfo, detail: str = 'standard', no_repeat_name: bool = False) -> str:
|
|
50
101
|
"""
|
|
51
102
|
Generate TOON format from ProjectInfo.
|
|
52
103
|
|
|
@@ -71,26 +122,33 @@ class TOONGenerator:
|
|
|
71
122
|
|
|
72
123
|
# Languages as primitive array
|
|
73
124
|
if project.languages:
|
|
74
|
-
lang_items = [f"{k}:{v}" for k, v in project.languages.items()]
|
|
125
|
+
lang_items = [f"{self._short_lang(k)}:{v}" for k, v in project.languages.items()]
|
|
75
126
|
lines.append(f" languages[{len(lang_items)}]: {self.delimiter.join(lang_items)}")
|
|
76
127
|
|
|
77
128
|
# Modules - tabular format for efficiency
|
|
78
129
|
if project.modules:
|
|
79
130
|
lines.append("")
|
|
80
|
-
lines.extend(self._generate_modules(project.modules, detail))
|
|
131
|
+
lines.extend(self._generate_modules(project.modules, detail, no_repeat_name=no_repeat_name))
|
|
81
132
|
|
|
82
133
|
return '\n'.join(lines)
|
|
83
134
|
|
|
84
|
-
def _generate_modules(self, modules: List[ModuleInfo], detail: str) -> List[str]:
|
|
135
|
+
def _generate_modules(self, modules: List[ModuleInfo], detail: str, no_repeat_name: bool = False) -> List[str]:
|
|
85
136
|
"""Generate modules section."""
|
|
86
137
|
lines = []
|
|
87
138
|
|
|
88
139
|
# Module summary as tabular array
|
|
89
140
|
lines.append(f"modules[{len(modules)}]{{path{self.delim_marker}lang{self.delim_marker}lines{self.delim_marker}kb}}:")
|
|
141
|
+
prev_dir: str | None = None
|
|
90
142
|
for m in modules:
|
|
91
|
-
|
|
143
|
+
if no_repeat_name:
|
|
144
|
+
path_out, prev_dir = self._compress_module_path(m.path, prev_dir)
|
|
145
|
+
else:
|
|
146
|
+
path_out = m.path
|
|
147
|
+
path = self._quote(path_out)
|
|
92
148
|
kb = round((getattr(m, 'file_bytes', 0) or 0) / 1024, 1)
|
|
93
|
-
lines.append(
|
|
149
|
+
lines.append(
|
|
150
|
+
f" {path}{self.delimiter}{self._short_lang(m.language)}{self.delimiter}{m.lines_code}{self.delimiter}{kb}"
|
|
151
|
+
)
|
|
94
152
|
|
|
95
153
|
# Detailed module info
|
|
96
154
|
if detail in ('standard', 'full'):
|
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "code2logic"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.37"
|
|
8
8
|
description = "Code2Logic - Source code to logical representation converter for LLM analysis, featuring Tree-sitter parsing, dependency graph analysis, and multi-language support."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|