Skip to content

feat(extractor): add Solidity language extractor - #3716

Closed
Abdul535 wants to merge 1 commit into
Graphify-Labs:v8from
Abdul535:codex/solidity-extractor
Closed

Abdul535 wants to merge 1 commit into
Graphify-Labs:v8from
Abdul535:codex/solidity-extractor

Conversation

@Abdul535

Copy link
Copy Markdown
Contributor

What does this PR do?

  • add a Solidity extractor for contracts, interfaces, libraries, members, events, errors, modifiers, and overloads
  • wire .sol discovery, dispatch, language-family isolation, imports, inheritance, and type-reference resolution
  • add the optional Solidity parser extra with fixtures and malformed-input coverage

Type of change

  • Bug fix
  • New feature
  • Documentation
  • Tests or CI
  • Refactor
  • Security fix

How was this tested?

  • 5 passed in the focused Solidity suite
  • Ruff passed
  • Pyright passed with 0 errors
  • graphify update . completed

Graphify-specific checklist

  • I added or updated tests for behavior changes.
  • I updated documentation or confirmed that no documentation is needed.
  • I updated generated skill artifacts when changing their source fragments.
  • I considered compatibility across supported Python versions.
  • I confirmed that no API keys, generated graph data, or local-only files are included.

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.


Graphify review — findings

Adds Solidity as a first-class language: registers .sol in the analyze family map, CODE_EXTENSIONS, the extractor dispatch, the LANGUAGE_EXTRACTORS registry, and the solidity extra hint shown when the grammar is missing. The new extract_solidity walks a tree-sitter parse to emit file/contract/interface/library/function nodes, import edges, and inheritance/using references, degrading to an empty result with an error string when tree-sitter-solidity isn't installed. resolve_solidity_type_references, wired in as a language resolver for .sol, rebinds solidity_type: context edges to matching type declarations in the same file or its imports, only when exactly one candidate matches.

Worth a look

  • Solidity type IDs collide for same-stem files in different directories — graphify/extractors/solidity.py:182 · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Optional tree-sitter fallback is bypassed by module-level import — graphify/extractors/solidity.py:6 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Solidity overload calls with arguments are not resolved because arity is read only from direct children — graphify/extractors/solidity.py · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 2978 functions depend on the 427 functions this change touches.

Health — this change adds coupling hotspots:

  • new: extract() — 661 callers, 45 callees
  • new: _rebuild_code() — 142 callers, 54 callees
  • new: detect() — 112 callers, 15 callees
  • new: to_obsidian() — 38 callers, 14 callees
  • new: _extract_generic() — 18 callers, 29 callees
  • new: save_manifest() — 40 callers, 11 callees
  • new: to_json() — 58 callers, 7 callees
  • new: extract_js() — 87 callers, 4 callees
  • …and 77 more — each is listed as a finding

Verification — 2978 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 2675 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

291 of 291 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/test_affected_cli.py — full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_agents_platform.py — full-run-safety
  • tests/test_analyze.py — impact, full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — impact, full-run-safety
  • tests/test_astro_import_ids.py — impact, full-run-safety
  • tests/test_atomic_canvas_export.py — impact, full-run-safety
  • tests/test_atomic_version_stamp.py — full-run-safety
  • tests/test_atomic_writes.py — impact, full-run-safety
  • tests/test_backend_env_isolation.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_build.py — impact, full-run-safety
  • tests/test_build_merge_dedup_scope.py — full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — full-run-safety
  • tests/test_build_merge_shrink_guard.py — full-run-safety
  • tests/test_builtin_global_type_refs.py — impact, full-run-safety
  • tests/test_cache.py — full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — impact, full-run-safety
  • tests/test_case_sensitive_resolution.py — impact, full-run-safety
  • tests/test_charmap_encoding.py — impact, full-run-safety
  • tests/test_chunking.py — impact, full-run-safety
  • tests/test_cjs_module_extension.py — impact, full-run-safety
  • tests/test_claude_cli_backend.py — impact, full-run-safety
  • tests/test_claude_md.py — full-run-safety
  • tests/test_cli_broken_pipe.py — full-run-safety
  • tests/test_cli_export.py — impact, full-run-safety
  • tests/test_cli_help.py — full-run-safety
  • tests/test_cluster.py — full-run-safety
  • tests/test_codebuddy.py — full-run-safety
  • tests/test_community_hub_labels.py — full-run-safety
  • tests/test_community_labels_skill.py — impact, full-run-safety
  • tests/test_confidence.py — impact, full-run-safety
  • tests/test_corrupt_graph_json.py — full-run-safety
  • tests/test_cpp_nested_and_cli.py — impact, full-run-safety
  • tests/test_cpp_objc_cross_file_calls.py — impact, full-run-safety
  • tests/test_cpp_preprocess.py — full-run-safety
  • tests/test_cross_extension_reexport_self_cycle.py — impact, full-run-safety
  • tests/test_cross_language_call_resolution.py — impact, full-run-safety
  • tests/test_cross_repo_external_call_guards.py — impact, full-run-safety
  • tests/test_cross_repo_member_calls.py — impact, full-run-safety
  • tests/test_cross_repo_shared_types.py — full-run-safety
  • tests/test_csharp_call_site_generic_args.py — impact, full-run-safety
  • … and 241 more

non-code file(s) changed (pyproject.toml, uv.lock) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (graphify/extractors/__init__.py, graphify/extractors/solidity.py, pyproject.toml, tests/fixtures/new_languages/sample.sol) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

· 1 grounded finding(s) anchored inline below; 84 more finding(s) on lines outside this diff (see the check run).

edge["target"] = candidates[0]


def extract_solidity(path: Path) -> dict:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression — extract_solidity()

fans out to 8 callees (efferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

safishamsi added a commit that referenced this pull request Sep 22, 2026
…3719, #3714 follow-ups)

- #3716 (Solidity): non-callable members (struct/enum/event/error/state-var) had
  no signature and fell back to the LINE NUMBER for their node id, churning ids on
  incremental rebuilds. Use the member name (unique per kind in a contract scope)
  as the discriminator instead.
- #3719 (method-ghost dedup): gate the candidate index on a method-shaped label
  (leading '.' AND '()' suffix) so a dotfile label like '.env' is never treated as
  a method; normalize the index/lookup key via make_id for parity with the alias
  path. Adds a negative test proving two same-named methods in one file are left
  unmerged (the len==1 ambiguity guard).
- #3714 (Erlang): the remote-call resolver reads module/name/arity off node
  metadata, which the incremental context builders stripped for non-Ruby langs,
  so foo:bar() silently failed to resolve on 'graphify update'. Forward the Erlang
  resolution metadata keys through the watch.py/cli.py allow-lists (same fix shape
  as the elixir _elixir_module marker).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@safishamsi

Copy link
Copy Markdown
Collaborator

Shipped in v0.9.66 (on PyPI). Cherry-picked with authorship preserved so it shows under your GitHub contributions. Thanks @Abdul535! (New Solidity extractor; on merge I made non-callable member ids name-based rather than line-number-based to keep them stable across incremental rebuilds.)

@safishamsi safishamsi closed this Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants