This is page 7 of 14. Use http://codebase.md/shashankss1205/codegraphcontext?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
--------------------------------------------------------------------------------
/organizer/cookbook.md:
--------------------------------------------------------------------------------
```markdown
# MCP Tool Cookbook
This cookbook provides examples of how to use the `mcp` tool to query and understand your Python codebase. The "Tool" indicates which `mcp` tool to use, and the "JSON Arguments" are what the LLM would provide to that tool.
---
## Basic Queries
### 1. Find a specific function by name
- **Natural Language:** "Where is the function `foo` defined?"
- **Tool:** `find_code`
- **JSON Arguments:**
```json
{
"query": "foo"
}
```

### 2. Find all calls to a specific function
- **Natural Language:** "Find all calls to the `helper` function."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_callers",
"target": "helper"
}
```

### 3. Find what a function calls
- **Natural Language:** "What functions are called inside the `foo` function?"
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_callees",
"target": "foo",
"context": "/teamspace/studios/this_studio/demo/CodeGraphContext/tests/sample_project/module_a.py"
}
```

### 4. Find all imports of a specific module
- **Natural Language:** "Where is the `math` module imported?"
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_importers",
"target": "math"
}
```

### 5. Find all methods of a class
- **Natural Language:** "What are the methods of the `A` class?"
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "class_hierarchy",
"target": "A"
}
```
- **Note:** The response for `class_hierarchy` includes a list of methods.

### 6. Find all classes that inherit from a specific class
- **Natural Language:** "Show me all classes that inherit from `Base`."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "class_hierarchy",
"target": "Base"
}
```
- **Note:** The response for `class_hierarchy` includes a list of child classes.

### 7. Find all functions with a specific decorator
- **Natural Language:** "Find all functions with the `log_decorator`."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_functions_by_decorator",
"target": "log_decorator"
}
```

### 8. Find all dataclasses
- **Natural Language:** "Find all dataclasses."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class) WHERE 'dataclass' IN c.decorators RETURN c.name, c.file_path"
}
```

---
## Code Analysis & Quality
### 9. Find the 5 most complex functions
- **Natural Language:** "Find the 5 most complex functions."
- **Tool:** `find_most_complex_functions`
- **JSON Arguments:**
```json
{
"limit": 5
}
```

### 10. Calculate cyclomatic complexity of a function
- **Natural Language:** "What is the cyclomatic complexity of `try_except_finally`?"
- **Tool:** `calculate_cyclomatic_complexity`
- **JSON Arguments:**
```json
{
"function_name": "try_except_finally"
}
```
### 11. Find unused code
- **Natural Language:** "Find unused code, but ignore API endpoints decorated with `@app.route`."
- **Tool:** `find_dead_code`
- **JSON Arguments:**
```json
{
"exclude_decorated_with": ["@app.route"]
}
```

### 12. Find the call chain between two functions
- **Natural Language:** "What is the call chain from `wrapper` to `helper`?"
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "call_chain",
"target": "wrapper->helper"
}
```

### 13. Find all direct and indirect callers of a function
- **Natural Language:** "Show me all functions that eventually call the `helper` function."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_all_callers",
"target": "helper"
}
```

### 14. Find functions by argument name
- **Natural Language:** "Find all functions that take `self` as an argument."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_functions_by_argument",
"target": "self"
}
```

### 15. List all python package imports from a directory
- **Natural Language:** "List all python package imports from my project directory."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:File)-[:IMPORTS]->(m:Module) WHERE f.path ENDS WITH '.py' RETURN DISTINCT m.name"
}
```
---
## Repository Information Queries
### 16. List all indexed projects
- **Natural Language:** "List all projects I have indexed."
- **Tool:** `list_indexed_repositories`
- **JSON Arguments:**
```json
{}
```

### 17. Check the status of an indexing job
- **Natural Language:** "What is the status of job `4cb9a60e-c1b1-43a7-9c94-c840771506bc`?"
- **Tool:** `check_job_status`
- **JSON Arguments:**
```json
{
"job_id": "4cb9a60e-c1b1-43a7-9c94-c840771506bc"
}
```
### 18. List all background jobs
- **Natural Language:** "Show me all background jobs."
- **Tool:** `list_jobs`
- **JSON Arguments:**
```json
{}
```
---
## Advanced Cypher Queries
These examples use the `execute_cypher_query` tool for more specific and complex questions.
### 19. Find all function definitions
- **Natural Language:** "Find all function definitions in the codebase."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (n:Function) RETURN n.name, n.file_path, n.line_number LIMIT 50"
}
```

### 20. Find all classes
- **Natural Language:** "Show me all the classes."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (n:Class) RETURN n.name, n.file_path, n.line_number LIMIT 50"
}
```

### 21. Find all functions in a file
- **Natural Language:** "Find all functions in `module_a.py`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) WHERE f.file_path ENDS WITH 'module_a.py' RETURN f.name"
}
```

### 22. Find all classes in a file
- **Natural Language:** "Find all classes in `advanced_classes.py`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class) WHERE c.file_path ENDS WITH 'advanced_classes.py' RETURN c.name"
}
```

### 23. List all top-level functions and classes in a file
- **Natural Language:** "List all top-level functions and classes in `module_a.py`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:File)-[:CONTAINS]->(n) WHERE f.name = 'module_a.py' AND (n:Function OR n:Class) AND n.context IS NULL RETURN n.name"
}
```

### 24. Find functions in one module that call a function in another
- **Natural Language:** "Find functions in `module_a.py` that call `helper` in `module_b.py`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (caller:Function)-[:CALLS]->(callee:Function {name: 'helper'}) WHERE caller.file_path ENDS WITH 'module_a.py' AND callee.file_path ENDS WITH 'module_b.py' RETURN caller.name"
}
```

### 25. Find circular file imports
- **Natural Language:** "Are there any circular dependencies between files?"
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f1:File)-[:IMPORTS]->(m2:Module), (f2:File)-[:IMPORTS]->(m1:Module) WHERE f1.name = m1.name + '.py' AND f2.name = m2.name + '.py' RETURN f1.name, f2.name"
}
```
### 26. Find all functions with more than 5 arguments
- **Natural Language:** "Find all functions with a large number of arguments."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) WHERE size(f.args) > 5 RETURN f.name, f.file_path, size(f.args) as arg_count"
}
```

### 27. Find all functions in a file that have a docstring
- **Natural Language:** "Find all functions in `module_a.py` that have a docstring."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) WHERE f.file_path ENDS WITH 'module_a.py' AND f.docstring IS NOT NULL AND f.docstring <> '' RETURN f.name"
}
```
### 28. Find all classes that have a specific method
- **Natural Language:** "Find all classes that have a `greet` method."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class)-[:CONTAINS]->(m:Function {name: 'greet'}) RETURN c.name, c.file_path"
}
```

### 29. Find the depth of inheritance for all classes
- **Natural Language:** "How deep are the inheritance chains for all classes?"
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class) OPTIONAL MATCH path = (c)-[:INHERITS*]->(parent:Class) RETURN c.name, c.file_path, length(path) AS depth ORDER BY depth DESC"
}
```

### 30. Find all functions that have a docstring
- **Natural Language:** "Show me all functions that are documented."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) WHERE f.docstring IS NOT NULL AND f.docstring <> '' RETURN f.name, f.file_path LIMIT 50"
}
```

### 31. Find all decorated methods in a class
- **Natural Language:** "Find all decorated methods in the `Child` class."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class {name: 'Child'})-[:CONTAINS]->(m:Function) WHERE m.decorators IS NOT NULL AND size(m.decorators) > 0 RETURN m.name"
}
```

### 32. Find the number of functions in each file
- **Natural Language:** "How many functions are in each file?"
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) RETURN f.file_path, count(f) AS function_count ORDER BY function_count DESC"
}
```

### 33. Find all methods that override a parent method
- **Natural Language:** "Find all methods that are overridden from a parent class."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Class)-[:INHERITS]->(p:Class), (c)-[:CONTAINS]->(m:Function), (p)-[:CONTAINS]->(m_parent:Function) WHERE m.name = m_parent.name RETURN m.name as method, c.name as child_class, p.name as parent_class"
}
```

### 34. Find all functions that call `super()`
- **Natural Language:** "Find all methods that call their parent's method via `super()`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function)-[r:CALLS]->() WHERE r.full_call_name STARTS WITH 'super(' RETURN f.name, f.file_path"
}
```

### 35. Find all calls to a function with a specific argument
- **Natural Language:** "Find all calls to `helper` with the argument `x`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH ()-[r:CALLS]->(f:Function {name: 'helper'}) WHERE 'x' IN r.args RETURN r.full_call_name, r.line_number, r.file_path"
}
```

### 36. Find all functions that are not called by any other function
- **Natural Language:** "Find all dead code (functions that are never called)."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function) WHERE NOT (()-[:CALLS]->(f)) AND f.is_dependency = false RETURN f.name, f.file_path"
}
```

### 37. Find all functions that are called with a specific argument
- **Natural Language:** "Find all calls to `print` with the argument `'hello'`."
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (c:Call) WHERE c.name = 'print' AND 'hello' IN c.args RETURN c.file, c.lineno"
}
```
### 38. Find all direct and indirect callees of a function
- **Natural Language:** "Show me all functions that are eventually called by the `foo` function."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "find_all_callees",
"target": "foo",
"context": "/teamspace/studios/this_studio/demo/CodeGraphContext/tests/sample_project/module_a.py"
}
```

### 39. Find all functions that are overridden
- **Natural Language:** "Find all functions that are overridden."
- **Tool:** `analyze_code_relationships`
- **JSON Arguments:**
```json
{
"query_type": "overrides",
"target": "foo"
}
```

### 40. Find all modules imported by `module_a`
- **Natural Language:** "Find all modules imported by `module_a`."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:File {name: 'module_a.py'})-[:IMPORTS]->(m:Module) RETURN m.name AS imported_module_name"
}
```

### 41. Find large functions that should be refactored
- **Natural Language:** "Find functions with more than 20 lines of code that might need refactoring."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function)
WHERE f.end_line - f.line_number > 20
RETURN f"
}
```

### 42. Find recursive functions
- **Natural Language:** "Find all functions that call themselves (recursive functions)."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH p=(f:Function)-[:CALLS]->(f2:Function)
WHERE f.name = f2.name AND f.file_path = f2.file_path
RETURN p"
}
```

### 42. Find most connected functions (hub functions)
- **Natural Language:** "Find the functions that are most central to the codebase (called by many and call many others)."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "MATCH (f:Function)
OPTIONAL MATCH (f)-[:CALLS]->(callee:Function)
OPTIONAL MATCH (caller:Function)-[:CALLS]->(f)
WITH f, count(DISTINCT callee) AS calls_out, count(DISTINCT caller) AS calls_in
ORDER BY (calls_out + calls_in) DESC
LIMIT 5
MATCH p=(f)-[*0..2]-()
RETURN p"
}
```

## Security & Sensitive Data Analysis
### 42. Find potential security vulnerabilities (hardcoded secrets)
- **Natural Language:** "Find potential hardcoded passwords, API keys, or secrets in the codebase."
- **Tool:** `execute_cypher_query`
- **JSON Arguments:**
```json
{
"cypher_query": "WITH ["password", "api_key", "apikey", "secret_token", "token", "auth", "access_key", "private_key", "client_secret", "sessionid", "jwt"] AS keywords
MATCH (f:Function)
WHERE ANY(word IN keywords WHERE toLower(f.source_code) CONTAINS word)
RETURN f"
}
```
```
--------------------------------------------------------------------------------
/docs/site/future_work/index.html:
--------------------------------------------------------------------------------
```html
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="prev" href="../troubleshooting/">
<link rel="next" href="../license/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
<title>Future Work - CodeGraphContext</title>
<link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<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">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<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>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#ongoing-concerns-and-future-work" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
CodeGraphContext
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Future Work
</span>
</div>
</div>
</div>
<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>
<label class="md-header__button md-icon" for="__search">
<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>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<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>
<label class="md-search__icon md-icon" for="__search">
<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>
<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>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<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>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
CodeGraphContext
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../use_cases/" class="md-nav__link">
<span class="md-ellipsis">
Use Cases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/" class="md-nav__link">
<span class="md-ellipsis">
CLI Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../server/" class="md-nav__link">
<span class="md-ellipsis">
Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../core/" class="md-nav__link">
<span class="md-ellipsis">
Core Concepts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/" class="md-nav__link">
<span class="md-ellipsis">
Tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cookbook/" class="md-nav__link">
<span class="md-ellipsis">
Cookbook
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
<label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
<span class="md-ellipsis">
Contributing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
Contributing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../contributing_languages/" class="md-nav__link">
<span class="md-ellipsis">
Adding New Languages
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../troubleshooting/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Future Work
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Future Work
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#semantic-search" class="md-nav__link">
<span class="md-ellipsis">
Semantic Search
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
License
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#semantic-search" class="md-nav__link">
<span class="md-ellipsis">
Semantic Search
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="ongoing-concerns-and-future-work">Ongoing Concerns and Future Work</h1>
<p>This page outlines some of the current limitations of CodeGraphContext and areas for future development.</p>
<h2 id="semantic-search">Semantic Search</h2>
<p>The tool is smart enough to find and analyze a function through millions of code files, but the tool is not yet smart enough to understand that a user searching for “calculate_sum” is also intending to look at the “calculate_addition” function. This level of semantic similarity needs to be researched, developed, tested and eventually implemented by our tool.</p>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<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>
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/decorators-metadata.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Decorators and Metadata
* Demonstrates TypeScript decorators for classes, methods, properties, and parameters
* Note: Requires experimentalDecorators and emitDecoratorMetadata in tsconfig.json
* Also requires reflect-metadata package for metadata reflection
*/
import "reflect-metadata";
// ========== Metadata Keys ==========
export const METADATA_KEYS = {
VALIDATION_RULES: Symbol("validation:rules"),
ROUTE_INFO: Symbol("route:info"),
INJECTABLE: Symbol("injectable"),
CACHE_CONFIG: Symbol("cache:config"),
LOG_CONFIG: Symbol("log:config"),
REQUIRED_ROLE: Symbol("required:role"),
SERIALIZABLE: Symbol("serializable"),
MAPPED_PROPERTY: Symbol("mapped:property")
};
// ========== Class Decorators ==========
export function Entity(tableName?: string): ClassDecorator {
return function <T extends Function>(constructor: T) {
Reflect.defineMetadata("entity:table", tableName || constructor.name.toLowerCase(), constructor);
return constructor;
};
}
export function Injectable(): ClassDecorator {
return function <T extends Function>(constructor: T) {
Reflect.defineMetadata(METADATA_KEYS.INJECTABLE, true, constructor);
return constructor;
};
}
export function Component(config: { selector: string; template?: string }): ClassDecorator {
return function <T extends Function>(constructor: T) {
Reflect.defineMetadata("component:config", config, constructor);
return constructor;
};
}
export function Serializable(): ClassDecorator {
return function <T extends Function>(constructor: T) {
Reflect.defineMetadata(METADATA_KEYS.SERIALIZABLE, true, constructor);
// Add serialize method to prototype if it doesn't exist
if (!constructor.prototype.serialize) {
constructor.prototype.serialize = function() {
const result: any = {};
const serializableProps = Reflect.getMetadata("serializable:properties", this.constructor) || [];
for (const prop of serializableProps) {
if (this[prop] !== undefined) {
result[prop] = this[prop];
}
}
return result;
};
}
return constructor;
};
}
// ========== Method Decorators ==========
export function Log(message?: string): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
const className = target.constructor.name;
descriptor.value = function (...args: any[]) {
console.log(`[${className}.${String(propertyName)}] ${message || 'Method called'} with args:`, args);
const result = originalMethod.apply(this, args);
console.log(`[${className}.${String(propertyName)}] Result:`, result);
return result;
};
return descriptor;
};
}
export function Validate(): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
// Get validation rules from metadata
const rules = Reflect.getMetadata(METADATA_KEYS.VALIDATION_RULES, target, propertyName) || [];
for (const rule of rules) {
if (!rule.validate(...args)) {
throw new Error(rule.message);
}
}
return originalMethod.apply(this, args);
};
return descriptor;
};
}
export function Cache(ttl: number = 60000): MethodDecorator {
const cache = new Map<string, { value: any; expires: number }>();
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const cacheKey = `${target.constructor.name}.${String(propertyName)}:${JSON.stringify(args)}`;
const cached = cache.get(cacheKey);
if (cached && Date.now() < cached.expires) {
console.log(`Cache hit for ${cacheKey}`);
return cached.value;
}
const result = originalMethod.apply(this, args);
cache.set(cacheKey, { value: result, expires: Date.now() + ttl });
console.log(`Cache set for ${cacheKey}`);
return result;
};
return descriptor;
};
}
export function Retry(maxAttempts: number = 3, delay: number = 1000): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = async function (...args: any[]) {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
return await originalMethod.apply(this, args);
} catch (error) {
if (attempt === maxAttempts) {
throw error;
}
console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
await new Promise(resolve => setTimeout(resolve, delay * attempt));
}
}
};
return descriptor;
};
}
export function RequireRole(role: string): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
Reflect.defineMetadata(METADATA_KEYS.REQUIRED_ROLE, role, target, propertyName);
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
const userRole = (this as any).currentUserRole;
const requiredRole = Reflect.getMetadata(METADATA_KEYS.REQUIRED_ROLE, target, propertyName);
if (!userRole || userRole !== requiredRole) {
throw new Error(`Access denied. Required role: ${requiredRole}, current role: ${userRole}`);
}
return originalMethod.apply(this, args);
};
return descriptor;
};
}
// ========== Property Decorators ==========
export function Column(options?: { name?: string; type?: string; nullable?: boolean }): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const columns = Reflect.getMetadata("entity:columns", target.constructor) || [];
columns.push({
propertyKey,
...options
});
Reflect.defineMetadata("entity:columns", columns, target.constructor);
};
}
export function Required(): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const required = Reflect.getMetadata("validation:required", target.constructor) || [];
required.push(propertyKey);
Reflect.defineMetadata("validation:required", required, target.constructor);
};
}
export function MinLength(length: number): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const validations = Reflect.getMetadata("validation:rules", target.constructor) || {};
validations[propertyKey] = validations[propertyKey] || [];
validations[propertyKey].push({
type: "minLength",
value: length,
message: `${String(propertyKey)} must be at least ${length} characters long`
});
Reflect.defineMetadata("validation:rules", validations, target.constructor);
};
}
export function Max(value: number): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const validations = Reflect.getMetadata("validation:rules", target.constructor) || {};
validations[propertyKey] = validations[propertyKey] || [];
validations[propertyKey].push({
type: "max",
value: value,
message: `${String(propertyKey)} must not exceed ${value}`
});
Reflect.defineMetadata("validation:rules", validations, target.constructor);
};
}
export function SerializableProperty(alias?: string): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const serializableProps = Reflect.getMetadata("serializable:properties", target.constructor) || [];
serializableProps.push(propertyKey);
Reflect.defineMetadata("serializable:properties", serializableProps, target.constructor);
if (alias) {
const aliases = Reflect.getMetadata("serializable:aliases", target.constructor) || {};
aliases[propertyKey] = alias;
Reflect.defineMetadata("serializable:aliases", aliases, target.constructor);
}
};
}
export function Computed(): PropertyDecorator {
return function (target: any, propertyKey: string | symbol) {
const computed = Reflect.getMetadata("computed:properties", target.constructor) || [];
computed.push(propertyKey);
Reflect.defineMetadata("computed:properties", computed, target.constructor);
};
}
// ========== Parameter Decorators ==========
export function Inject(token?: string): ParameterDecorator {
return function (target: any, propertyKey: string | symbol | undefined, parameterIndex: number) {
const existingTokens = Reflect.getMetadata("inject:tokens", target) || [];
existingTokens[parameterIndex] = token;
Reflect.defineMetadata("inject:tokens", existingTokens, target);
};
}
export function ValidateParam(validator: (value: any) => boolean, message: string): ParameterDecorator {
return function (target: any, propertyKey: string | symbol | undefined, parameterIndex: number) {
const existingRules = Reflect.getMetadata(METADATA_KEYS.VALIDATION_RULES, target, propertyKey) || [];
existingRules.push({
parameterIndex,
validate: (args: any[]) => validator(args[parameterIndex]),
message
});
Reflect.defineMetadata(METADATA_KEYS.VALIDATION_RULES, existingRules, target, propertyKey);
};
}
// ========== Accessor Decorators ==========
export function Getter(): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
Reflect.defineMetadata("accessor:type", "getter", target, propertyName);
return descriptor;
};
}
export function Setter(): MethodDecorator {
return function (target: any, propertyName: string | symbol, descriptor: PropertyDescriptor) {
Reflect.defineMetadata("accessor:type", "setter", target, propertyName);
return descriptor;
};
}
// ========== Utility Functions for Metadata ==========
export class MetadataReader {
static getClassMetadata<T>(target: any, key: string | symbol): T | undefined {
return Reflect.getMetadata(key, target);
}
static getMethodMetadata<T>(target: any, method: string, key: string | symbol): T | undefined {
return Reflect.getMetadata(key, target, method);
}
static getPropertyMetadata<T>(target: any, property: string, key: string | symbol): T | undefined {
return Reflect.getMetadata(key, target, property);
}
static getAllMethodNames(target: any): string[] {
const methods: string[] = [];
let current = target.prototype;
while (current && current !== Object.prototype) {
const names = Object.getOwnPropertyNames(current);
for (const name of names) {
if (name !== 'constructor' && typeof current[name] === 'function' && !methods.includes(name)) {
methods.push(name);
}
}
current = Object.getPrototypeOf(current);
}
return methods;
}
static getValidationRules(target: any): any {
return Reflect.getMetadata("validation:rules", target) || {};
}
static getInjectableInfo(target: any): boolean {
return Reflect.getMetadata(METADATA_KEYS.INJECTABLE, target) || false;
}
}
// ========== Example Classes Using Decorators ==========
@Entity("users")
@Injectable()
@Serializable()
export class User {
@Column({ name: "id", type: "integer" })
@Required()
@SerializableProperty()
public id!: number;
@Column({ name: "username", type: "varchar" })
@Required()
@MinLength(3)
@SerializableProperty()
public username!: string;
@Column({ name: "email", type: "varchar" })
@Required()
@SerializableProperty("emailAddress")
public email!: string;
@Column({ name: "age", type: "integer" })
@Max(120)
@SerializableProperty()
public age!: number;
private password!: string;
public currentUserRole?: string;
constructor(id: number, username: string, email: string, age: number) {
this.id = id;
this.username = username;
this.email = email;
this.age = age;
}
@Log("Getting user info")
@Cache(30000)
public getInfo(): string {
return `User: ${this.username} (${this.email})`;
}
@Validate()
public updateAge(
@ValidateParam((value: number) => value > 0 && value <= 120, "Age must be between 1 and 120")
newAge: number
): void {
this.age = newAge;
}
@RequireRole("admin")
public deleteUser(): string {
return `User ${this.username} has been deleted`;
}
@Retry(3, 1000)
public async syncWithExternalService(): Promise<string> {
// Simulate an operation that might fail
if (Math.random() > 0.7) {
throw new Error("External service unavailable");
}
return "Sync completed successfully";
}
@Computed()
public get isAdult(): boolean {
return this.age >= 18;
}
}
@Component({ selector: "user-service", template: "<div>User Service</div>" })
export class UserService {
constructor(
@Inject("userRepository") private userRepo: any,
@Inject("logger") private logger: any
) {}
@Log("Finding user by ID")
public async findById(id: number): Promise<User | null> {
// Simulate database lookup
await new Promise(resolve => setTimeout(resolve, 100));
return new User(id, `user${id}`, `user${id}@example.com`, 25);
}
}
// ========== Validation Engine ==========
export class ValidationEngine {
static validate(instance: any): { valid: boolean; errors: string[] } {
const errors: string[] = [];
const constructor = instance.constructor;
// Check required properties
const required = Reflect.getMetadata("validation:required", constructor) || [];
for (const prop of required) {
if (instance[prop] === undefined || instance[prop] === null) {
errors.push(`${prop} is required`);
}
}
// Check validation rules
const rules = Reflect.getMetadata("validation:rules", constructor) || {};
for (const [prop, propRules] of Object.entries(rules)) {
const value = instance[prop];
for (const rule of (propRules as any[])) {
if (rule.type === "minLength" && typeof value === "string" && value.length < rule.value) {
errors.push(rule.message);
}
if (rule.type === "max" && typeof value === "number" && value > rule.value) {
errors.push(rule.message);
}
}
}
return {
valid: errors.length === 0,
errors
};
}
}
// ========== Usage Examples ==========
export const decoratorExamples = {
// Create a user instance
user: new User(1, "john_doe", "[email protected]", 30),
// Validation examples
validateUser: (user: User) => ValidationEngine.validate(user),
// Metadata reader examples
getEntityInfo: (target: any) => ({
tableName: MetadataReader.getClassMetadata(target, "entity:table"),
columns: MetadataReader.getClassMetadata(target, "entity:columns"),
isInjectable: MetadataReader.getInjectableInfo(target)
}),
// Service instance
userService: new UserService("mockUserRepo", "mockLogger")
};
// Example usage of the decorated user
decoratorExamples.user.currentUserRole = "admin";
// This will use caching
console.log(decoratorExamples.user.getInfo());
// This will validate the parameter
try {
decoratorExamples.user.updateAge(25);
} catch (error) {
console.error("Validation error:", error);
}
// Get metadata about the User class
console.log("User metadata:", decoratorExamples.getEntityInfo(User));
```
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/cpp.py:
--------------------------------------------------------------------------------
```python
from pathlib import Path
from typing import Any, Dict, Optional, Tuple
from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger
CPP_QUERIES = {
"functions": """
(function_definition
declarator: (function_declarator
declarator: (identifier) @name
)
) @function_node
""",
"classes": """
(class_specifier
name: (type_identifier) @name
) @class
""",
"imports": """
(preproc_include
path: [
(string_literal) @path
(system_lib_string) @path
]
) @import
""",
"calls": """
(call_expression
function: [
(identifier) @function_name
(field_expression
field: (field_identifier) @method_name
)
]
arguments: (argument_list) @args
)
""",
"enums":"""
(enum_specifier
name: (type_identifier) @name
body: (enumerator_list
(enumerator
name: (identifier) @value
)*
)? @body
) @enum
""",
"structs":"""
(struct_specifier
name: (type_identifier) @name
body: (field_declaration_list)? @body
) @struct
""",
"unions": """
(union_specifier
name: (type_identifier)? @name
body: (field_declaration_list
(field_declaration
declarator: [
(field_identifier) @value
(pointer_declarator (field_identifier) @value)
(array_declarator (field_identifier) @value)
]
)*
)? @body
) @union
""",
"macros": """
(preproc_def
name: (identifier) @name
) @macro
""",
"variables": """
(declaration
declarator: (init_declarator
declarator: (identifier) @name))
(declaration
declarator: (init_declarator
declarator: (pointer_declarator
declarator: (identifier) @name)))
""",
"lambda_assignments": """
; Match a lambda assigned to a variable
(declaration
declarator: (init_declarator
declarator: (identifier) @name
value: (lambda_expression) @lambda_node))
"""
}
class CppTreeSitterParser:
"""A C++-specific parser using tree-sitter."""
def __init__(self, generic_parser_wrapper):
self.generic_parser_wrapper = generic_parser_wrapper
self.language_name = "cpp"
self.language = generic_parser_wrapper.language
self.parser = generic_parser_wrapper.parser
self.queries = {
name: self.language.query(query_str)
for name, query_str in CPP_QUERIES.items()
}
def _get_node_text(self, node) -> str:
return node.text.decode('utf-8')
def parse(self, file_path: Path, is_dependency: bool = False, **kwargs) -> Dict:
"""Parses a C++ file and returns its structure."""
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
source_code = f.read()
tree = self.parser.parse(bytes(source_code, "utf8"))
root_node = tree.root_node
functions = self._find_functions(root_node)
functions.extend(self._find_lambda_assignments(root_node))
function_calls = self._find_calls(root_node)
classes = self._find_classes(root_node)
imports = self._find_imports(root_node)
structs = self._find_structs(root_node)
enums = self._find_enums(root_node)
unions = self._find_unions(root_node)
macros = self._find_macros(root_node)
variables = self._find_variables(root_node)
return {
"file_path": str(file_path),
"functions": functions,
"classes": classes,
"structs": structs,
"enums": enums,
"unions": unions,
"macros": macros,
"variables": variables,
"declarations": [], # Placeholder
"imports": imports,
"function_calls": function_calls,
"is_dependency": is_dependency,
"lang": self.language_name,
}
def _find_functions(self, root_node):
functions = []
query = self.queries['functions']
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'name':
func_node = node.parent.parent.parent
name = self._get_node_text(node)
functions.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": func_node.end_point[0] + 1,
"source_code": self._get_node_text(func_node),
"args": [], # Placeholder
})
return functions
def _find_classes(self, root_node):
classes = []
query = self.queries['classes']
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'name':
class_node = node.parent
name = self._get_node_text(node)
classes.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": class_node.end_point[0] + 1,
"source_code": self._get_node_text(class_node),
"bases": [], # Placeholder
})
return classes
def _find_imports(self, root_node):
imports = []
query = self.queries['imports']
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'path':
path = self._get_node_text(node).strip('<>')
imports.append({
"name": path,
"full_import_name": path,
"line_number": node.start_point[0] + 1,
"alias": None,
})
return imports
def _find_enums(self, root_node):
enums = []
query = self.queries['enums']
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
name = self._get_node_text(node)
enum_node = node.parent
enums.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": enum_node.end_point[0] + 1,
"source_code": self._get_node_text(enum_node),
})
return enums
def _find_structs(self, root_node):
structs = []
query = self.queries['structs']
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
name = self._get_node_text(node)
struct_node = node.parent
structs.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": struct_node.end_point[0] + 1,
"source_code": self._get_node_text(struct_node),
})
return structs
def _find_unions(self, root_node):
unions = []
query = self.queries['unions']
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
name = self._get_node_text(node)
union_node = node.parent
unions.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": union_node.end_point[0] + 1,
"source_code": self._get_node_text(union_node),
})
return unions
def _find_macros(self, root_node):
macros = []
query = self.queries['macros']
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'name':
macro_node = node.parent
name = self._get_node_text(node)
macros.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": macro_node.end_point[0] + 1,
"source_code": self._get_node_text(macro_node),
})
return macros
def _find_lambda_assignments(self, root_node):
functions = []
query = self.queries.get('lambda_assignments')
if not query: return []
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'name':
assignment_node = node.parent
lambda_node = assignment_node.child_by_field_name('value')
if lambda_node is None or lambda_node.type != 'lambda_expression':
continue
params_node = lambda_node.child_by_field_name('declarator')
if params_node:
params_node = params_node.child_by_field_name('parameters')
name = self._get_node_text(node)
params_node = lambda_node.child_by_field_name('parameters')
context, context_type, _ = self._get_parent_context(assignment_node)
class_context, _, _ = self._get_parent_context(assignment_node, types=('class_definition',))
func_data = {
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": assignment_node.end_point[0] + 1,
"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 [],
"source": self._get_node_text(assignment_node),
"source_code": self._get_node_text(assignment_node),
"docstring": None,
"cyclomatic_complexity": 1,
"context": context,
"context_type": context_type,
"class_context": class_context,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
}
functions.append(func_data)
return functions
def _find_variables(self, root_node):
variables = []
query = self.queries['variables']
for match in query.captures(root_node):
capture_name = match[1]
node = match[0]
if capture_name == 'name':
assignment_node = node.parent
# Skip lambda assignments, they are handled by _find_lambda_assignments
right_node = assignment_node.child_by_field_name('value')
if right_node and right_node.type == 'lambda_expression':
continue
name = self._get_node_text(node)
value = self._get_node_text(right_node) if right_node else None
type_node = assignment_node.child_by_field_name('type')
type_text = self._get_node_text(type_node) if type_node else None
context, _, _ = self._get_parent_context(node)
class_context, _, _ = self._get_parent_context(node, types=('class_definition',))
variable_data = {
"name": name,
"line_number": node.start_point[0] + 1,
"value": value,
"type": type_text,
"context": context,
"class_context": class_context,
"lang": self.language_name,
"is_dependency": False,
}
variables.append(variable_data)
return variables
def _get_parent_context(self, node, types=('function_definition', 'class_definition')):
curr = node.parent
while curr:
if curr.type in types:
name_node = curr.child_by_field_name('name')
return self._get_node_text(name_node) if name_node else None, curr.type, curr.start_point[0] + 1
curr = curr.parent
return None, None, None
def _find_calls(self, root_node):
calls = []
query = self.queries['calls']
for node, capture_name in query.captures(root_node):
if capture_name == "function_name":
func_name = self._get_node_text(node)
func_node = node.parent.parent # function_declarator -> function_definition
full_name = self._get_full_name(func_node) or func_name
# Find return type node (captured separately)
return_type_node = None
for n, cap in query.captures(func_node):
if cap == "return_type":
return_type_node = n
break
return_type = self._get_node_text(return_type_node) if return_type_node else None
# Extract parameters
args = []
parameters_node = func_node.child_by_field_name("declarator")
if parameters_node:
param_list_node = parameters_node.child_by_field_name("parameters")
if param_list_node:
for param in param_list_node.children:
if param.type == "parameter_declaration":
type_node = param.child_by_field_name("type")
name_node = param.child_by_field_name("declarator")
param_type = self._get_node_text(type_node) if type_node else None
param_name = self._get_node_text(name_node) if name_node else None
args.append({
"type": param_type,
"name": param_name
})
# Get context info (function may be inside class)
context, _, _ = self._get_parent_context(node)
class_context, _, _ = self._get_parent_context(node, types=("class_definition",))
call_data = {
"name": func_name,
"full_name": full_name,
"line_number": node.start_point[0] + 1,
"args": args,
"inferred_obj_type": None,
"context": context,
"class_context": class_context,
"lang": self.language_name,
"is_dependency": False,
}
calls.append(call_data)
return calls
def _get_full_name(self, node):
"Builds a fully qualified name for a function or call node."
name_parts = []
# Move upward and collect parent scopes
curr = node
while curr:
if curr.type in ("function_definition", "function_declarator"):
id_node = curr.child_by_field_name("declarator")
if id_node and id_node.type == "identifier":
name_parts.insert(0, id_node.text.decode("utf8"))
elif curr.type == "class_specifier":
name_node = curr.child_by_field_name("name")
if name_node:
name_parts.insert(0, name_node.text.decode("utf8"))
elif curr.type == "namespace_definition":
name_node = curr.child_by_field_name("name")
if name_node:
name_parts.insert(0, name_node.text.decode("utf8"))
curr = curr.parent
return "::".join(name_parts) if name_parts else None
def pre_scan_cpp(files: list[Path], parser_wrapper) -> dict:
"""
Quickly scans C++ files to build a map of top-level class, struct, and function names
to their file paths.
"""
imports_map = {}
query_str = """
(class_specifier name: (type_identifier) @name)
(struct_specifier name: (type_identifier) @name)
(function_definition declarator: (function_declarator declarator: (identifier) @name))
"""
query = parser_wrapper.language.query(query_str)
for file_path in files:
try:
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
source_bytes = f.read().encode("utf-8")
tree = parser_wrapper.parser.parse(source_bytes)
for node, capture_name in query.captures(tree.root_node):
if capture_name == "name":
name = node.text.decode("utf-8")
imports_map.setdefault(name, []).append(str(file_path.resolve()))
except Exception as e:
warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
return imports_map
```
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/package_resolver.py:
--------------------------------------------------------------------------------
```python
# src/codegraphcontext/tools/package_resolver.py
import importlib
import stdlibs
from pathlib import Path
import subprocess
from typing import Optional
from ..utils.debug_log import debug_log
def _get_python_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a Python package.
"""
try:
debug_log(f"Getting local path for Python package: {package_name}")
module = importlib.import_module(package_name)
if hasattr(module, '__file__') and module.__file__:
module_file = Path(module.__file__)
if module_file.name == '__init__.py':
return str(module_file.parent)
elif package_name in stdlibs.module_names:
return str(module_file)
else:
return str(module_file.parent)
elif hasattr(module, '__path__'):
if isinstance(module.__path__, list) and module.__path__:
return str(Path(module.__path__[0]))
else:
return str(Path(str(module.__path__)))
return None
except ImportError:
return None
except Exception as e:
debug_log(f"Error getting local path for {package_name}: {e}")
return None
def _get_npm_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a Node.js package using `npm root`.
"""
try:
debug_log(f"Getting local path for npm package: {package_name}")
local_path = Path(f"./node_modules/{package_name}")
if local_path.exists():
return str(local_path.resolve())
result = subprocess.run(["npm", "root", "-g"], capture_output=True, text=True)
if result.returncode == 0:
global_root = result.stdout.strip()
package_path = Path(global_root) / package_name
if package_path.exists():
return str(package_path.resolve())
return None
except Exception as e:
debug_log(f"Error getting npm package path for {package_name}: {e}")
return None
def _get_typescript_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a TypeScript package.
TypeScript packages are typically npm packages, so this uses the same logic as npm.
"""
try:
debug_log(f"Getting local path for TypeScript package: {package_name}")
# Check local node_modules first
local_path = Path(f"./node_modules/{package_name}")
if local_path.exists():
return str(local_path.resolve())
# Check global npm packages
result = subprocess.run(["npm", "root", "-g"], capture_output=True, text=True, timeout=5)
if result.returncode == 0:
global_root = result.stdout.strip()
package_path = Path(global_root) / package_name
if package_path.exists():
return str(package_path.resolve())
return None
except subprocess.TimeoutExpired:
debug_log(f"npm command timed out for {package_name}")
return None
except Exception as e:
debug_log(f"Error getting TypeScript package path for {package_name}: {e}")
return None
def _get_java_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a Java package (JAR).
Searches in Maven and Gradle cache directories.
Args:
package_name: Package name in format "groupId:artifactId" (e.g., "com.google.code.gson:gson")
or just "artifactId" for simple search.
"""
try:
debug_log(f"Getting local path for Java package: {package_name}")
# Parse package name - expect format "groupId:artifactId" or just "artifactId"
if ':' in package_name:
group_id, artifact_id = package_name.split(':', 1)
# Convert group_id dots to path separators (e.g., com.google.gson -> com/google/gson)
group_path = group_id.replace('.', '/')
else:
# If only artifact_id provided, search for it
artifact_id = package_name
group_path = None
search_paths = []
# Maven repository (~/.m2/repository)
maven_repo = Path.home() / ".m2" / "repository"
if maven_repo.exists():
if group_path:
# Search for specific group/artifact
package_path = maven_repo / group_path / artifact_id
if package_path.exists():
# Find the latest version directory
version_dirs = [d for d in package_path.iterdir() if d.is_dir()]
if version_dirs:
# Sort by name (assumes semantic versioning) and get the latest
latest_version = sorted(version_dirs, key=lambda x: x.name)[-1]
return str(latest_version.resolve())
else:
# Search for artifact_id in the entire Maven repo
search_paths.append(maven_repo)
# Gradle cache (~/.gradle/caches/modules-2/files-2.1)
gradle_cache = Path.home() / ".gradle" / "caches" / "modules-2" / "files-2.1"
if gradle_cache.exists():
if group_path:
group_id_full = group_id if ':' in package_name else None
if group_id_full:
package_path = gradle_cache / group_id_full / artifact_id
if package_path.exists():
# Find the latest version directory
version_dirs = [d for d in package_path.iterdir() if d.is_dir()]
if version_dirs:
latest_version = sorted(version_dirs, key=lambda x: x.name)[-1]
# Gradle stores files in hash subdirectories
hash_dirs = [d for d in latest_version.iterdir() if d.is_dir()]
if hash_dirs:
return str(hash_dirs[0].resolve())
else:
search_paths.append(gradle_cache)
# If group_path wasn't provided or not found, search in the cache directories
if not group_path or search_paths:
for base_path in search_paths:
for jar_file in base_path.rglob(f"*{artifact_id}*.jar"):
return str(jar_file.parent.resolve())
# Check local lib directories
local_lib_paths = [
Path("./lib"),
Path("./libs"),
Path("/usr/local/lib/java"),
Path("/opt/java/lib"),
]
for lib_path in local_lib_paths:
if not lib_path.exists():
continue
# Look for JAR files matching the artifact name
for jar_file in lib_path.glob(f"*{artifact_id}*.jar"):
return str(jar_file.resolve())
return None
except Exception as e:
debug_log(f"Error getting Java package path for {package_name}: {e}")
def _get_c_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a C package.
"""
try:
debug_log(f"Getting local path for C package: {package_name}")
# Try using pkg-config to find the package
try:
result = subprocess.run(
["pkg-config", "--variable=includedir", package_name],
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0 and result.stdout.strip():
include_dir = Path(result.stdout.strip())
package_path = include_dir / package_name
if package_path.exists():
return str(package_path.resolve())
if include_dir.exists():
return str(include_dir.resolve())
except (subprocess.TimeoutExpired, FileNotFoundError):
debug_log(f"pkg-config not available or timed out for {package_name}")
# Search in standard system include directories
common_include_paths = [
"/usr/include",
"/usr/local/include",
"/opt/homebrew/include",
"/opt/local/include",
Path.home() / ".local" / "include",
]
for base_path in common_include_paths:
base_path = Path(base_path)
if not base_path.exists():
continue
# Check if package exists as a directory
package_dir = base_path / package_name
if package_dir.exists() and package_dir.is_dir():
return str(package_dir.resolve())
# Check for header files with package name
header_file = base_path / f"{package_name}.h"
if header_file.exists():
return str(header_file.resolve())
# Check current directory for local installations
local_package = Path(f"./{package_name}")
if local_package.exists():
return str(local_package.resolve())
return None
except Exception as e:
debug_log(f"Error getting C package path for {package_name}: {e}")
return None
def _get_ruby_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a Ruby gem.
"""
try:
debug_log(f"Getting local path for Ruby gem: {package_name}")
result = subprocess.run(
["gem", "which", package_name],
capture_output=True,
text=True,
timeout=5
)
if result.returncode == 0 and result.stdout.strip():
gem_path = Path(result.stdout.strip())
if gem_path.exists():
lib_dir = gem_path.parent if gem_path.is_file() else gem_path
# If we are inside a gem (…/gems/foo-x.y.z/lib/foo.rb), prefer the lib/ dir:
if (lib_dir.name == "lib") and lib_dir.is_dir():
return str(lib_dir.resolve())
# Try parent/lib in case `gem which` returned .../lib/foo.rb
if (lib_dir / "lib").is_dir():
return str((lib_dir / "lib").resolve())
# Fallback: just return the directory containing the file (stdlib case like 'json')
return str(lib_dir.resolve())
return None
except (subprocess.TimeoutExpired, FileNotFoundError):
debug_log(f"gem command not available or timed out for {package_name}")
return None
except Exception as e:
debug_log(f"Error getting Ruby gem path for {package_name}: {e}")
return None
def _get_go_package_path(package_name: str) -> Optional[str]:
"""
Finds the local installation path of a Go package using `go list`.
Tries multiple approaches in sequence to handle different package scenarios:
1) package dir: go list -f '{{.Dir}}' <pkg> (works for stdlib, GOPATH, or module subpackages)
2) module root: go list -m -f '{{.Dir}}' <module> (works for full module paths)
3) force mod: go list -mod=mod -f '{{.Dir}}' <pkg> (works when outside a module context)
4) GOROOT check: for standard library packages
5) GOPATH check: for packages in GOPATH
"""
def _first_existing_dir(output: str) -> Optional[str]:
for line in (l.strip().strip("'\"") for l in output.splitlines() if l.strip()):
p = Path(line)
if p.exists() and p.is_dir():
return str(p.resolve())
return None
try:
debug_log(f"Getting local path for Go package: {package_name}")
# 1. Package directory (works for stdlib, GOPATH, or subpackages)
cp = subprocess.run(
["go", "list", "-f", "{{.Dir}}", package_name],
capture_output=True, text=True, timeout=15
)
if cp.returncode == 0:
d = _first_existing_dir(cp.stdout)
if d:
return d
# 2. Module root directory (where go.mod lives)
cp2 = subprocess.run(
["go", "list", "-m", "-f", "{{.Dir}}", package_name],
capture_output=True, text=True, timeout=15
)
if cp2.returncode == 0:
d = _first_existing_dir(cp2.stdout)
if d:
debug_log(f"Found Go module {package_name} at {d}")
return d
# 3. Retry forcing module mode
cp3 = subprocess.run(
["go", "list", "-mod=mod", "-f", "{{.Dir}}", package_name],
capture_output=True, text=True, timeout=15
)
if cp3.returncode == 0:
d = _first_existing_dir(cp3.stdout)
if d:
return d
# 4. Check in GOROOT for standard library packages
try:
cp4 = subprocess.run(
["go", "env", "GOROOT"],
capture_output=True, text=True, timeout=5
)
if cp4.returncode == 0:
goroot = cp4.stdout.strip()
if goroot:
std_lib_path = Path(goroot) / "src" / package_name
if std_lib_path.exists() and std_lib_path.is_dir():
return str(std_lib_path.resolve())
except Exception as e:
debug_log(f"Error checking GOROOT for {package_name}: {e}")
# 5. Check in GOPATH as fallback
try:
cp5 = subprocess.run(
["go", "env", "GOPATH"],
capture_output=True, text=True, timeout=5
)
if cp5.returncode == 0:
gopath = cp5.stdout.strip()
if gopath:
gopath_lib_path = Path(gopath) / "src" / package_name
if gopath_lib_path.exists() and gopath_lib_path.is_dir():
debug_log(f"Found Go package in GOPATH {package_name} at {gopath_lib_path}")
return str(gopath_lib_path.resolve())
except Exception as e:
debug_log(f"Error checking GOPATH for {package_name}: {e}")
debug_log(f"Could not find Go package: {package_name}")
return None
except (subprocess.TimeoutExpired, FileNotFoundError):
debug_log(f"go command not available or timed out for {package_name}")
return None
except Exception as e:
debug_log(f"Error getting Go package path for {package_name}: {e}")
return None
def _get_php_package_path(package_name: str) -> Optional[str]:
try:
debug_log(f"Getting local path for PHP package: {package_name}")
local_vendor = Path("./vendor") / package_name
if local_vendor.exists() and local_vendor.is_dir():
return str(local_vendor.resolve())
current_dir = Path.cwd()
for parent in [current_dir] + list(current_dir.parents):
vendor_path = parent / "vendor" / package_name
if vendor_path.exists() and vendor_path.is_dir():
return str(vendor_path.resolve())
if (parent / "composer.json").exists():
break
composer_home = Path.home() / ".composer" / "vendor" / package_name
if composer_home.exists() and composer_home.is_dir():
return str(composer_home.resolve())
composer_global = Path.home() / ".config" / "composer" / "vendor" / package_name
if composer_global.exists() and composer_global.is_dir():
return str(composer_global.resolve())
return None
except Exception as e:
debug_log(f"Error getting PHP package path for {package_name}: {e}")
return None
def get_local_package_path(package_name: str, language: str) -> Optional[str]:
"""
Dispatches to the correct package path finder based on the language.
"""
finders = {
"python": _get_python_package_path,
"javascript": _get_npm_package_path,
"typescript": _get_typescript_package_path,
"java": _get_java_package_path,
"c": _get_c_package_path,
"go": _get_go_package_path,
"ruby": _get_ruby_package_path,
"php": _get_php_package_path,
"cpp": _get_cpp_package_path,
}
finder = finders.get(language)
if finder:
return finder(package_name)
return None
def _get_cpp_package_path(package_name: str) -> Optional[str]:
"""
C++ package ka local path find karta hai.
Pehle pkg-config try karta hai, fir common system paths check karta hai.
"""
import subprocess
import os
# Try pkg-config
try:
result = subprocess.run(
["pkg-config", "--variable=includedir", package_name],
capture_output=True,
text=True,
check=False
)
path = result.stdout.strip()
if path and os.path.exists(path):
return path
except FileNotFoundError:
pass
# Common system include/lib folders
common_paths = [
f"/usr/include/{package_name}",
f"/usr/local/include/{package_name}",
f"/usr/lib/{package_name}",
f"/usr/local/lib/{package_name}",
]
for path in common_paths:
if os.path.exists(path):
return path
return None
```
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/go.py:
--------------------------------------------------------------------------------
```python
from pathlib import Path
from typing import Any, Dict, Optional, Tuple
from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger
GO_QUERIES = {
"functions": """
(function_declaration
name: (identifier) @name
parameters: (parameter_list) @params
) @function_node
(method_declaration
receiver: (parameter_list) @receiver
name: (field_identifier) @name
parameters: (parameter_list) @params
) @function_node
""",
"structs": """
(type_declaration
(type_spec
name: (type_identifier) @name
type: (struct_type) @struct_body
)
) @struct_node
""",
"interfaces": """
(type_declaration
(type_spec
name: (type_identifier) @name
type: (interface_type) @interface_body
)
) @interface_node
""",
"imports": """
(import_declaration
(import_spec
path: (interpreted_string_literal) @path
)
) @import
(import_declaration
(import_spec
name: (package_identifier) @alias
path: (interpreted_string_literal) @path
)
) @import_alias
""",
"calls": """
(call_expression
function: (identifier) @name
)
(call_expression
function: (selector_expression
field: (field_identifier) @name
)
)
""",
"variables": """
(var_declaration
(var_spec
name: (identifier) @name
)
)
(short_var_declaration
left: (expression_list
(identifier) @name
)
)
""",
}
class GoTreeSitterParser:
"""A Go-specific parser using tree-sitter, encapsulating language-specific logic."""
def __init__(self, generic_parser_wrapper):
self.generic_parser_wrapper = generic_parser_wrapper
self.language_name = generic_parser_wrapper.language_name
self.language = generic_parser_wrapper.language
self.parser = generic_parser_wrapper.parser
self.queries = {
name: self.language.query(query_str)
for name, query_str in GO_QUERIES.items()
}
def _get_node_text(self, node) -> str:
return node.text.decode('utf-8')
def _get_parent_context(self, node, types=('function_declaration', 'method_declaration', 'type_declaration')):
curr = node.parent
while curr:
if curr.type in types:
if curr.type == 'type_declaration':
type_spec = curr.child_by_field_name('type_spec')
if type_spec:
name_node = type_spec.child_by_field_name('name')
return self._get_node_text(name_node) if name_node else None, curr.type, curr.start_point[0] + 1
else:
name_node = curr.child_by_field_name('name')
return self._get_node_text(name_node) if name_node else None, curr.type, curr.start_point[0] + 1
curr = curr.parent
return None, None, None
def _calculate_complexity(self, node):
complexity_nodes = {
"if_statement", "for_statement", "switch_statement", "case_clause",
"expression_switch_statement", "type_switch_statement",
"binary_expression", "call_expression"
}
count = 1
def traverse(n):
nonlocal count
if n.type in complexity_nodes:
count += 1
for child in n.children:
traverse(child)
traverse(node)
return count
def _get_docstring(self, func_node):
"""Extract Go doc comment preceding the function."""
prev_sibling = func_node.prev_sibling
while prev_sibling and prev_sibling.type in ('comment', '\n', ' '):
if prev_sibling.type == 'comment':
comment_text = self._get_node_text(prev_sibling)
if comment_text.startswith('//'):
return comment_text.strip()
prev_sibling = prev_sibling.prev_sibling
return None
def parse(self, file_path: Path, is_dependency: bool = False) -> Dict:
"""Parses a file and returns its structure in a standardized dictionary format."""
# This method orchestrates the parsing of a single file.
# It calls specialized `_find_*` methods for each language construct.
# The returned dictionary should map a specific key (e.g., 'functions', 'interfaces')
# to a list of dictionaries, where each dictionary represents a single code construct.
# The GraphBuilder will then use these keys to create nodes with corresponding labels.
with open(file_path, "r", encoding="utf-8") as f:
source_code = f.read()
tree = self.parser.parse(bytes(source_code, "utf8"))
root_node = tree.root_node
functions = self._find_functions(root_node)
structs = self._find_structs(root_node)
interfaces = self._find_interfaces(root_node)
imports = self._find_imports(root_node)
function_calls = self._find_calls(root_node)
variables = self._find_variables(root_node)
return {
"file_path": str(file_path),
"functions": functions,
"classes": structs,
"interfaces": interfaces,
"variables": variables,
"imports": imports,
"function_calls": function_calls,
"is_dependency": is_dependency,
"lang": self.language_name,
}
def _find_functions(self, root_node):
functions = []
query = self.queries['functions']
captures_by_function = {}
for node, capture_name in query.captures(root_node):
if capture_name == 'function_node':
func_id = id(node)
if func_id not in captures_by_function:
captures_by_function[func_id] = {
'node': node,
'name': None,
'params': None,
'receiver': None
}
elif capture_name == 'name':
func_node = self._find_function_node_for_name(node)
if func_node:
func_id = id(func_node)
if func_id not in captures_by_function:
captures_by_function[func_id] = {
'node': func_node,
'name': None,
'params': None,
'receiver': None
}
captures_by_function[func_id]['name'] = self._get_node_text(node)
elif capture_name == 'params':
func_node = self._find_function_node_for_params(node)
if func_node:
func_id = id(func_node)
if func_id not in captures_by_function:
captures_by_function[func_id] = {
'node': func_node,
'name': None,
'params': None,
'receiver': None
}
captures_by_function[func_id]['params'] = node
elif capture_name == 'receiver':
func_node = node.parent
if func_node and func_node.type == 'method_declaration':
func_id = id(func_node)
if func_id not in captures_by_function:
captures_by_function[func_id] = {
'node': func_node,
'name': None,
'params': None,
'receiver': None
}
captures_by_function[func_id]['receiver'] = node
for func_id, data in captures_by_function.items():
if data['name']:
func_node = data['node']
name = data['name']
args = []
if data['params']:
args = self._extract_parameters(data['params'])
receiver_type = None
if data['receiver']:
receiver_type = self._extract_receiver(data['receiver'])
context, context_type, context_line = self._get_parent_context(func_node)
class_context = receiver_type or (context if context_type == 'type_declaration' else None)
docstring = self._get_docstring(func_node)
func_data = {
"name": name,
"line_number": func_node.start_point[0] + 1,
"end_line": func_node.end_point[0] + 1,
"args": args,
"source": self._get_node_text(func_node),
"source_code": self._get_node_text(func_node),
"docstring": docstring,
"cyclomatic_complexity": self._calculate_complexity(func_node),
"context": context,
"context_type": context_type,
"class_context": class_context,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
}
functions.append(func_data)
return functions
def _find_function_node_for_name(self, name_node):
current = name_node.parent
while current:
if current.type in ('function_declaration', 'method_declaration'):
return current
current = current.parent
return None
def _find_function_node_for_params(self, params_node):
current = params_node.parent
while current:
if current.type in ('function_declaration', 'method_declaration'):
return current
current = current.parent
return None
def _extract_parameters(self, params_node):
params = []
if params_node.type == 'parameter_list':
for child in params_node.children:
if child.type == 'parameter_declaration':
name_node = child.child_by_field_name('name')
if name_node:
params.append(self._get_node_text(name_node))
elif child.type == 'variadic_parameter_declaration':
name_node = child.child_by_field_name('name')
if name_node:
params.append(f"...{self._get_node_text(name_node)}")
return params
def _extract_receiver(self, receiver_node):
if receiver_node.type == 'parameter_list' and receiver_node.named_child_count > 0:
param = receiver_node.named_child(0)
type_node = param.child_by_field_name('type')
if type_node:
type_text = self._get_node_text(type_node)
return type_text.strip('*')
return None
def _find_structs(self, root_node):
structs = []
struct_query = self.queries['structs']
for node, capture_name in struct_query.captures(root_node):
if capture_name == 'name':
struct_node = self._find_type_declaration_for_name(node)
if struct_node:
name = self._get_node_text(node)
class_data = {
"name": name,
"line_number": struct_node.start_point[0] + 1,
"end_line": struct_node.end_point[0] + 1,
"bases": [],
"source": self._get_node_text(struct_node),
"docstring": self._get_docstring(struct_node),
"context": None,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
}
structs.append(class_data)
return structs
def _find_interfaces(self, root_node):
interfaces = []
interface_query = self.queries['interfaces']
for node, capture_name in interface_query.captures(root_node):
if capture_name == 'name':
interface_node = self._find_type_declaration_for_name(node)
if interface_node:
name = self._get_node_text(node)
class_data = {
"name": name,
"line_number": interface_node.start_point[0] + 1,
"end_line": interface_node.end_point[0] + 1,
"bases": [],
"source": self._get_node_text(interface_node),
"docstring": self._get_docstring(interface_node),
"context": None,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
}
interfaces.append(class_data)
return interfaces
def _find_type_declaration_for_name(self, name_node):
current = name_node.parent
while current:
if current.type == 'type_declaration':
return current
current = current.parent
return None
def _find_imports(self, root_node):
imports = []
query = self.queries['imports']
for node, capture_name in query.captures(root_node):
line_number = node.start_point[0] + 1
if capture_name == 'path':
path_text = self._get_node_text(node).strip('"')
package_name = path_text.split('/')[-1]
alias = None
import_spec = node.parent
if import_spec and import_spec.type == 'import_spec':
alias_node = import_spec.child_by_field_name('name')
if alias_node:
alias = self._get_node_text(alias_node)
imports.append({
'name': package_name,
'source': path_text,
'alias': alias,
'line_number': line_number,
'lang': self.language_name
})
return imports
def _find_calls(self, root_node):
calls = []
query = self.queries['calls']
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
call_node = node.parent
while call_node and call_node.type != 'call_expression':
call_node = call_node.parent
if call_node:
name = self._get_node_text(node)
call_data = {
"name": name,
"full_name": self._get_node_text(call_node.child_by_field_name('function')) if call_node.child_by_field_name('function') else name,
"line_number": node.start_point[0] + 1,
"args": [],
"inferred_obj_type": None,
"context": None,
"class_context": None,
"lang": self.language_name,
"is_dependency": False,
}
calls.append(call_data)
return calls
def _find_variables(self, root_node):
variables = []
query = self.queries['variables']
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
name = self._get_node_text(node)
variable_data = {
"name": name,
"line_number": node.start_point[0] + 1,
"value": None,
"type": None,
"context": None,
"class_context": None,
"lang": self.language_name,
"is_dependency": False,
}
variables.append(variable_data)
return variables
def pre_scan_go(files: list[Path], parser_wrapper) -> dict:
"""Scans Go files to create a map of function/struct names to their file paths."""
imports_map = {}
query_str = """
(function_declaration name: (identifier) @name)
(method_declaration name: (field_identifier) @name)
(type_declaration (type_spec name: (type_identifier) @name))
"""
query = parser_wrapper.language.query(query_str)
for file_path in files:
try:
with open(file_path, "r", encoding="utf-8") as f:
tree = parser_wrapper.parser.parse(bytes(f.read(), "utf8"))
for capture, _ in query.captures(tree.root_node):
name = capture.text.decode('utf-8')
if name not in imports_map:
imports_map[name] = []
imports_map[name].append(str(file_path.resolve()))
except Exception as e:
warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
return imports_map
```
--------------------------------------------------------------------------------
/tests/sample_project_typescript/src/utilities-helpers.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Utilities and Helpers
* Demonstrates common utility functions, type helpers, and patterns
* used in TypeScript projects for enhanced development experience
*/
// ========== String Utilities ==========
export const StringUtils = {
/**
* Capitalizes the first letter of a string
*/
capitalize: (str: string): string =>
str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(),
/**
* Converts string to camelCase
*/
camelCase: (str: string): string =>
str.replace(/[-_\s]+(.)?/g, (_, char) => (char ? char.toUpperCase() : '')),
/**
* Converts string to kebab-case
*/
kebabCase: (str: string): string =>
str.replace(/[A-Z]/g, letter => `-${letter.toLowerCase()}`).replace(/^-/, ''),
/**
* Converts string to snake_case
*/
snakeCase: (str: string): string =>
str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`).replace(/^_/, ''),
/**
* Truncates a string to specified length with ellipsis
*/
truncate: (str: string, length: number, suffix: string = '...'): string =>
str.length <= length ? str : str.slice(0, length) + suffix,
/**
* Removes extra whitespace and trims
*/
normalize: (str: string): string =>
str.replace(/\s+/g, ' ').trim(),
/**
* Pluralizes a word (simple English rules)
*/
pluralize: (word: string, count: number = 2): string => {
if (count === 1) return word;
if (word.endsWith('y')) return word.slice(0, -1) + 'ies';
if (word.endsWith('s') || word.endsWith('x') || word.endsWith('ch') || word.endsWith('sh')) {
return word + 'es';
}
return word + 's';
}
};
// ========== Array Utilities ==========
export const ArrayUtils = {
/**
* Chunks array into smaller arrays of specified size
*/
chunk: <T>(array: T[], size: number): T[][] => {
const chunks: T[][] = [];
for (let i = 0; i < array.length; i += size) {
chunks.push(array.slice(i, i + size));
}
return chunks;
},
/**
* Removes duplicate values from array
*/
unique: <T>(array: T[]): T[] => [...new Set(array)],
/**
* Groups array items by a key function
*/
groupBy: <T, K extends string | number | symbol>(
array: T[],
keyFn: (item: T) => K
): Record<K, T[]> => {
return array.reduce((groups, item) => {
const key = keyFn(item);
groups[key] = groups[key] || [];
groups[key]!.push(item);
return groups;
}, {} as Record<K, T[]>);
},
/**
* Flattens nested arrays by one level
*/
flatten: <T>(array: (T | T[])[]): T[] => array.flat() as T[],
/**
* Deeply flattens nested arrays
*/
flattenDeep: <T>(array: any[]): T[] => {
return array.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(ArrayUtils.flattenDeep(val)) : acc.concat(val), []
);
},
/**
* Shuffles array elements randomly
*/
shuffle: <T>(array: T[]): T[] => {
const result = [...array];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j]!, result[i]!];
}
return result;
},
/**
* Returns random element from array
*/
sample: <T>(array: T[]): T | undefined => {
return array[Math.floor(Math.random() * array.length)];
},
/**
* Returns multiple random elements from array
*/
sampleSize: <T>(array: T[], n: number): T[] => {
const shuffled = ArrayUtils.shuffle(array);
return shuffled.slice(0, Math.min(n, array.length));
}
};
// ========== Object Utilities ==========
export const ObjectUtils = {
/**
* Deep clones an object
*/
deepClone: <T>(obj: T): T => {
if (obj === null || typeof obj !== 'object') return obj;
if (obj instanceof Date) return new Date(obj.getTime()) as unknown as T;
if (obj instanceof Array) return obj.map(item => ObjectUtils.deepClone(item)) as unknown as T;
if (typeof obj === 'object') {
const copy = {} as T;
Object.keys(obj).forEach(key => {
(copy as any)[key] = ObjectUtils.deepClone((obj as any)[key]);
});
return copy;
}
return obj;
},
/**
* Merges objects deeply
*/
deepMerge: <T extends Record<string, any>, U extends Record<string, any>>(
target: T,
source: U
): T & U => {
const result = { ...target } as T & U;
Object.keys(source).forEach(key => {
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
if (result[key as keyof (T & U)] && typeof result[key as keyof (T & U)] === 'object') {
(result as any)[key] = ObjectUtils.deepMerge(
result[key as keyof (T & U)] as any,
source[key]
);
} else {
(result as any)[key] = ObjectUtils.deepClone(source[key]);
}
} else {
(result as any)[key] = source[key];
}
});
return result;
},
/**
* Picks specified keys from object
*/
pick: <T extends Record<string, any>, K extends keyof T>(
obj: T,
keys: K[]
): Pick<T, K> => {
const result = {} as Pick<T, K>;
keys.forEach(key => {
if (key in obj) {
result[key] = obj[key];
}
});
return result;
},
/**
* Omits specified keys from object
*/
omit: <T extends Record<string, any>, K extends keyof T>(
obj: T,
keys: K[]
): Omit<T, K> => {
const result = { ...obj };
keys.forEach(key => {
delete result[key];
});
return result as Omit<T, K>;
},
/**
* Gets nested value from object using dot notation
*/
get: <T>(obj: any, path: string, defaultValue?: T): T | undefined => {
const keys = path.split('.');
let result = obj;
for (const key of keys) {
if (result == null || typeof result !== 'object') {
return defaultValue;
}
result = result[key];
}
return result !== undefined ? result : defaultValue;
},
/**
* Sets nested value in object using dot notation
*/
set: (obj: any, path: string, value: any): void => {
const keys = path.split('.');
const lastKey = keys.pop()!;
let current = obj;
for (const key of keys) {
if (!(key in current) || typeof current[key] !== 'object') {
current[key] = {};
}
current = current[key];
}
current[lastKey] = value;
},
/**
* Checks if object has nested property
*/
has: (obj: any, path: string): boolean => {
const keys = path.split('.');
let current = obj;
for (const key of keys) {
if (current == null || typeof current !== 'object' || !(key in current)) {
return false;
}
current = current[key];
}
return true;
}
};
// ========== Function Utilities ==========
export const FunctionUtils = {
/**
* Debounces function execution
*/
debounce: <T extends (...args: any[]) => any>(
fn: T,
delay: number
): ((...args: Parameters<T>) => void) => {
let timeoutId: NodeJS.Timeout;
return (...args: Parameters<T>) => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => fn(...args), delay);
};
},
/**
* Throttles function execution
*/
throttle: <T extends (...args: any[]) => any>(
fn: T,
limit: number
): ((...args: Parameters<T>) => void) => {
let inThrottle: boolean;
return (...args: Parameters<T>) => {
if (!inThrottle) {
fn(...args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
},
/**
* Memoizes function results
*/
memoize: <T extends (...args: any[]) => any>(fn: T): T => {
const cache = new Map();
return ((...args: any[]) => {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;
}) as T;
},
/**
* Creates a curried version of function
*/
curry: <T extends (...args: any[]) => any>(
fn: T,
arity: number = fn.length
): any => {
return (...args: any[]) => {
if (args.length >= arity) {
return fn(...args);
}
return FunctionUtils.curry(fn.bind(null, ...args), arity - args.length);
};
},
/**
* Composes functions from right to left
*/
compose: <T>(...fns: Function[]): (arg: T) => any => {
return (arg: T) => fns.reduceRight((result, fn) => fn(result), arg);
},
/**
* Pipes functions from left to right
*/
pipe: <T>(...fns: Function[]): (arg: T) => any => {
return (arg: T) => fns.reduce((result, fn) => fn(result), arg);
}
};
// ========== Date Utilities ==========
export const DateUtils = {
/**
* Formats date to ISO string with timezone
*/
toISOString: (date: Date): string => date.toISOString(),
/**
* Formats date to readable string
*/
format: (date: Date, locale: string = 'en-US'): string =>
date.toLocaleDateString(locale),
/**
* Gets difference between dates in various units
*/
diff: (date1: Date, date2: Date, unit: 'days' | 'hours' | 'minutes' | 'seconds' = 'days'): number => {
const diffMs = Math.abs(date1.getTime() - date2.getTime());
switch (unit) {
case 'seconds': return Math.floor(diffMs / 1000);
case 'minutes': return Math.floor(diffMs / (1000 * 60));
case 'hours': return Math.floor(diffMs / (1000 * 60 * 60));
case 'days': return Math.floor(diffMs / (1000 * 60 * 60 * 24));
}
},
/**
* Adds time to date
*/
add: (date: Date, amount: number, unit: 'days' | 'hours' | 'minutes' | 'seconds'): Date => {
const result = new Date(date);
switch (unit) {
case 'seconds': result.setSeconds(result.getSeconds() + amount); break;
case 'minutes': result.setMinutes(result.getMinutes() + amount); break;
case 'hours': result.setHours(result.getHours() + amount); break;
case 'days': result.setDate(result.getDate() + amount); break;
}
return result;
},
/**
* Checks if date is between two dates
*/
isBetween: (date: Date, start: Date, end: Date): boolean =>
date >= start && date <= end,
/**
* Gets start of day
*/
startOfDay: (date: Date): Date => {
const result = new Date(date);
result.setHours(0, 0, 0, 0);
return result;
},
/**
* Gets end of day
*/
endOfDay: (date: Date): Date => {
const result = new Date(date);
result.setHours(23, 59, 59, 999);
return result;
}
};
// ========== Number Utilities ==========
export const NumberUtils = {
/**
* Clamps number between min and max
*/
clamp: (value: number, min: number, max: number): number =>
Math.min(Math.max(value, min), max),
/**
* Rounds to specified decimal places
*/
round: (value: number, decimals: number = 0): number =>
Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals),
/**
* Generates random number between min and max
*/
random: (min: number, max: number): number =>
Math.random() * (max - min) + min,
/**
* Generates random integer between min and max (inclusive)
*/
randomInt: (min: number, max: number): number =>
Math.floor(Math.random() * (max - min + 1)) + min,
/**
* Checks if number is in range
*/
inRange: (value: number, min: number, max: number): boolean =>
value >= min && value <= max,
/**
* Converts number to percentage string
*/
toPercent: (value: number, decimals: number = 2): string =>
`${NumberUtils.round(value * 100, decimals)}%`,
/**
* Formats number with thousands separators
*/
format: (value: number, locale: string = 'en-US'): string =>
value.toLocaleString(locale)
};
// ========== Type Utilities ==========
export type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
export type DeepRequired<T> = {
[P in keyof T]-?: T[P] extends object ? DeepRequired<T[P]> : T[P];
};
export type KeysOfType<T, U> = {
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T];
export type Writeable<T> = {
-readonly [P in keyof T]: T[P];
};
export type OptionalExcept<T, K extends keyof T> = Partial<T> & Pick<T, K>;
export type RequiredExcept<T, K extends keyof T> = Required<Omit<T, K>> & Partial<Pick<T, K>>;
// ========== Validation Helpers ==========
export const ValidationHelpers = {
/**
* Email validation
*/
isEmail: (value: string): boolean =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
/**
* URL validation
*/
isUrl: (value: string): boolean => {
try {
new URL(value);
return true;
} catch {
return false;
}
},
/**
* UUID validation
*/
isUuid: (value: string): boolean =>
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value),
/**
* Credit card number validation (Luhn algorithm)
*/
isCreditCard: (value: string): boolean => {
const num = value.replace(/\D/g, '');
if (num.length < 13 || num.length > 19) return false;
let sum = 0;
let isEven = false;
for (let i = num.length - 1; i >= 0; i--) {
let digit = parseInt(num[i]!);
if (isEven) {
digit *= 2;
if (digit > 9) digit -= 9;
}
sum += digit;
isEven = !isEven;
}
return sum % 10 === 0;
},
/**
* Strong password validation
*/
isStrongPassword: (value: string): boolean => {
const minLength = value.length >= 8;
const hasLower = /[a-z]/.test(value);
const hasUpper = /[A-Z]/.test(value);
const hasNumber = /\d/.test(value);
const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(value);
return minLength && hasLower && hasUpper && hasNumber && hasSpecial;
}
};
// ========== Color Utilities ==========
export const ColorUtils = {
/**
* Converts hex to RGB
*/
hexToRgb: (hex: string): { r: number; g: number; b: number } | null => {
const match = hex.match(/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i);
return match ? {
r: parseInt(match[1]!, 16),
g: parseInt(match[2]!, 16),
b: parseInt(match[3]!, 16)
} : null;
},
/**
* Converts RGB to hex
*/
rgbToHex: (r: number, g: number, b: number): string => {
const componentToHex = (c: number) => {
const hex = c.toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${componentToHex(r)}${componentToHex(g)}${componentToHex(b)}`;
},
/**
* Lightens a color by percentage
*/
lighten: (hex: string, percent: number): string => {
const rgb = ColorUtils.hexToRgb(hex);
if (!rgb) return hex;
const factor = 1 + percent / 100;
return ColorUtils.rgbToHex(
Math.min(255, Math.round(rgb.r * factor)),
Math.min(255, Math.round(rgb.g * factor)),
Math.min(255, Math.round(rgb.b * factor))
);
}
};
// ========== Performance Utilities ==========
export const PerformanceUtils = {
/**
* Measures execution time of a function
*/
measure: async <T>(fn: () => T | Promise<T>): Promise<{ result: T; duration: number }> => {
const start = performance.now();
const result = await fn();
const end = performance.now();
return { result, duration: end - start };
},
/**
* Creates a performance timer
*/
timer: () => {
const start = performance.now();
return {
stop: () => performance.now() - start,
lap: () => {
const current = performance.now();
return current - start;
}
};
},
/**
* Batches synchronous operations
*/
batch: <T, R>(
items: T[],
processor: (batch: T[]) => R[],
batchSize: number = 100
): R[] => {
const results: R[] = [];
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
results.push(...processor(batch));
}
return results;
}
};
// ========== Usage Examples ==========
export const utilityExamples = {
// String utilities
camelCased: StringUtils.camelCase("hello-world-example"),
kebabCased: StringUtils.kebabCase("HelloWorldExample"),
truncated: StringUtils.truncate("This is a very long string", 15),
// Array utilities
chunked: ArrayUtils.chunk([1, 2, 3, 4, 5, 6, 7], 3),
unique: ArrayUtils.unique([1, 2, 2, 3, 3, 3, 4]),
grouped: ArrayUtils.groupBy(
[{ type: 'fruit', name: 'apple' }, { type: 'vegetable', name: 'carrot' }],
item => item.type
),
// Object utilities
picked: ObjectUtils.pick({ a: 1, b: 2, c: 3 }, ['a', 'c']),
deepValue: ObjectUtils.get({ user: { profile: { name: 'John' } } }, 'user.profile.name'),
// Function utilities
debouncedLog: FunctionUtils.debounce((message: string) => console.log(message), 1000),
memoizedFib: FunctionUtils.memoize((n: number): number => {
if (n <= 1) return n;
return utilityExamples.memoizedFib(n - 1) + utilityExamples.memoizedFib(n - 2);
}),
// Date utilities
futureDate: DateUtils.add(new Date(), 7, 'days'),
daysDiff: DateUtils.diff(new Date('2023-12-31'), new Date('2023-01-01')),
// Number utilities
clamped: NumberUtils.clamp(150, 0, 100),
rounded: NumberUtils.round(3.14159, 2),
percentage: NumberUtils.toPercent(0.85),
// Validation
emailValid: ValidationHelpers.isEmail('[email protected]'),
strongPassword: ValidationHelpers.isStrongPassword('StrongPass123!'),
// Colors
rgbColor: ColorUtils.hexToRgb('#ff0000'),
lighterColor: ColorUtils.lighten('#ff0000', 20)
};
// Initialize some examples
console.log('Utility examples initialized:', {
camelCased: utilityExamples.camelCased,
chunked: utilityExamples.chunked,
deepValue: utilityExamples.deepValue
});
```
--------------------------------------------------------------------------------
/docs/site/use_cases/index.html:
--------------------------------------------------------------------------------
```html
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="prev" href="../installation/">
<link rel="next" href="../architecture/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
<title>Use Cases - CodeGraphContext</title>
<link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<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">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<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>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#real-world-use-cases" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
CodeGraphContext
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Use Cases
</span>
</div>
</div>
</div>
<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>
<label class="md-header__button md-icon" for="__search">
<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>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<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>
<label class="md-search__icon md-icon" for="__search">
<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>
<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>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<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>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
CodeGraphContext
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Use Cases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/" class="md-nav__link">
<span class="md-ellipsis">
CLI Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../server/" class="md-nav__link">
<span class="md-ellipsis">
Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../core/" class="md-nav__link">
<span class="md-ellipsis">
Core Concepts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/" class="md-nav__link">
<span class="md-ellipsis">
Tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cookbook/" class="md-nav__link">
<span class="md-ellipsis">
Cookbook
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" >
<label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
<span class="md-ellipsis">
Contributing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
Contributing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../contributing/" class="md-nav__link">
<span class="md-ellipsis">
Overview
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../contributing_languages/" class="md-nav__link">
<span class="md-ellipsis">
Adding New Languages
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../troubleshooting/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../future_work/" class="md-nav__link">
<span class="md-ellipsis">
Future Work
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
License
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="real-world-use-cases">Real World Use Cases</h1>
<p>CodeGraphContext can be a powerful ally in your daily coding journey. Here are some real-world scenarios where it can significantly boost your productivity and understanding of a codebase:</p>
<ol>
<li>
<p><strong>Onboarding New Developers:</strong> A new team member can quickly get up to speed by asking questions like:</p>
<ul>
<li>"Where is the authentication logic handled?"</li>
<li>"Show me the main entry point of the application."</li>
</ul>
</li>
<li>
<p><strong>Impact Analysis:</strong> Before making a change, assess the potential ripple effects:</p>
<ul>
<li>"What other parts of the code will be affected if I change the <code>calculate_total</code> function?"</li>
</ul>
</li>
<li>
<p><strong>Code Review:</strong> Gain context on pull requests faster:</p>
<ul>
<li>"Show me the callers of this new function."</li>
<li>"Does this change introduce any new dependencies?"</li>
</ul>
</li>
<li>
<p><strong>Debugging:</strong> Trace execution flows to pinpoint the source of a bug:</p>
<ul>
<li>"Show me the call chain from <code>handle_request</code> to <code>process_payment</code>."</li>
</ul>
</li>
<li>
<p><strong>Refactoring:</strong> Identify and plan large-scale code changes:</p>
<ul>
<li>"Find all instances of the deprecated <code>OldApiClass</code>."</li>
<li>"List all functions that use the <code>urllib</code> library so I can replace them with <code>requests</code>."</li>
</ul>
</li>
<li>
<p><strong>Identifying Code Smells:</strong> Proactively find areas that need improvement:</p>
<ul>
<li>"Find the 10 most complex functions in the codebase."</li>
<li>"Show me functions with more than 5 arguments."</li>
</ul>
</li>
<li>
<p><strong>Security Audits:</strong> Search for potentially vulnerable code patterns:</p>
<ul>
<li>"Find all functions that use the <code>eval</code> function."</li>
<li>"Show me where raw SQL queries are being executed."</li>
</ul>
</li>
<li>
<p><strong>Automated Documentation:</strong> Use the tool's understanding of the code to generate documentation. (This is what this agent is doing!)</p>
</li>
<li>
<p><strong>Dependency Management:</strong> Understand how your project uses its dependencies:</p>
<ul>
<li>"Which files import the <code>requests</code> library?"</li>
<li>"Are there any circular dependencies between modules?"</li>
</ul>
</li>
<li>
<p><strong>Cleaning Up Unused Code:</strong> Keep your codebase lean and maintainable:</p>
<ul>
<li>"Is there any dead or unused code in this project?"</li>
</ul>
</li>
<li>
<p><strong>Exploring a Large Codebase:</strong> Navigate large, unfamiliar projects with ease:</p>
<ul>
<li>"List all the classes in the <code>core</code> module."</li>
<li>"What are the top-level functions in the <code>utils</code> directory?"</li>
</ul>
</li>
<li>
<p><strong>Enforcing Coding Standards:</strong> Check for adherence to team conventions:</p>
<ul>
<li>"Find all functions that are not decorated with <code>@log_execution</code>."</li>
<li>"Show me all public methods that don't have a docstring."</li>
</ul>
</li>
<li>
<p><strong>Discovering API Usage:</strong> Find examples of how to use internal or external APIs:</p>
<ul>
<li>"Show me how other parts of the code use the <code>UserService</code>."</li>
</ul>
</li>
<li>
<p><strong>Improving Test Coverage:</strong> Identify areas that may lack test coverage:</p>
<ul>
<li>"Find all functions that are not called by any test files."</li>
</ul>
</li>
<li>
<p><strong>Visualizing Code Structure:</strong> Get a bird's-eye view of your project's architecture:</p>
<ul>
<li>"Generate a graph visualization of the <code>auth</code> module and its dependencies."</li>
</ul>
</li>
<li>
<p><strong>Learning a New Framework:</strong> Understand how a new framework operates by exploring its source code.</p>
</li>
<li>
<p><strong>Code Archeology:</strong> Investigate legacy code to understand its history and purpose.</p>
</li>
<li>
<p><strong>Planning a Migration:</strong> Identify all points of contact when migrating a library or framework:</p>
<ul>
<li>"Find all the places where the <code>old_payment_gateway</code> is used."</li>
</ul>
</li>
<li>
<p><strong>Knowledge Sharing:</strong> Use the code graph as a centralized, always-up-to-date knowledge base for your team.</p>
</li>
<li>
<p><strong>Automated Code Reviews:</strong> Integrate CodeGraphContext into your CI/CD pipeline to automatically flag potential issues in pull requests.</p>
</li>
</ol>
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<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>
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>
```
--------------------------------------------------------------------------------
/docs/site/contributing/index.html:
--------------------------------------------------------------------------------
```html
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="prev" href="../cookbook/">
<link rel="next" href="../contributing_languages/">
<link rel="icon" href="../assets/images/favicon.png">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.6.21">
<title>Overview - CodeGraphContext</title>
<link rel="stylesheet" href="../assets/stylesheets/main.2a3383ac.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<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">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<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>
</head>
<body dir="ltr">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#contributing-to-codegraphcontext" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header md-header--shadow" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
CodeGraphContext
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Overview
</span>
</div>
</div>
</div>
<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>
<label class="md-header__button md-icon" for="__search">
<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>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<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>
<label class="md-search__icon md-icon" for="__search">
<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>
<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>
</label>
<nav class="md-search__options" aria-label="Search">
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<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>
</button>
</nav>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
<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>
</a>
CodeGraphContext
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href=".." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../use_cases/" class="md-nav__link">
<span class="md-ellipsis">
Use Cases
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../architecture/" class="md-nav__link">
<span class="md-ellipsis">
Architecture
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cli/" class="md-nav__link">
<span class="md-ellipsis">
CLI Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../server/" class="md-nav__link">
<span class="md-ellipsis">
Server
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../core/" class="md-nav__link">
<span class="md-ellipsis">
Core Concepts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tools/" class="md-nav__link">
<span class="md-ellipsis">
Tools
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../cookbook/" class="md-nav__link">
<span class="md-ellipsis">
Cookbook
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_10" checked>
<label class="md-nav__link" for="__nav_10" id="__nav_10_label" tabindex="0">
<span class="md-ellipsis">
Contributing
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_10_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_10">
<span class="md-nav__icon md-icon"></span>
Contributing
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Overview
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Overview
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#general-guidelines" class="md-nav__link">
<span class="md-ellipsis">
General Guidelines
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-your-development-environment" class="md-nav__link">
<span class="md-ellipsis">
Setting up Your Development Environment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging" class="md-nav__link">
<span class="md-ellipsis">
Debugging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#running-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#submitting-changes" class="md-nav__link">
<span class="md-ellipsis">
Submitting Changes
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../contributing_languages/" class="md-nav__link">
<span class="md-ellipsis">
Adding New Languages
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../troubleshooting/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../future_work/" class="md-nav__link">
<span class="md-ellipsis">
Future Work
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../license/" class="md-nav__link">
<span class="md-ellipsis">
License
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#general-guidelines" class="md-nav__link">
<span class="md-ellipsis">
General Guidelines
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#setting-up-your-development-environment" class="md-nav__link">
<span class="md-ellipsis">
Setting up Your Development Environment
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#debugging" class="md-nav__link">
<span class="md-ellipsis">
Debugging
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#running-tests" class="md-nav__link">
<span class="md-ellipsis">
Running Tests
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#submitting-changes" class="md-nav__link">
<span class="md-ellipsis">
Submitting Changes
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="contributing-to-codegraphcontext">Contributing to CodeGraphContext</h1>
<p>We welcome contributions! Please follow these steps:</p>
<h2 id="general-guidelines">General Guidelines</h2>
<ul>
<li>Ensure your code adheres to the existing style and conventions of the project.</li>
<li>Write clear, concise, and well-documented code.</li>
<li>All new features or bug fixes should be accompanied by appropriate tests.</li>
<li>Keep your pull requests focused on a single feature or bug fix.</li>
</ul>
<h2 id="setting-up-your-development-environment">Setting up Your Development Environment</h2>
<ol>
<li>Fork the repository.</li>
<li>Set up your development environment: <code>pip install -e ".[dev]"</code></li>
<li>Create a new branch for your feature or bugfix (e.g., <code>git checkout -b feature/my-new-feature</code>).</li>
</ol>
<h2 id="debugging">Debugging</h2>
<p>To enable debug mode for detailed logging, locate the <code>debug_mode</code> variable in <code>src/codegraphcontext/tools/graph_builder.py</code> and set its value to <code>1</code>.</p>
<pre><code class="language-python"># src/codegraphcontext/tools/graph_builder.py
debug_mode = 1
</code></pre>
<h2 id="running-tests">Running Tests</h2>
<p>Tests are located in the <code>tests/</code> directory and are run using <code>pytest</code>.</p>
<ol>
<li>Navigate to the root of the <code>CodeGraphContext</code> directory.</li>
<li>Run all tests using the command: <code>pytest</code></li>
<li>To run specific tests, you can provide the path to the test file, for example: <code>pytest tests/test_tools.py</code></li>
<li><strong>Skipping Re-indexing:</strong> To speed up test runs, especially during development, you can set the <code>CGC_SKIP_REINDEX</code> environment variable to <code>true</code>. This will prevent the test suite from re-indexing the sample project if it's already indexed.
<code>bash
CGC_SKIP_REINDEX=true pytest</code></li>
</ol>
<h2 id="submitting-changes">Submitting Changes</h2>
<ol>
<li>Write your code and add corresponding tests in the <code>tests/</code> directory.</li>
<li>Ensure all tests pass and your code lints without errors.</li>
<li>Commit your changes with a descriptive commit message.</li>
<li>Submit a pull request to the <code>main</code> branch.</li>
</ol>
<!-- "Failed to check job status: 'JobManager' object has no attribute 'JobStatus'" -->
</article>
</div>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
</main>
<footer class="md-footer">
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<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>
<script src="../assets/javascripts/bundle.f55a23d4.min.js"></script>
</body>
</html>
```
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/languages/ruby.py:
--------------------------------------------------------------------------------
```python
from pathlib import Path
from typing import Any, Dict, Optional, Tuple
from codegraphcontext.utils.debug_log import debug_log, info_logger, error_logger, warning_logger, debug_logger
RUBY_QUERIES = {
"functions": """
(method
name: (identifier) @name
) @function_node
""",
"classes": """
(class
name: (constant) @name
) @class
""",
"modules": """
(module
name: (constant) @name
) @module_node
""",
"imports": """
(call
method: (identifier) @method_name
arguments: (argument_list
(string) @path
)
) @import
""",
"calls": """
(call
method: (identifier) @name
)
""",
"variables": """
(assignment
left: (identifier) @name
right: (_) @value
)
(assignment
left: (instance_variable) @name
right: (_) @value
)
""",
"comments": """
(comment) @comment
""",
"module_includes": """
(call
method: (identifier) @method
arguments: (argument_list (constant) @module)
) @include_call
""",
}
class RubyTreeSitterParser:
"""A Ruby-specific parser using tree-sitter."""
def __init__(self, generic_parser_wrapper: Any):
self.generic_parser_wrapper = generic_parser_wrapper
self.language_name = "ruby"
self.language = generic_parser_wrapper.language
self.parser = generic_parser_wrapper.parser
self.queries = {
name: self.language.query(query_str)
for name, query_str in RUBY_QUERIES.items()
}
def _get_node_text(self, node: Any) -> str:
return node.text.decode("utf-8")
def _enclosing_class_name(self, node: Any) -> Optional[str]:
name, typ, _ = self._get_parent_context(node, ('class',))
return name
def _find_modules(self, root_node: Any) -> list[Dict[str, Any]]:
modules = []
query = self.queries["modules"]
# name via captures
captures = list(query.captures(root_node))
for node, cap in captures:
if cap == "module_node":
name = None
for n, c in captures:
if c == "name":
if n.start_byte >= node.start_byte and n.end_byte <= node.end_byte:
name = self._get_node_text(n)
break
if name:
modules.append({
"name": name,
"line_number": node.start_point[0] + 1,
"end_line": node.end_point[0] + 1,
"source": self._get_node_text(node),
"source_code": self._get_node_text(node),
"lang": self.language_name,
"is_dependency": False,
})
return modules
def _find_module_inclusions(self, root_node: Any) -> list[Dict[str, Any]]:
includes = []
query = self.queries["module_includes"]
for node, cap in query.captures(root_node):
if cap == "method":
method_name = self._get_node_text(node)
if method_name != "include":
continue
if cap == "include_call":
method = None
module = None
for n, c in query.captures(node):
if c == "method":
method = self._get_node_text(n)
elif c == "module":
module = self._get_node_text(n)
if method == "include" and module:
cls = self._enclosing_class_name(node)
if cls:
includes.append({
"class": cls,
"module": module,
"line_number": node.start_point[0] + 1,
"lang": self.language_name,
"is_dependency": False,
})
return includes
def _get_parent_context(self, node: Any, types: Tuple[str, ...] = ('class', 'module', 'method')):
"""Find parent context for Ruby constructs."""
curr = node.parent
while curr:
if curr.type in types:
name_node = curr.child_by_field_name('name')
if name_node:
return self._get_node_text(name_node), curr.type, curr.start_point[0] + 1
curr = curr.parent
return None, None, None
def _calculate_complexity(self, node: Any) -> int:
"""Calculate cyclomatic complexity for Ruby constructs."""
complexity_nodes = {
"if", "unless", "case", "when", "while", "until", "for", "rescue", "ensure",
"and", "or", "&&", "||", "?", "ternary"
}
count = 1
def traverse(n):
nonlocal count
if n.type in complexity_nodes:
count += 1
for child in n.children:
traverse(child)
traverse(node)
return count
def _get_docstring(self, node: Any) -> Optional[str]:
"""Extract comments as docstrings for Ruby constructs."""
# Look for comments before the node
prev_sibling = node.prev_sibling
while prev_sibling and prev_sibling.type in ('comment', '\n', ' '):
if prev_sibling.type == 'comment':
comment_text = self._get_node_text(prev_sibling)
if comment_text.startswith('#') and not comment_text.startswith('#!'):
return comment_text.strip()
prev_sibling = prev_sibling.prev_sibling
return None
def _parse_method_parameters(self, method_node: Any) -> list[str]:
"""Parse method parameters from a method node."""
params = []
# Look for parameters in the method node
for child in method_node.children:
if child.type == 'identifier' and child != method_node.child_by_field_name('name'):
# This is likely a parameter
params.append(self._get_node_text(child))
return params
def parse(self, file_path: Path, is_dependency: bool = False) -> Dict[str, Any]:
"""Parses a Ruby file and returns its structure."""
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
source_code = f.read()
tree = self.parser.parse(bytes(source_code, "utf8"))
root_node = tree.root_node
functions = self._find_functions(root_node)
classes = self._find_classes(root_node)
imports = self._find_imports(root_node)
function_calls = self._find_calls(root_node)
variables = self._find_variables(root_node)
modules = self._find_modules(root_node)
module_inclusions = self._find_module_inclusions(root_node)
return {
"file_path": str(file_path),
"functions": functions,
"classes": classes,
"variables": variables,
"imports": imports,
"function_calls": function_calls,
"is_dependency": is_dependency,
"lang": self.language_name,
"modules": modules,
"module_inclusions": module_inclusions,
}
def _find_functions(self, root_node: Any) -> list[Dict[str, Any]]:
"""Find all function/method definitions."""
functions = []
query = self.queries["functions"]
# Collect all captures first
all_captures = list(query.captures(root_node))
# Group captures by function node using a different approach
captures_by_function = {}
for node, capture_name in all_captures:
if capture_name == 'function_node':
captures_by_function[id(node)] = {'node': node, 'name': None}
# Now find names for each function
for node, capture_name in all_captures:
if capture_name == 'name':
# Find which function this name belongs to
for func_id, func_data in captures_by_function.items():
func_node = func_data['node']
# Check if this name node is within the function node
if (node.start_byte >= func_node.start_byte and
node.end_byte <= func_node.end_byte):
captures_by_function[func_id]['name'] = self._get_node_text(node)
break
# Build function entries
for func_data in captures_by_function.values():
func_node = func_data['node']
name = func_data['name']
if name:
args = self._parse_method_parameters(func_node)
# Get context and docstring
context, context_type, _ = self._get_parent_context(func_node)
class_context = context if context_type in ('class', 'module') else None
docstring = self._get_docstring(func_node)
functions.append({
"name": name,
"line_number": func_node.start_point[0] + 1,
"end_line": func_node.end_point[0] + 1,
"args": args,
"source": self._get_node_text(func_node),
"source_code": self._get_node_text(func_node),
"docstring": docstring,
"cyclomatic_complexity": self._calculate_complexity(func_node),
"context": context,
"context_type": context_type,
"class_context": class_context,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
})
return functions
def _find_classes(self, root_node: Any) -> list[Dict[str, Any]]:
"""Find all class and module definitions."""
classes = []
query = self.queries["classes"]
# Collect all captures first
all_captures = list(query.captures(root_node))
# Group captures by class node using a different approach
captures_by_class = {}
for node, capture_name in all_captures:
if capture_name == 'class':
captures_by_class[id(node)] = {'node': node, 'name': None}
# Now find names for each class
for node, capture_name in all_captures:
if capture_name == 'name':
# Find which class this name belongs to
for class_id, class_data in captures_by_class.items():
class_node = class_data['node']
# Check if this name node is within the class node
if (node.start_byte >= class_node.start_byte and
node.end_byte <= class_node.end_byte):
captures_by_class[class_id]['name'] = self._get_node_text(node)
break
# Build class entries
for class_data in captures_by_class.values():
class_node = class_data['node']
name = class_data['name']
if name:
# Get superclass for inheritance (simplified)
bases = []
# Get docstring
docstring = self._get_docstring(class_node)
classes.append({
"name": name,
"line_number": class_node.start_point[0] + 1,
"end_line": class_node.end_point[0] + 1,
"bases": bases,
"source": self._get_node_text(class_node),
"source_code": self._get_node_text(class_node),
"docstring": docstring,
"context": None,
"decorators": [],
"lang": self.language_name,
"is_dependency": False,
})
return classes
def _find_imports(self, root_node: Any) -> list[Dict[str, Any]]:
"""Find all require/load statements."""
imports = []
query = self.queries["imports"]
# Collect all captures first
all_captures = list(query.captures(root_node))
# Group captures by import node using a different approach
captures_by_import = {}
for node, capture_name in all_captures:
if capture_name == 'import':
captures_by_import[id(node)] = {'node': node, 'method_name': None, 'path': None}
# Now find method names and paths for each import
for node, capture_name in all_captures:
if capture_name == 'method_name':
# Find which import this method name belongs to
for import_id, import_data in captures_by_import.items():
import_node = import_data['node']
# Check if this method name node is within the import node
if (node.start_byte >= import_node.start_byte and
node.end_byte <= import_node.end_byte):
captures_by_import[import_id]['method_name'] = self._get_node_text(node)
break
elif capture_name == 'path':
# Find which import this path belongs to
for import_id, import_data in captures_by_import.items():
import_node = import_data['node']
# Check if this path node is within the import node
if (node.start_byte >= import_node.start_byte and
node.end_byte <= import_node.end_byte):
captures_by_import[import_id]['path'] = self._get_node_text(node)
break
# Build import entries
for import_data in captures_by_import.values():
import_node = import_data['node']
method_name = import_data['method_name']
path = import_data['path']
if method_name and path:
path = path.strip('\'"')
# Only process require/load statements
if method_name in ('require', 'require_relative', 'load'):
imports.append({
"name": path,
"full_import_name": f"{method_name} '{path}'",
"line_number": import_node.start_point[0] + 1,
"alias": None,
"lang": self.language_name,
"is_dependency": False,
})
return imports
def _find_calls(self, root_node: Any) -> list[Dict[str, Any]]:
"""Find all function and method calls."""
calls = []
query = self.queries["calls"]
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
name = self._get_node_text(node)
full_name = name
calls.append({
"name": name,
"full_name": full_name,
"line_number": node.start_point[0] + 1,
"args": [], # Placeholder - could be enhanced to extract arguments
"inferred_obj_type": None,
"context": None, # Placeholder
"class_context": None, # Placeholder
"lang": self.language_name,
"is_dependency": False,
})
return calls
def _find_variables(self, root_node: Any) -> list[Dict[str, Any]]:
"""Find all variable assignments."""
variables = []
query = self.queries["variables"]
# Group captures by assignment node
captures_by_assignment = {}
for node, capture_name in query.captures(root_node):
if capture_name == 'name':
# Find the parent assignment node
current = node.parent
while current and current.type != 'assignment':
current = current.parent
if current:
assignment_id = id(current)
if assignment_id not in captures_by_assignment:
captures_by_assignment[assignment_id] = {'node': current, 'name': None, 'value': None}
captures_by_assignment[assignment_id]['name'] = self._get_node_text(node)
elif capture_name == 'value':
# Find the parent assignment node
current = node.parent
while current and current.type != 'assignment':
current = current.parent
if current:
assignment_id = id(current)
if assignment_id not in captures_by_assignment:
captures_by_assignment[assignment_id] = {'node': current, 'name': None, 'value': None}
captures_by_assignment[assignment_id]['value'] = self._get_node_text(node)
# Build variable entries
for var_data in captures_by_assignment.values():
name = var_data['name']
value = var_data['value']
if name:
# Determine variable type based on name prefix
var_type = "local"
if name.startswith("@"):
var_type = "instance"
elif name.startswith("@@"):
var_type = "class"
elif name.startswith("$"):
var_type = "global"
variables.append({
"name": name,
"line_number": var_data['node'].start_point[0] + 1,
"value": value,
"type": var_type,
"context": None, # Placeholder
"class_context": None, # Placeholder
"lang": self.language_name,
"is_dependency": False,
})
return variables
def pre_scan_ruby(files: list[Path], parser_wrapper) -> dict:
"""Scans Ruby files to create a map of class/method names to their file paths."""
imports_map = {}
query_str = """
(class
name: (constant) @name
)
(module
name: (constant) @name
)
(method
name: (identifier) @name
)
"""
query = parser_wrapper.language.query(query_str)
for file_path in files:
try:
with open(file_path, "r", encoding="utf-8") as f:
tree = parser_wrapper.parser.parse(bytes(f.read(), "utf8"))
for capture, _ in query.captures(tree.root_node):
name = capture.text.decode('utf-8')
if name not in imports_map:
imports_map[name] = []
imports_map[name].append(str(file_path.resolve()))
except Exception as e:
warning_logger(f"Tree-sitter pre-scan failed for {file_path}: {e}")
return imports_map
```