codecortex 0.8.3__tar.gz → 0.8.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.
- {codecortex-0.8.3/src/codecortex.egg-info → codecortex-0.8.5}/PKG-INFO +1 -1
- {codecortex-0.8.3 → codecortex-0.8.5/src/codecortex.egg-info}/PKG-INFO +1 -1
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codecortex.egg-info/SOURCES.txt +1 -0
- codecortex-0.8.5/src/codeintel/__init__.py +1 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/doctor.py +15 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/indexer.py +27 -4
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/server.py +44 -5
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_doctor.py +19 -0
- codecortex-0.8.5/tests/test_mcp_server.py +42 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_treesitter.py +23 -0
- codecortex-0.8.3/src/codeintel/__init__.py +0 -1
- {codecortex-0.8.3 → codecortex-0.8.5}/LICENSE +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/README.md +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/pyproject.toml +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/setup.cfg +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codecortex.egg-info/dependency_links.txt +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codecortex.egg-info/entry_points.txt +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codecortex.egg-info/requires.txt +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codecortex.egg-info/top_level.txt +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/__main__.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/auth.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/cache.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/config.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/gateway.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/http_server.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/injector.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/installer.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/logconfig.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/mapper.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/metrics.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/onboarding.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/policy.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/provider.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/providers/__init__.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/providers/graph.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/providers/lsp.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/providers/none.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/providers/semantic.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/reindexer.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/reset.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/searcher.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/semantic_db.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/src/codeintel/term.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_cache.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_chunking.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_config.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_e2e.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_enterprise.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_gateway.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_graph_provider.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_graph_real.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_graph_stdin.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_hardening.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_http_auth.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_http_server.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_installer.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_integration.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_lsp_provider.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_lsp_real.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_mapper.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_model_dimension.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_never_raise.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_onboarding.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_rbac.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_reindexer.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_rerank.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_reset.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_semantic_provider.py +0 -0
- {codecortex-0.8.3 → codecortex-0.8.5}/tests/test_term.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecortex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.5
|
|
4
4
|
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
5
|
Author: Shammai Hamilton
|
|
6
6
|
License-Expression: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecortex
|
|
3
|
-
Version: 0.8.
|
|
3
|
+
Version: 0.8.5
|
|
4
4
|
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
5
|
Author: Shammai Hamilton
|
|
6
6
|
License-Expression: MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.8.5"
|
|
@@ -102,11 +102,21 @@ def run_doctor(
|
|
|
102
102
|
"runnable": False, "repo_indexed": None,
|
|
103
103
|
"detail": "semantic provider unavailable", "remediation": None}
|
|
104
104
|
|
|
105
|
+
# Is def-aligned (tree-sitter) chunking active for non-Python files? The semantic engine works
|
|
106
|
+
# without it (line-window fallback) but SILENTLY — surface it so a broken/missing grammar pack
|
|
107
|
+
# doesn't degrade chunking invisibly. find_spec (not import) keeps this cheap + never-load.
|
|
108
|
+
try:
|
|
109
|
+
import importlib.util
|
|
110
|
+
treesitter = importlib.util.find_spec("tree_sitter_language_pack") is not None
|
|
111
|
+
except Exception:
|
|
112
|
+
treesitter = False
|
|
113
|
+
|
|
105
114
|
ready = sum(1 for e in engines.values() if e.get("status") != "fail")
|
|
106
115
|
return {
|
|
107
116
|
"ok": True,
|
|
108
117
|
"project_root": root,
|
|
109
118
|
"deep": bool(deep),
|
|
119
|
+
"treesitter": treesitter,
|
|
110
120
|
"summary": {"ready": ready, "total": len(engines),
|
|
111
121
|
"healthy": all(e.get("status") != "fail" for e in engines.values())},
|
|
112
122
|
"engines": engines,
|
|
@@ -163,4 +173,9 @@ def render_doctor_text(report: dict) -> str:
|
|
|
163
173
|
"tip: `codeintel setup --install-uv --install-deps --index` bootstraps the "
|
|
164
174
|
"pip-installable backends; each fix: line above has the per-engine command."
|
|
165
175
|
))
|
|
176
|
+
if report.get("treesitter") is False:
|
|
177
|
+
out.append(" " + c.dim(
|
|
178
|
+
"def-aligned chunking: OFF for non-Python — tree-sitter-language-pack not importable, "
|
|
179
|
+
"so TS/JS/Go/Rust/… fall back to line windows. fix: pip install tree-sitter-language-pack"
|
|
180
|
+
))
|
|
166
181
|
return "\n".join(out)
|
|
@@ -85,6 +85,22 @@ _TS_CONTAINER_TYPES = {
|
|
|
85
85
|
"c": set(),
|
|
86
86
|
"cpp": {"class_specifier", "struct_specifier", "namespace_definition"},
|
|
87
87
|
}
|
|
88
|
+
# JS/TS assign functions to bindings — `const C = () => {}`, `export const f = function(){}` — which
|
|
89
|
+
# is how React components and hooks (and most modern TS) are written. A lexical/variable declaration
|
|
90
|
+
# counts as a def ONLY when a declarator's value is a function, not a plain `const x = 5`.
|
|
91
|
+
_TS_ARROW_LANGS = frozenset({"typescript", "tsx", "javascript"})
|
|
92
|
+
_TS_DECL_TYPES = frozenset({"lexical_declaration", "variable_declaration"})
|
|
93
|
+
_TS_FUNC_VALUE_TYPES = frozenset({"arrow_function", "function_expression", "function",
|
|
94
|
+
"generator_function"})
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _ts_decl_is_function(node) -> bool:
|
|
98
|
+
"""True if a lexical/variable declaration binds a function (arrow or function expression)."""
|
|
99
|
+
for child in node.children:
|
|
100
|
+
if child.type == "variable_declarator":
|
|
101
|
+
if any(gc.type in _TS_FUNC_VALUE_TYPES for gc in child.children):
|
|
102
|
+
return True
|
|
103
|
+
return False
|
|
88
104
|
|
|
89
105
|
|
|
90
106
|
class Indexer:
|
|
@@ -330,19 +346,26 @@ class Indexer:
|
|
|
330
346
|
func_types = _TS_FUNC_TYPES.get(lang, set())
|
|
331
347
|
cont_types = _TS_CONTAINER_TYPES.get(lang, set())
|
|
332
348
|
all_types = func_types | cont_types
|
|
349
|
+
arrow_ok = lang in _TS_ARROW_LANGS
|
|
333
350
|
if not all_types:
|
|
334
351
|
return [] # unknown language -> caller windows the whole file
|
|
335
352
|
spans: list[tuple[int, int]] = []
|
|
336
353
|
|
|
354
|
+
def is_def(c) -> bool:
|
|
355
|
+
if c.type in all_types:
|
|
356
|
+
return True
|
|
357
|
+
# a const/let bound to an arrow/function (React components, hooks, callbacks)
|
|
358
|
+
return arrow_ok and c.type in _TS_DECL_TYPES and _ts_decl_is_function(c)
|
|
359
|
+
|
|
337
360
|
def nearest_defs(node):
|
|
338
|
-
"""Def
|
|
339
|
-
|
|
340
|
-
|
|
361
|
+
"""Def nodes reachable without crossing another def — top-level defs from the root, a
|
|
362
|
+
container's direct members from the container. Iterative, so deep nesting can't blow the
|
|
363
|
+
stack. Function-bound `const`/`let` declarations count as defs (is_def)."""
|
|
341
364
|
found = []
|
|
342
365
|
stack = [c for c in reversed(node.children) if c.is_named]
|
|
343
366
|
while stack:
|
|
344
367
|
c = stack.pop()
|
|
345
|
-
if c
|
|
368
|
+
if is_def(c):
|
|
346
369
|
found.append(c)
|
|
347
370
|
else:
|
|
348
371
|
stack.extend(g for g in reversed(c.children) if g.is_named)
|
|
@@ -218,10 +218,32 @@ def code_map_handler(args: dict) -> dict:
|
|
|
218
218
|
return {"ok": True, "path": None, "size_bytes": 0, "note": "map-error"}
|
|
219
219
|
|
|
220
220
|
|
|
221
|
+
# Surfaced by the MCP client to the model on connect (the standard `instructions` field): this is
|
|
222
|
+
# how codeintel becomes the *default* way an agent understands code after `codeintel install`,
|
|
223
|
+
# rather than just an available tool the agent may ignore in favor of grep/file-read.
|
|
224
|
+
_MCP_INSTRUCTIONS = (
|
|
225
|
+
"codeintel unifies three code-intelligence engines — graph (call/import structure), LSP "
|
|
226
|
+
"(precise symbols/references), and semantic (embedding search) — behind one never-raise "
|
|
227
|
+
"`code.query` tool.\n\n"
|
|
228
|
+
"Prefer `code.query` as your FIRST step for understanding an unfamiliar or large codebase, "
|
|
229
|
+
"instead of grepping or reading files one by one: use it for who-calls-X (callers), what-X-calls "
|
|
230
|
+
"(callees), impact of a change, where-a-symbol-is-defined, how a call chain flows, and "
|
|
231
|
+
"natural-language 'find the code that does Y' search. It is graph-augmented and ranked, so it "
|
|
232
|
+
"beats raw grep for locating and relating code.\n\n"
|
|
233
|
+
"Orient on a new repo with `code.map` (ranked architecture: top symbols, entry points, routes). "
|
|
234
|
+
"If results look empty, call `code.doctor` — it says exactly what to index or install. "
|
|
235
|
+
"`code.status` reports engine health.\n\n"
|
|
236
|
+
"Every result is a safe envelope: `ok` is always true; a null `result` with a `reason` means "
|
|
237
|
+
"'nothing found / not indexed yet', NOT an error — read the `reason`/`hint` and, if it says the "
|
|
238
|
+
"repo isn't indexed, that resolves on the first query or via `codeintel index`."
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
221
242
|
def run() -> None:
|
|
243
|
+
from codeintel import __version__
|
|
222
244
|
from codeintel.logconfig import configure_logging
|
|
223
245
|
configure_logging() # logs to stderr; stdout is the MCP protocol channel
|
|
224
|
-
mcp = MCPServer(name="codeintel")
|
|
246
|
+
mcp = MCPServer(name="codeintel", version=__version__, instructions=_MCP_INSTRUCTIONS)
|
|
225
247
|
|
|
226
248
|
async def _code_query(
|
|
227
249
|
op: str = "",
|
|
@@ -243,9 +265,26 @@ def run() -> None:
|
|
|
243
265
|
async def _code_map(project_root: str = "", budget: int = 32768, inject: bool = False) -> dict:
|
|
244
266
|
return code_map_handler({"project_root": project_root, "budget": budget, "inject": inject})
|
|
245
267
|
|
|
246
|
-
mcp.add_tool(_code_query, name="code.query", description=
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
268
|
+
mcp.add_tool(_code_query, name="code.query", description=(
|
|
269
|
+
"Understand code across graph + LSP + semantic engines — prefer this over grep/file-read "
|
|
270
|
+
"for locating and relating code. ops: `search` (natural-language or symbol semantic search), "
|
|
271
|
+
"`symbol` (definition/signature), `callers`, `callees`, `impact`, `chain` (\"A->B\" call "
|
|
272
|
+
"path), `pattern` (graph-augmented grep), `overview` (architecture), `context` (fan-out). "
|
|
273
|
+
"`target` is the symbol/query; optional `engine` (auto|graph|lsp|semantic), `project_root`. "
|
|
274
|
+
"Never raises: `ok` is always true; a null `result` + `reason` means not-found/not-indexed."
|
|
275
|
+
))
|
|
276
|
+
mcp.add_tool(_code_status, name="code.status", description=(
|
|
277
|
+
"Which engines (graph/LSP/semantic) are available and whether this repo is indexed. Check "
|
|
278
|
+
"this first if code.query keeps returning nothing."
|
|
279
|
+
))
|
|
280
|
+
mcp.add_tool(_code_doctor, name="code.doctor", description=(
|
|
281
|
+
"Diagnose engine health + this repo's index status, with a concrete fix for each gap (what "
|
|
282
|
+
"to install or index). Run when code.query results look empty or an engine seems missing."
|
|
283
|
+
))
|
|
284
|
+
mcp.add_tool(_code_map, name="code.map", description=(
|
|
285
|
+
"Generate/refresh CODE_INTEL.md — a ranked architecture overview (node/edge counts, top "
|
|
286
|
+
"symbols by caller count, entry points, routes). A great first call to orient on an "
|
|
287
|
+
"unfamiliar repo."
|
|
288
|
+
))
|
|
250
289
|
|
|
251
290
|
anyio.run(mcp.run_stdio_async)
|
|
@@ -64,6 +64,25 @@ def test_setup_tip_footer_only_when_unhealthy():
|
|
|
64
64
|
assert "codeintel setup" in unhealthy # actionable guidance only when something is missing
|
|
65
65
|
|
|
66
66
|
|
|
67
|
+
def test_treesitter_advisory_only_when_missing():
|
|
68
|
+
# the silent tree-sitter fallback (found by dogfooding) must be visible: an advisory when
|
|
69
|
+
# def-aligned chunking is OFF, nothing when it's on
|
|
70
|
+
base = {"project_root": "/repo", "deep": False,
|
|
71
|
+
"summary": {"ready": 3, "total": 3, "healthy": True},
|
|
72
|
+
"engines": {"semantic": {"engine": "semantic", "status": "ok", "installed": True,
|
|
73
|
+
"runnable": True, "repo_indexed": True, "detail": "ok",
|
|
74
|
+
"remediation": None}}}
|
|
75
|
+
off = doctor.render_doctor_text({**base, "treesitter": False})
|
|
76
|
+
on = doctor.render_doctor_text({**base, "treesitter": True})
|
|
77
|
+
assert "def-aligned chunking: OFF" in off and "tree-sitter-language-pack" in off
|
|
78
|
+
assert "def-aligned chunking" not in on # no noise when it's active
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_run_doctor_reports_treesitter_availability():
|
|
82
|
+
r = doctor.run_doctor("/tmp/x", deep=False)
|
|
83
|
+
assert isinstance(r.get("treesitter"), bool) # always reported (bool), never raises
|
|
84
|
+
|
|
85
|
+
|
|
67
86
|
# --------------------------------------------------------------------------- #
|
|
68
87
|
# never-raise + no-hang orchestration
|
|
69
88
|
# --------------------------------------------------------------------------- #
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""MCP server advertisement (0.8.4).
|
|
2
|
+
|
|
3
|
+
`codeintel install` only makes the tools *available*; for an agent to actually reach for them
|
|
4
|
+
instead of grep/file-read, the server must advertise itself — the standard MCP `instructions`
|
|
5
|
+
field plus tool descriptions that say when to use each. These assert that wiring.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import codeintel.server as srv
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_server_advertises_instructions_and_rich_tool_descriptions(monkeypatch):
|
|
13
|
+
captured: dict = {"kwargs": None, "tools": {}}
|
|
14
|
+
|
|
15
|
+
class _FakeMCP:
|
|
16
|
+
def __init__(self, **kwargs):
|
|
17
|
+
captured["kwargs"] = kwargs
|
|
18
|
+
|
|
19
|
+
def add_tool(self, fn, name=None, description=None):
|
|
20
|
+
captured["tools"][name] = description or ""
|
|
21
|
+
|
|
22
|
+
async def run_stdio_async(self): # pragma: no cover - never awaited (anyio.run stubbed)
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
monkeypatch.setattr(srv, "MCPServer", _FakeMCP)
|
|
26
|
+
monkeypatch.setattr(srv.anyio, "run", lambda *a, **k: None) # don't block on stdio
|
|
27
|
+
|
|
28
|
+
srv.run()
|
|
29
|
+
|
|
30
|
+
kw = captured["kwargs"]
|
|
31
|
+
assert kw["name"] == "codeintel"
|
|
32
|
+
assert kw.get("version") # server reports its version
|
|
33
|
+
instr = kw.get("instructions") or ""
|
|
34
|
+
assert "code.query" in instr
|
|
35
|
+
assert "grep" in instr.lower() # explicitly steers the agent away from grep/file-read
|
|
36
|
+
assert "reason" in instr # explains the never-raise safe-null envelope
|
|
37
|
+
|
|
38
|
+
tools = captured["tools"]
|
|
39
|
+
assert set(tools) == {"code.query", "code.status", "code.doctor", "code.map"}
|
|
40
|
+
# the primary tool sells when to use it, not the old throwaway one-liner
|
|
41
|
+
q = tools["code.query"]
|
|
42
|
+
assert "callers" in q and "grep" in q.lower() and len(q) > 100
|
|
@@ -97,6 +97,29 @@ def test_java_class_method():
|
|
|
97
97
|
assert 0 in starts and 1 in starts # class header + method m
|
|
98
98
|
|
|
99
99
|
|
|
100
|
+
def test_arrow_function_consts_are_def_aligned():
|
|
101
|
+
# React components / hooks / callbacks are `const X = () => {}`, not `function` declarations —
|
|
102
|
+
# they must def-align too (the common modern-TS/React case); a plain data const must NOT.
|
|
103
|
+
src = (
|
|
104
|
+
"import x from 'y';\n" # 0
|
|
105
|
+
"\n" # 1
|
|
106
|
+
"export const Header = () => {\n" # 2 arrow component
|
|
107
|
+
" return null;\n" # 3
|
|
108
|
+
"};\n" # 4
|
|
109
|
+
"\n" # 5
|
|
110
|
+
"const useThing = (id) => {\n" # 6 arrow hook
|
|
111
|
+
" return id;\n" # 7
|
|
112
|
+
"};\n" # 8
|
|
113
|
+
"\n" # 9
|
|
114
|
+
"const PLAIN = 42;\n" # 10 plain data const — NOT a def
|
|
115
|
+
)
|
|
116
|
+
spans, n = _spans("c.tsx", src)
|
|
117
|
+
_assert_gapless_cover(spans, n)
|
|
118
|
+
starts = {s for s, _ in spans}
|
|
119
|
+
assert 2 in starts and 6 in starts # both arrow consts are their own chunks
|
|
120
|
+
assert 10 not in starts # a plain `const x = 42` is not a def chunk
|
|
121
|
+
|
|
122
|
+
|
|
100
123
|
def test_cpp_class_and_free_function():
|
|
101
124
|
src = ("class C {\npublic:\n int m() { return 1; }\n};\nint free_fn() { return 2; }\n")
|
|
102
125
|
spans, n = _spans("e.cpp", src)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.8.3"
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|