codespine 0.1.3__tar.gz → 0.1.5__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.
Files changed (49) hide show
  1. {codespine-0.1.3 → codespine-0.1.5}/PKG-INFO +1 -1
  2. {codespine-0.1.3 → codespine-0.1.5}/codespine/__init__.py +1 -1
  3. {codespine-0.1.3 → codespine-0.1.5}/codespine/cli.py +40 -4
  4. {codespine-0.1.3 → codespine-0.1.5}/codespine/indexer/engine.py +38 -6
  5. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/PKG-INFO +1 -1
  6. {codespine-0.1.3 → codespine-0.1.5}/pyproject.toml +1 -1
  7. {codespine-0.1.3 → codespine-0.1.5}/LICENSE +0 -0
  8. {codespine-0.1.3 → codespine-0.1.5}/README.md +0 -0
  9. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/__init__.py +0 -0
  10. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/community.py +0 -0
  11. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/context.py +0 -0
  12. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/coupling.py +0 -0
  13. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/deadcode.py +0 -0
  14. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/flow.py +0 -0
  15. {codespine-0.1.3 → codespine-0.1.5}/codespine/analysis/impact.py +0 -0
  16. {codespine-0.1.3 → codespine-0.1.5}/codespine/config.py +0 -0
  17. {codespine-0.1.3 → codespine-0.1.5}/codespine/db/__init__.py +0 -0
  18. {codespine-0.1.3 → codespine-0.1.5}/codespine/db/schema.py +0 -0
  19. {codespine-0.1.3 → codespine-0.1.5}/codespine/db/store.py +0 -0
  20. {codespine-0.1.3 → codespine-0.1.5}/codespine/diff/__init__.py +0 -0
  21. {codespine-0.1.3 → codespine-0.1.5}/codespine/diff/branch_diff.py +0 -0
  22. {codespine-0.1.3 → codespine-0.1.5}/codespine/indexer/__init__.py +0 -0
  23. {codespine-0.1.3 → codespine-0.1.5}/codespine/indexer/call_resolver.py +0 -0
  24. {codespine-0.1.3 → codespine-0.1.5}/codespine/indexer/java_parser.py +0 -0
  25. {codespine-0.1.3 → codespine-0.1.5}/codespine/indexer/symbol_builder.py +0 -0
  26. {codespine-0.1.3 → codespine-0.1.5}/codespine/mcp/__init__.py +0 -0
  27. {codespine-0.1.3 → codespine-0.1.5}/codespine/mcp/server.py +0 -0
  28. {codespine-0.1.3 → codespine-0.1.5}/codespine/noise/__init__.py +0 -0
  29. {codespine-0.1.3 → codespine-0.1.5}/codespine/noise/blocklist.py +0 -0
  30. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/__init__.py +0 -0
  31. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/bm25.py +0 -0
  32. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/fuzzy.py +0 -0
  33. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/hybrid.py +0 -0
  34. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/rrf.py +0 -0
  35. {codespine-0.1.3 → codespine-0.1.5}/codespine/search/vector.py +0 -0
  36. {codespine-0.1.3 → codespine-0.1.5}/codespine/watch/__init__.py +0 -0
  37. {codespine-0.1.3 → codespine-0.1.5}/codespine/watch/watcher.py +0 -0
  38. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/SOURCES.txt +0 -0
  39. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/dependency_links.txt +0 -0
  40. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/entry_points.txt +0 -0
  41. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/requires.txt +0 -0
  42. {codespine-0.1.3 → codespine-0.1.5}/codespine.egg-info/top_level.txt +0 -0
  43. {codespine-0.1.3 → codespine-0.1.5}/gindex.py +0 -0
  44. {codespine-0.1.3 → codespine-0.1.5}/setup.cfg +0 -0
  45. {codespine-0.1.3 → codespine-0.1.5}/tests/test_branch_diff_normalize.py +0 -0
  46. {codespine-0.1.3 → codespine-0.1.5}/tests/test_call_resolver.py +0 -0
  47. {codespine-0.1.3 → codespine-0.1.5}/tests/test_index_and_hybrid.py +0 -0
  48. {codespine-0.1.3 → codespine-0.1.5}/tests/test_java_parser.py +0 -0
  49. {codespine-0.1.3 → codespine-0.1.5}/tests/test_search_ranking.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codespine
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Local Java code intelligence indexer backed by a graph database
5
5
  Author: CodeSpine contributors
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
1
  """CodeSpine package."""
2
2
 
3
3
  __all__ = ["__version__"]
4
- __version__ = "0.1.0"
4
+ __version__ = "0.1.5"
@@ -88,10 +88,46 @@ def analyse(path: str, full: bool) -> None:
88
88
  abs_path = os.path.abspath(path)
89
89
  store = GraphStore(read_only=False)
90
90
  indexer = JavaIndexer(store)
91
-
92
- result = indexer.index_project(abs_path, full=full)
93
- _phase("Walking files...", f"{result.files_found} files found")
94
- _phase("Parsing code...", f"{result.files_indexed}/{result.files_found}")
91
+ parse_state = {"shown": False, "indexed": 0, "total": 0, "last_ts": 0.0}
92
+
93
+ def _progress(event: str, payload: dict) -> None:
94
+ now = time.perf_counter()
95
+ if event == "scan_done":
96
+ _phase("Walking files...", f"{int(payload.get('files_found', 0))} files found")
97
+ return
98
+ if event == "plan_done":
99
+ to_index = int(payload.get("files_to_index", 0))
100
+ deleted = int(payload.get("deleted_files", 0))
101
+ mode = str(payload.get("mode", "incremental"))
102
+ parse_state["total"] = to_index
103
+ _phase("Index mode...", f"{mode} ({to_index} files to index, {deleted} deleted)")
104
+ if to_index == 0:
105
+ _phase("Parsing code...", "0/0")
106
+ return
107
+ if event == "parse_progress":
108
+ indexed = int(payload.get("indexed", 0))
109
+ total = int(payload.get("total", 0))
110
+ parse_state["indexed"] = indexed
111
+ parse_state["total"] = total
112
+ if total == 0:
113
+ return
114
+ if indexed == total or (now - parse_state["last_ts"]) >= 0.2:
115
+ click.echo(f"\rParsing code... {indexed}/{total}", nl=False)
116
+ parse_state["shown"] = True
117
+ parse_state["last_ts"] = now
118
+ return
119
+ if event == "resolve_calls_start" and parse_state["shown"]:
120
+ click.echo()
121
+ parse_state["shown"] = False
122
+ return
123
+
124
+ result = indexer.index_project(abs_path, full=full, progress=_progress)
125
+ if parse_state["shown"]:
126
+ click.echo()
127
+ if parse_state["total"] == 0:
128
+ _phase("Parsing code...", "0/0")
129
+ elif parse_state["indexed"] < parse_state["total"]:
130
+ _phase("Parsing code...", f"{parse_state['indexed']}/{parse_state['total']}")
95
131
  _phase("Tracing calls...", f"{result.calls_resolved} calls resolved")
96
132
  _phase("Analyzing types...", f"{result.type_relationships} type relationships")
97
133
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import os
4
4
  from dataclasses import dataclass
5
+ from typing import Callable
5
6
 
6
7
  from codespine.indexer.call_resolver import resolve_calls
7
8
  from codespine.indexer.java_parser import parse_java_source
@@ -25,12 +26,18 @@ class JavaIndexer:
25
26
  def __init__(self, store):
26
27
  self.store = store
27
28
 
28
- def index_project(self, root_path: str, full: bool = True) -> IndexResult:
29
+ def index_project(
30
+ self,
31
+ root_path: str,
32
+ full: bool = True,
33
+ progress: Callable[[str, dict], None] | None = None,
34
+ ) -> IndexResult:
29
35
  root_path = os.path.abspath(root_path)
30
36
  project_id = os.path.basename(root_path)
31
37
  current_files = self._collect_java_files(root_path)
32
- current_hashes = self._hash_files(project_id, root_path, current_files)
38
+ self._emit(progress, "scan_done", files_found=len(current_files))
33
39
  db_files = self.store.project_file_hashes(project_id) if not full else {}
40
+ current_hashes = self._hash_files(project_id, root_path, current_files) if not full else {}
34
41
 
35
42
  if full:
36
43
  to_reindex = current_files
@@ -45,6 +52,13 @@ class JavaIndexer:
45
52
  old = db_files.get(fid, {}).get("hash")
46
53
  if old != digest:
47
54
  to_reindex.append(file_path)
55
+ self._emit(
56
+ progress,
57
+ "plan_done",
58
+ files_to_index=len(to_reindex),
59
+ deleted_files=len(deleted_file_ids),
60
+ mode="full" if full else "incremental",
61
+ )
48
62
 
49
63
  files_indexed = 0
50
64
  classes_indexed = 0
@@ -151,12 +165,23 @@ class JavaIndexer:
151
165
  }
152
166
  class_methods[cls.fqcn][method.signature] = m_id
153
167
  files_indexed += 1
168
+ self._emit(
169
+ progress,
170
+ "parse_progress",
171
+ indexed=files_indexed,
172
+ total=len(to_reindex),
173
+ file_path=file_path,
174
+ )
154
175
 
176
+ self._emit(progress, "resolve_calls_start")
155
177
  for src, dst, confidence, reason in resolve_calls(method_catalog, method_calls, method_context, class_catalog):
156
178
  self.store.add_call(src, dst, confidence, reason)
157
179
  calls_resolved += 1
180
+ self._emit(progress, "resolve_calls_done", calls_resolved=calls_resolved)
158
181
 
182
+ self._emit(progress, "resolve_types_start")
159
183
  type_relationships += self._build_inheritance_edges(class_meta, class_catalog, class_methods)
184
+ self._emit(progress, "resolve_types_done", type_relationships=type_relationships)
160
185
 
161
186
  return IndexResult(
162
187
  project_id=project_id,
@@ -172,10 +197,11 @@ class JavaIndexer:
172
197
  @staticmethod
173
198
  def _collect_java_files(root_path: str) -> list[str]:
174
199
  out: list[str] = []
175
- for root, _, files in os.walk(root_path):
176
- if "src" not in root:
177
- continue
178
- if any(skip in root for skip in ["target", "build", "out", ".git"]):
200
+ skip_dirs = {".git", "target", "build", "out", ".idea", ".gradle", ".mvn", "node_modules"}
201
+ for root, dirs, files in os.walk(root_path, topdown=True):
202
+ dirs[:] = [d for d in dirs if d not in skip_dirs]
203
+ normalized = root.replace("\\", "/")
204
+ if "/src/" not in normalized and not normalized.endswith("/src"):
179
205
  continue
180
206
  for filename in files:
181
207
  if filename.endswith(".java"):
@@ -303,3 +329,9 @@ class JavaIndexer:
303
329
  self.store.add_reference("OVERRIDES", "Method", method_id, "Method", iface_method, 1.0)
304
330
  rel_count += 1
305
331
  return rel_count
332
+
333
+ @staticmethod
334
+ def _emit(progress: Callable[[str, dict], None] | None, event: str, **payload: object) -> None:
335
+ if progress is None:
336
+ return
337
+ progress(event, payload)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codespine
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Local Java code intelligence indexer backed by a graph database
5
5
  Author: CodeSpine contributors
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codespine"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "Local Java code intelligence indexer backed by a graph database"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
File without changes
File without changes
File without changes
File without changes
File without changes