#
tokens: 46427/50000 6/367 files (page 10/18)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 10 of 18. Use http://codebase.md/shashankss1205/codegraphcontext?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .github
│   └── workflows
│       ├── e2e-tests.yml
│       ├── post_discord_invite.yml
│       ├── test.yml
│       └── update-contributors.yml
├── .gitignore
├── CONTRIBUTING.md
├── contributors.md
├── docs
│   ├── docs
│   │   ├── architecture.md
│   │   ├── cli.md
│   │   ├── contributing_languages.md
│   │   ├── contributing.md
│   │   ├── cookbook.md
│   │   ├── core.md
│   │   ├── future_work.md
│   │   ├── images
│   │   │   ├── 1.png
│   │   │   ├── 11.png
│   │   │   ├── 12.png
│   │   │   ├── 13.png
│   │   │   ├── 14.png
│   │   │   ├── 16.png
│   │   │   ├── 19.png
│   │   │   ├── 2.png
│   │   │   ├── 20.png
│   │   │   ├── 21.png
│   │   │   ├── 22.png
│   │   │   ├── 23.png
│   │   │   ├── 24.png
│   │   │   ├── 26.png
│   │   │   ├── 28.png
│   │   │   ├── 29.png
│   │   │   ├── 3.png
│   │   │   ├── 30.png
│   │   │   ├── 31.png
│   │   │   ├── 32.png
│   │   │   ├── 33.png
│   │   │   ├── 34.png
│   │   │   ├── 35.png
│   │   │   ├── 36.png
│   │   │   ├── 38.png
│   │   │   ├── 39.png
│   │   │   ├── 4.png
│   │   │   ├── 40.png
│   │   │   ├── 41.png
│   │   │   ├── 42.png
│   │   │   ├── 43.png
│   │   │   ├── 44.png
│   │   │   ├── 5.png
│   │   │   ├── 6.png
│   │   │   ├── 7.png
│   │   │   ├── 8.png
│   │   │   ├── 9.png
│   │   │   ├── Indexing.gif
│   │   │   ├── tool_images
│   │   │   │   ├── 1.png
│   │   │   │   ├── 2.png
│   │   │   │   └── 3.png
│   │   │   └── Usecase.gif
│   │   ├── index.md
│   │   ├── installation.md
│   │   ├── license.md
│   │   ├── server.md
│   │   ├── tools.md
│   │   ├── troubleshooting.md
│   │   └── use_cases.md
│   ├── mkdocs.yml
│   └── site
│       ├── 404.html
│       ├── architecture
│       │   └── index.html
│       ├── assets
│       │   ├── images
│       │   │   └── favicon.png
│       │   ├── javascripts
│       │   │   ├── bundle.f55a23d4.min.js
│       │   │   ├── bundle.f55a23d4.min.js.map
│       │   │   ├── lunr
│       │   │   │   ├── min
│       │   │   │   │   ├── lunr.ar.min.js
│       │   │   │   │   ├── lunr.da.min.js
│       │   │   │   │   ├── lunr.de.min.js
│       │   │   │   │   ├── lunr.du.min.js
│       │   │   │   │   ├── lunr.el.min.js
│       │   │   │   │   ├── lunr.es.min.js
│       │   │   │   │   ├── lunr.fi.min.js
│       │   │   │   │   ├── lunr.fr.min.js
│       │   │   │   │   ├── lunr.he.min.js
│       │   │   │   │   ├── lunr.hi.min.js
│       │   │   │   │   ├── lunr.hu.min.js
│       │   │   │   │   ├── lunr.hy.min.js
│       │   │   │   │   ├── lunr.it.min.js
│       │   │   │   │   ├── lunr.ja.min.js
│       │   │   │   │   ├── lunr.jp.min.js
│       │   │   │   │   ├── lunr.kn.min.js
│       │   │   │   │   ├── lunr.ko.min.js
│       │   │   │   │   ├── lunr.multi.min.js
│       │   │   │   │   ├── lunr.nl.min.js
│       │   │   │   │   ├── lunr.no.min.js
│       │   │   │   │   ├── lunr.pt.min.js
│       │   │   │   │   ├── lunr.ro.min.js
│       │   │   │   │   ├── lunr.ru.min.js
│       │   │   │   │   ├── lunr.sa.min.js
│       │   │   │   │   ├── lunr.stemmer.support.min.js
│       │   │   │   │   ├── lunr.sv.min.js
│       │   │   │   │   ├── lunr.ta.min.js
│       │   │   │   │   ├── lunr.te.min.js
│       │   │   │   │   ├── lunr.th.min.js
│       │   │   │   │   ├── lunr.tr.min.js
│       │   │   │   │   ├── lunr.vi.min.js
│       │   │   │   │   └── lunr.zh.min.js
│       │   │   │   ├── tinyseg.js
│       │   │   │   └── wordcut.js
│       │   │   └── workers
│       │   │       ├── search.973d3a69.min.js
│       │   │       └── search.973d3a69.min.js.map
│       │   └── stylesheets
│       │       ├── main.2a3383ac.min.css
│       │       ├── main.2a3383ac.min.css.map
│       │       ├── palette.06af60db.min.css
│       │       └── palette.06af60db.min.css.map
│       ├── cli
│       │   └── index.html
│       ├── contributing
│       │   └── index.html
│       ├── contributing_languages
│       │   └── index.html
│       ├── cookbook
│       │   └── index.html
│       ├── core
│       │   └── index.html
│       ├── future_work
│       │   └── index.html
│       ├── images
│       │   ├── 1.png
│       │   ├── 11.png
│       │   ├── 12.png
│       │   ├── 13.png
│       │   ├── 14.png
│       │   ├── 16.png
│       │   ├── 19.png
│       │   ├── 2.png
│       │   ├── 20.png
│       │   ├── 21.png
│       │   ├── 22.png
│       │   ├── 23.png
│       │   ├── 24.png
│       │   ├── 26.png
│       │   ├── 28.png
│       │   ├── 29.png
│       │   ├── 3.png
│       │   ├── 30.png
│       │   ├── 31.png
│       │   ├── 32.png
│       │   ├── 33.png
│       │   ├── 34.png
│       │   ├── 35.png
│       │   ├── 36.png
│       │   ├── 38.png
│       │   ├── 39.png
│       │   ├── 4.png
│       │   ├── 40.png
│       │   ├── 41.png
│       │   ├── 42.png
│       │   ├── 43.png
│       │   ├── 44.png
│       │   ├── 5.png
│       │   ├── 6.png
│       │   ├── 7.png
│       │   ├── 8.png
│       │   ├── 9.png
│       │   ├── Indexing.gif
│       │   ├── tool_images
│       │   │   ├── 1.png
│       │   │   ├── 2.png
│       │   │   └── 3.png
│       │   └── Usecase.gif
│       ├── index.html
│       ├── installation
│       │   └── index.html
│       ├── license
│       │   └── index.html
│       ├── search
│       │   └── search_index.json
│       ├── server
│       │   └── index.html
│       ├── sitemap.xml
│       ├── sitemap.xml.gz
│       ├── tools
│       │   └── index.html
│       ├── troubleshooting
│       │   └── index.html
│       └── use_cases
│           └── index.html
├── images
│   ├── 1.png
│   ├── 11.png
│   ├── 12.png
│   ├── 13.png
│   ├── 14.png
│   ├── 16.png
│   ├── 19.png
│   ├── 2.png
│   ├── 20.png
│   ├── 21.png
│   ├── 22.png
│   ├── 23.png
│   ├── 24.png
│   ├── 26.png
│   ├── 28.png
│   ├── 29.png
│   ├── 3.png
│   ├── 30.png
│   ├── 31.png
│   ├── 32.png
│   ├── 33.png
│   ├── 34.png
│   ├── 35.png
│   ├── 36.png
│   ├── 38.png
│   ├── 39.png
│   ├── 4.png
│   ├── 40.png
│   ├── 41.png
│   ├── 42.png
│   ├── 43.png
│   ├── 44.png
│   ├── 5.png
│   ├── 6.png
│   ├── 7.png
│   ├── 8.png
│   ├── 9.png
│   ├── Indexing.gif
│   ├── tool_images
│   │   ├── 1.png
│   │   ├── 2.png
│   │   └── 3.png
│   └── Usecase.gif
├── LICENSE
├── MANIFEST.in
├── organizer
│   ├── CONTRIBUTING_LANGUAGES.md
│   ├── cookbook.md
│   ├── docs.md
│   ├── language_specific_nodes.md
│   ├── Tools_Exploration.md
│   └── troubleshoot.md
├── package-lock.json
├── pyproject.toml
├── README.md
├── scripts
│   ├── generate_lang_contributors.py
│   └── post_install_fix.sh
├── SECURITY.md
├── src
│   └── codegraphcontext
│       ├── __init__.py
│       ├── __main__.py
│       ├── cli
│       │   ├── __init__.py
│       │   ├── cli_helpers.py
│       │   ├── main.py
│       │   ├── setup_macos.py
│       │   └── setup_wizard.py
│       ├── core
│       │   ├── __init__.py
│       │   ├── database.py
│       │   ├── jobs.py
│       │   └── watcher.py
│       ├── prompts.py
│       ├── server.py
│       ├── tools
│       │   ├── __init__.py
│       │   ├── advanced_language_query_tool.py
│       │   ├── code_finder.py
│       │   ├── graph_builder.py
│       │   ├── languages
│       │   │   ├── c.py
│       │   │   ├── cpp.py
│       │   │   ├── go.py
│       │   │   ├── java.py
│       │   │   ├── javascript.py
│       │   │   ├── python.py
│       │   │   ├── ruby.py
│       │   │   ├── rust.py
│       │   │   └── typescript.py
│       │   ├── package_resolver.py
│       │   ├── query_tool_languages
│       │   │   ├── c_toolkit.py
│       │   │   ├── cpp_toolkit.py
│       │   │   ├── go_toolkit.py
│       │   │   ├── java_toolkit.py
│       │   │   ├── javascript_toolkit.py
│       │   │   ├── python_toolkit.py
│       │   │   ├── ruby_toolkit.py
│       │   │   ├── rust_toolkit.py
│       │   │   └── typescript_toolkit.py
│       │   └── system.py
│       └── utils
│           └── debug_log.py
├── tests
│   ├── __init__.py
│   ├── conftest.py
│   ├── sample_project
│   │   ├── advanced_calls.py
│   │   ├── advanced_classes.py
│   │   ├── advanced_classes2.py
│   │   ├── advanced_functions.py
│   │   ├── advanced_imports.py
│   │   ├── async_features.py
│   │   ├── callbacks_decorators.py
│   │   ├── circular1.py
│   │   ├── circular2.py
│   │   ├── class_instantiation.py
│   │   ├── cli_and_dunder.py
│   │   ├── complex_classes.py
│   │   ├── comprehensions_generators.py
│   │   ├── context_managers.py
│   │   ├── control_flow.py
│   │   ├── datatypes.py
│   │   ├── dynamic_dispatch.py
│   │   ├── dynamic_imports.py
│   │   ├── edge_cases
│   │   │   ├── comments_only.py
│   │   │   ├── docstring_only.py
│   │   │   ├── empty.py
│   │   │   ├── hardcoded_secrets.py
│   │   │   ├── long_functions.py
│   │   │   └── syntax_error.py
│   │   ├── function_chains.py
│   │   ├── generators.py
│   │   ├── import_reexports.py
│   │   ├── mapping_calls.py
│   │   ├── module_a.py
│   │   ├── module_b.py
│   │   ├── module_c
│   │   │   ├── __init__.py
│   │   │   ├── submodule1.py
│   │   │   └── submodule2.py
│   │   ├── namespace_pkg
│   │   │   └── ns_module.py
│   │   ├── pattern_matching.py
│   │   └── typing_examples.py
│   ├── sample_project_c
│   │   ├── cgc_sample
│   │   ├── include
│   │   │   ├── config.h
│   │   │   ├── math
│   │   │   │   └── vec.h
│   │   │   ├── module.h
│   │   │   ├── platform.h
│   │   │   └── util.h
│   │   ├── Makefile
│   │   ├── README.md
│   │   └── src
│   │       ├── main.c
│   │       ├── math
│   │       │   └── vec.c
│   │       ├── module.c
│   │       └── util.c
│   ├── sample_project_cpp
│   │   ├── class_features.cpp
│   │   ├── classes.cpp
│   │   ├── control_flow.cpp
│   │   ├── edge_cases.cpp
│   │   ├── enum_struct_union.cpp
│   │   ├── exceptions.cpp
│   │   ├── file_io.cpp
│   │   ├── function_chain.cpp
│   │   ├── function_chain.h
│   │   ├── function_types.cpp
│   │   ├── main.cpp
│   │   ├── main.exe
│   │   ├── namespaces.cpp
│   │   ├── raii_example.cpp
│   │   ├── README.md
│   │   ├── sample_project.exe
│   │   ├── stl_usage.cpp
│   │   ├── templates.cpp
│   │   └── types_variable_assignments.cpp
│   ├── sample_project_go
│   │   ├── advanced_types.go
│   │   ├── basic_functions.go
│   │   ├── embedded_composition.go
│   │   ├── error_handling.go
│   │   ├── generics.go
│   │   ├── go.mod
│   │   ├── goroutines_channels.go
│   │   ├── interfaces.go
│   │   ├── packages_imports.go
│   │   ├── README.md
│   │   ├── structs_methods.go
│   │   └── util
│   │       └── helpers.go
│   ├── sample_project_java
│   │   ├── out
│   │   │   └── com
│   │   │       └── example
│   │   │           └── app
│   │   │               ├── annotations
│   │   │               │   └── Logged.class
│   │   │               ├── Main.class
│   │   │               ├── misc
│   │   │               │   ├── Outer.class
│   │   │               │   └── Outer$Inner.class
│   │   │               ├── model
│   │   │               │   ├── Role.class
│   │   │               │   └── User.class
│   │   │               ├── service
│   │   │               │   ├── AbstractGreeter.class
│   │   │               │   ├── GreetingService.class
│   │   │               │   └── impl
│   │   │               │       └── GreetingServiceImpl.class
│   │   │               └── util
│   │   │                   ├── CollectionUtils.class
│   │   │                   └── IOHelper.class
│   │   ├── README.md
│   │   ├── sources.txt
│   │   └── src
│   │       └── com
│   │           └── example
│   │               └── app
│   │                   ├── annotations
│   │                   │   └── Logged.java
│   │                   ├── Main.java
│   │                   ├── misc
│   │                   │   └── Outer.java
│   │                   ├── model
│   │                   │   ├── Role.java
│   │                   │   └── User.java
│   │                   ├── service
│   │                   │   ├── AbstractGreeter.java
│   │                   │   ├── GreetingService.java
│   │                   │   └── impl
│   │                   │       └── GreetingServiceImpl.java
│   │                   └── util
│   │                       ├── CollectionUtils.java
│   │                       └── IOHelper.java
│   ├── sample_project_javascript
│   │   ├── arrays.js
│   │   ├── asyncAwait.js
│   │   ├── classes.js
│   │   ├── dom.js
│   │   ├── errorHandling.js
│   │   ├── events.js
│   │   ├── exporter.js
│   │   ├── fetchAPI.js
│   │   ├── fixtures
│   │   │   └── js
│   │   │       └── accessors.js
│   │   ├── functions.js
│   │   ├── importer.js
│   │   ├── objects.js
│   │   ├── promises.js
│   │   ├── README.md
│   │   └── variables.js
│   ├── sample_project_misc
│   │   ├── index.html
│   │   ├── README.md
│   │   ├── styles.css
│   │   ├── tables.css
│   │   └── tables.html
│   ├── sample_project_php
│   │   ├── classes_objects.php
│   │   ├── database.php
│   │   ├── edgecases.php
│   │   ├── error_handling.php
│   │   ├── file_handling.php
│   │   ├── functions.php
│   │   ├── generators_iterators.php
│   │   ├── globals_superglobals.php
│   │   ├── Inheritance.php
│   │   ├── interface_traits.php
│   │   └── README.md
│   ├── sample_project_ruby
│   │   ├── class_example.rb
│   │   ├── enumerables.rb
│   │   ├── error_handling.rb
│   │   ├── file_io.rb
│   │   ├── inheritance_example.rb
│   │   ├── main.rb
│   │   ├── metaprogramming.rb
│   │   ├── mixins_example.rb
│   │   ├── module_example.rb
│   │   └── tests
│   │       ├── test_mixins.py
│   │       └── test_sample.rb
│   ├── sample_project_rust
│   │   ├── Cargo.toml
│   │   ├── README.md
│   │   └── src
│   │       ├── basic_functions.rs
│   │       ├── concurrency.rs
│   │       ├── error_handling.rs
│   │       ├── generics.rs
│   │       ├── iterators_closures.rs
│   │       ├── lib.rs
│   │       ├── lifetimes_references.rs
│   │       ├── modules.rs
│   │       ├── smart_pointers.rs
│   │       ├── structs_enums.rs
│   │       └── traits.rs
│   ├── sample_project_typescript
│   │   ├── package.json
│   │   ├── README.md
│   │   ├── src
│   │   │   ├── advanced-types.ts
│   │   │   ├── async-promises.ts
│   │   │   ├── classes-inheritance.ts
│   │   │   ├── decorators-metadata.ts
│   │   │   ├── error-validation.ts
│   │   │   ├── functions-generics.ts
│   │   │   ├── index.ts
│   │   │   ├── modules-namespaces.ts
│   │   │   ├── types-interfaces.ts
│   │   │   └── utilities-helpers.ts
│   │   └── tsconfig.json
│   ├── test_cpp_parser.py
│   ├── test_database_validation.py
│   ├── test_end_to_end.py
│   ├── test_graph_indexing_js.py
│   ├── test_graph_indexing.py
│   ├── test_tree_sitter
│   │   ├── __init__.py
│   │   ├── class_instantiation.py
│   │   ├── complex_classes.py
│   │   └── test_file.py
│   └── test_typescript_parser.py
└── website
    ├── .example.env
    ├── .gitignore
    ├── api
    │   └── pypi.ts
    ├── bun.lockb
    ├── components.json
    ├── eslint.config.js
    ├── index.html
    ├── package-lock.json
    ├── package.json
    ├── postcss.config.js
    ├── public
    │   ├── favicon.ico
    │   ├── placeholder.svg
    │   └── robots.txt
    ├── README.md
    ├── src
    │   ├── App.css
    │   ├── App.tsx
    │   ├── assets
    │   │   ├── function-calls.png
    │   │   ├── graph-total.png
    │   │   ├── hero-graph.jpg
    │   │   └── hierarchy.png
    │   ├── components
    │   │   ├── ComparisonTable.tsx
    │   │   ├── CookbookSection.tsx
    │   │   ├── DemoSection.tsx
    │   │   ├── ExamplesSection.tsx
    │   │   ├── FeaturesSection.tsx
    │   │   ├── Footer.tsx
    │   │   ├── HeroSection.tsx
    │   │   ├── InstallationSection.tsx
    │   │   ├── MoveToTop.tsx
    │   │   ├── ShowDownloads.tsx
    │   │   ├── ShowStarGraph.tsx
    │   │   ├── TestimonialSection.tsx
    │   │   ├── ThemeProvider.tsx
    │   │   ├── ThemeToggle.tsx
    │   │   └── ui
    │   │       ├── accordion.tsx
    │   │       ├── alert-dialog.tsx
    │   │       ├── alert.tsx
    │   │       ├── aspect-ratio.tsx
    │   │       ├── avatar.tsx
    │   │       ├── badge.tsx
    │   │       ├── breadcrumb.tsx
    │   │       ├── button.tsx
    │   │       ├── calendar.tsx
    │   │       ├── card.tsx
    │   │       ├── carousel.tsx
    │   │       ├── chart.tsx
    │   │       ├── checkbox.tsx
    │   │       ├── collapsible.tsx
    │   │       ├── command.tsx
    │   │       ├── context-menu.tsx
    │   │       ├── dialog.tsx
    │   │       ├── drawer.tsx
    │   │       ├── dropdown-menu.tsx
    │   │       ├── form.tsx
    │   │       ├── hover-card.tsx
    │   │       ├── input-otp.tsx
    │   │       ├── input.tsx
    │   │       ├── label.tsx
    │   │       ├── menubar.tsx
    │   │       ├── navigation-menu.tsx
    │   │       ├── orbiting-circles.tsx
    │   │       ├── pagination.tsx
    │   │       ├── popover.tsx
    │   │       ├── progress.tsx
    │   │       ├── radio-group.tsx
    │   │       ├── resizable.tsx
    │   │       ├── scroll-area.tsx
    │   │       ├── select.tsx
    │   │       ├── separator.tsx
    │   │       ├── sheet.tsx
    │   │       ├── sidebar.tsx
    │   │       ├── skeleton.tsx
    │   │       ├── slider.tsx
    │   │       ├── sonner.tsx
    │   │       ├── switch.tsx
    │   │       ├── table.tsx
    │   │       ├── tabs.tsx
    │   │       ├── textarea.tsx
    │   │       ├── toast.tsx
    │   │       ├── toaster.tsx
    │   │       ├── toggle-group.tsx
    │   │       ├── toggle.tsx
    │   │       ├── tooltip.tsx
    │   │       └── use-toast.ts
    │   ├── hooks
    │   │   ├── use-mobile.tsx
    │   │   └── use-toast.ts
    │   ├── index.css
    │   ├── lib
    │   │   └── utils.ts
    │   ├── main.tsx
    │   ├── pages
    │   │   ├── Index.tsx
    │   │   └── NotFound.tsx
    │   └── vite-env.d.ts
    ├── tailwind.config.ts
    ├── tsconfig.app.json
    ├── tsconfig.json
    ├── tsconfig.node.json
    ├── vercel.json
    └── vite.config.ts
```

# Files

--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/python.py:
--------------------------------------------------------------------------------

```python
  1 | import os
  2 | import tempfile
  3 | import nbformat
  4 | from nbconvert import PythonExporter
  5 | from pathlib import Path
  6 | from typing import Any, Dict, Optional, Tuple
  7 | import ast
  8 | from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger, debug_logger
  9 | 
 10 | 
 11 | PY_QUERIES = {
 12 |     "imports": """
 13 |         (import_statement name: (_) @import)
 14 |         (import_from_statement) @from_import_stmt
 15 |     """,
 16 |     "classes": """
 17 |         (class_definition
 18 |             name: (identifier) @name
 19 |             superclasses: (argument_list)? @superclasses
 20 |             body: (block) @body)
 21 |     """,
 22 |     "functions": """
 23 |         (function_definition
 24 |             name: (identifier) @name
 25 |             parameters: (parameters) @parameters
 26 |             body: (block) @body
 27 |             return_type: (_)? @return_type)
 28 |     """,
 29 |     "calls": """
 30 |         (call
 31 |             function: (identifier) @name)
 32 |         (call
 33 |             function: (attribute attribute: (identifier) @name) @full_call)
 34 |     """,
 35 |     "variables": """
 36 |         (assignment
 37 |             left: (identifier) @name)
 38 |     """,
 39 |     "lambda_assignments": """
 40 |         (assignment
 41 |             left: (identifier) @name
 42 |             right: (lambda) @lambda_node)
 43 |     """,
 44 |     "docstrings": """
 45 |         (expression_statement (string) @docstring)
 46 |     """,
 47 | }
 48 | 
 49 | class PythonTreeSitterParser:
 50 |     """A Python-specific parser using tree-sitter, encapsulating language-specific logic."""
 51 | 
 52 |     def __init__(self, generic_parser_wrapper):
 53 |         self.generic_parser_wrapper = generic_parser_wrapper
 54 |         self.language_name = generic_parser_wrapper.language_name
 55 |         self.language = generic_parser_wrapper.language
 56 |         self.parser = generic_parser_wrapper.parser
 57 | 
 58 |         self.queries = {
 59 |             name: self.language.query(query_str)
 60 |             for name, query_str in PY_QUERIES.items()
 61 |         }
 62 | 
 63 |     def _get_node_text(self, node) -> str:
 64 |         return node.text.decode('utf-8')
 65 | 
 66 |     def _get_parent_context(self, node, types=('function_definition', 'class_definition')):
 67 |         curr = node.parent
 68 |         while curr:
 69 |             if curr.type in types:
 70 |                 name_node = curr.child_by_field_name('name')
 71 |                 return self._get_node_text(name_node) if name_node else None, curr.type, curr.start_point[0] + 1
 72 |             curr = curr.parent
 73 |         return None, None, None
 74 | 
 75 |     def _calculate_complexity(self, node):
 76 |         complexity_nodes = {
 77 |             "if_statement", "for_statement", "while_statement", "except_clause",
 78 |             "with_statement", "boolean_operator", "list_comprehension", 
 79 |             "generator_expression", "case_clause"
 80 |         }
 81 |         count = 1
 82 |         
 83 |         def traverse(n):
 84 |             nonlocal count
 85 |             if n.type in complexity_nodes:
 86 |                 count += 1
 87 |             for child in n.children:
 88 |                 traverse(child)
 89 |         
 90 |         traverse(node)
 91 |         return count
 92 | 
 93 |     def _get_docstring(self, body_node):
 94 |         if body_node and body_node.child_count > 0:
 95 |             first_child = body_node.children[0]
 96 |             if first_child.type == 'expression_statement' and first_child.children[0].type == 'string':
 97 |                 try:
 98 |                     return ast.literal_eval(self._get_node_text(first_child.children[0]))
 99 |                 except (ValueError, SyntaxError):
100 |                     return self._get_node_text(first_child.children[0])
101 |         return None
102 | 
103 |     def parse(self, file_path: Path, is_dependency: bool = False, is_notebook: bool = False) -> Dict:
104 |         """Parses a file and returns its structure in a standardized dictionary format."""
105 |         original_file_path = file_path
106 |         temp_py_file = None
107 |         source_code = None
108 | 
109 |         try:
110 |             if is_notebook:
111 |                 info_logger(f"Converting notebook {file_path} to temporary Python file.")
112 |                 with open(file_path, 'r', encoding='utf-8') as f:
113 |                     notebook_node = nbformat.read(f, as_version=4)
114 |                 
115 |                 exporter = PythonExporter()
116 |                 python_code, _ = exporter.from_notebook_node(notebook_node)
117 | 
118 |                 with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.py', encoding='utf-8') as tf:
119 |                     tf.write(python_code)
120 |                     temp_py_file = Path(tf.name)
121 |                 
122 |                 # The file to be parsed is now the temporary file
123 |                 file_path = temp_py_file
124 | 
125 |             with open(file_path, "r", encoding="utf-8") as f:
126 |                 source_code = f.read()
127 |             
128 |             tree = self.parser.parse(bytes(source_code, "utf8"))
129 |             root_node = tree.root_node
130 | 
131 |             functions = self._find_functions(root_node)
132 |             functions.extend(self._find_lambda_assignments(root_node))
133 |             classes = self._find_classes(root_node)
134 |             imports = self._find_imports(root_node)
135 |             function_calls = self._find_calls(root_node)
136 |             variables = self._find_variables(root_node)
137 | 
138 |             return {
139 |                 "file_path": str(original_file_path), # Always return the original path
140 |                 "functions": functions,
141 |                 "classes": classes,
142 |                 "variables": variables,
143 |                 "imports": imports,
144 |                 "function_calls": function_calls,
145 |                 "is_dependency": is_dependency,
146 |                 "lang": self.language_name,
147 |             }
148 |         except Exception as e:
149 |             error_logger(f"Failed to parse {original_file_path}: {e}")
150 |             return {"file_path": str(original_file_path), "error": str(e)}
151 |         finally:
152 |             if temp_py_file and temp_py_file.exists():
153 |                 os.remove(temp_py_file)
154 |                 info_logger(f"Removed temporary file: {temp_py_file}")
155 | 
156 |     def _find_lambda_assignments(self, root_node):
157 |         functions = []
158 |         query = self.queries.get('lambda_assignments')
159 |         if not query: return []
160 | 
161 |         for match in query.captures(root_node):
162 |             capture_name = match[1]
163 |             node = match[0]
164 | 
165 |             if capture_name == 'name':
166 |                 assignment_node = node.parent
167 |                 lambda_node = assignment_node.child_by_field_name('right')
168 |                 name = self._get_node_text(node)
169 |                 params_node = lambda_node.child_by_field_name('parameters')
170 |                 
171 |                 context, context_type, _ = self._get_parent_context(assignment_node)
172 |                 class_context, _, _ = self._get_parent_context(assignment_node, types=('class_definition',))
173 | 
174 |                 func_data = {
175 |                     "name": name,
176 |                     "line_number": node.start_point[0] + 1,
177 |                     "end_line": assignment_node.end_point[0] + 1,
178 |                     "args": [p for p in [self._get_node_text(p) for p in params_node.children if p.type == 'identifier'] if p] if params_node else [],
179 |                     "source": self._get_node_text(assignment_node),
180 |                     "source_code": self._get_node_text(assignment_node),
181 |                     "docstring": None,
182 |                     "cyclomatic_complexity": 1,
183 |                     "context": context,
184 |                     "context_type": context_type,
185 |                     "class_context": class_context,
186 |                     "decorators": [],
187 |                     "lang": self.language_name,
188 |                     "is_dependency": False,
189 |                 }
190 |                 functions.append(func_data)
191 |         return functions
192 | 
193 |     def _find_functions(self, root_node):
194 |         functions = []
195 |         query = self.queries['functions']
196 |         for match in query.captures(root_node):
197 |             capture_name = match[1]
198 |             node = match[0]
199 | 
200 |             if capture_name == 'name':
201 |                 func_node = node.parent
202 |                 name = self._get_node_text(node)
203 |                 params_node = func_node.child_by_field_name('parameters')
204 |                 body_node = func_node.child_by_field_name('body')
205 |                 
206 |                 decorators = [self._get_node_text(child) for child in func_node.children if child.type == 'decorator']
207 | 
208 |                 context, context_type, _ = self._get_parent_context(func_node)
209 |                 class_context, _, _ = self._get_parent_context(func_node, types=('class_definition',))
210 | 
211 |                 args = []
212 |                 if params_node:
213 |                     for p in params_node.children:
214 |                         arg_text = None
215 |                         if p.type == 'identifier':
216 |                             arg_text = self._get_node_text(p)
217 |                         elif p.type == 'default_parameter':
218 |                             name_node = p.child_by_field_name('name')
219 |                             if name_node:
220 |                                 arg_text = self._get_node_text(name_node)
221 |                         if arg_text:
222 |                             args.append(arg_text)
223 | 
224 |                 func_data = {
225 |                     "name": name,
226 |                     "line_number": node.start_point[0] + 1,
227 |                     "end_line": func_node.end_point[0] + 1,
228 |                     "args": args,
229 |                     "source": self._get_node_text(func_node),
230 |                     "source_code": self._get_node_text(func_node),
231 |                     "docstring": self._get_docstring(body_node),
232 |                     "cyclomatic_complexity": self._calculate_complexity(func_node),
233 |                     "context": context,
234 |                     "context_type": context_type,
235 |                     "class_context": class_context,
236 |                     "decorators": [d for d in decorators if d],
237 |                     "lang": self.language_name,
238 |                     "is_dependency": False,
239 |                 }
240 |                 functions.append(func_data)
241 |         return functions
242 | 
243 |     def _find_classes(self, root_node):
244 |         classes = []
245 |         query = self.queries['classes']
246 |         for match in query.captures(root_node):
247 |             capture_name = match[1]
248 |             node = match[0]
249 | 
250 |             if capture_name == 'name':
251 |                 class_node = node.parent
252 |                 name = self._get_node_text(node)
253 |                 body_node = class_node.child_by_field_name('body')
254 |                 superclasses_node = class_node.child_by_field_name('superclasses')
255 |                 
256 |                 bases = []
257 |                 if superclasses_node:
258 |                     bases = [self._get_node_text(child) for child in superclasses_node.children if child.type in ('identifier', 'attribute')]
259 | 
260 |                 decorators = [self._get_node_text(child) for child in class_node.children if child.type == 'decorator']
261 | 
262 |                 context, _, _ = self._get_parent_context(class_node)
263 | 
264 |                 class_data = {
265 |                     "name": name,
266 |                     "line_number": node.start_point[0] + 1,
267 |                     "end_line": class_node.end_point[0] + 1,
268 |                     "bases": [b for b in bases if b],
269 |                     "source": self._get_node_text(class_node),
270 |                     "docstring": self._get_docstring(body_node),
271 |                     "context": context,
272 |                     "decorators": [d for d in decorators if d],
273 |                     "lang": self.language_name,
274 |                     "is_dependency": False,
275 |                 }
276 |                 classes.append(class_data)
277 |         return classes
278 | 
279 |     def _find_imports(self, root_node):
280 |         imports = []
281 |         seen_modules = set()
282 |         query = self.queries['imports']
283 |         for node, capture_name in query.captures(root_node):
284 |             if capture_name in ('import', 'from_import_stmt'):
285 |                 # For 'import_statement'
286 |                 if capture_name == 'import':
287 |                     node_text = self._get_node_text(node)
288 |                     alias = None
289 |                     if ' as ' in node_text:
290 |                         parts = node_text.split(' as ')
291 |                         full_name = parts[0].strip()
292 |                         alias = parts[1].strip()
293 |                     else:
294 |                         full_name = node_text.strip()
295 | 
296 |                     if full_name in seen_modules:
297 |                         continue
298 |                     seen_modules.add(full_name)
299 | 
300 |                     import_data = {
301 |                         "name": full_name,
302 |                         "full_import_name": full_name,
303 |                         "line_number": node.start_point[0] + 1,
304 |                         "alias": alias,
305 |                         "context": self._get_parent_context(node)[:2],
306 |                         "lang": self.language_name,
307 |                         "is_dependency": False,
308 |                     }
309 |                     imports.append(import_data)
310 |                 # For 'import_from_statement'
311 |                 elif capture_name == 'from_import_stmt':
312 |                     module_name_node = node.child_by_field_name('module_name')
313 |                     if not module_name_node: continue
314 |                     
315 |                     module_name = self._get_node_text(module_name_node)
316 |                     
317 |                     # Handle 'from ... import ...'
318 |                     import_list_node = node.child_by_field_name('name')
319 |                     if import_list_node:
320 |                         for child in import_list_node.children:
321 |                             imported_name = None
322 |                             alias = None
323 |                             if child.type == 'aliased_import':
324 |                                 name_node = child.child_by_field_name('name')
325 |                                 alias_node = child.child_by_field_name('alias')
326 |                                 if name_node: imported_name = self._get_node_text(name_node)
327 |                                 if alias_node: alias = self._get_node_text(alias_node)
328 |                             elif child.type == 'dotted_name' or child.type == 'identifier':
329 |                                 imported_name = self._get_node_text(child)
330 |                             
331 |                             if imported_name:
332 |                                 full_import_name = f"{module_name}.{imported_name}"
333 |                                 if full_import_name in seen_modules:                                                                                                
334 |                                     continue                                                                                                                        
335 |                                 seen_modules.add(full_import_name) 
336 |                                 imports.append({
337 |                                     "name": imported_name,
338 |                                     "full_import_name": full_import_name,
339 |                                     "line_number": child.start_point[0] + 1,
340 |                                     "alias": alias,
341 |                                     "context": self._get_parent_context(child)[:2],
342 |                                     "lang": self.language_name,
343 |                                     "is_dependency": False,
344 |                                 })
345 | 
346 |         return imports
347 | 
348 |     def _find_calls(self, root_node):
349 |         calls = []
350 |         query = self.queries['calls']
351 |         for node, capture_name in query.captures(root_node):
352 |             if capture_name == 'name':
353 |                 call_node = node.parent if node.parent.type == 'call' else node.parent.parent
354 |                 full_call_node = call_node.child_by_field_name('function')
355 |                 
356 |                 args = []
357 |                 arguments_node = call_node.child_by_field_name('arguments')
358 |                 if arguments_node:
359 |                     for arg in arguments_node.children:
360 |                         arg_text = self._get_node_text(arg)
361 |                         if arg_text is not None:
362 |                             args.append(arg_text)
363 | 
364 |                 call_data = {
365 |                     "name": self._get_node_text(node),
366 |                     "full_name": self._get_node_text(full_call_node),
367 |                     "line_number": node.start_point[0] + 1,
368 |                     "args": args,
369 |                     "inferred_obj_type": None, # Type inference is a complex topic to be added
370 |                     "context": self._get_parent_context(node),
371 |                     "class_context": self._get_parent_context(node, types=('class_definition',))[:2],
372 |                     "lang": self.language_name,
373 |                     "is_dependency": False,
374 |                 }
375 |                 calls.append(call_data)
376 |         return calls
377 | 
378 |     def _find_variables(self, root_node):
379 |         variables = []
380 |         query = self.queries['variables']
381 |         for match in query.captures(root_node):
382 |             capture_name = match[1]
383 |             node = match[0]
384 | 
385 |             if capture_name == 'name':
386 |                 assignment_node = node.parent
387 | 
388 |                 # Skip lambda assignments, they are handled by _find_lambda_assignments
389 |                 right_node = assignment_node.child_by_field_name('right')
390 |                 if right_node and right_node.type == 'lambda':
391 |                     continue
392 | 
393 |                 name = self._get_node_text(node)
394 |                 value = self._get_node_text(right_node) if right_node else None
395 |                 
396 |                 type_node = assignment_node.child_by_field_name('type')
397 |                 type_text = self._get_node_text(type_node) if type_node else None
398 | 
399 |                 context, _, _ = self._get_parent_context(node)
400 |                 class_context, _, _ = self._get_parent_context(node, types=('class_definition',))
401 | 
402 |                 variable_data = {
403 |                     "name": name,
404 |                     "line_number": node.start_point[0] + 1,
405 |                     "value": value,
406 |                     "type": type_text,
407 |                     "context": context,
408 |                     "class_context": class_context,
409 |                     "lang": self.language_name,
410 |                     "is_dependency": False,
411 |                 }
412 |                 variables.append(variable_data)
413 |         return variables
414 | 
415 | def pre_scan_python(files: list[Path], parser_wrapper) -> dict:
416 |     """Scans Python files to create a map of class/function names to their file paths."""
417 |     imports_map = {}
418 |     query_str = """
419 |         (class_definition name: (identifier) @name)
420 |         (function_definition name: (identifier) @name)
421 |     """
422 |     query = parser_wrapper.language.query(query_str)
423 |     
424 |     for file_path in files:
425 |         temp_py_file = None
426 |         try:
427 |             source_to_parse = ""
428 |             if file_path.suffix == '.ipynb':
429 |                 with open(file_path, 'r', encoding='utf-8') as f:
430 |                     notebook_node = nbformat.read(f, as_version=4)
431 |                 exporter = PythonExporter()
432 |                 python_code, _ = exporter.from_notebook_node(notebook_node)
433 |                 with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.py', encoding='utf-8') as tf:
434 |                     tf.write(python_code)
435 |                     temp_py_file = Path(tf.name)
436 |                 with open(temp_py_file, "r", encoding="utf-8") as f:
437 |                     source_to_parse = f.read()
438 |             else:
439 |                 with open(file_path, "r", encoding="utf-8") as f:
440 |                     source_to_parse = f.read()
441 | 
442 |             tree = parser_wrapper.parser.parse(bytes(source_to_parse, "utf8"))
443 |             
444 |             for capture, _ in query.captures(tree.root_node):
445 |                 name = capture.text.decode('utf-8')
446 |                 if name not in imports_map:
447 |                     imports_map[name] = []
448 |                 imports_map[name].append(str(file_path.resolve()))
449 |         except Exception as e:
450 |             warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
451 |         finally:
452 |             if temp_py_file and temp_py_file.exists():
453 |                 os.remove(temp_py_file)
454 |     return imports_map
```

--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/c.py:
--------------------------------------------------------------------------------

```python
  1 | from pathlib import Path
  2 | from typing import Any, Dict, Optional, Tuple
  3 | from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger
  4 | 
  5 | C_QUERIES = {
  6 |     "functions": """
  7 |         (function_definition
  8 |             declarator: (function_declarator
  9 |                 declarator: (identifier) @name
 10 |             )
 11 |         ) @function_node
 12 |         
 13 |         (function_definition
 14 |             declarator: (function_declarator
 15 |                 declarator: (pointer_declarator
 16 |                     declarator: (identifier) @name
 17 |                 )
 18 |             )
 19 |         ) @function_node
 20 |     """,
 21 |     "structs": """
 22 |         (struct_specifier
 23 |             name: (type_identifier) @name
 24 |         ) @struct
 25 |     """,
 26 |     "unions": """
 27 |         (union_specifier
 28 |             name: (type_identifier) @name
 29 |         ) @union
 30 |     """,
 31 |     "enums": """
 32 |         (enum_specifier
 33 |             name: (type_identifier) @name
 34 |         ) @enum
 35 |     """,
 36 |     "typedefs": """
 37 |         (type_definition
 38 |             declarator: (type_identifier) @name
 39 |         ) @typedef
 40 |     """,
 41 |     "imports": """
 42 |         (preproc_include
 43 |             path: [
 44 |                 (string_literal) @path
 45 |                 (system_lib_string) @path
 46 |             ]
 47 |         ) @import
 48 |     """,
 49 |     "calls": """
 50 |         (call_expression
 51 |             function: (identifier) @name
 52 |         )
 53 |     """,
 54 |     "variables": """
 55 |         (declaration
 56 |             declarator: (init_declarator
 57 |                 declarator: (identifier) @name
 58 |             )
 59 |         )
 60 |         
 61 |         (declaration
 62 |             declarator: (init_declarator
 63 |                 declarator: (pointer_declarator
 64 |                     declarator: (identifier) @name
 65 |                 )
 66 |             )
 67 |         )
 68 |         
 69 |         (declaration
 70 |             declarator: (identifier) @name
 71 |         )
 72 |         
 73 |         (declaration
 74 |             declarator: (pointer_declarator
 75 |                 declarator: (identifier) @name
 76 |             )
 77 |         )
 78 |     """,
 79 |     "macros": """
 80 |         (preproc_def
 81 |             name: (identifier) @name
 82 |         ) @macro
 83 |     """,
 84 | }
 85 | 
 86 | class CTreeSitterParser:
 87 |     """A C-specific parser using tree-sitter."""
 88 | 
 89 |     def __init__(self, generic_parser_wrapper: Any):
 90 |         self.generic_parser_wrapper = generic_parser_wrapper
 91 |         self.language_name = "c"
 92 |         self.language = generic_parser_wrapper.language
 93 |         self.parser = generic_parser_wrapper.parser
 94 | 
 95 |         self.queries = {
 96 |             name: self.language.query(query_str)
 97 |             for name, query_str in C_QUERIES.items()
 98 |         }
 99 | 
100 |     def _get_node_text(self, node: Any) -> str:
101 |         return node.text.decode("utf-8")
102 | 
103 |     def parse(self, file_path: Path, is_dependency: bool = False) -> Dict[str, Any]:
104 |         """Parses a C file and returns its structure."""
105 |         with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
106 |             source_code = f.read()
107 | 
108 |         tree = self.parser.parse(bytes(source_code, "utf8"))
109 |         root_node = tree.root_node
110 | 
111 |         functions = self._find_functions(root_node)
112 |         classes = self._find_structs_unions_enums(root_node)
113 |         imports = self._find_imports(root_node)
114 |         function_calls = self._find_calls(root_node)
115 |         variables = self._find_variables(root_node)
116 |         macros = self._find_macros(root_node)
117 | 
118 |         return {
119 |             "file_path": str(file_path),
120 |             "functions": functions,
121 |             "classes": classes,
122 |             "variables": variables,
123 |             "imports": imports,
124 |             "function_calls": function_calls,
125 |             "macros": macros,
126 |             "is_dependency": is_dependency,
127 |             "lang": self.language_name,
128 |         }
129 | 
130 |     def _get_parent_context(self, node: Any, types: tuple = ('function_definition', 'struct_specifier', 'union_specifier', 'enum_specifier')) -> tuple:
131 |         """Get parent context for nested constructs."""
132 |         curr = node.parent
133 |         while curr:
134 |             if curr.type in types:
135 |                 name_node = curr.child_by_field_name('name')
136 |                 if name_node:
137 |                     return self._get_node_text(name_node), curr.type, curr.start_point[0] + 1
138 |             curr = curr.parent
139 |         return None, None, None
140 | 
141 |     def _calculate_complexity(self, node: Any) -> int:
142 |         """Calculate cyclomatic complexity for C functions."""
143 |         complexity_nodes = {
144 |             "if_statement", "for_statement", "while_statement", "do_statement",
145 |             "switch_statement", "case_statement", "conditional_expression",
146 |             "logical_expression", "binary_expression", "goto_statement"
147 |         }
148 |         count = 1
149 |         
150 |         def traverse(n):
151 |             nonlocal count
152 |             if n.type in complexity_nodes:
153 |                 count += 1
154 |             for child in n.children:
155 |                 traverse(child)
156 |         
157 |         traverse(node)
158 |         return count
159 | 
160 |     def _get_docstring(self, node: Any) -> Optional[str]:
161 |         """Extract comments as documentation."""
162 |         # Look for comments before the node
163 |         if node.parent:
164 |             for child in node.parent.children:
165 |                 if child.type == 'comment' and child.start_point[0] < node.start_point[0]:
166 |                     return self._get_node_text(child)
167 |         return None
168 | 
169 |     def _parse_function_args(self, params_node: Any) -> list[Dict[str, Any]]:
170 |         """Enhanced helper to parse function arguments from a (parameter_list) node."""
171 |         args = []
172 |         if not params_node:
173 |             return args
174 |             
175 |         for param in params_node.named_children:
176 |             if param.type == "parameter_declaration":
177 |                 arg_info: Dict[str, Any] = {"name": "", "type": None, "is_pointer": False, "is_array": False}
178 |                 
179 |                 # Find the declarator (variable name)
180 |                 declarator = param.child_by_field_name("declarator")
181 |                 if declarator:
182 |                     if declarator.type == "identifier":
183 |                         arg_info["name"] = self._get_node_text(declarator)
184 |                     elif declarator.type == "pointer_declarator":
185 |                         arg_info["is_pointer"] = True
186 |                         inner_declarator = declarator.child_by_field_name("declarator")
187 |                         if inner_declarator and inner_declarator.type == "identifier":
188 |                             arg_info["name"] = self._get_node_text(inner_declarator)
189 |                     elif declarator.type == "array_declarator":
190 |                         arg_info["is_array"] = True
191 |                         inner_declarator = declarator.child_by_field_name("declarator")
192 |                         if inner_declarator and inner_declarator.type == "identifier":
193 |                             arg_info["name"] = self._get_node_text(inner_declarator)
194 |                 
195 |                 # Find the type
196 |                 type_node = param.child_by_field_name("type")
197 |                 if type_node:
198 |                     arg_info["type"] = self._get_node_text(type_node)
199 |                 
200 |                 # Handle variadic arguments
201 |                 if param.type == "variadic_parameter":
202 |                     arg_info["name"] = "..."
203 |                     arg_info["type"] = "variadic"
204 |                 
205 |                 args.append(arg_info)
206 |         return args
207 | 
208 |     def _find_functions(self, root_node: Any) -> list[Dict[str, Any]]:
209 |         functions = []
210 |         query = self.queries["functions"]
211 |         for match in query.captures(root_node):
212 |             capture_name = match[1]
213 |             node = match[0]
214 |             if capture_name == 'name':
215 |                 func_node = node.parent.parent.parent
216 |                 name = self._get_node_text(node)
217 |                 
218 |                 # Find parameters
219 |                 params_node = None
220 |                 body_node = None
221 |                 for child in func_node.children:
222 |                     if child.type == "function_declarator":
223 |                         params_node = child.child_by_field_name("parameters")
224 |                     elif child.type == "compound_statement":
225 |                         body_node = child
226 |                 
227 |                 args = self._parse_function_args(params_node) if params_node else []
228 |                 context, context_type, _ = self._get_parent_context(func_node)
229 | 
230 |                 functions.append({
231 |                     "name": name,
232 |                     "line_number": node.start_point[0] + 1,
233 |                     "end_line": func_node.end_point[0] + 1,
234 |                     "args": [arg["name"] for arg in args if arg["name"]],  # Simplified args for compatibility
235 |                     "source": self._get_node_text(func_node),
236 |                     "source_code": self._get_node_text(func_node),
237 |                     "docstring": self._get_docstring(func_node),
238 |                     "cyclomatic_complexity": self._calculate_complexity(func_node),
239 |                     "context": context,
240 |                     "context_type": context_type,
241 |                     "class_context": None,
242 |                     "decorators": [],
243 |                     "lang": self.language_name,
244 |                     "is_dependency": False,
245 |                     "detailed_args": args,  # Keep detailed args for future use
246 |                 })
247 |         return functions
248 | 
249 |     def _find_structs_unions_enums(self, root_node: Any) -> list[Dict[str, Any]]:
250 |         """Find structs, unions, and enums (treated as classes in C)."""
251 |         classes = []
252 |         
253 |         # Find structs
254 |         query = self.queries["structs"]
255 |         for match in query.captures(root_node):
256 |             capture_name = match[1]
257 |             node = match[0]
258 |             if capture_name == 'name':
259 |                 struct_node = node.parent
260 |                 name = self._get_node_text(node)
261 |                 context, context_type, _ = self._get_parent_context(struct_node)
262 |                 
263 |                 classes.append({
264 |                     "name": name,
265 |                     "line_number": node.start_point[0] + 1,
266 |                     "end_line": struct_node.end_point[0] + 1,
267 |                     "bases": [],  # C doesn't have inheritance
268 |                     "source": self._get_node_text(struct_node),
269 |                     "docstring": self._get_docstring(struct_node),
270 |                     "context": context,
271 |                     "decorators": [],
272 |                     "lang": self.language_name,
273 |                     "is_dependency": False,
274 |                     "type": "struct",
275 |                 })
276 | 
277 |         # Find unions
278 |         query = self.queries["unions"]
279 |         for match in query.captures(root_node):
280 |             capture_name = match[1]
281 |             node = match[0]
282 |             if capture_name == 'name':
283 |                 union_node = node.parent
284 |                 name = self._get_node_text(node)
285 |                 context, context_type, _ = self._get_parent_context(union_node)
286 |                 
287 |                 classes.append({
288 |                     "name": name,
289 |                     "line_number": node.start_point[0] + 1,
290 |                     "end_line": union_node.end_point[0] + 1,
291 |                     "bases": [],
292 |                     "source": self._get_node_text(union_node),
293 |                     "docstring": self._get_docstring(union_node),
294 |                     "context": context,
295 |                     "decorators": [],
296 |                     "lang": self.language_name,
297 |                     "is_dependency": False,
298 |                     "type": "union",
299 |                 })
300 | 
301 |         # Find enums
302 |         query = self.queries["enums"]
303 |         for match in query.captures(root_node):
304 |             capture_name = match[1]
305 |             node = match[0]
306 |             if capture_name == 'name':
307 |                 enum_node = node.parent
308 |                 name = self._get_node_text(node)
309 |                 context, context_type, _ = self._get_parent_context(enum_node)
310 |                 
311 |                 classes.append({
312 |                     "name": name,
313 |                     "line_number": node.start_point[0] + 1,
314 |                     "end_line": enum_node.end_point[0] + 1,
315 |                     "bases": [],
316 |                     "source": self._get_node_text(enum_node),
317 |                     "docstring": self._get_docstring(enum_node),
318 |                     "context": context,
319 |                     "decorators": [],
320 |                     "lang": self.language_name,
321 |                     "is_dependency": False,
322 |                     "type": "enum",
323 |                 })
324 | 
325 |         return classes
326 | 
327 |     def _find_imports(self, root_node: Any) -> list[Dict[str, Any]]:
328 |         imports = []
329 |         query = self.queries["imports"]
330 |         for match in query.captures(root_node):
331 |             capture_name = match[1]
332 |             node = match[0]
333 |             if capture_name == 'path':
334 |                 path = self._get_node_text(node).strip('"<>')
335 |                 context, context_type, _ = self._get_parent_context(node)
336 |                 
337 |                 imports.append({
338 |                     "name": path,
339 |                     "full_import_name": path,
340 |                     "line_number": node.start_point[0] + 1,
341 |                     "alias": None,
342 |                     "context": context,
343 |                     "lang": self.language_name,
344 |                     "is_dependency": False,
345 |                 })
346 |         return imports
347 | 
348 |     def _find_calls(self, root_node: Any) -> list[Dict[str, Any]]:
349 |         """Enhanced function call detection."""
350 |         calls = []
351 |         query = self.queries["calls"]
352 |         for match in query.captures(root_node):
353 |             capture_name = match[1]
354 |             node = match[0]
355 |             if capture_name == "name":
356 |                 call_node = node.parent if node.parent.type == "call_expression" else node.parent.parent
357 |                 call_name = self._get_node_text(node)
358 |                 
359 |                 # Extract arguments
360 |                 args = []
361 |                 args_node = call_node.child_by_field_name("arguments")
362 |                 if args_node:
363 |                     for child in args_node.children:
364 |                         if child.type not in ['(', ')', ',']:
365 |                             args.append(self._get_node_text(child))
366 |                 
367 |                 context, context_type, _ = self._get_parent_context(call_node)
368 |                 
369 |                 calls.append({
370 |                     "name": call_name,
371 |                     "full_name": call_name,  # For C, function name is the same as full name
372 |                     "line_number": node.start_point[0] + 1,
373 |                     "args": args,
374 |                     "inferred_obj_type": None,
375 |                     "context": context,
376 |                     "class_context": None,
377 |                     "lang": self.language_name,
378 |                     "is_dependency": False,
379 |                 })
380 |         return calls
381 | 
382 |     def _find_variables(self, root_node: Any) -> list[Dict[str, Any]]:
383 |         """Enhanced variable declaration detection."""
384 |         variables = []
385 |         query = self.queries["variables"]
386 |         for match in query.captures(root_node):
387 |             capture_name = match[1]
388 |             node = match[0]
389 |             if capture_name == "name":
390 |                 var_name = self._get_node_text(node)
391 |                 
392 |                 # Find the declaration node
393 |                 decl_node = node.parent
394 |                 while decl_node and decl_node.type != "declaration":
395 |                     decl_node = decl_node.parent
396 |                 
397 |                 # Extract type information
398 |                 var_type = None
399 |                 is_pointer = False
400 |                 is_array = False
401 |                 value = None
402 |                 
403 |                 if decl_node:
404 |                     # Find type
405 |                     for child in decl_node.children:
406 |                         if child.type in ["primitive_type", "type_identifier", "sized_type_specifier"]:
407 |                             var_type = self._get_node_text(child)
408 |                         elif child.type == "init_declarator":
409 |                             # Check for pointer/array
410 |                             if child.child_by_field_name("declarator"):
411 |                                 declarator = child.child_by_field_name("declarator")
412 |                                 if declarator.type == "pointer_declarator":
413 |                                     is_pointer = True
414 |                                 elif declarator.type == "array_declarator":
415 |                                     is_array = True
416 |                             
417 |                             # Check for initial value
418 |                             if child.child_by_field_name("value"):
419 |                                 value = self._get_node_text(child.child_by_field_name("value"))
420 |                 
421 |                 context, context_type, _ = self._get_parent_context(node)
422 |                 class_context, _, _ = self._get_parent_context(node, types=('struct_specifier', 'union_specifier', 'enum_specifier'))
423 |                 
424 |                 variables.append({
425 |                     "name": var_name,
426 |                     "line_number": node.start_point[0] + 1,
427 |                     "value": value,
428 |                     "type": var_type,
429 |                     "context": context,
430 |                     "class_context": class_context,
431 |                     "lang": self.language_name,
432 |                     "is_dependency": False,
433 |                     "is_pointer": is_pointer,
434 |                     "is_array": is_array,
435 |                 })
436 |         return variables
437 | 
438 |     def _find_macros(self, root_node: Any) -> list[Dict[str, Any]]:
439 |         """Enhanced preprocessor macro detection."""
440 |         macros = []
441 |         query = self.queries["macros"]
442 |         for match in query.captures(root_node):
443 |             capture_name = match[1]
444 |             node = match[0]
445 |             if capture_name == 'name':
446 |                 macro_node = node.parent
447 |                 name = self._get_node_text(node)
448 |                 
449 |                 # Extract macro value
450 |                 value = None
451 |                 if macro_node.child_by_field_name("value"):
452 |                     value = self._get_node_text(macro_node.child_by_field_name("value"))
453 |                 
454 |                 # Extract parameters for function-like macros
455 |                 params = []
456 |                 if macro_node.child_by_field_name("parameters"):
457 |                     params_node = macro_node.child_by_field_name("parameters")
458 |                     for child in params_node.children:
459 |                         if child.type == "identifier":
460 |                             params.append(self._get_node_text(child))
461 |                 
462 |                 context, context_type, _ = self._get_parent_context(macro_node)
463 |                 
464 |                 macros.append({
465 |                     "name": name,
466 |                     "line_number": node.start_point[0] + 1,
467 |                     "end_line": macro_node.end_point[0] + 1,
468 |                     "source": self._get_node_text(macro_node),
469 |                     "value": value,
470 |                     "params": params,
471 |                     "context": context,
472 |                     "lang": self.language_name,
473 |                     "is_dependency": False,
474 |                 })
475 |         return macros
476 | 
477 | 
478 | def pre_scan_c(files: list[Path], parser_wrapper) -> dict:
479 |     """Scans C files to create a map of function/struct/union/enum names to their file paths."""
480 |     imports_map = {}
481 |     query_str = """
482 |         (function_definition
483 |             declarator: (function_declarator
484 |                 declarator: (identifier) @name
485 |             )
486 |         )
487 |         
488 |         (function_definition
489 |             declarator: (function_declarator
490 |                 declarator: (pointer_declarator
491 |                     declarator: (identifier) @name
492 |                 )
493 |             )
494 |         )
495 |         
496 |         (struct_specifier
497 |             name: (type_identifier) @name
498 |         )
499 |         
500 |         (union_specifier
501 |             name: (type_identifier) @name
502 |         )
503 |         
504 |         (enum_specifier
505 |             name: (type_identifier) @name
506 |         )
507 |         
508 |         (type_definition
509 |             declarator: (type_identifier) @name
510 |         )
511 |         
512 |         (preproc_def
513 |             name: (identifier) @name
514 |         )
515 |     """
516 |     query = parser_wrapper.language.query(query_str)
517 |     
518 |     for file_path in files:
519 |         try:
520 |             with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
521 |                 tree = parser_wrapper.parser.parse(bytes(f.read(), "utf8"))
522 |             
523 |             for capture, _ in query.captures(tree.root_node):
524 |                 name = capture.text.decode('utf-8')
525 |                 if name not in imports_map:
526 |                     imports_map[name] = []
527 |                 imports_map[name].append(str(file_path.resolve()))
528 |         except Exception as e:
529 |             warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
530 |     return imports_map
531 | 
```

--------------------------------------------------------------------------------
/docs/site/core/index.html:
--------------------------------------------------------------------------------

```html
  1 | 
  2 | <!doctype html>
  3 | <html lang="en" class="no-js">
  4 |   <head>
  5 |     
  6 |       <meta charset="utf-8">
  7 |       <meta name="viewport" content="width=device-width,initial-scale=1">
  8 |       
  9 |       
 10 |       
 11 |       
 12 |         <link rel="prev" href="../server/">
 13 |       
 14 |       
 15 |         <link rel="next" href="../tools/">
 16 |       
 17 |       
 18 |       <link rel="icon" href="../assets/images/favicon.png">
 19 |       <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
 20 |     
 21 |     
 22 |       
 23 |         <title>Core Concepts - CodeGraphContext</title>
 24 |       
 25 |     
 26 |     
 27 |       <link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
 28 |       
 29 |       
 30 | 
 31 | 
 32 |     
 33 |     
 34 |       
 35 |     
 36 |     
 37 |       
 38 |         
 39 |         
 40 |         <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 41 |         <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
 42 |         <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
 43 |       
 44 |     
 45 |     
 46 |     <script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
 47 |     
 48 |       
 49 | 
 50 |     
 51 |     
 52 |     
 53 |   </head>
 54 |   
 55 |   
 56 |     <body dir="ltr">
 57 |   
 58 |     
 59 |     <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
 60 |     <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
 61 |     <label class="md-overlay" for="__drawer"></label>
 62 |     <div data-md-component="skip">
 63 |       
 64 |         
 65 |         <a href="#core-concepts" class="md-skip">
 66 |           Skip to content
 67 |         </a>
 68 |       
 69 |     </div>
 70 |     <div data-md-component="announce">
 71 |       
 72 |     </div>
 73 |     
 74 |     
 75 |       
 76 | 
 77 |   
 78 | 
 79 | <header class="md-header md-header--shadow" data-md-component="header">
 80 |   <nav class="md-header__inner md-grid" aria-label="Header">
 81 |     <a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
 82 |       
 83 |   
 84 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
 85 | 
 86 |     </a>
 87 |     <label class="md-header__button md-icon" for="__drawer">
 88 |       
 89 |       <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
 90 |     </label>
 91 |     <div class="md-header__title" data-md-component="header-title">
 92 |       <div class="md-header__ellipsis">
 93 |         <div class="md-header__topic">
 94 |           <span class="md-ellipsis">
 95 |             CodeGraphContext
 96 |           </span>
 97 |         </div>
 98 |         <div class="md-header__topic" data-md-component="header-topic">
 99 |           <span class="md-ellipsis">
100 |             
101 |               Core Concepts
102 |             
103 |           </span>
104 |         </div>
105 |       </div>
106 |     </div>
107 |     
108 |     
109 |       <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
110 |     
111 |     
112 |     
113 |       
114 |       
115 |         <label class="md-header__button md-icon" for="__search">
116 |           
117 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
118 |         </label>
119 |         <div class="md-search" data-md-component="search" role="dialog">
120 |   <label class="md-search__overlay" for="__search"></label>
121 |   <div class="md-search__inner" role="search">
122 |     <form class="md-search__form" name="search">
123 |       <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
124 |       <label class="md-search__icon md-icon" for="__search">
125 |         
126 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
127 |         
128 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
129 |       </label>
130 |       <nav class="md-search__options" aria-label="Search">
131 |         
132 |         <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
133 |           
134 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
135 |         </button>
136 |       </nav>
137 |       
138 |     </form>
139 |     <div class="md-search__output">
140 |       <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
141 |         <div class="md-search-result" data-md-component="search-result">
142 |           <div class="md-search-result__meta">
143 |             Initializing search
144 |           </div>
145 |           <ol class="md-search-result__list" role="presentation"></ol>
146 |         </div>
147 |       </div>
148 |     </div>
149 |   </div>
150 | </div>
151 |       
152 |     
153 |     
154 |   </nav>
155 |   
156 | </header>
157 |     
158 |     <div class="md-container" data-md-component="container">
159 |       
160 |       
161 |         
162 |           
163 |         
164 |       
165 |       <main class="md-main" data-md-component="main">
166 |         <div class="md-main__inner md-grid">
167 |           
168 |             
169 |               
170 |               <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
171 |                 <div class="md-sidebar__scrollwrap">
172 |                   <div class="md-sidebar__inner">
173 |                     
174 | 
175 | 
176 | 
177 | <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
178 |   <label class="md-nav__title" for="__drawer">
179 |     <a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
180 |       
181 |   
182 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
183 | 
184 |     </a>
185 |     CodeGraphContext
186 |   </label>
187 |   
188 |   <ul class="md-nav__list" data-md-scrollfix>
189 |     
190 |       
191 |       
192 |   
193 |   
194 |   
195 |   
196 |     <li class="md-nav__item">
197 |       <a href=".." class="md-nav__link">
198 |         
199 |   
200 |   
201 |   <span class="md-ellipsis">
202 |     Home
203 |     
204 |   </span>
205 |   
206 | 
207 |       </a>
208 |     </li>
209 |   
210 | 
211 |     
212 |       
213 |       
214 |   
215 |   
216 |   
217 |   
218 |     <li class="md-nav__item">
219 |       <a href="../installation/" class="md-nav__link">
220 |         
221 |   
222 |   
223 |   <span class="md-ellipsis">
224 |     Installation
225 |     
226 |   </span>
227 |   
228 | 
229 |       </a>
230 |     </li>
231 |   
232 | 
233 |     
234 |       
235 |       
236 |   
237 |   
238 |   
239 |   
240 |     <li class="md-nav__item">
241 |       <a href="../use_cases/" class="md-nav__link">
242 |         
243 |   
244 |   
245 |   <span class="md-ellipsis">
246 |     Use Cases
247 |     
248 |   </span>
249 |   
250 | 
251 |       </a>
252 |     </li>
253 |   
254 | 
255 |     
256 |       
257 |       
258 |   
259 |   
260 |   
261 |   
262 |     <li class="md-nav__item">
263 |       <a href="../architecture/" class="md-nav__link">
264 |         
265 |   
266 |   
267 |   <span class="md-ellipsis">
268 |     Architecture
269 |     
270 |   </span>
271 |   
272 | 
273 |       </a>
274 |     </li>
275 |   
276 | 
277 |     
278 |       
279 |       
280 |   
281 |   
282 |   
283 |   
284 |     <li class="md-nav__item">
285 |       <a href="../cli/" class="md-nav__link">
286 |         
287 |   
288 |   
289 |   <span class="md-ellipsis">
290 |     CLI Reference
291 |     
292 |   </span>
293 |   
294 | 
295 |       </a>
296 |     </li>
297 |   
298 | 
299 |     
300 |       
301 |       
302 |   
303 |   
304 |   
305 |   
306 |     <li class="md-nav__item">
307 |       <a href="../server/" class="md-nav__link">
308 |         
309 |   
310 |   
311 |   <span class="md-ellipsis">
312 |     Server
313 |     
314 |   </span>
315 |   
316 | 
317 |       </a>
318 |     </li>
319 |   
320 | 
321 |     
322 |       
323 |       
324 |   
325 |   
326 |     
327 |   
328 |   
329 |   
330 |     <li class="md-nav__item md-nav__item--active">
331 |       
332 |       <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
333 |       
334 |       
335 |         
336 |       
337 |       
338 |         <label class="md-nav__link md-nav__link--active" for="__toc">
339 |           
340 |   
341 |   
342 |   <span class="md-ellipsis">
343 |     Core Concepts
344 |     
345 |   </span>
346 |   
347 | 
348 |           <span class="md-nav__icon md-icon"></span>
349 |         </label>
350 |       
351 |       <a href="./" class="md-nav__link md-nav__link--active">
352 |         
353 |   
354 |   
355 |   <span class="md-ellipsis">
356 |     Core Concepts
357 |     
358 |   </span>
359 |   
360 | 
361 |       </a>
362 |       
363 |         
364 | 
365 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
366 |   
367 |   
368 |   
369 |     
370 |   
371 |   
372 |     <label class="md-nav__title" for="__toc">
373 |       <span class="md-nav__icon md-icon"></span>
374 |       Table of contents
375 |     </label>
376 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
377 |       
378 |         <li class="md-nav__item">
379 |   <a href="#databasemanager" class="md-nav__link">
380 |     <span class="md-ellipsis">
381 |       DatabaseManager
382 |     </span>
383 |   </a>
384 |   
385 |     <nav class="md-nav" aria-label="DatabaseManager">
386 |       <ul class="md-nav__list">
387 |         
388 |           <li class="md-nav__item">
389 |   <a href="#key-methods" class="md-nav__link">
390 |     <span class="md-ellipsis">
391 |       Key Methods
392 |     </span>
393 |   </a>
394 |   
395 | </li>
396 |         
397 |       </ul>
398 |     </nav>
399 |   
400 | </li>
401 |       
402 |         <li class="md-nav__item">
403 |   <a href="#jobmanager" class="md-nav__link">
404 |     <span class="md-ellipsis">
405 |       JobManager
406 |     </span>
407 |   </a>
408 |   
409 |     <nav class="md-nav" aria-label="JobManager">
410 |       <ul class="md-nav__list">
411 |         
412 |           <li class="md-nav__item">
413 |   <a href="#jobstatus" class="md-nav__link">
414 |     <span class="md-ellipsis">
415 |       JobStatus
416 |     </span>
417 |   </a>
418 |   
419 | </li>
420 |         
421 |           <li class="md-nav__item">
422 |   <a href="#jobinfo" class="md-nav__link">
423 |     <span class="md-ellipsis">
424 |       JobInfo
425 |     </span>
426 |   </a>
427 |   
428 | </li>
429 |         
430 |           <li class="md-nav__item">
431 |   <a href="#key-methods_1" class="md-nav__link">
432 |     <span class="md-ellipsis">
433 |       Key Methods
434 |     </span>
435 |   </a>
436 |   
437 | </li>
438 |         
439 |       </ul>
440 |     </nav>
441 |   
442 | </li>
443 |       
444 |         <li class="md-nav__item">
445 |   <a href="#codewatcher" class="md-nav__link">
446 |     <span class="md-ellipsis">
447 |       CodeWatcher
448 |     </span>
449 |   </a>
450 |   
451 |     <nav class="md-nav" aria-label="CodeWatcher">
452 |       <ul class="md-nav__list">
453 |         
454 |           <li class="md-nav__item">
455 |   <a href="#repositoryeventhandler" class="md-nav__link">
456 |     <span class="md-ellipsis">
457 |       RepositoryEventHandler
458 |     </span>
459 |   </a>
460 |   
461 | </li>
462 |         
463 |           <li class="md-nav__item">
464 |   <a href="#key-methods_2" class="md-nav__link">
465 |     <span class="md-ellipsis">
466 |       Key Methods
467 |     </span>
468 |   </a>
469 |   
470 | </li>
471 |         
472 |       </ul>
473 |     </nav>
474 |   
475 | </li>
476 |       
477 |     </ul>
478 |   
479 | </nav>
480 |       
481 |     </li>
482 |   
483 | 
484 |     
485 |       
486 |       
487 |   
488 |   
489 |   
490 |   
491 |     <li class="md-nav__item">
492 |       <a href="../tools/" class="md-nav__link">
493 |         
494 |   
495 |   
496 |   <span class="md-ellipsis">
497 |     Tools
498 |     
499 |   </span>
500 |   
501 | 
502 |       </a>
503 |     </li>
504 |   
505 | 
506 |     
507 |       
508 |       
509 |   
510 |   
511 |   
512 |   
513 |     <li class="md-nav__item">
514 |       <a href="../cookbook/" class="md-nav__link">
515 |         
516 |   
517 |   
518 |   <span class="md-ellipsis">
519 |     Cookbook
520 |     
521 |   </span>
522 |   
523 | 
524 |       </a>
525 |     </li>
526 |   
527 | 
528 |     
529 |       
530 |       
531 |   
532 |   
533 |   
534 |   
535 |     
536 |     
537 |     
538 |     
539 |     
540 |     <li class="md-nav__item md-nav__item--nested">
541 |       
542 |         
543 |         
544 |         <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
545 |         
546 |           
547 |           <label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
548 |             
549 |   
550 |   
551 |   <span class="md-ellipsis">
552 |     Contributing
553 |     
554 |   </span>
555 |   
556 | 
557 |             <span class="md-nav__icon md-icon"></span>
558 |           </label>
559 |         
560 |         <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
561 |           <label class="md-nav__title" for="__nav_10">
562 |             <span class="md-nav__icon md-icon"></span>
563 |             Contributing
564 |           </label>
565 |           <ul class="md-nav__list" data-md-scrollfix>
566 |             
567 |               
568 |                 
569 |   
570 |   
571 |   
572 |   
573 |     <li class="md-nav__item">
574 |       <a href="../contributing/" class="md-nav__link">
575 |         
576 |   
577 |   
578 |   <span class="md-ellipsis">
579 |     Overview
580 |     
581 |   </span>
582 |   
583 | 
584 |       </a>
585 |     </li>
586 |   
587 | 
588 |               
589 |             
590 |               
591 |                 
592 |   
593 |   
594 |   
595 |   
596 |     <li class="md-nav__item">
597 |       <a href="../contributing_languages/" class="md-nav__link">
598 |         
599 |   
600 |   
601 |   <span class="md-ellipsis">
602 |     Adding New Languages
603 |     
604 |   </span>
605 |   
606 | 
607 |       </a>
608 |     </li>
609 |   
610 | 
611 |               
612 |             
613 |           </ul>
614 |         </nav>
615 |       
616 |     </li>
617 |   
618 | 
619 |     
620 |       
621 |       
622 |   
623 |   
624 |   
625 |   
626 |     <li class="md-nav__item">
627 |       <a href="../troubleshooting/" class="md-nav__link">
628 |         
629 |   
630 |   
631 |   <span class="md-ellipsis">
632 |     Troubleshooting
633 |     
634 |   </span>
635 |   
636 | 
637 |       </a>
638 |     </li>
639 |   
640 | 
641 |     
642 |       
643 |       
644 |   
645 |   
646 |   
647 |   
648 |     <li class="md-nav__item">
649 |       <a href="../future_work/" class="md-nav__link">
650 |         
651 |   
652 |   
653 |   <span class="md-ellipsis">
654 |     Future Work
655 |     
656 |   </span>
657 |   
658 | 
659 |       </a>
660 |     </li>
661 |   
662 | 
663 |     
664 |       
665 |       
666 |   
667 |   
668 |   
669 |   
670 |     <li class="md-nav__item">
671 |       <a href="../license/" class="md-nav__link">
672 |         
673 |   
674 |   
675 |   <span class="md-ellipsis">
676 |     License
677 |     
678 |   </span>
679 |   
680 | 
681 |       </a>
682 |     </li>
683 |   
684 | 
685 |     
686 |   </ul>
687 | </nav>
688 |                   </div>
689 |                 </div>
690 |               </div>
691 |             
692 |             
693 |               
694 |               <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
695 |                 <div class="md-sidebar__scrollwrap">
696 |                   <div class="md-sidebar__inner">
697 |                     
698 | 
699 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
700 |   
701 |   
702 |   
703 |     
704 |   
705 |   
706 |     <label class="md-nav__title" for="__toc">
707 |       <span class="md-nav__icon md-icon"></span>
708 |       Table of contents
709 |     </label>
710 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
711 |       
712 |         <li class="md-nav__item">
713 |   <a href="#databasemanager" class="md-nav__link">
714 |     <span class="md-ellipsis">
715 |       DatabaseManager
716 |     </span>
717 |   </a>
718 |   
719 |     <nav class="md-nav" aria-label="DatabaseManager">
720 |       <ul class="md-nav__list">
721 |         
722 |           <li class="md-nav__item">
723 |   <a href="#key-methods" class="md-nav__link">
724 |     <span class="md-ellipsis">
725 |       Key Methods
726 |     </span>
727 |   </a>
728 |   
729 | </li>
730 |         
731 |       </ul>
732 |     </nav>
733 |   
734 | </li>
735 |       
736 |         <li class="md-nav__item">
737 |   <a href="#jobmanager" class="md-nav__link">
738 |     <span class="md-ellipsis">
739 |       JobManager
740 |     </span>
741 |   </a>
742 |   
743 |     <nav class="md-nav" aria-label="JobManager">
744 |       <ul class="md-nav__list">
745 |         
746 |           <li class="md-nav__item">
747 |   <a href="#jobstatus" class="md-nav__link">
748 |     <span class="md-ellipsis">
749 |       JobStatus
750 |     </span>
751 |   </a>
752 |   
753 | </li>
754 |         
755 |           <li class="md-nav__item">
756 |   <a href="#jobinfo" class="md-nav__link">
757 |     <span class="md-ellipsis">
758 |       JobInfo
759 |     </span>
760 |   </a>
761 |   
762 | </li>
763 |         
764 |           <li class="md-nav__item">
765 |   <a href="#key-methods_1" class="md-nav__link">
766 |     <span class="md-ellipsis">
767 |       Key Methods
768 |     </span>
769 |   </a>
770 |   
771 | </li>
772 |         
773 |       </ul>
774 |     </nav>
775 |   
776 | </li>
777 |       
778 |         <li class="md-nav__item">
779 |   <a href="#codewatcher" class="md-nav__link">
780 |     <span class="md-ellipsis">
781 |       CodeWatcher
782 |     </span>
783 |   </a>
784 |   
785 |     <nav class="md-nav" aria-label="CodeWatcher">
786 |       <ul class="md-nav__list">
787 |         
788 |           <li class="md-nav__item">
789 |   <a href="#repositoryeventhandler" class="md-nav__link">
790 |     <span class="md-ellipsis">
791 |       RepositoryEventHandler
792 |     </span>
793 |   </a>
794 |   
795 | </li>
796 |         
797 |           <li class="md-nav__item">
798 |   <a href="#key-methods_2" class="md-nav__link">
799 |     <span class="md-ellipsis">
800 |       Key Methods
801 |     </span>
802 |   </a>
803 |   
804 | </li>
805 |         
806 |       </ul>
807 |     </nav>
808 |   
809 | </li>
810 |       
811 |     </ul>
812 |   
813 | </nav>
814 |                   </div>
815 |                 </div>
816 |               </div>
817 |             
818 |           
819 |           
820 |             <div class="md-content" data-md-component="content">
821 |               <article class="md-content__inner md-typeset">
822 |                 
823 |                   
824 | 
825 | 
826 | 
827 | <h1 id="core-concepts">Core Concepts</h1>
828 | <p>The core of CodeGraphContext is built upon a few key components that manage the database connection, handle background tasks, and watch for file system changes.</p>
829 | <h2 id="databasemanager"><code>DatabaseManager</code></h2>
830 | <p>The <code>DatabaseManager</code> class in <code>database.py</code> is a thread-safe singleton responsible for managing the connection to the Neo4j database. This ensures that only one connection pool is created and shared across the application, which is crucial for performance and resource management.</p>
831 | <h3 id="key-methods">Key Methods</h3>
832 | <ul>
833 | <li><code>get_driver()</code>: Returns the active Neo4j Driver instance, creating it if it doesn't exist.</li>
834 | <li><code>close_driver()</code>: Closes the Neo4j driver connection.</li>
835 | <li><code>is_connected()</code>: Checks if the database connection is currently active.</li>
836 | </ul>
837 | <h2 id="jobmanager"><code>JobManager</code></h2>
838 | <p>The <code>JobManager</code> class in <code>jobs.py</code> handles long-running, background jobs, such as code indexing. It stores job information in memory and provides a thread-safe way to create, update, and retrieve information about these jobs.</p>
839 | <h3 id="jobstatus"><code>JobStatus</code></h3>
840 | <p>An enumeration for the possible statuses of a background job:
841 | - <code>PENDING</code>
842 | - <code>RUNNING</code>
843 | - <code>COMPLETED</code>
844 | - <code>FAILED</code>
845 | - <code>CANCELLED</code></p>
846 | <h3 id="jobinfo"><code>JobInfo</code></h3>
847 | <p>A data class that holds all information about a single background job, including its ID, status, start/end times, progress, and any errors.</p>
848 | <h3 id="key-methods_1">Key Methods</h3>
849 | <ul>
850 | <li><code>create_job()</code>: Creates a new job with a unique ID.</li>
851 | <li><code>update_job()</code>: Updates the information for a specific job.</li>
852 | <li><code>get_job()</code>: Retrieves the information for a single job.</li>
853 | <li><code>list_jobs()</code>: Returns a list of all jobs.</li>
854 | <li><code>cleanup_old_jobs()</code>: Removes old, completed jobs from memory.</li>
855 | </ul>
856 | <h2 id="codewatcher"><code>CodeWatcher</code></h2>
857 | <p>The <code>CodeWatcher</code> class in <code>watcher.py</code> implements the live file-watching functionality using the <code>watchdog</code> library. It observes directories for changes and triggers updates to the code graph.</p>
858 | <h3 id="repositoryeventhandler"><code>RepositoryEventHandler</code></h3>
859 | <p>A dedicated event handler for a single repository. It performs an initial scan and then uses a debouncing mechanism to efficiently handle file changes, creations, or deletions.</p>
860 | <h3 id="key-methods_2">Key Methods</h3>
861 | <ul>
862 | <li><code>watch_directory()</code>: Schedules a directory to be watched for changes.</li>
863 | <li><code>unwatch_directory()</code>: Stops watching a directory.</li>
864 | <li><code>list_watched_paths()</code>: Returns a list of all currently watched directory paths.</li>
865 | <li><code>start()</code>: Starts the observer thread.</li>
866 | <li><code>stop()</code>: Stops the observer thread gracefully.</li>
867 | </ul>
868 | 
869 | 
870 | 
871 | 
872 | 
873 | 
874 | 
875 | 
876 | 
877 | 
878 | 
879 | 
880 |                 
881 |               </article>
882 |             </div>
883 |           
884 |           
885 | <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
886 |         </div>
887 |         
888 |       </main>
889 |       
890 |         <footer class="md-footer">
891 |   
892 |   <div class="md-footer-meta md-typeset">
893 |     <div class="md-footer-meta__inner md-grid">
894 |       <div class="md-copyright">
895 |   
896 |   
897 |     Made with
898 |     <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
899 |       Material for MkDocs
900 |     </a>
901 |   
902 | </div>
903 |       
904 |     </div>
905 |   </div>
906 | </footer>
907 |       
908 |     </div>
909 |     <div class="md-dialog" data-md-component="dialog">
910 |       <div class="md-dialog__inner md-typeset"></div>
911 |     </div>
912 |     
913 |     
914 |     
915 |       
916 |       <script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
917 |     
918 |     
919 |       <script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
920 |       
921 |     
922 |   </body>
923 | </html>
```

--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/typescript.py:
--------------------------------------------------------------------------------

```python
  1 | from pathlib import Path
  2 | from typing import Dict
  3 | from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger, debug_logger
  4 | 
  5 | TS_QUERIES = {
  6 |     "functions": """
  7 |         (function_declaration
  8 |             name: (identifier) @name
  9 |             parameters: (formal_parameters) @params
 10 |         ) @function_node
 11 | 
 12 |         (variable_declarator
 13 |             name: (identifier) @name
 14 |             value: (function
 15 |                 parameters: (formal_parameters) @params
 16 |             ) @function_node
 17 |         )
 18 | 
 19 |         (variable_declarator
 20 |             name: (identifier) @name
 21 |             value: (arrow_function
 22 |                 parameters: (formal_parameters) @params
 23 |             ) @function_node
 24 |         )
 25 | 
 26 |         (variable_declarator
 27 |             name: (identifier) @name
 28 |             value: (arrow_function
 29 |                 parameter: (identifier) @single_param
 30 |             ) @function_node
 31 |         )
 32 | 
 33 |         (method_definition
 34 |             name: (property_identifier) @name
 35 |             parameters: (formal_parameters) @params
 36 |         ) @function_node
 37 | 
 38 |         (assignment_expression
 39 |             left: (member_expression
 40 |                 property: (property_identifier) @name
 41 |             )
 42 |             right: (function
 43 |                 parameters: (formal_parameters) @params
 44 |             ) @function_node
 45 |         )
 46 | 
 47 |         (assignment_expression
 48 |             left: (member_expression
 49 |                 property: (property_identifier) @name
 50 |             )
 51 |             right: (arrow_function
 52 |                 parameters: (formal_parameters) @params
 53 |             ) @function_node
 54 |         )
 55 |     """,
 56 |     "classes": """
 57 |         (class_declaration) @class
 58 |         (class) @class
 59 |     """,
 60 |     "interfaces": """
 61 |         (interface_declaration
 62 |             name: (type_identifier) @name
 63 |         ) @interface_node
 64 |     """,
 65 |     "type_aliases": """
 66 |         (type_alias_declaration
 67 |             name: (type_identifier) @name
 68 |         ) @type_alias_node
 69 |     """,
 70 |     "imports": """
 71 |         (import_statement) @import
 72 |         (call_expression
 73 |             function: (identifier) @require_call (#eq? @require_call "require")
 74 |         ) @import
 75 |     """,
 76 |     "calls": """
 77 |         (call_expression function: (identifier) @name)
 78 |         (call_expression function: (member_expression property: (property_identifier) @name))
 79 |     """,
 80 |     "variables": """
 81 |         (variable_declarator name: (identifier) @name)
 82 |     """,
 83 |     "docstrings": """
 84 |         (comment) @docstring_comment
 85 |     """,
 86 | }
 87 | 
 88 | def is_typescript_file(file_path: Path) -> bool:
 89 |     return file_path.suffix in {".ts", ".tsx"}
 90 | 
 91 | class TypescriptTreeSitterParser:
 92 |     """A TypeScript-specific parser using tree-sitter, encapsulating language-specific logic."""
 93 | 
 94 |     def __init__(self, generic_parser_wrapper):
 95 |         self.generic_parser_wrapper = generic_parser_wrapper
 96 |         self.language_name = generic_parser_wrapper.language_name
 97 |         self.language = generic_parser_wrapper.language
 98 |         self.parser = generic_parser_wrapper.parser
 99 | 
100 |         self.queries = {
101 |             name: self.language.query(query_str)
102 |             for name, query_str in TS_QUERIES.items()
103 |         }
104 | 
105 |     def _get_node_text(self, node) -> str:
106 |         return node.text.decode('utf-8')
107 | 
108 |     def _get_parent_context(self, node, types=('function_declaration', 'class_declaration')):
109 |         curr = node.parent
110 |         while curr:
111 |             if curr.type in types:
112 |                 name_node = curr.child_by_field_name('name')
113 |                 return self._get_node_text(name_node) if name_node else None, curr.type, curr.start_point[0] + 1
114 |             curr = curr.parent
115 |         return None, None, None
116 | 
117 |     def _calculate_complexity(self, node):
118 |         complexity_nodes = {
119 |             "if_statement", "for_statement", "while_statement", "do_statement",
120 |             "switch_statement", "case_statement", "conditional_expression",
121 |             "logical_expression", "binary_expression", "catch_clause"
122 |         }
123 |         count = 1
124 |         def traverse(n):
125 |             nonlocal count
126 |             if n.type in complexity_nodes:
127 |                 count += 1
128 |             for child in n.children:
129 |                 traverse(child)
130 |         traverse(node)
131 |         return count
132 | 
133 |     def _get_docstring(self, body_node):
134 |         return None
135 | 
136 |     def parse(self, file_path: Path, is_dependency: bool = False) -> Dict:
137 |         with open(file_path, "r", encoding="utf-8") as f:
138 |             source_code = f.read()
139 |         tree = self.parser.parse(bytes(source_code, "utf8"))
140 |         root_node = tree.root_node
141 | 
142 |         functions = self._find_functions(root_node)
143 |         classes = self._find_classes(root_node)
144 |         interfaces = self._find_interfaces(root_node)
145 |         type_aliases = self._find_type_aliases(root_node)
146 |         imports = self._find_imports(root_node)
147 |         function_calls = self._find_calls(root_node)
148 |         variables = self._find_variables(root_node)
149 | 
150 |         return {
151 |             "file_path": str(file_path),
152 |             "functions": functions,
153 |             "classes": classes,
154 |             "interfaces": interfaces,
155 |             "type_aliases": type_aliases,
156 |             "variables": variables,
157 |             "imports": imports,
158 |             "function_calls": function_calls,
159 |             "is_dependency": is_dependency,
160 |             "lang": self.language_name,
161 |         }
162 | 
163 | 
164 |     def _find_functions(self, root_node):
165 |         functions = []
166 |         query = self.queries['functions']
167 |         def _fn_for_name(name_node):
168 |             current = name_node.parent
169 |             while current:
170 |                 if current.type in ('function_declaration', 'function', 'arrow_function', 'method_definition'):
171 |                     return current
172 |                 elif current.type in ('variable_declarator', 'assignment_expression'):
173 |                     for child in current.children:
174 |                         if child.type in ('function', 'arrow_function'):
175 |                             return child
176 |                 current = current.parent
177 |             return None
178 |         def _fn_for_params(params_node):
179 |             current = params_node.parent
180 |             while current:
181 |                 if current.type in ('function_declaration', 'function', 'arrow_function', 'method_definition'):
182 |                     return current
183 |                 current = current.parent
184 |             return None
185 |         def _key(n):
186 |             return (n.start_byte, n.end_byte, n.type)
187 |         captures_by_function = {}
188 |         def _bucket_for(node):
189 |             fid = id(node)
190 |             return captures_by_function.setdefault(fid, {
191 |                 'node': node, 'name': None, 'params': None, 'single_param': None
192 |             })
193 |         for node, capture_name in query.captures(root_node):
194 |             if capture_name == 'function_node':
195 |                 _bucket_for(node)
196 |             elif capture_name == 'name':
197 |                 fn = _fn_for_name(node)
198 |                 if fn:
199 |                     b = _bucket_for(fn)
200 |                     b['name'] = self._get_node_text(node)
201 |             elif capture_name == 'params':
202 |                 fn = _fn_for_params(node)
203 |                 if fn:
204 |                     b = _bucket_for(fn)
205 |                     b['params'] = node
206 |             elif capture_name == 'single_param':
207 |                 fn = _fn_for_params(node)
208 |                 if fn:
209 |                     b = _bucket_for(fn)
210 |                     b['single_param'] = node
211 |         for _, data in captures_by_function.items():
212 |             func_node = data['node']
213 |             name = data.get('name')
214 |             if not name and func_node.type == 'method_definition':
215 |                 nm = func_node.child_by_field_name('name')
216 |                 if nm:
217 |                     name = self._get_node_text(nm)
218 |             if not name:
219 |                 continue
220 |             args = []
221 |             if data.get('params'):
222 |                 args = self._extract_parameters(data['params'])
223 |             elif data.get('single_param'):
224 |                 args = [self._get_node_text(data['single_param'])]
225 |             context, context_type, _ = self._get_parent_context(func_node)
226 |             class_context = context if context_type == 'class_declaration' else None
227 |             docstring = None
228 |             func_data = {
229 |                 "name": name,
230 |                 "line_number": func_node.start_point[0] + 1,
231 |                 "end_line": func_node.end_point[0] + 1,
232 |                 "args": args,
233 |                 "source": self._get_node_text(func_node),
234 |                 "source_code": self._get_node_text(func_node),
235 |                 "docstring": docstring,
236 |                 "cyclomatic_complexity": self._calculate_complexity(func_node),
237 |                 "context": context,
238 |                 "context_type": context_type,
239 |                 "class_context": class_context,
240 |                 "decorators": [],
241 |                 "lang": self.language_name,
242 |                 "is_dependency": False,
243 |             }
244 |             functions.append(func_data)
245 |         return functions
246 | 
247 |     def _extract_parameters(self, params_node):
248 |         params = []
249 |         if params_node.type == 'formal_parameters':
250 |             for child in params_node.children:
251 |                 if child.type == 'identifier':
252 |                     params.append(self._get_node_text(child))
253 |                 elif child.type == 'assignment_pattern':
254 |                     left_child = child.child_by_field_name('left')
255 |                     if left_child and left_child.type == 'identifier':
256 |                         params.append(self._get_node_text(left_child))
257 |                 elif child.type == 'rest_pattern':
258 |                     argument = child.child_by_field_name('argument')
259 |                     if argument and argument.type == 'identifier':
260 |                         params.append(f"...{self._get_node_text(argument)}")
261 |         return params
262 | 
263 |     def _find_classes(self, root_node):
264 |         classes = []
265 |         query = self.queries['classes']
266 |         for class_node, capture_name in query.captures(root_node):
267 |             if capture_name == 'class':
268 |                 name_node = class_node.child_by_field_name('name')
269 |                 if not name_node: continue
270 |                 name = self._get_node_text(name_node)
271 |                 bases = []
272 |                 heritage_node = next((child for child in class_node.children if child.type == 'class_heritage'), None)
273 |                 if heritage_node:
274 |                     if heritage_node.named_child_count > 0:
275 |                         base_expr_node = heritage_node.named_child(0)
276 |                         bases.append(self._get_node_text(base_expr_node))
277 |                     elif heritage_node.child_count > 0:
278 |                         base_expr_node = heritage_node.child(heritage_node.child_count - 1)
279 |                         bases.append(self._get_node_text(base_expr_node))
280 |                 class_data = {
281 |                     "name": name,
282 |                     "line_number": class_node.start_point[0] + 1,
283 |                     "end_line": class_node.end_point[0] + 1,
284 |                     "bases": bases,
285 |                     "source": self._get_node_text(class_node),
286 |                     "docstring": self._get_docstring(class_node),
287 |                     "context": None,
288 |                     "decorators": [],
289 |                     "lang": self.language_name,
290 |                     "is_dependency": False,
291 |                 }
292 |                 classes.append(class_data)
293 |         return classes
294 |     
295 |     def _find_interfaces(self, root_node):
296 |         interfaces = []
297 |         query = self.queries['interfaces']
298 |         for node, capture_name in query.captures(root_node):
299 |             if capture_name == 'interface_node':
300 |                 name_node = node.child_by_field_name('name')
301 |                 if not name_node: continue
302 |                 
303 |                 name = self._get_node_text(name_node)
304 |                 interface_data = {
305 |                     "name": name,
306 |                     "line_number": node.start_point[0] + 1,
307 |                     "end_line": node.end_point[0] + 1,
308 |                     "source_code": self._get_node_text(node),
309 |                 }
310 |                 interfaces.append(interface_data)
311 |         return interfaces
312 | 
313 |     def _find_type_aliases(self, root_node):
314 |         type_aliases = []
315 |         query = self.queries['type_aliases']
316 |         for node, capture_name in query.captures(root_node):
317 |             if capture_name == 'type_alias_node':
318 |                 name_node = node.child_by_field_name('name')
319 |                 if not name_node: continue
320 | 
321 |                 name = self._get_node_text(name_node)
322 |                 type_alias_data = {
323 |                     "name": name,
324 |                     "line_number": node.start_point[0] + 1,
325 |                     "end_line": node.end_point[0] + 1,
326 |                     "source_code": self._get_node_text(node),
327 |                 }
328 |                 type_aliases.append(type_alias_data)
329 |         return type_aliases
330 | 
331 |     def _find_imports(self, root_node):
332 |         imports = []
333 |         query = self.queries['imports']
334 |         for node, capture_name in query.captures(root_node):
335 |             if capture_name != 'import':
336 |                 continue
337 |             line_number = node.start_point[0] + 1
338 |             if node.type == 'import_statement':
339 |                 source = self._get_node_text(node.child_by_field_name('source')).strip('\'"')
340 |                 import_clause = node.child_by_field_name('import')
341 |                 if not import_clause:
342 |                     imports.append({'name': source, 'source': source, 'alias': None, 'line_number': line_number,
343 |                                     'lang': self.language_name})
344 |                     continue
345 |                 if import_clause.type == 'identifier':
346 |                     alias = self._get_node_text(import_clause)
347 |                     imports.append({'name': 'default', 'source': source, 'alias': alias, 'line_number': line_number,
348 |                                     'lang': self.language_name})
349 |                 elif import_clause.type == 'namespace_import':
350 |                     alias_node = import_clause.child_by_field_name('alias')
351 |                     if alias_node:
352 |                         alias = self._get_node_text(alias_node)
353 |                         imports.append({'name': '*', 'source': source, 'alias': alias, 'line_number': line_number,
354 |                                         'lang': self.language_name})
355 |                 elif import_clause.type == 'named_imports':
356 |                     for specifier in import_clause.children:
357 |                         if specifier.type == 'import_specifier':
358 |                             name_node = specifier.child_by_field_name('name')
359 |                             alias_node = specifier.child_by_field_name('alias')
360 |                             original_name = self._get_node_text(name_node)
361 |                             alias = self._get_node_text(alias_node) if alias_node else None
362 |                             imports.append(
363 |                                 {'name': original_name, 'source': source, 'alias': alias, 'line_number': line_number,
364 |                                  'lang': self.language_name})
365 |             elif node.type == 'call_expression':
366 |                 args = node.child_by_field_name('arguments')
367 |                 if not args or args.named_child_count == 0: continue
368 |                 source_node = args.named_child(0)
369 |                 if not source_node or source_node.type != 'string': continue
370 |                 source = self._get_node_text(source_node).strip('\'"')
371 |                 alias = None
372 |                 if node.parent.type == 'variable_declarator':
373 |                     alias_node = node.parent.child_by_field_name('name')
374 |                     if alias_node:
375 |                         alias = self._get_node_text(alias_node)
376 |                 imports.append({'name': source, 'source': source, 'alias': alias, 'line_number': line_number,
377 |                                 'lang': self.language_name})
378 |         return imports
379 | 
380 |     def _find_calls(self, root_node):
381 |         calls = []
382 |         query = self.queries['calls']
383 |         for node, capture_name in query.captures(root_node):
384 |             if capture_name == 'name':
385 |                 call_node = node.parent
386 |                 name = self._get_node_text(node)
387 |                 args = []
388 |                 call_data = {
389 |                     "name": name,
390 |                     "full_name": self._get_node_text(call_node),
391 |                     "line_number": node.start_point[0] + 1,
392 |                     "args": args,
393 |                     "inferred_obj_type": None,
394 |                     "context": None,
395 |                     "class_context": None,
396 |                     "lang": self.language_name,
397 |                     "is_dependency": False,
398 |                 }
399 |                 calls.append(call_data)
400 |         return calls
401 | 
402 |     def _find_variables(self, root_node):
403 |         variables = []
404 |         query = self.queries['variables']
405 |         for match in query.captures(root_node):
406 |             capture_name = match[1]
407 |             node = match[0]
408 |             if capture_name == 'name':
409 |                 var_node = node.parent
410 |                 name = self._get_node_text(node)
411 |                 value = None
412 |                 type_text = None
413 |                 variable_data = {
414 |                     "name": name,
415 |                     "line_number": node.start_point[0] + 1,
416 |                     "value": value,
417 |                     "type": type_text,
418 |                     "context": None,
419 |                     "class_context": None,
420 |                     "lang": self.language_name,
421 |                     "is_dependency": False,
422 |                 }
423 |                 variables.append(variable_data)
424 |         return variables
425 | 
426 | def pre_scan_typescript(files: list[Path], parser_wrapper) -> dict:
427 |     """Scans TypeScript files to create a map of class/function names to their file paths."""
428 |     imports_map = {}
429 |     
430 |     # Simplified queries that capture the parent nodes, then extract names manually
431 |     query_strings = [
432 |         "(class_declaration) @class",
433 |         "(function_declaration) @function",
434 |         "(variable_declarator) @var_decl",
435 |         "(method_definition) @method",
436 |         "(interface_declaration) @interface",
437 |         "(type_alias_declaration) @type_alias",
438 |     ]
439 |     
440 |     for file_path in files:
441 |         try:
442 |             with open(file_path, "r", encoding="utf-8") as f:
443 |                 source_code = f.read()
444 |                 tree = parser_wrapper.parser.parse(bytes(source_code, "utf8"))
445 |             
446 |             # Run each query separately
447 |             for query_str in query_strings:
448 |                 try:
449 |                     query = parser_wrapper.language.query(query_str)
450 |                     for node, capture_name in query.captures(tree.root_node):
451 |                         name = None
452 |                         
453 |                         # Extract name based on node type
454 |                         if capture_name == 'class':
455 |                             name_node = node.child_by_field_name('name')
456 |                             if name_node:
457 |                                 name = name_node.text.decode('utf-8')
458 |                         
459 |                         elif capture_name == 'function':
460 |                             name_node = node.child_by_field_name('name')
461 |                             if name_node:
462 |                                 name = name_node.text.decode('utf-8')
463 |                         
464 |                         elif capture_name == 'var_decl':
465 |                             # Check if it's a function or arrow function
466 |                             name_node = node.child_by_field_name('name')
467 |                             value_node = node.child_by_field_name('value')
468 |                             if name_node and value_node:
469 |                                 if value_node.type in ('function', 'arrow_function'):
470 |                                     name = name_node.text.decode('utf-8')
471 |                         
472 |                         elif capture_name == 'method':
473 |                             name_node = node.child_by_field_name('name')
474 |                             if name_node:
475 |                                 name = name_node.text.decode('utf-8')
476 |                         
477 |                         elif capture_name == 'interface':
478 |                             name_node = node.child_by_field_name('name')
479 |                             if name_node:
480 |                                 name = name_node.text.decode('utf-8')
481 |                         
482 |                         elif capture_name == 'type_alias':
483 |                             name_node = node.child_by_field_name('name')
484 |                             if name_node:
485 |                                 name = name_node.text.decode('utf-8')
486 |                         
487 |                         # Add to imports map if we found a name
488 |                         if name:
489 |                             if name not in imports_map:
490 |                                 imports_map[name] = []
491 |                             file_path_str = str(file_path.resolve())
492 |                             if file_path_str not in imports_map[name]:
493 |                                 imports_map[name].append(file_path_str)
494 |                                 
495 |                 except Exception as query_error:
496 |                     warning_logger(f"Query failed for pattern '{query_str}': {query_error}")
497 |                     
498 |         except Exception as e:
499 |             warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
500 |     
501 |     return imports_map
```

--------------------------------------------------------------------------------
/docs/site/architecture/index.html:
--------------------------------------------------------------------------------

```html
  1 | 
  2 | <!doctype html>
  3 | <html lang="en" class="no-js">
  4 |   <head>
  5 |     
  6 |       <meta charset="utf-8">
  7 |       <meta name="viewport" content="width=device-width,initial-scale=1">
  8 |       
  9 |       
 10 |       
 11 |       
 12 |         <link rel="prev" href="../use_cases/">
 13 |       
 14 |       
 15 |         <link rel="next" href="../cli/">
 16 |       
 17 |       
 18 |       <link rel="icon" href="../assets/images/favicon.png">
 19 |       <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
 20 |     
 21 |     
 22 |       
 23 |         <title>Architecture - CodeGraphContext</title>
 24 |       
 25 |     
 26 |     
 27 |       <link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
 28 |       
 29 |       
 30 | 
 31 | 
 32 |     
 33 |     
 34 |       
 35 |     
 36 |     
 37 |       
 38 |         
 39 |         
 40 |         <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 41 |         <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
 42 |         <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
 43 |       
 44 |     
 45 |     
 46 |     <script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
 47 |     
 48 |       
 49 | 
 50 |     
 51 |     
 52 |     
 53 |   </head>
 54 |   
 55 |   
 56 |     <body dir="ltr">
 57 |   
 58 |     
 59 |     <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
 60 |     <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
 61 |     <label class="md-overlay" for="__drawer"></label>
 62 |     <div data-md-component="skip">
 63 |       
 64 |         
 65 |         <a href="#architecture-documentation" class="md-skip">
 66 |           Skip to content
 67 |         </a>
 68 |       
 69 |     </div>
 70 |     <div data-md-component="announce">
 71 |       
 72 |     </div>
 73 |     
 74 |     
 75 |       
 76 | 
 77 |   
 78 | 
 79 | <header class="md-header md-header--shadow" data-md-component="header">
 80 |   <nav class="md-header__inner md-grid" aria-label="Header">
 81 |     <a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
 82 |       
 83 |   
 84 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
 85 | 
 86 |     </a>
 87 |     <label class="md-header__button md-icon" for="__drawer">
 88 |       
 89 |       <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
 90 |     </label>
 91 |     <div class="md-header__title" data-md-component="header-title">
 92 |       <div class="md-header__ellipsis">
 93 |         <div class="md-header__topic">
 94 |           <span class="md-ellipsis">
 95 |             CodeGraphContext
 96 |           </span>
 97 |         </div>
 98 |         <div class="md-header__topic" data-md-component="header-topic">
 99 |           <span class="md-ellipsis">
100 |             
101 |               Architecture
102 |             
103 |           </span>
104 |         </div>
105 |       </div>
106 |     </div>
107 |     
108 |     
109 |       <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
110 |     
111 |     
112 |     
113 |       
114 |       
115 |         <label class="md-header__button md-icon" for="__search">
116 |           
117 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
118 |         </label>
119 |         <div class="md-search" data-md-component="search" role="dialog">
120 |   <label class="md-search__overlay" for="__search"></label>
121 |   <div class="md-search__inner" role="search">
122 |     <form class="md-search__form" name="search">
123 |       <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
124 |       <label class="md-search__icon md-icon" for="__search">
125 |         
126 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
127 |         
128 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
129 |       </label>
130 |       <nav class="md-search__options" aria-label="Search">
131 |         
132 |         <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
133 |           
134 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
135 |         </button>
136 |       </nav>
137 |       
138 |     </form>
139 |     <div class="md-search__output">
140 |       <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
141 |         <div class="md-search-result" data-md-component="search-result">
142 |           <div class="md-search-result__meta">
143 |             Initializing search
144 |           </div>
145 |           <ol class="md-search-result__list" role="presentation"></ol>
146 |         </div>
147 |       </div>
148 |     </div>
149 |   </div>
150 | </div>
151 |       
152 |     
153 |     
154 |   </nav>
155 |   
156 | </header>
157 |     
158 |     <div class="md-container" data-md-component="container">
159 |       
160 |       
161 |         
162 |           
163 |         
164 |       
165 |       <main class="md-main" data-md-component="main">
166 |         <div class="md-main__inner md-grid">
167 |           
168 |             
169 |               
170 |               <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
171 |                 <div class="md-sidebar__scrollwrap">
172 |                   <div class="md-sidebar__inner">
173 |                     
174 | 
175 | 
176 | 
177 | <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
178 |   <label class="md-nav__title" for="__drawer">
179 |     <a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
180 |       
181 |   
182 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
183 | 
184 |     </a>
185 |     CodeGraphContext
186 |   </label>
187 |   
188 |   <ul class="md-nav__list" data-md-scrollfix>
189 |     
190 |       
191 |       
192 |   
193 |   
194 |   
195 |   
196 |     <li class="md-nav__item">
197 |       <a href=".." class="md-nav__link">
198 |         
199 |   
200 |   
201 |   <span class="md-ellipsis">
202 |     Home
203 |     
204 |   </span>
205 |   
206 | 
207 |       </a>
208 |     </li>
209 |   
210 | 
211 |     
212 |       
213 |       
214 |   
215 |   
216 |   
217 |   
218 |     <li class="md-nav__item">
219 |       <a href="../installation/" class="md-nav__link">
220 |         
221 |   
222 |   
223 |   <span class="md-ellipsis">
224 |     Installation
225 |     
226 |   </span>
227 |   
228 | 
229 |       </a>
230 |     </li>
231 |   
232 | 
233 |     
234 |       
235 |       
236 |   
237 |   
238 |   
239 |   
240 |     <li class="md-nav__item">
241 |       <a href="../use_cases/" class="md-nav__link">
242 |         
243 |   
244 |   
245 |   <span class="md-ellipsis">
246 |     Use Cases
247 |     
248 |   </span>
249 |   
250 | 
251 |       </a>
252 |     </li>
253 |   
254 | 
255 |     
256 |       
257 |       
258 |   
259 |   
260 |     
261 |   
262 |   
263 |   
264 |     <li class="md-nav__item md-nav__item--active">
265 |       
266 |       <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
267 |       
268 |       
269 |         
270 |       
271 |       
272 |         <label class="md-nav__link md-nav__link--active" for="__toc">
273 |           
274 |   
275 |   
276 |   <span class="md-ellipsis">
277 |     Architecture
278 |     
279 |   </span>
280 |   
281 | 
282 |           <span class="md-nav__icon md-icon"></span>
283 |         </label>
284 |       
285 |       <a href="./" class="md-nav__link md-nav__link--active">
286 |         
287 |   
288 |   
289 |   <span class="md-ellipsis">
290 |     Architecture
291 |     
292 |   </span>
293 |   
294 | 
295 |       </a>
296 |       
297 |         
298 | 
299 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
300 |   
301 |   
302 |   
303 |     
304 |   
305 |   
306 |     <label class="md-nav__title" for="__toc">
307 |       <span class="md-nav__icon md-icon"></span>
308 |       Table of contents
309 |     </label>
310 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
311 |       
312 |         <li class="md-nav__item">
313 |   <a href="#high-level-overview" class="md-nav__link">
314 |     <span class="md-ellipsis">
315 |       High-Level Overview
316 |     </span>
317 |   </a>
318 |   
319 | </li>
320 |       
321 |         <li class="md-nav__item">
322 |   <a href="#backend-architecture" class="md-nav__link">
323 |     <span class="md-ellipsis">
324 |       Backend Architecture
325 |     </span>
326 |   </a>
327 |   
328 |     <nav class="md-nav" aria-label="Backend Architecture">
329 |       <ul class="md-nav__list">
330 |         
331 |           <li class="md-nav__item">
332 |   <a href="#core-components" class="md-nav__link">
333 |     <span class="md-ellipsis">
334 |       Core Components
335 |     </span>
336 |   </a>
337 |   
338 | </li>
339 |         
340 |           <li class="md-nav__item">
341 |   <a href="#tools" class="md-nav__link">
342 |     <span class="md-ellipsis">
343 |       Tools
344 |     </span>
345 |   </a>
346 |   
347 | </li>
348 |         
349 |           <li class="md-nav__item">
350 |   <a href="#server" class="md-nav__link">
351 |     <span class="md-ellipsis">
352 |       Server
353 |     </span>
354 |   </a>
355 |   
356 | </li>
357 |         
358 |           <li class="md-nav__item">
359 |   <a href="#cli" class="md-nav__link">
360 |     <span class="md-ellipsis">
361 |       CLI
362 |     </span>
363 |   </a>
364 |   
365 | </li>
366 |         
367 |       </ul>
368 |     </nav>
369 |   
370 | </li>
371 |       
372 |         <li class="md-nav__item">
373 |   <a href="#frontend-architecture" class="md-nav__link">
374 |     <span class="md-ellipsis">
375 |       Frontend Architecture
376 |     </span>
377 |   </a>
378 |   
379 | </li>
380 |       
381 |         <li class="md-nav__item">
382 |   <a href="#testing" class="md-nav__link">
383 |     <span class="md-ellipsis">
384 |       Testing
385 |     </span>
386 |   </a>
387 |   
388 | </li>
389 |       
390 |     </ul>
391 |   
392 | </nav>
393 |       
394 |     </li>
395 |   
396 | 
397 |     
398 |       
399 |       
400 |   
401 |   
402 |   
403 |   
404 |     <li class="md-nav__item">
405 |       <a href="../cli/" class="md-nav__link">
406 |         
407 |   
408 |   
409 |   <span class="md-ellipsis">
410 |     CLI Reference
411 |     
412 |   </span>
413 |   
414 | 
415 |       </a>
416 |     </li>
417 |   
418 | 
419 |     
420 |       
421 |       
422 |   
423 |   
424 |   
425 |   
426 |     <li class="md-nav__item">
427 |       <a href="../server/" class="md-nav__link">
428 |         
429 |   
430 |   
431 |   <span class="md-ellipsis">
432 |     Server
433 |     
434 |   </span>
435 |   
436 | 
437 |       </a>
438 |     </li>
439 |   
440 | 
441 |     
442 |       
443 |       
444 |   
445 |   
446 |   
447 |   
448 |     <li class="md-nav__item">
449 |       <a href="../core/" class="md-nav__link">
450 |         
451 |   
452 |   
453 |   <span class="md-ellipsis">
454 |     Core Concepts
455 |     
456 |   </span>
457 |   
458 | 
459 |       </a>
460 |     </li>
461 |   
462 | 
463 |     
464 |       
465 |       
466 |   
467 |   
468 |   
469 |   
470 |     <li class="md-nav__item">
471 |       <a href="../tools/" class="md-nav__link">
472 |         
473 |   
474 |   
475 |   <span class="md-ellipsis">
476 |     Tools
477 |     
478 |   </span>
479 |   
480 | 
481 |       </a>
482 |     </li>
483 |   
484 | 
485 |     
486 |       
487 |       
488 |   
489 |   
490 |   
491 |   
492 |     <li class="md-nav__item">
493 |       <a href="../cookbook/" class="md-nav__link">
494 |         
495 |   
496 |   
497 |   <span class="md-ellipsis">
498 |     Cookbook
499 |     
500 |   </span>
501 |   
502 | 
503 |       </a>
504 |     </li>
505 |   
506 | 
507 |     
508 |       
509 |       
510 |   
511 |   
512 |   
513 |   
514 |     
515 |     
516 |     
517 |     
518 |     
519 |     <li class="md-nav__item md-nav__item--nested">
520 |       
521 |         
522 |         
523 |         <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
524 |         
525 |           
526 |           <label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
527 |             
528 |   
529 |   
530 |   <span class="md-ellipsis">
531 |     Contributing
532 |     
533 |   </span>
534 |   
535 | 
536 |             <span class="md-nav__icon md-icon"></span>
537 |           </label>
538 |         
539 |         <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
540 |           <label class="md-nav__title" for="__nav_10">
541 |             <span class="md-nav__icon md-icon"></span>
542 |             Contributing
543 |           </label>
544 |           <ul class="md-nav__list" data-md-scrollfix>
545 |             
546 |               
547 |                 
548 |   
549 |   
550 |   
551 |   
552 |     <li class="md-nav__item">
553 |       <a href="../contributing/" class="md-nav__link">
554 |         
555 |   
556 |   
557 |   <span class="md-ellipsis">
558 |     Overview
559 |     
560 |   </span>
561 |   
562 | 
563 |       </a>
564 |     </li>
565 |   
566 | 
567 |               
568 |             
569 |               
570 |                 
571 |   
572 |   
573 |   
574 |   
575 |     <li class="md-nav__item">
576 |       <a href="../contributing_languages/" class="md-nav__link">
577 |         
578 |   
579 |   
580 |   <span class="md-ellipsis">
581 |     Adding New Languages
582 |     
583 |   </span>
584 |   
585 | 
586 |       </a>
587 |     </li>
588 |   
589 | 
590 |               
591 |             
592 |           </ul>
593 |         </nav>
594 |       
595 |     </li>
596 |   
597 | 
598 |     
599 |       
600 |       
601 |   
602 |   
603 |   
604 |   
605 |     <li class="md-nav__item">
606 |       <a href="../troubleshooting/" class="md-nav__link">
607 |         
608 |   
609 |   
610 |   <span class="md-ellipsis">
611 |     Troubleshooting
612 |     
613 |   </span>
614 |   
615 | 
616 |       </a>
617 |     </li>
618 |   
619 | 
620 |     
621 |       
622 |       
623 |   
624 |   
625 |   
626 |   
627 |     <li class="md-nav__item">
628 |       <a href="../future_work/" class="md-nav__link">
629 |         
630 |   
631 |   
632 |   <span class="md-ellipsis">
633 |     Future Work
634 |     
635 |   </span>
636 |   
637 | 
638 |       </a>
639 |     </li>
640 |   
641 | 
642 |     
643 |       
644 |       
645 |   
646 |   
647 |   
648 |   
649 |     <li class="md-nav__item">
650 |       <a href="../license/" class="md-nav__link">
651 |         
652 |   
653 |   
654 |   <span class="md-ellipsis">
655 |     License
656 |     
657 |   </span>
658 |   
659 | 
660 |       </a>
661 |     </li>
662 |   
663 | 
664 |     
665 |   </ul>
666 | </nav>
667 |                   </div>
668 |                 </div>
669 |               </div>
670 |             
671 |             
672 |               
673 |               <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
674 |                 <div class="md-sidebar__scrollwrap">
675 |                   <div class="md-sidebar__inner">
676 |                     
677 | 
678 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
679 |   
680 |   
681 |   
682 |     
683 |   
684 |   
685 |     <label class="md-nav__title" for="__toc">
686 |       <span class="md-nav__icon md-icon"></span>
687 |       Table of contents
688 |     </label>
689 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
690 |       
691 |         <li class="md-nav__item">
692 |   <a href="#high-level-overview" class="md-nav__link">
693 |     <span class="md-ellipsis">
694 |       High-Level Overview
695 |     </span>
696 |   </a>
697 |   
698 | </li>
699 |       
700 |         <li class="md-nav__item">
701 |   <a href="#backend-architecture" class="md-nav__link">
702 |     <span class="md-ellipsis">
703 |       Backend Architecture
704 |     </span>
705 |   </a>
706 |   
707 |     <nav class="md-nav" aria-label="Backend Architecture">
708 |       <ul class="md-nav__list">
709 |         
710 |           <li class="md-nav__item">
711 |   <a href="#core-components" class="md-nav__link">
712 |     <span class="md-ellipsis">
713 |       Core Components
714 |     </span>
715 |   </a>
716 |   
717 | </li>
718 |         
719 |           <li class="md-nav__item">
720 |   <a href="#tools" class="md-nav__link">
721 |     <span class="md-ellipsis">
722 |       Tools
723 |     </span>
724 |   </a>
725 |   
726 | </li>
727 |         
728 |           <li class="md-nav__item">
729 |   <a href="#server" class="md-nav__link">
730 |     <span class="md-ellipsis">
731 |       Server
732 |     </span>
733 |   </a>
734 |   
735 | </li>
736 |         
737 |           <li class="md-nav__item">
738 |   <a href="#cli" class="md-nav__link">
739 |     <span class="md-ellipsis">
740 |       CLI
741 |     </span>
742 |   </a>
743 |   
744 | </li>
745 |         
746 |       </ul>
747 |     </nav>
748 |   
749 | </li>
750 |       
751 |         <li class="md-nav__item">
752 |   <a href="#frontend-architecture" class="md-nav__link">
753 |     <span class="md-ellipsis">
754 |       Frontend Architecture
755 |     </span>
756 |   </a>
757 |   
758 | </li>
759 |       
760 |         <li class="md-nav__item">
761 |   <a href="#testing" class="md-nav__link">
762 |     <span class="md-ellipsis">
763 |       Testing
764 |     </span>
765 |   </a>
766 |   
767 | </li>
768 |       
769 |     </ul>
770 |   
771 | </nav>
772 |                   </div>
773 |                 </div>
774 |               </div>
775 |             
776 |           
777 |           
778 |             <div class="md-content" data-md-component="content">
779 |               <article class="md-content__inner md-typeset">
780 |                 
781 |                   
782 | 
783 | 
784 | 
785 | <h1 id="architecture-documentation">Architecture Documentation</h1>
786 | <p>This document provides a detailed overview of the architecture of the CodeGraphContext project.</p>
787 | <h2 id="high-level-overview">High-Level Overview</h2>
788 | <p>The project is a client-server application designed to analyze and visualize codebases. It consists of:</p>
789 | <ul>
790 | <li><strong>A Python backend:</strong> This is the core of the application, responsible for parsing and analyzing code, building a graph representation of the codebase, and exposing this data through an API.</li>
791 | <li><strong>A web-based frontend:</strong> A user interface for interacting with the backend, visualizing the code graph, and exploring the codebase.</li>
792 | <li><strong>A command-line interface (CLI):</strong> For managing the backend and performing analysis from the terminal.</li>
793 | </ul>
794 | <h2 id="backend-architecture">Backend Architecture</h2>
795 | <p>The backend is a Python application located in the <code>src/codegraphcontext</code> directory.</p>
796 | <h3 id="core-components">Core Components</h3>
797 | <p>The <code>src/codegraphcontext/core</code> directory contains the fundamental building blocks of the backend:</p>
798 | <ul>
799 | <li><strong>Database:</strong> A graph database is used to store the code graph. This allows for efficient querying of relationships between code elements (e.g., function calls, class inheritance).</li>
800 | <li><strong>Jobs:</strong> Asynchronous jobs are used for long-running tasks like indexing a new codebase. This prevents the application from becoming unresponsive.</li>
801 | <li><strong>Watcher:</strong> A file system watcher monitors the codebase for changes and triggers re-indexing, keeping the code graph up-to-date.</li>
802 | </ul>
803 | <h3 id="tools">Tools</h3>
804 | <p>The <code>src/codegraphcontext/tools</code> directory contains the logic for code analysis:</p>
805 | <ul>
806 | <li><strong>Graph Builder:</strong> This component is responsible for parsing the code and building the graph representation that is stored in the database.</li>
807 | <li><strong>Code Finder:</strong> Provides functionality to search for specific code elements within the indexed codebase.</li>
808 | <li><strong>Import Extractor:</strong> This tool analyzes the import statements in the code to understand dependencies between modules.</li>
809 | </ul>
810 | <h3 id="server">Server</h3>
811 | <p>The <code>src/codegraphcontext/server.py</code> file implements the API server. It exposes the functionality of the backend to the frontend through a JSON-RPC API.</p>
812 | <h3 id="cli">CLI</h3>
813 | <p>The <code>src/codegraphcontext/cli</code> directory contains the implementation of the command-line interface. It allows users to:</p>
814 | <ul>
815 | <li>Start and stop the backend server.</li>
816 | <li>Index new projects.</li>
817 | <li>Run analysis tools from the command line.</li>
818 | </ul>
819 | <h2 id="frontend-architecture">Frontend Architecture</h2>
820 | <p>The frontend is a modern web application located in the <code>website/</code> directory.</p>
821 | <ul>
822 | <li><strong>Framework:</strong> It is built using React and TypeScript.</li>
823 | <li><strong>Build Tool:</strong> Vite is used for fast development and building the application.</li>
824 | <li><strong>Component-Based:</strong> The UI is organized into reusable components, located in <code>website/src/components</code>. This includes UI elements like buttons and dialogs, as well as higher-level components for different sections of the application.</li>
825 | <li><strong>Styling:</strong> Tailwind CSS is used for styling the application.</li>
826 | </ul>
827 | <h2 id="testing">Testing</h2>
828 | <p>The <code>tests/</code> directory contains the test suite for the project.</p>
829 | <ul>
830 | <li><strong>Integration Tests:</strong> <code>test_cgc_integration.py</code> contains tests that verify the interaction between different components of the backend.</li>
831 | <li><strong>Unit Tests:</strong> Other files in this directory contain unit tests for specific modules and functions.</li>
832 | <li><strong>Sample Project:</strong> The <code>tests/sample_project</code> directory contains a variety of Python files used as input for testing the code analysis tools.</li>
833 | </ul>
834 | 
835 | 
836 | 
837 | 
838 | 
839 | 
840 | 
841 | 
842 | 
843 | 
844 | 
845 | 
846 |                 
847 |               </article>
848 |             </div>
849 |           
850 |           
851 | <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
852 |         </div>
853 |         
854 |       </main>
855 |       
856 |         <footer class="md-footer">
857 |   
858 |   <div class="md-footer-meta md-typeset">
859 |     <div class="md-footer-meta__inner md-grid">
860 |       <div class="md-copyright">
861 |   
862 |   
863 |     Made with
864 |     <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
865 |       Material for MkDocs
866 |     </a>
867 |   
868 | </div>
869 |       
870 |     </div>
871 |   </div>
872 | </footer>
873 |       
874 |     </div>
875 |     <div class="md-dialog" data-md-component="dialog">
876 |       <div class="md-dialog__inner md-typeset"></div>
877 |     </div>
878 |     
879 |     
880 |     
881 |       
882 |       <script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
883 |     
884 |     
885 |       <script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
886 |       
887 |     
888 |   </body>
889 | </html>
```

--------------------------------------------------------------------------------
/docs/site/installation/index.html:
--------------------------------------------------------------------------------

```html
  1 | 
  2 | <!doctype html>
  3 | <html lang="en" class="no-js">
  4 |   <head>
  5 |     
  6 |       <meta charset="utf-8">
  7 |       <meta name="viewport" content="width=device-width,initial-scale=1">
  8 |       
  9 |       
 10 |       
 11 |       
 12 |         <link rel="prev" href="..">
 13 |       
 14 |       
 15 |         <link rel="next" href="../use_cases/">
 16 |       
 17 |       
 18 |       <link rel="icon" href="../assets/images/favicon.png">
 19 |       <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
 20 |     
 21 |     
 22 |       
 23 |         <title>Installation - CodeGraphContext</title>
 24 |       
 25 |     
 26 |     
 27 |       <link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
 28 |       
 29 |       
 30 | 
 31 | 
 32 |     
 33 |     
 34 |       
 35 |     
 36 |     
 37 |       
 38 |         
 39 |         
 40 |         <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
 41 |         <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
 42 |         <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
 43 |       
 44 |     
 45 |     
 46 |     <script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
 47 |     
 48 |       
 49 | 
 50 |     
 51 |     
 52 |     
 53 |   </head>
 54 |   
 55 |   
 56 |     <body dir="ltr">
 57 |   
 58 |     
 59 |     <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
 60 |     <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
 61 |     <label class="md-overlay" for="__drawer"></label>
 62 |     <div data-md-component="skip">
 63 |       
 64 |         
 65 |         <a href="#installation-guide" class="md-skip">
 66 |           Skip to content
 67 |         </a>
 68 |       
 69 |     </div>
 70 |     <div data-md-component="announce">
 71 |       
 72 |     </div>
 73 |     
 74 |     
 75 |       
 76 | 
 77 |   
 78 | 
 79 | <header class="md-header md-header--shadow" data-md-component="header">
 80 |   <nav class="md-header__inner md-grid" aria-label="Header">
 81 |     <a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
 82 |       
 83 |   
 84 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
 85 | 
 86 |     </a>
 87 |     <label class="md-header__button md-icon" for="__drawer">
 88 |       
 89 |       <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
 90 |     </label>
 91 |     <div class="md-header__title" data-md-component="header-title">
 92 |       <div class="md-header__ellipsis">
 93 |         <div class="md-header__topic">
 94 |           <span class="md-ellipsis">
 95 |             CodeGraphContext
 96 |           </span>
 97 |         </div>
 98 |         <div class="md-header__topic" data-md-component="header-topic">
 99 |           <span class="md-ellipsis">
100 |             
101 |               Installation
102 |             
103 |           </span>
104 |         </div>
105 |       </div>
106 |     </div>
107 |     
108 |     
109 |       <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
110 |     
111 |     
112 |     
113 |       
114 |       
115 |         <label class="md-header__button md-icon" for="__search">
116 |           
117 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
118 |         </label>
119 |         <div class="md-search" data-md-component="search" role="dialog">
120 |   <label class="md-search__overlay" for="__search"></label>
121 |   <div class="md-search__inner" role="search">
122 |     <form class="md-search__form" name="search">
123 |       <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
124 |       <label class="md-search__icon md-icon" for="__search">
125 |         
126 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
127 |         
128 |         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
129 |       </label>
130 |       <nav class="md-search__options" aria-label="Search">
131 |         
132 |         <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
133 |           
134 |           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
135 |         </button>
136 |       </nav>
137 |       
138 |     </form>
139 |     <div class="md-search__output">
140 |       <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
141 |         <div class="md-search-result" data-md-component="search-result">
142 |           <div class="md-search-result__meta">
143 |             Initializing search
144 |           </div>
145 |           <ol class="md-search-result__list" role="presentation"></ol>
146 |         </div>
147 |       </div>
148 |     </div>
149 |   </div>
150 | </div>
151 |       
152 |     
153 |     
154 |   </nav>
155 |   
156 | </header>
157 |     
158 |     <div class="md-container" data-md-component="container">
159 |       
160 |       
161 |         
162 |           
163 |         
164 |       
165 |       <main class="md-main" data-md-component="main">
166 |         <div class="md-main__inner md-grid">
167 |           
168 |             
169 |               
170 |               <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
171 |                 <div class="md-sidebar__scrollwrap">
172 |                   <div class="md-sidebar__inner">
173 |                     
174 | 
175 | 
176 | 
177 | <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
178 |   <label class="md-nav__title" for="__drawer">
179 |     <a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
180 |       
181 |   
182 |   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg>
183 | 
184 |     </a>
185 |     CodeGraphContext
186 |   </label>
187 |   
188 |   <ul class="md-nav__list" data-md-scrollfix>
189 |     
190 |       
191 |       
192 |   
193 |   
194 |   
195 |   
196 |     <li class="md-nav__item">
197 |       <a href=".." class="md-nav__link">
198 |         
199 |   
200 |   
201 |   <span class="md-ellipsis">
202 |     Home
203 |     
204 |   </span>
205 |   
206 | 
207 |       </a>
208 |     </li>
209 |   
210 | 
211 |     
212 |       
213 |       
214 |   
215 |   
216 |     
217 |   
218 |   
219 |   
220 |     <li class="md-nav__item md-nav__item--active">
221 |       
222 |       <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
223 |       
224 |       
225 |       
226 |         <label class="md-nav__link md-nav__link--active" for="__toc">
227 |           
228 |   
229 |   
230 |   <span class="md-ellipsis">
231 |     Installation
232 |     
233 |   </span>
234 |   
235 | 
236 |           <span class="md-nav__icon md-icon"></span>
237 |         </label>
238 |       
239 |       <a href="./" class="md-nav__link md-nav__link--active">
240 |         
241 |   
242 |   
243 |   <span class="md-ellipsis">
244 |     Installation
245 |     
246 |   </span>
247 |   
248 | 
249 |       </a>
250 |       
251 |         
252 | 
253 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
254 |   
255 |   
256 |   
257 |   
258 |     <label class="md-nav__title" for="__toc">
259 |       <span class="md-nav__icon md-icon"></span>
260 |       Table of contents
261 |     </label>
262 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
263 |       
264 |         <li class="md-nav__item">
265 |   <a href="#installation-guide" class="md-nav__link">
266 |     <span class="md-ellipsis">
267 |       🧩 Installation Guide
268 |     </span>
269 |   </a>
270 |   
271 | </li>
272 |       
273 |         <li class="md-nav__item">
274 |   <a href="#prerequisites" class="md-nav__link">
275 |     <span class="md-ellipsis">
276 |       ⚙️ Prerequisites
277 |     </span>
278 |   </a>
279 |   
280 | </li>
281 |       
282 |         <li class="md-nav__item">
283 |   <a href="#getting-started" class="md-nav__link">
284 |     <span class="md-ellipsis">
285 |       🚀 Getting Started
286 |     </span>
287 |   </a>
288 |   
289 |     <nav class="md-nav" aria-label="🚀 Getting Started">
290 |       <ul class="md-nav__list">
291 |         
292 |           <li class="md-nav__item">
293 |   <a href="#1-install-from-pypi" class="md-nav__link">
294 |     <span class="md-ellipsis">
295 |       1. Install from PyPI
296 |     </span>
297 |   </a>
298 |   
299 | </li>
300 |         
301 |           <li class="md-nav__item">
302 |   <a href="#2-run-the-setup-wizard" class="md-nav__link">
303 |     <span class="md-ellipsis">
304 |       2. Run the Setup Wizard
305 |     </span>
306 |   </a>
307 |   
308 | </li>
309 |         
310 |       </ul>
311 |     </nav>
312 |   
313 | </li>
314 |       
315 |         <li class="md-nav__item">
316 |   <a href="#step-by-step-guide-for-the-setup-wizard" class="md-nav__link">
317 |     <span class="md-ellipsis">
318 |       🧭 "Step-by-Step Guide for the Setup Wizard"
319 |     </span>
320 |   </a>
321 |   
322 |     <nav class="md-nav" aria-label="🧭 &#34;Step-by-Step Guide for the Setup Wizard&#34;">
323 |       <ul class="md-nav__list">
324 |         
325 |           <li class="md-nav__item">
326 |   <a href="#3-start-the-server" class="md-nav__link">
327 |     <span class="md-ellipsis">
328 |       3. Start the Server
329 |     </span>
330 |   </a>
331 |   
332 | </li>
333 |         
334 |       </ul>
335 |     </nav>
336 |   
337 | </li>
338 |       
339 |         <li class="md-nav__item">
340 |   <a href="#next-steps" class="md-nav__link">
341 |     <span class="md-ellipsis">
342 |       Next Steps
343 |     </span>
344 |   </a>
345 |   
346 | </li>
347 |       
348 |     </ul>
349 |   
350 | </nav>
351 |       
352 |     </li>
353 |   
354 | 
355 |     
356 |       
357 |       
358 |   
359 |   
360 |   
361 |   
362 |     <li class="md-nav__item">
363 |       <a href="../use_cases/" class="md-nav__link">
364 |         
365 |   
366 |   
367 |   <span class="md-ellipsis">
368 |     Use Cases
369 |     
370 |   </span>
371 |   
372 | 
373 |       </a>
374 |     </li>
375 |   
376 | 
377 |     
378 |       
379 |       
380 |   
381 |   
382 |   
383 |   
384 |     <li class="md-nav__item">
385 |       <a href="../architecture/" class="md-nav__link">
386 |         
387 |   
388 |   
389 |   <span class="md-ellipsis">
390 |     Architecture
391 |     
392 |   </span>
393 |   
394 | 
395 |       </a>
396 |     </li>
397 |   
398 | 
399 |     
400 |       
401 |       
402 |   
403 |   
404 |   
405 |   
406 |     <li class="md-nav__item">
407 |       <a href="../cli/" class="md-nav__link">
408 |         
409 |   
410 |   
411 |   <span class="md-ellipsis">
412 |     CLI Reference
413 |     
414 |   </span>
415 |   
416 | 
417 |       </a>
418 |     </li>
419 |   
420 | 
421 |     
422 |       
423 |       
424 |   
425 |   
426 |   
427 |   
428 |     <li class="md-nav__item">
429 |       <a href="../server/" class="md-nav__link">
430 |         
431 |   
432 |   
433 |   <span class="md-ellipsis">
434 |     Server
435 |     
436 |   </span>
437 |   
438 | 
439 |       </a>
440 |     </li>
441 |   
442 | 
443 |     
444 |       
445 |       
446 |   
447 |   
448 |   
449 |   
450 |     <li class="md-nav__item">
451 |       <a href="../core/" class="md-nav__link">
452 |         
453 |   
454 |   
455 |   <span class="md-ellipsis">
456 |     Core Concepts
457 |     
458 |   </span>
459 |   
460 | 
461 |       </a>
462 |     </li>
463 |   
464 | 
465 |     
466 |       
467 |       
468 |   
469 |   
470 |   
471 |   
472 |     <li class="md-nav__item">
473 |       <a href="../tools/" class="md-nav__link">
474 |         
475 |   
476 |   
477 |   <span class="md-ellipsis">
478 |     Tools
479 |     
480 |   </span>
481 |   
482 | 
483 |       </a>
484 |     </li>
485 |   
486 | 
487 |     
488 |       
489 |       
490 |   
491 |   
492 |   
493 |   
494 |     <li class="md-nav__item">
495 |       <a href="../cookbook/" class="md-nav__link">
496 |         
497 |   
498 |   
499 |   <span class="md-ellipsis">
500 |     Cookbook
501 |     
502 |   </span>
503 |   
504 | 
505 |       </a>
506 |     </li>
507 |   
508 | 
509 |     
510 |       
511 |       
512 |   
513 |   
514 |   
515 |   
516 |     
517 |     
518 |     
519 |     
520 |     
521 |     <li class="md-nav__item md-nav__item--nested">
522 |       
523 |         
524 |         
525 |         <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
526 |         
527 |           
528 |           <label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
529 |             
530 |   
531 |   
532 |   <span class="md-ellipsis">
533 |     Contributing
534 |     
535 |   </span>
536 |   
537 | 
538 |             <span class="md-nav__icon md-icon"></span>
539 |           </label>
540 |         
541 |         <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
542 |           <label class="md-nav__title" for="__nav_10">
543 |             <span class="md-nav__icon md-icon"></span>
544 |             Contributing
545 |           </label>
546 |           <ul class="md-nav__list" data-md-scrollfix>
547 |             
548 |               
549 |                 
550 |   
551 |   
552 |   
553 |   
554 |     <li class="md-nav__item">
555 |       <a href="../contributing/" class="md-nav__link">
556 |         
557 |   
558 |   
559 |   <span class="md-ellipsis">
560 |     Overview
561 |     
562 |   </span>
563 |   
564 | 
565 |       </a>
566 |     </li>
567 |   
568 | 
569 |               
570 |             
571 |               
572 |                 
573 |   
574 |   
575 |   
576 |   
577 |     <li class="md-nav__item">
578 |       <a href="../contributing_languages/" class="md-nav__link">
579 |         
580 |   
581 |   
582 |   <span class="md-ellipsis">
583 |     Adding New Languages
584 |     
585 |   </span>
586 |   
587 | 
588 |       </a>
589 |     </li>
590 |   
591 | 
592 |               
593 |             
594 |           </ul>
595 |         </nav>
596 |       
597 |     </li>
598 |   
599 | 
600 |     
601 |       
602 |       
603 |   
604 |   
605 |   
606 |   
607 |     <li class="md-nav__item">
608 |       <a href="../troubleshooting/" class="md-nav__link">
609 |         
610 |   
611 |   
612 |   <span class="md-ellipsis">
613 |     Troubleshooting
614 |     
615 |   </span>
616 |   
617 | 
618 |       </a>
619 |     </li>
620 |   
621 | 
622 |     
623 |       
624 |       
625 |   
626 |   
627 |   
628 |   
629 |     <li class="md-nav__item">
630 |       <a href="../future_work/" class="md-nav__link">
631 |         
632 |   
633 |   
634 |   <span class="md-ellipsis">
635 |     Future Work
636 |     
637 |   </span>
638 |   
639 | 
640 |       </a>
641 |     </li>
642 |   
643 | 
644 |     
645 |       
646 |       
647 |   
648 |   
649 |   
650 |   
651 |     <li class="md-nav__item">
652 |       <a href="../license/" class="md-nav__link">
653 |         
654 |   
655 |   
656 |   <span class="md-ellipsis">
657 |     License
658 |     
659 |   </span>
660 |   
661 | 
662 |       </a>
663 |     </li>
664 |   
665 | 
666 |     
667 |   </ul>
668 | </nav>
669 |                   </div>
670 |                 </div>
671 |               </div>
672 |             
673 |             
674 |               
675 |               <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
676 |                 <div class="md-sidebar__scrollwrap">
677 |                   <div class="md-sidebar__inner">
678 |                     
679 | 
680 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
681 |   
682 |   
683 |   
684 |   
685 |     <label class="md-nav__title" for="__toc">
686 |       <span class="md-nav__icon md-icon"></span>
687 |       Table of contents
688 |     </label>
689 |     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
690 |       
691 |         <li class="md-nav__item">
692 |   <a href="#installation-guide" class="md-nav__link">
693 |     <span class="md-ellipsis">
694 |       🧩 Installation Guide
695 |     </span>
696 |   </a>
697 |   
698 | </li>
699 |       
700 |         <li class="md-nav__item">
701 |   <a href="#prerequisites" class="md-nav__link">
702 |     <span class="md-ellipsis">
703 |       ⚙️ Prerequisites
704 |     </span>
705 |   </a>
706 |   
707 | </li>
708 |       
709 |         <li class="md-nav__item">
710 |   <a href="#getting-started" class="md-nav__link">
711 |     <span class="md-ellipsis">
712 |       🚀 Getting Started
713 |     </span>
714 |   </a>
715 |   
716 |     <nav class="md-nav" aria-label="🚀 Getting Started">
717 |       <ul class="md-nav__list">
718 |         
719 |           <li class="md-nav__item">
720 |   <a href="#1-install-from-pypi" class="md-nav__link">
721 |     <span class="md-ellipsis">
722 |       1. Install from PyPI
723 |     </span>
724 |   </a>
725 |   
726 | </li>
727 |         
728 |           <li class="md-nav__item">
729 |   <a href="#2-run-the-setup-wizard" class="md-nav__link">
730 |     <span class="md-ellipsis">
731 |       2. Run the Setup Wizard
732 |     </span>
733 |   </a>
734 |   
735 | </li>
736 |         
737 |       </ul>
738 |     </nav>
739 |   
740 | </li>
741 |       
742 |         <li class="md-nav__item">
743 |   <a href="#step-by-step-guide-for-the-setup-wizard" class="md-nav__link">
744 |     <span class="md-ellipsis">
745 |       🧭 "Step-by-Step Guide for the Setup Wizard"
746 |     </span>
747 |   </a>
748 |   
749 |     <nav class="md-nav" aria-label="🧭 &#34;Step-by-Step Guide for the Setup Wizard&#34;">
750 |       <ul class="md-nav__list">
751 |         
752 |           <li class="md-nav__item">
753 |   <a href="#3-start-the-server" class="md-nav__link">
754 |     <span class="md-ellipsis">
755 |       3. Start the Server
756 |     </span>
757 |   </a>
758 |   
759 | </li>
760 |         
761 |       </ul>
762 |     </nav>
763 |   
764 | </li>
765 |       
766 |         <li class="md-nav__item">
767 |   <a href="#next-steps" class="md-nav__link">
768 |     <span class="md-ellipsis">
769 |       Next Steps
770 |     </span>
771 |   </a>
772 |   
773 | </li>
774 |       
775 |     </ul>
776 |   
777 | </nav>
778 |                   </div>
779 |                 </div>
780 |               </div>
781 |             
782 |           
783 |           
784 |             <div class="md-content" data-md-component="content">
785 |               <article class="md-content__inner md-typeset">
786 |                 
787 |                   
788 | 
789 | 
790 | 
791 |   <h1>Installation</h1>
792 | 
793 | <h2 id="installation-guide">🧩 Installation Guide</h2>
794 | <p>Welcome to <strong>CodeGraphContext</strong>! This guide provides a clear and seamless path to installing and configuring the tool, from prerequisites to launching your server.</p>
795 | <h2 id="prerequisites">⚙️ Prerequisites</h2>
796 | <p>Ensure the following are installed before you begin:</p>
797 | <ul>
798 | <li><strong>Python</strong>: Version 3.8 or higher.</li>
799 | <li><strong>AI Agentic Coding Tool</strong>: An MCP-compatible AI assistant (e.g., Gemini, Claude) if you plan to use the MCP server.</li>
800 | </ul>
801 | <h2 id="getting-started">🚀 Getting Started</h2>
802 | <p>Follow these steps to set up <strong>CodeGraphContext</strong> effortlessly.</p>
803 | <h3 id="1-install-from-pypi">1. Install from PyPI</h3>
804 | <p>Install the <code>codegraphcontext</code> package directly from PyPI using pip:</p>
805 | <pre><code class="language-bash">pip install codegraphcontext
806 | </code></pre>
807 | <h3 id="2-run-the-setup-wizard">2. Run the Setup Wizard</h3>
808 | <p>Launch the interactive setup wizard to configure your Neo4j database and development environment:</p>
809 | <pre><code class="language-bash">cgc setup
810 | </code></pre>
811 | <p>The wizard guides you through a series of intuitive prompts to tailor your setup.</p>
812 | <h2 id="step-by-step-guide-for-the-setup-wizard">🧭 "Step-by-Step Guide for the Setup Wizard"</h2>
813 | <p>When you run <code>cgc setup</code>, the wizard offers a thoughtful journey through configuration. Follow these steps to complete your setup with ease:</p>
814 | <p><strong>1. Select Your Database Location</strong></p>
815 | <p>Choose where your Neo4j database will reside:</p>
816 | <ul>
817 | <li><strong>Local (Recommended)</strong>: Host Neo4j on your machine for simplicity.  </li>
818 | <li><strong>Docker</strong>: With Docker installed, the wizard crafts a <code>docker-compose.yml</code> file and launches a Neo4j container seamlessly.  </li>
819 | <li><strong>Local Binary</strong>: On Debian-based systems (e.g., Ubuntu) or Mac Systems, the wizard installs Neo4j directly with your permission.  </li>
820 | <li><strong>Hosted</strong>: Connect to a remote Neo4j instance, such as AuraDB, by providing your database URI, username, and password.  </li>
821 | <li><strong>Existing Instance</strong>: For an existing Neo4j server (local or remote), enter its connection credentials.</li>
822 | </ul>
823 | <p><strong>2. Configure Your Development Environment</strong></p>
824 | <p>Integrate CodeGraphContext with your preferred development tool for a harmonious workflow. Select from supported options:</p>
825 | <ul>
826 | <li>VS Code</li>
827 | <li>Cursor</li>
828 | <li>Windsurf</li>
829 | <li>Claude</li>
830 | <li>Gemini CLI</li>
831 | <li>ChatGPT Codex</li>
832 | <li>Cline</li>
833 | <li>RooCode</li>
834 | <li>Amazon Q Developer</li>
835 | </ul>
836 | <p>The wizard automatically updates configuration files to align with your choice.
837 | Upon completing the prompts, the wizard creates two essential files:</p>
838 | <ul>
839 | <li><strong><code>mcp.json</code></strong>: Placed in your working directory, this file configures the MCP server.  </li>
840 | <li><strong><code>.env</code></strong>: Stored securely in <code>~/.codegraphcontext</code>, this file safeguards your Neo4j credentials.</li>
841 | </ul>
842 | <p>These files ensure smooth communication between CodeGraphContext, your Neo4j instance, and your AI assistant.</p>
843 | <h3 id="3-start-the-server">3. Start the Server</h3>
844 | <p>Once configuration is complete, launch the MCP server with:</p>
845 | <pre><code class="language-bash">cgc start
846 | </code></pre>
847 | <p>Your <strong>CodeGraphContext</strong> server is now active, ready to power AI-assisted graph queries.</p>
848 | <h2 id="next-steps">Next Steps</h2>
849 | <p>With <strong>CodeGraphContext</strong> installed and configured, you’re ready to explore its AI-powered capabilities. Happy coding ✨!</p>
850 | 
851 | 
852 | 
853 | 
854 | 
855 | 
856 | 
857 | 
858 | 
859 | 
860 | 
861 | 
862 |                 
863 |               </article>
864 |             </div>
865 |           
866 |           
867 | <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
868 |         </div>
869 |         
870 |       </main>
871 |       
872 |         <footer class="md-footer">
873 |   
874 |   <div class="md-footer-meta md-typeset">
875 |     <div class="md-footer-meta__inner md-grid">
876 |       <div class="md-copyright">
877 |   
878 |   
879 |     Made with
880 |     <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
881 |       Material for MkDocs
882 |     </a>
883 |   
884 | </div>
885 |       
886 |     </div>
887 |   </div>
888 | </footer>
889 |       
890 |     </div>
891 |     <div class="md-dialog" data-md-component="dialog">
892 |       <div class="md-dialog__inner md-typeset"></div>
893 |     </div>
894 |     
895 |     
896 |     
897 |       
898 |       <script id="__config" type="application/json">{"base": "..", "features": [], "search": "../assets/javascripts/workers/search.973d3a69.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
899 |     
900 |     
901 |       <script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
902 |       
903 |     
904 |   </body>
905 | </html>
```
Page 10/18FirstPrevNextLast