This is page 18 of 22. Use http://codebase.md/shashankss1205/codegraphcontext?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .cgcignore
├── .github
│ ├── FUNDING.yml
│ └── workflows
│ ├── e2e-tests.yml
│ ├── post_discord_invite.yml
│ ├── test.yml
│ └── update-contributors.yml
├── .gitignore
├── CLI_Commands.md
├── 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
│ │ └── watching.md
│ ├── mkdocs.yml
│ └── site
│ ├── 404.html
│ ├── architecture
│ │ └── index.html
│ ├── assets
│ │ ├── images
│ │ │ └── favicon.png
│ │ ├── javascripts
│ │ │ ├── bundle.79ae519e.min.js
│ │ │ ├── bundle.79ae519e.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.2c215733.min.js
│ │ │ └── search.2c215733.min.js.map
│ │ └── stylesheets
│ │ ├── main.484c7ddc.min.css
│ │ ├── main.484c7ddc.min.css.map
│ │ ├── palette.ab4e12ef.min.css
│ │ └── palette.ab4e12ef.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
│ └── watching
│ └── index.html
├── funding.json
├── 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
├── pyproject.toml
├── README.md
├── scripts
│ ├── generate_lang_contributors.py
│ ├── post_install_fix.sh
│ ├── test_all_parsers.py
│ └── update_language_parsers.py
├── SECURITY.md
├── src
│ └── codegraphcontext
│ ├── __init__.py
│ ├── __main__.py
│ ├── cli
│ │ ├── __init__.py
│ │ ├── cli_helpers.py
│ │ ├── config_manager.py
│ │ ├── main.py
│ │ ├── setup_macos.py
│ │ └── setup_wizard.py
│ ├── core
│ │ ├── __init__.py
│ │ ├── database_falkordb.py
│ │ ├── database.py
│ │ ├── falkor_worker.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
│ │ │ ├── csharp.py
│ │ │ ├── go.py
│ │ │ ├── java.py
│ │ │ ├── javascript.py
│ │ │ ├── kotlin.py
│ │ │ ├── php.py
│ │ │ ├── python.py
│ │ │ ├── ruby.py
│ │ │ ├── rust.py
│ │ │ ├── scala.py
│ │ │ ├── swift.py
│ │ │ ├── typescript.py
│ │ │ └── typescriptjsx.py
│ │ ├── package_resolver.py
│ │ ├── query_tool_languages
│ │ │ ├── c_toolkit.py
│ │ │ ├── cpp_toolkit.py
│ │ │ ├── csharp_toolkit.py
│ │ │ ├── go_toolkit.py
│ │ │ ├── java_toolkit.py
│ │ │ ├── javascript_toolkit.py
│ │ │ ├── python_toolkit.py
│ │ │ ├── ruby_toolkit.py
│ │ │ ├── rust_toolkit.py
│ │ │ ├── scala_toolkit.py
│ │ │ ├── swift_toolkit.py
│ │ │ └── typescript_toolkit.py
│ │ └── system.py
│ └── utils
│ ├── debug_log.py
│ └── tree_sitter_manager.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_csharp
│ │ ├── README.md
│ │ └── src
│ │ └── Example.App
│ │ ├── Attributes
│ │ │ └── CustomAttributes.cs
│ │ ├── Example.App.csproj
│ │ ├── Models
│ │ │ ├── Person.cs
│ │ │ ├── Point.cs
│ │ │ ├── Role.cs
│ │ │ └── User.cs
│ │ ├── OuterClass.cs
│ │ ├── Program.cs
│ │ ├── Services
│ │ │ ├── GreetingService.cs
│ │ │ ├── IGreetingService.cs
│ │ │ └── LegacyService.cs
│ │ └── Utils
│ │ ├── CollectionHelper.cs
│ │ └── FileHelper.cs
│ ├── 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_kotlin
│ │ ├── AdvancedClasses.kt
│ │ ├── Annotations.kt
│ │ ├── Coroutines.kt
│ │ ├── EdgeCases.kt
│ │ ├── Functions.kt
│ │ ├── Main.kt
│ │ ├── Properties.kt
│ │ └── User.kt
│ ├── 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_scala
│ │ ├── Animals.scala
│ │ ├── Complex.scala
│ │ ├── Functional.scala
│ │ ├── Geometry.scala
│ │ ├── Main.scala
│ │ ├── PackageObject.scala
│ │ ├── Script.sc
│ │ ├── Services.scala
│ │ ├── Shapes.scala
│ │ ├── Utils.scala
│ │ └── Variables.scala
│ ├── sample_project_swift
│ │ ├── Generics.swift
│ │ ├── Main.swift
│ │ ├── README.md
│ │ ├── Shapes.swift
│ │ ├── User.swift
│ │ └── Vehicles.swift
│ ├── sample_project_typescript
│ │ ├── package.json
│ │ ├── README.md
│ │ ├── sample_tsx.tsx
│ │ ├── 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_kotlin_parser.py
│ ├── test_swift_parser.py
│ ├── test_tree_sitter
│ │ ├── __init__.py
│ │ ├── class_instantiation.py
│ │ ├── complex_classes.py
│ │ └── test_file.py
│ ├── test_tree_sitter_manager.py
│ └── test_typescript_parser.py
├── visualize_graph.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
│ │ │ ├── SocialMentionsTimeline.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
└── windows_setup_guide.md
```
# Files
--------------------------------------------------------------------------------
/src/codegraphcontext/tools/graph_builder.py:
--------------------------------------------------------------------------------
```python
1 |
2 | # src/codegraphcontext/tools/graph_builder.py
3 | import asyncio
4 | import pathspec
5 | from pathlib import Path
6 | from typing import Any, Coroutine, Dict, Optional, Tuple
7 | from datetime import datetime
8 |
9 | from ..core.database import DatabaseManager
10 | from ..core.jobs import JobManager, JobStatus
11 | from ..utils.debug_log import debug_log, info_logger, error_logger, warning_logger
12 |
13 | # New imports for tree-sitter (using tree-sitter-language-pack)
14 | from tree_sitter import Language, Parser
15 | from ..utils.tree_sitter_manager import get_tree_sitter_manager
16 | from ..cli.config_manager import get_config_value
17 |
18 | class TreeSitterParser:
19 | """A generic parser wrapper for a specific language using tree-sitter."""
20 |
21 | def __init__(self, language_name: str):
22 | self.language_name = language_name
23 | self.ts_manager = get_tree_sitter_manager()
24 |
25 | # Get the language (cached) and create a new parser for this instance
26 | self.language: Language = self.ts_manager.get_language_safe(language_name)
27 | # In tree-sitter 0.25+, Parser takes language in constructor
28 | self.parser = Parser(self.language)
29 |
30 | self.language_specific_parser = None
31 | if self.language_name == 'python':
32 | from .languages.python import PythonTreeSitterParser
33 | self.language_specific_parser = PythonTreeSitterParser(self)
34 | elif self.language_name == 'javascript':
35 | from .languages.javascript import JavascriptTreeSitterParser
36 | self.language_specific_parser = JavascriptTreeSitterParser(self)
37 | elif self.language_name == 'go':
38 | from .languages.go import GoTreeSitterParser
39 | self.language_specific_parser = GoTreeSitterParser(self)
40 | elif self.language_name == 'typescript':
41 | from .languages.typescript import TypescriptTreeSitterParser
42 | self.language_specific_parser = TypescriptTreeSitterParser(self)
43 | elif self.language_name == 'cpp':
44 | from .languages.cpp import CppTreeSitterParser
45 | self.language_specific_parser = CppTreeSitterParser(self)
46 | elif self.language_name == 'rust':
47 | from .languages.rust import RustTreeSitterParser
48 | self.language_specific_parser = RustTreeSitterParser(self)
49 | elif self.language_name == 'c':
50 | from .languages.c import CTreeSitterParser
51 | self.language_specific_parser = CTreeSitterParser(self)
52 | elif self.language_name == 'java':
53 | from .languages.java import JavaTreeSitterParser
54 | self.language_specific_parser = JavaTreeSitterParser(self)
55 | elif self.language_name == 'ruby':
56 | from .languages.ruby import RubyTreeSitterParser
57 | self.language_specific_parser = RubyTreeSitterParser(self)
58 | elif self.language_name == 'c_sharp':
59 | from .languages.csharp import CSharpTreeSitterParser
60 | self.language_specific_parser = CSharpTreeSitterParser(self)
61 | elif self.language_name == 'php':
62 | from .languages.php import PhpTreeSitterParser
63 | self.language_specific_parser = PhpTreeSitterParser(self)
64 | elif self.language_name == 'kotlin':
65 | from .languages.kotlin import KotlinTreeSitterParser
66 | self.language_specific_parser = KotlinTreeSitterParser(self)
67 | elif self.language_name == 'scala':
68 | from .languages.scala import ScalaTreeSitterParser
69 | self.language_specific_parser = ScalaTreeSitterParser(self)
70 | elif self.language_name == 'swift':
71 | from .languages.swift import SwiftTreeSitterParser
72 | self.language_specific_parser = SwiftTreeSitterParser(self)
73 |
74 |
75 |
76 | def parse(self, file_path: Path, is_dependency: bool = False, **kwargs) -> Dict:
77 | """Dispatches parsing to the language-specific parser."""
78 | if self.language_specific_parser:
79 | return self.language_specific_parser.parse(file_path, is_dependency, **kwargs)
80 | else:
81 | raise NotImplementedError(f"No language-specific parser implemented for {self.language_name}")
82 |
83 | class GraphBuilder:
84 | """Module for building and managing the Neo4j code graph."""
85 |
86 | def __init__(self, db_manager: DatabaseManager, job_manager: JobManager, loop: asyncio.AbstractEventLoop):
87 | self.db_manager = db_manager
88 | self.job_manager = job_manager
89 | self.loop = loop
90 | self.driver = self.db_manager.get_driver()
91 | self.parsers = {
92 | '.py': TreeSitterParser('python'),
93 | '.ipynb': TreeSitterParser('python'),
94 | '.js': TreeSitterParser('javascript'),
95 | '.jsx': TreeSitterParser('javascript'),
96 | '.mjs': TreeSitterParser('javascript'),
97 | '.cjs': TreeSitterParser('javascript'),
98 | '.go': TreeSitterParser('go'),
99 | '.ts': TreeSitterParser('typescript'),
100 | '.tsx': TreeSitterParser('typescript'),
101 | '.cpp': TreeSitterParser('cpp'),
102 | '.h': TreeSitterParser('cpp'),
103 | '.hpp': TreeSitterParser('cpp'),
104 | '.rs': TreeSitterParser('rust'),
105 | '.c': TreeSitterParser('c'),
106 | # '.h': TreeSitterParser('c'), # Need to write an algo for distinguishing C vs C++ headers
107 | '.java': TreeSitterParser('java'),
108 | '.rb': TreeSitterParser('ruby'),
109 | '.java': TreeSitterParser('java'),
110 | '.rb': TreeSitterParser('ruby'),
111 | '.cs': TreeSitterParser('c_sharp'),
112 | '.php': TreeSitterParser('php'),
113 | '.kt': TreeSitterParser('kotlin'),
114 | '.scala': TreeSitterParser('scala'),
115 | '.sc': TreeSitterParser('scala'),
116 | '.swift': TreeSitterParser('swift'),
117 | }
118 | self.create_schema()
119 |
120 | # A general schema creation based on common features across languages
121 | def create_schema(self):
122 | """Create constraints and indexes in Neo4j."""
123 | # When adding a new node type with a unique key, add its constraint here.
124 | with self.driver.session() as session:
125 | try:
126 | session.run("CREATE CONSTRAINT repository_path IF NOT EXISTS FOR (r:Repository) REQUIRE r.path IS UNIQUE")
127 | session.run("CREATE CONSTRAINT file_path IF NOT EXISTS FOR (f:File) REQUIRE f.path IS UNIQUE")
128 | session.run("CREATE CONSTRAINT directory_path IF NOT EXISTS FOR (d:Directory) REQUIRE d.path IS UNIQUE")
129 | session.run("CREATE CONSTRAINT function_unique IF NOT EXISTS FOR (f:Function) REQUIRE (f.name, f.file_path, f.line_number) IS UNIQUE")
130 | session.run("CREATE CONSTRAINT class_unique IF NOT EXISTS FOR (c:Class) REQUIRE (c.name, c.file_path, c.line_number) IS UNIQUE")
131 | session.run("CREATE CONSTRAINT trait_unique IF NOT EXISTS FOR (t:Trait) REQUIRE (t.name, t.file_path, t.line_number) IS UNIQUE") # Added trait constraint
132 | session.run("CREATE CONSTRAINT interface_unique IF NOT EXISTS FOR (i:Interface) REQUIRE (i.name, i.file_path, i.line_number) IS UNIQUE")
133 | session.run("CREATE CONSTRAINT macro_unique IF NOT EXISTS FOR (m:Macro) REQUIRE (m.name, m.file_path, m.line_number) IS UNIQUE")
134 | session.run("CREATE CONSTRAINT variable_unique IF NOT EXISTS FOR (v:Variable) REQUIRE (v.name, v.file_path, v.line_number) IS UNIQUE")
135 | session.run("CREATE CONSTRAINT module_name IF NOT EXISTS FOR (m:Module) REQUIRE m.name IS UNIQUE")
136 | session.run("CREATE CONSTRAINT struct_cpp IF NOT EXISTS FOR (cstruct: Struct) REQUIRE (cstruct.name, cstruct.file_path, cstruct.line_number) IS UNIQUE")
137 | session.run("CREATE CONSTRAINT enum_cpp IF NOT EXISTS FOR (cenum: Enum) REQUIRE (cenum.name, cenum.file_path, cenum.line_number) IS UNIQUE")
138 | session.run("CREATE CONSTRAINT union_cpp IF NOT EXISTS FOR (cunion: Union) REQUIRE (cunion.name, cunion.file_path, cunion.line_number) IS UNIQUE")
139 | session.run("CREATE CONSTRAINT annotation_unique IF NOT EXISTS FOR (a:Annotation) REQUIRE (a.name, a.file_path, a.line_number) IS UNIQUE")
140 | session.run("CREATE CONSTRAINT record_unique IF NOT EXISTS FOR (r:Record) REQUIRE (r.name, r.file_path, r.line_number) IS UNIQUE")
141 | session.run("CREATE CONSTRAINT property_unique IF NOT EXISTS FOR (p:Property) REQUIRE (p.name, p.file_path, p.line_number) IS UNIQUE")
142 |
143 | # Indexes for language attribute
144 | session.run("CREATE INDEX function_lang IF NOT EXISTS FOR (f:Function) ON (f.lang)")
145 | session.run("CREATE INDEX class_lang IF NOT EXISTS FOR (c:Class) ON (c.lang)")
146 | session.run("CREATE INDEX annotation_lang IF NOT EXISTS FOR (a:Annotation) ON (a.lang)")
147 | session.run("""
148 | CREATE FULLTEXT INDEX code_search_index IF NOT EXISTS
149 | FOR (n:Function|Class|Variable)
150 | ON EACH [n.name, n.source, n.docstring]
151 | """ )
152 |
153 | info_logger("Database schema verified/created successfully")
154 | except Exception as e:
155 | warning_logger(f"Schema creation warning: {e}")
156 |
157 |
158 | def _pre_scan_for_imports(self, files: list[Path]) -> dict:
159 | """Dispatches pre-scan to the correct language-specific implementation."""
160 | imports_map = {}
161 |
162 | # Group files by language/extension
163 | files_by_lang = {}
164 | for file in files:
165 | if file.suffix in self.parsers:
166 | lang_ext = file.suffix
167 | if lang_ext not in files_by_lang:
168 | files_by_lang[lang_ext] = []
169 | files_by_lang[lang_ext].append(file)
170 |
171 | if '.py' in files_by_lang:
172 | from .languages import python as python_lang_module
173 | imports_map.update(python_lang_module.pre_scan_python(files_by_lang['.py'], self.parsers['.py']))
174 | if '.ipynb' in files_by_lang:
175 | from .languages import python as python_lang_module
176 | imports_map.update(python_lang_module.pre_scan_python(files_by_lang['.ipynb'], self.parsers['.ipynb']))
177 | if '.js' in files_by_lang:
178 | from .languages import javascript as js_lang_module
179 | imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.js'], self.parsers['.js']))
180 | if '.jsx' in files_by_lang:
181 | from .languages import javascript as js_lang_module
182 | imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.jsx'], self.parsers['.jsx']))
183 | if '.mjs' in files_by_lang:
184 | from .languages import javascript as js_lang_module
185 | imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.mjs'], self.parsers['.mjs']))
186 | if '.cjs' in files_by_lang:
187 | from .languages import javascript as js_lang_module
188 | imports_map.update(js_lang_module.pre_scan_javascript(files_by_lang['.cjs'], self.parsers['.cjs']))
189 | if '.go' in files_by_lang:
190 | from .languages import go as go_lang_module
191 | imports_map.update(go_lang_module.pre_scan_go(files_by_lang['.go'], self.parsers['.go']))
192 | if '.ts' in files_by_lang:
193 | from .languages import typescript as ts_lang_module
194 | imports_map.update(ts_lang_module.pre_scan_typescript(files_by_lang['.ts'], self.parsers['.ts']))
195 | if '.tsx' in files_by_lang:
196 | from .languages import typescriptjsx as tsx_lang_module
197 | imports_map.update(tsx_lang_module.pre_scan_typescript(files_by_lang['.tsx'], self.parsers['.tsx']))
198 | if '.cpp' in files_by_lang:
199 | from .languages import cpp as cpp_lang_module
200 | imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.cpp'], self.parsers['.cpp']))
201 | if '.h' in files_by_lang:
202 | from .languages import cpp as cpp_lang_module
203 | imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.h'], self.parsers['.h']))
204 | if '.hpp' in files_by_lang:
205 | from .languages import cpp as cpp_lang_module
206 | imports_map.update(cpp_lang_module.pre_scan_cpp(files_by_lang['.hpp'], self.parsers['.hpp']))
207 | if '.rs' in files_by_lang:
208 | from .languages import rust as rust_lang_module
209 | imports_map.update(rust_lang_module.pre_scan_rust(files_by_lang['.rs'], self.parsers['.rs']))
210 | if '.c' in files_by_lang:
211 | from .languages import c as c_lang_module
212 | imports_map.update(c_lang_module.pre_scan_c(files_by_lang['.c'], self.parsers['.c']))
213 | elif '.java' in files_by_lang:
214 | from .languages import java as java_lang_module
215 | imports_map.update(java_lang_module.pre_scan_java(files_by_lang['.java'], self.parsers['.java']))
216 | elif '.rb' in files_by_lang:
217 | from .languages import ruby as ruby_lang_module
218 | imports_map.update(ruby_lang_module.pre_scan_ruby(files_by_lang['.rb'], self.parsers['.rb']))
219 | elif '.cs' in files_by_lang:
220 | from .languages import csharp as csharp_lang_module
221 | imports_map.update(csharp_lang_module.pre_scan_csharp(files_by_lang['.cs'], self.parsers['.cs']))
222 | if '.kt' in files_by_lang:
223 | from .languages import kotlin as kotlin_lang_module
224 | imports_map.update(kotlin_lang_module.pre_scan_kotlin(files_by_lang['.kt'], self.parsers['.kt']))
225 | if '.scala' in files_by_lang:
226 | from .languages import scala as scala_lang_module
227 | imports_map.update(scala_lang_module.pre_scan_scala(files_by_lang['.scala'], self.parsers['.scala']))
228 | if '.sc' in files_by_lang:
229 | from .languages import scala as scala_lang_module
230 | imports_map.update(scala_lang_module.pre_scan_scala(files_by_lang['.sc'], self.parsers['.sc']))
231 | if '.swift' in files_by_lang:
232 | from .languages import swift as swift_lang_module
233 | imports_map.update(swift_lang_module.pre_scan_swift(files_by_lang['.swift'], self.parsers['.swift']))
234 |
235 | return imports_map
236 |
237 | # Language-agnostic method
238 | def add_repository_to_graph(self, repo_path: Path, is_dependency: bool = False):
239 | """Adds a repository node using its absolute path as the unique key."""
240 | repo_name = repo_path.name
241 | repo_path_str = str(repo_path.resolve())
242 | with self.driver.session() as session:
243 | session.run(
244 | """
245 | MERGE (r:Repository {path: $path})
246 | SET r.name = $name, r.is_dependency = $is_dependency
247 | """,
248 | path=repo_path_str,
249 | name=repo_name,
250 | is_dependency=is_dependency,
251 | )
252 |
253 | # First pass to add file and its contents
254 | def add_file_to_graph(self, file_data: Dict, repo_name: str, imports_map: dict):
255 | info_logger("Executing add_file_to_graph with my change!")
256 | """Adds a file and its contents within a single, unified session."""
257 | file_path_str = str(Path(file_data['file_path']).resolve())
258 | file_name = Path(file_path_str).name
259 | is_dependency = file_data.get('is_dependency', False)
260 |
261 | with self.driver.session() as session:
262 | try:
263 | # Match repository by path, not name, to avoid conflicts with same-named folders at different locations
264 | repo_result = session.run("MATCH (r:Repository {path: $repo_path}) RETURN r.path as path", repo_path=str(Path(file_data['repo_path']).resolve())).single()
265 | relative_path = str(Path(file_path_str).relative_to(Path(repo_result['path']))) if repo_result else file_name
266 | except ValueError:
267 | relative_path = file_name
268 |
269 | session.run("""
270 | MERGE (f:File {path: $path})
271 | SET f.name = $name, f.relative_path = $relative_path, f.is_dependency = $is_dependency
272 | """, path=file_path_str, name=file_name, relative_path=relative_path, is_dependency=is_dependency)
273 |
274 | file_path_obj = Path(file_path_str)
275 | repo_path_obj = Path(repo_result['path'])
276 |
277 | relative_path_to_file = file_path_obj.relative_to(repo_path_obj)
278 |
279 | parent_path = str(repo_path_obj)
280 | parent_label = 'Repository'
281 |
282 | for part in relative_path_to_file.parts[:-1]:
283 | current_path = Path(parent_path) / part
284 | current_path_str = str(current_path)
285 |
286 | session.run(f"""
287 | MATCH (p:{parent_label} {{path: $parent_path}})
288 | MERGE (d:Directory {{path: $current_path}})
289 | SET d.name = $part
290 | MERGE (p)-[:CONTAINS]->(d)
291 | """, parent_path=parent_path, current_path=current_path_str, part=part)
292 |
293 | parent_path = current_path_str
294 | parent_label = 'Directory'
295 |
296 | session.run(f"""
297 | MATCH (p:{parent_label} {{path: $parent_path}})
298 | MATCH (f:File {{path: $file_path}})
299 | MERGE (p)-[:CONTAINS]->(f)
300 | """, parent_path=parent_path, file_path=file_path_str)
301 |
302 | # CONTAINS relationships for functions, classes, and variables
303 | # To add a new language-specific node type (e.g., 'Trait' for Rust):
304 | # 1. Ensure your language-specific parser returns a list under a unique key (e.g., 'traits': [...] ).
305 | # 2. Add a new constraint for the new label in the `create_schema` method.
306 | # 3. Add a new entry to the `item_mappings` list below (e.g., (file_data.get('traits', []), 'Trait') ).
307 | item_mappings = [
308 | (file_data.get('functions', []), 'Function'),
309 | (file_data.get('classes', []), 'Class'),
310 | (file_data.get('traits', []), 'Trait'), # <-- Added trait mapping
311 | (file_data.get('variables', []), 'Variable'),
312 | (file_data.get('interfaces', []), 'Interface'),
313 | (file_data.get('macros', []), 'Macro'),
314 | (file_data.get('structs',[]), 'Struct'),
315 | (file_data.get('enums',[]), 'Enum'),
316 | (file_data.get('unions',[]), 'Union'),
317 | (file_data.get('records',[]), 'Record'),
318 | (file_data.get('properties',[]), 'Property'),
319 | ]
320 | for item_data, label in item_mappings:
321 | for item in item_data:
322 | # Ensure cyclomatic_complexity is set for functions
323 | if label == 'Function' and 'cyclomatic_complexity' not in item:
324 | item['cyclomatic_complexity'] = 1 # Default value
325 |
326 | query = f"""
327 | MATCH (f:File {{path: $file_path}})
328 | MERGE (n:{label} {{name: $name, file_path: $file_path, line_number: $line_number}})
329 | SET n += $props
330 | MERGE (f)-[:CONTAINS]->(n)
331 | """
332 | session.run(query, file_path=file_path_str, name=item['name'], line_number=item['line_number'], props=item)
333 |
334 | if label == 'Function':
335 | for arg_name in item.get('args', []):
336 | session.run("""
337 | MATCH (fn:Function {name: $func_name, file_path: $file_path, line_number: $line_number})
338 | MERGE (p:Parameter {name: $arg_name, file_path: $file_path, function_line_number: $line_number})
339 | MERGE (fn)-[:HAS_PARAMETER]->(p)
340 | """, func_name=item['name'], file_path=file_path_str, line_number=item['line_number'], arg_name=arg_name)
341 |
342 | # --- NEW: persist Ruby Modules ---
343 | for m in file_data.get('modules', []):
344 | session.run("""
345 | MERGE (mod:Module {name: $name})
346 | ON CREATE SET mod.lang = $lang
347 | ON MATCH SET mod.lang = coalesce(mod.lang, $lang)
348 | """, name=m["name"], lang=file_data.get("lang"))
349 |
350 | # Create CONTAINS relationships for nested functions
351 | for item in file_data.get('functions', []):
352 | if item.get("context_type") == "function_definition":
353 | session.run("""
354 | MATCH (outer:Function {name: $context, file_path: $file_path})
355 | MATCH (inner:Function {name: $name, file_path: $file_path, line_number: $line_number})
356 | MERGE (outer)-[:CONTAINS]->(inner)
357 | """, context=item["context"], file_path=file_path_str, name=item["name"], line_number=item["line_number"])
358 |
359 | # Handle imports and create IMPORTS relationships
360 | for imp in file_data.get('imports', []):
361 | info_logger(f"Processing import: {imp}")
362 | lang = file_data.get('lang')
363 | if lang == 'javascript':
364 | # New, correct logic for JS
365 | module_name = imp.get('source')
366 | if not module_name: continue
367 |
368 | # Use a map for relationship properties to handle optional alias and line_number
369 | rel_props = {'imported_name': imp.get('name', '*')}
370 | if imp.get('alias'):
371 | rel_props['alias'] = imp.get('alias')
372 | if imp.get('line_number'):
373 | rel_props['line_number'] = imp.get('line_number')
374 |
375 | session.run("""
376 | MATCH (f:File {path: $file_path})
377 | MERGE (m:Module {name: $module_name})
378 | MERGE (f)-[r:IMPORTS]->(m)
379 | SET r += $props
380 | """, file_path=file_path_str, module_name=module_name, props=rel_props)
381 | else:
382 | # Existing logic for Python (and other languages)
383 | set_clauses = ["m.alias = $alias"]
384 | if 'full_import_name' in imp:
385 | set_clauses.append("m.full_import_name = $full_import_name")
386 | set_clause_str = ", ".join(set_clauses)
387 |
388 | # Build relationship properties
389 | rel_props = {}
390 | if imp.get('line_number'):
391 | rel_props['line_number'] = imp.get('line_number')
392 | if imp.get('alias'):
393 | rel_props['alias'] = imp.get('alias')
394 |
395 | session.run(f"""
396 | MATCH (f:File {{path: $file_path}})
397 | MERGE (m:Module {{name: $name}})
398 | SET {set_clause_str}
399 | MERGE (f)-[r:IMPORTS]->(m)
400 | SET r += $rel_props
401 | """, file_path=file_path_str, rel_props=rel_props, **imp)
402 |
403 |
404 | # Handle CONTAINS relationship between class to their children like variables
405 | for func in file_data.get('functions', []):
406 | if func.get('class_context'):
407 | session.run("""
408 | MATCH (c:Class {name: $class_name, file_path: $file_path})
409 | MATCH (fn:Function {name: $func_name, file_path: $file_path, line_number: $func_line})
410 | MERGE (c)-[:CONTAINS]->(fn)
411 | """,
412 | class_name=func['class_context'],
413 | file_path=file_path_str,
414 | func_name=func['name'],
415 | func_line=func['line_number'])
416 |
417 | # --- NEW: Class INCLUDES Module (Ruby mixins) ---
418 | for inc in file_data.get('module_inclusions', []):
419 | session.run("""
420 | MATCH (c:Class {name: $class_name, file_path: $file_path})
421 | MERGE (m:Module {name: $module_name})
422 | MERGE (c)-[:INCLUDES]->(m)
423 | """,
424 | class_name=inc["class"],
425 | file_path=file_path_str,
426 | module_name=inc["module"])
427 |
428 | # Class inheritance is handled in a separate pass after all files are processed.
429 | # Function calls are also handled in a separate pass after all files are processed.
430 |
431 | # Second pass to create relationships that depend on all files being present like call functions and class inheritance
432 | def _create_function_calls(self, session, file_data: Dict, imports_map: dict):
433 | """Create CALLS relationships with a unified, prioritized logic flow for all call types."""
434 | caller_file_path = str(Path(file_data['file_path']).resolve())
435 | local_names = {f['name'] for f in file_data.get('functions', [])} | \
436 | {c['name'] for c in file_data.get('classes', [])}
437 | local_imports = {imp.get('alias') or imp['name'].split('.')[-1]: imp['name']
438 | for imp in file_data.get('imports', [])}
439 |
440 | for call in file_data.get('function_calls', []):
441 | called_name = call['name']
442 | if called_name in __builtins__: continue
443 |
444 | resolved_path = None
445 | full_call = call.get('full_name', called_name)
446 | base_obj = full_call.split('.')[0] if '.' in full_call else None
447 |
448 | # For chained calls like self.graph_builder.method(), we need to look up 'method'
449 | # For direct calls like self.method(), we can use the caller's file
450 | is_chained_call = full_call.count('.') > 1 if '.' in full_call else False
451 |
452 | # Determine the lookup name:
453 | # - For chained calls (self.attr.method), use the actual method name
454 | # - For direct calls (self.method or module.function), use the base object
455 | if is_chained_call and base_obj in ('self', 'this', 'super', 'super()', 'cls', '@'):
456 | lookup_name = called_name # Use the actual method name for lookup
457 | else:
458 | lookup_name = base_obj if base_obj else called_name
459 |
460 | # 1. Check for local context keywords/direct local names
461 | # Only resolve to caller_file_path for DIRECT self/this calls, not chained ones
462 | if base_obj in ('self', 'this', 'super', 'super()', 'cls', '@') and not is_chained_call:
463 | resolved_path = caller_file_path
464 | elif lookup_name in local_names:
465 | resolved_path = caller_file_path
466 |
467 | # 2. Check inferred type if available
468 | elif call.get('inferred_obj_type'):
469 | obj_type = call['inferred_obj_type']
470 | possible_paths = imports_map.get(obj_type, [])
471 | if len(possible_paths) > 0:
472 | resolved_path = possible_paths[0]
473 |
474 | # 3. Check imports map with validation against local imports
475 | if not resolved_path:
476 | possible_paths = imports_map.get(lookup_name, [])
477 | if len(possible_paths) == 1:
478 | resolved_path = possible_paths[0]
479 | elif len(possible_paths) > 1:
480 | if lookup_name in local_imports:
481 | full_import_name = local_imports[lookup_name]
482 |
483 | # Optimization: Check if the FQN is directly in imports_map (from pre-scan)
484 | if full_import_name in imports_map:
485 | direct_paths = imports_map[full_import_name]
486 | if direct_paths and len(direct_paths) == 1:
487 | resolved_path = direct_paths[0]
488 |
489 | if not resolved_path:
490 | for path in possible_paths:
491 | if full_import_name.replace('.', '/') in path:
492 | resolved_path = path
493 | break
494 |
495 | if not resolved_path:
496 | warning_logger(f"Could not resolve call {called_name} (lookup: {lookup_name}) in {caller_file_path}")
497 | # else:
498 | # info_logger(f"Resolved call {called_name} -> {resolved_path}")
499 |
500 | # Legacy fallback block (was mis-indented)
501 | if not resolved_path:
502 | possible_paths = imports_map.get(lookup_name, [])
503 | if len(possible_paths) > 0:
504 | # Final fallback: global candidate
505 | # Check if it was imported explicitly, otherwise risky
506 | if lookup_name in local_imports:
507 | # We already tried specific matching above, but if we are here
508 | # it means we had ambiguity without matching path?
509 | pass
510 | else:
511 | # Fallback to first available if not imported? Or skip?
512 | # Original logic: resolved_path = possible_paths[0]
513 | # But wait, original code logic was:
514 | pass
515 | if not resolved_path:
516 | if called_name in local_names:
517 | resolved_path = caller_file_path
518 | elif called_name in imports_map and imports_map[called_name]:
519 | # Check if any path in imports_map for called_name matches current file's imports
520 | candidates = imports_map[called_name]
521 | for path in candidates:
522 | for imp_name in local_imports.values():
523 | if imp_name.replace('.', '/') in path:
524 | resolved_path = path
525 | break
526 | if resolved_path: break
527 | if not resolved_path:
528 | resolved_path = candidates[0]
529 | else:
530 | resolved_path = caller_file_path
531 |
532 | caller_context = call.get('context')
533 | if caller_context and len(caller_context) == 3 and caller_context[0] is not None:
534 | caller_name, _, caller_line_number = caller_context
535 | # if called_name == "sumOfSquares":
536 | # print(f"DEBUG_CYPHER: caller={caller_name}, caller_line={caller_line_number}, called={called_name}, path={resolved_path}")
537 |
538 | session.run("""
539 | MATCH (caller) WHERE (caller:Function OR caller:Class)
540 | AND caller.name = $caller_name
541 | AND caller.file_path = $caller_file_path
542 | AND caller.line_number = $caller_line_number
543 | MATCH (called) WHERE (called:Function OR called:Class)
544 | AND called.name = $called_name
545 | AND called.file_path = $called_file_path
546 |
547 | WITH caller, called
548 | OPTIONAL MATCH (called)-[:CONTAINS]->(init:Function)
549 | WHERE called:Class AND init.name IN ["__init__", "constructor"]
550 | WITH caller, COALESCE(init, called) as final_target
551 |
552 | MERGE (caller)-[:CALLS {line_number: $line_number, args: $args, full_call_name: $full_call_name}]->(final_target)
553 | """,
554 | caller_name=caller_name,
555 | caller_file_path=caller_file_path,
556 | caller_line_number=caller_line_number,
557 | called_name=called_name,
558 | called_file_path=resolved_path,
559 | line_number=call['line_number'],
560 | args=call.get('args', []),
561 | full_call_name=call.get('full_name', called_name))
562 | else:
563 | session.run("""
564 | MATCH (caller:File {path: $caller_file_path})
565 | MATCH (called) WHERE (called:Function OR called:Class)
566 | AND called.name = $called_name
567 | AND called.file_path = $called_file_path
568 |
569 | WITH caller, called
570 | OPTIONAL MATCH (called)-[:CONTAINS]->(init:Function)
571 | WHERE called:Class AND init.name IN ["__init__", "constructor"]
572 | WITH caller, COALESCE(init, called) as final_target
573 |
574 | MERGE (caller)-[:CALLS {line_number: $line_number, args: $args, full_call_name: $full_call_name}]->(final_target)
575 | """,
576 | caller_file_path=caller_file_path,
577 | called_name=called_name,
578 | called_file_path=resolved_path,
579 | line_number=call['line_number'],
580 | args=call.get('args', []),
581 | full_call_name=call.get('full_name', called_name))
582 |
583 | def _create_all_function_calls(self, all_file_data: list[Dict], imports_map: dict):
584 | """Create CALLS relationships for all functions after all files have been processed."""
585 | with self.driver.session() as session:
586 | for file_data in all_file_data:
587 | self._create_function_calls(session, file_data, imports_map)
588 |
589 | def _create_inheritance_links(self, session, file_data: Dict, imports_map: dict):
590 | """Create INHERITS relationships with a more robust resolution logic."""
591 | caller_file_path = str(Path(file_data['file_path']).resolve())
592 | local_class_names = {c['name'] for c in file_data.get('classes', [])}
593 | # Create a map of local import aliases/names to full import names
594 | local_imports = {imp.get('alias') or imp['name'].split('.')[-1]: imp['name']
595 | for imp in file_data.get('imports', [])}
596 |
597 | for class_item in file_data.get('classes', []):
598 | if not class_item.get('bases'):
599 | continue
600 |
601 | for base_class_str in class_item['bases']:
602 | if base_class_str == 'object':
603 | continue
604 |
605 | resolved_path = None
606 | target_class_name = base_class_str.split('.')[-1]
607 |
608 | # Handle qualified names like module.Class or alias.Class
609 | if '.' in base_class_str:
610 | lookup_name = base_class_str.split('.')[0]
611 |
612 | # Case 1: The prefix is a known import
613 | if lookup_name in local_imports:
614 | full_import_name = local_imports[lookup_name]
615 | possible_paths = imports_map.get(target_class_name, [])
616 | # Find the path that corresponds to the imported module
617 | for path in possible_paths:
618 | if full_import_name.replace('.', '/') in path:
619 | resolved_path = path
620 | break
621 | # Handle simple names
622 | else:
623 | lookup_name = base_class_str
624 | # Case 2: The base class is in the same file
625 | if lookup_name in local_class_names:
626 | resolved_path = caller_file_path
627 | # Case 3: The base class was imported directly (e.g., from module import Parent)
628 | elif lookup_name in local_imports:
629 | full_import_name = local_imports[lookup_name]
630 | possible_paths = imports_map.get(target_class_name, [])
631 | for path in possible_paths:
632 | if full_import_name.replace('.', '/') in path:
633 | resolved_path = path
634 | break
635 | # Case 4: Fallback to global map (less reliable)
636 | elif lookup_name in imports_map:
637 | possible_paths = imports_map[lookup_name]
638 | if len(possible_paths) == 1:
639 | resolved_path = possible_paths[0]
640 |
641 | # If a path was found, create the relationship
642 | if resolved_path:
643 | session.run("""
644 | MATCH (child:Class {name: $child_name, file_path: $file_path})
645 | MATCH (parent:Class {name: $parent_name, file_path: $resolved_parent_file_path})
646 | MERGE (child)-[:INHERITS]->(parent)
647 | """,
648 | child_name=class_item['name'],
649 | file_path=caller_file_path,
650 | parent_name=target_class_name,
651 | resolved_parent_file_path=resolved_path)
652 |
653 |
654 | def _create_csharp_inheritance_and_interfaces(self, session, file_data: Dict, imports_map: dict):
655 | """Create INHERITS and IMPLEMENTS relationships for C# types."""
656 | if file_data.get('lang') != 'c_sharp':
657 | return
658 |
659 | caller_file_path = str(Path(file_data['file_path']).resolve())
660 |
661 | # Collect all local type names
662 | local_type_names = set()
663 | for type_list in ['classes', 'interfaces', 'structs', 'records']:
664 | local_type_names.update(t['name'] for t in file_data.get(type_list, []))
665 |
666 | # Process all type declarations that can have bases
667 | for type_list_name, type_label in [('classes', 'Class'), ('structs', 'Struct'), ('records', 'Record'), ('interfaces', 'Interface')]:
668 | for type_item in file_data.get(type_list_name, []):
669 | if not type_item.get('bases'):
670 | continue
671 |
672 | for base_str in type_item['bases']:
673 | # Clean up the base name (remove generic parameters, etc.)
674 | base_name = base_str.split('<')[0].strip()
675 |
676 | # Determine if this is an interface
677 | is_interface = False
678 | resolved_path = caller_file_path
679 |
680 | # Check if base is a local interface
681 | for iface in file_data.get('interfaces', []):
682 | if iface['name'] == base_name:
683 | is_interface = True
684 | break
685 |
686 | # Check if base is in imports_map
687 | if base_name in imports_map:
688 | possible_paths = imports_map[base_name]
689 | if len(possible_paths) > 0:
690 | resolved_path = possible_paths[0]
691 |
692 | # For C#, first base is usually the class (if any), rest are interfaces
693 | base_index = type_item['bases'].index(base_str)
694 |
695 | # Try to determine if it's an interface
696 | if is_interface or (base_index > 0 and type_label == 'Class'):
697 | # This is an IMPLEMENTS relationship
698 | session.run("""
699 | MATCH (child {name: $child_name, file_path: $file_path})
700 | WHERE child:Class OR child:Struct OR child:Record
701 | MATCH (iface:Interface {name: $interface_name})
702 | MERGE (child)-[:IMPLEMENTS]->(iface)
703 | """,
704 | child_name=type_item['name'],
705 | file_path=caller_file_path,
706 | interface_name=base_name)
707 | else:
708 | # This is an INHERITS relationship
709 | session.run("""
710 | MATCH (child {name: $child_name, file_path: $file_path})
711 | WHERE child:Class OR child:Record OR child:Interface
712 | MATCH (parent {name: $parent_name})
713 | WHERE parent:Class OR parent:Record OR parent:Interface
714 | MERGE (child)-[:INHERITS]->(parent)
715 | """,
716 | child_name=type_item['name'],
717 | file_path=caller_file_path,
718 | parent_name=base_name)
719 |
720 | def _create_all_inheritance_links(self, all_file_data: list[Dict], imports_map: dict):
721 | """Create INHERITS relationships for all classes after all files have been processed."""
722 | with self.driver.session() as session:
723 | for file_data in all_file_data:
724 | # Handle C# separately
725 | if file_data.get('lang') == 'c_sharp':
726 | self._create_csharp_inheritance_and_interfaces(session, file_data, imports_map)
727 | else:
728 | self._create_inheritance_links(session, file_data, imports_map)
729 |
730 | def delete_file_from_graph(self, file_path: str):
731 | """Deletes a file and all its contained elements and relationships."""
732 | file_path_str = str(Path(file_path).resolve())
733 | with self.driver.session() as session:
734 | parents_res = session.run("""
735 | MATCH (f:File {path: $path})<-[:CONTAINS*]-(d:Directory)
736 | RETURN d.path as path ORDER BY d.path DESC
737 | """, path=file_path_str)
738 | parent_paths = [record["path"] for record in parents_res]
739 |
740 | session.run(
741 | """
742 | MATCH (f:File {path: $path})
743 | OPTIONAL MATCH (f)-[:CONTAINS]->(element)
744 | DETACH DELETE f, element
745 | """,
746 | path=file_path_str,
747 | )
748 | info_logger(f"Deleted file and its elements from graph: {file_path_str}")
749 |
750 | for path in parent_paths:
751 | session.run("""
752 | MATCH (d:Directory {path: $path})
753 | WHERE NOT (d)-[:CONTAINS]->()
754 | DETACH DELETE d
755 | """, path=path)
756 |
757 | def delete_repository_from_graph(self, repo_path: str) -> bool:
758 | """Deletes a repository and all its contents from the graph. Returns True if deleted, False if not found."""
759 | repo_path_str = str(Path(repo_path).resolve())
760 | with self.driver.session() as session:
761 | # Check if it exists
762 | result = session.run("MATCH (r:Repository {path: $path}) RETURN count(r) as cnt", path=repo_path_str).single()
763 | if not result or result["cnt"] == 0:
764 | warning_logger(f"Attempted to delete non-existent repository: {repo_path_str}")
765 | return False
766 |
767 | session.run("""MATCH (r:Repository {path: $path})
768 | OPTIONAL MATCH (r)-[:CONTAINS*]->(e)
769 | DETACH DELETE r, e""", path=repo_path_str)
770 | info_logger(f"Deleted repository and its contents from graph: {repo_path_str}")
771 | return True
772 |
773 | def update_file_in_graph(self, file_path: Path, repo_path: Path, imports_map: dict):
774 | """Updates a single file's nodes in the graph."""
775 | file_path_str = str(file_path.resolve())
776 | repo_name = repo_path.name
777 |
778 | self.delete_file_from_graph(file_path_str)
779 |
780 | if file_path.exists():
781 | file_data = self.parse_file(repo_path, file_path)
782 |
783 | if "error" not in file_data:
784 | self.add_file_to_graph(file_data, repo_name, imports_map)
785 | return file_data
786 | else:
787 | error_logger(f"Skipping graph add for {file_path_str} due to parsing error: {file_data['error']}")
788 | return None
789 | else:
790 | return {"deleted": True, "path": file_path_str}
791 |
792 | def parse_file(self, repo_path: Path, file_path: Path, is_dependency: bool = False) -> Dict:
793 | """Parses a file with the appropriate language parser and extracts code elements."""
794 | parser = self.parsers.get(file_path.suffix)
795 | if not parser:
796 | warning_logger(f"No parser found for file extension {file_path.suffix}. Skipping {file_path}")
797 | return {"file_path": str(file_path), "error": f"No parser for {file_path.suffix}"}
798 |
799 | debug_log(f"[parse_file] Starting parsing for: {file_path} with {parser.language_name} parser")
800 | try:
801 | if parser.language_name == 'python':
802 | is_notebook = file_path.suffix == '.ipynb'
803 | file_data = parser.parse(file_path, is_dependency, is_notebook=is_notebook)
804 | else:
805 | file_data = parser.parse(file_path, is_dependency)
806 | file_data['repo_path'] = str(repo_path)
807 | debug_log(f"[parse_file] Successfully parsed: {file_path}")
808 | return file_data
809 |
810 | except Exception as e:
811 | error_logger(f"Error parsing {file_path} with {parser.language_name} parser: {e}")
812 | debug_log(f"[parse_file] Error parsing {file_path}: {e}")
813 | return {"file_path": str(file_path), "error": str(e)}
814 |
815 | def estimate_processing_time(self, path: Path) -> Optional[Tuple[int, float]]:
816 | """Estimate processing time and file count"""
817 | try:
818 | supported_extensions = self.parsers.keys()
819 | if path.is_file():
820 | if path.suffix in supported_extensions:
821 | files = [path]
822 | else:
823 | return 0, 0.0 # Not a supported file type
824 | else:
825 | all_files = path.rglob("*")
826 | files = [f for f in all_files if f.is_file() and f.suffix in supported_extensions]
827 |
828 | # Filter default ignored directories
829 | ignore_dirs_str = get_config_value("IGNORE_DIRS") or ""
830 | if ignore_dirs_str:
831 | ignore_dirs = {d.strip().lower() for d in ignore_dirs_str.split(',') if d.strip()}
832 | if ignore_dirs:
833 | kept_files = []
834 | for f in files:
835 | try:
836 | parts = set(p.lower() for p in f.relative_to(path).parent.parts)
837 | if not parts.intersection(ignore_dirs):
838 | kept_files.append(f)
839 | except ValueError:
840 | kept_files.append(f)
841 | files = kept_files
842 |
843 | total_files = len(files)
844 | estimated_time = total_files * 0.05 # tree-sitter is faster
845 | return total_files, estimated_time
846 | except Exception as e:
847 | error_logger(f"Could not estimate processing time for {path}: {e}")
848 | return None
849 |
850 | async def build_graph_from_path_async(
851 | self, path: Path, is_dependency: bool = False, job_id: str = None
852 | ):
853 | """Builds graph from a directory or file path."""
854 | try:
855 | if job_id:
856 | self.job_manager.update_job(job_id, status=JobStatus.RUNNING)
857 |
858 | self.add_repository_to_graph(path, is_dependency)
859 | repo_name = path.name
860 |
861 | # Search for .cgcignore upwards
862 | cgcignore_path = None
863 | ignore_root = path.resolve()
864 |
865 | # Start search from path (or parent if path is file)
866 | curr = path.resolve()
867 | if not curr.is_dir():
868 | curr = curr.parent
869 |
870 | # Walk up looking for .cgcignore
871 | while True:
872 | candidate = curr / ".cgcignore"
873 | if candidate.exists():
874 | cgcignore_path = candidate
875 | ignore_root = curr
876 | debug_log(f"Found .cgcignore at {ignore_root}")
877 | break
878 | if curr.parent == curr: # Root hit
879 | break
880 | curr = curr.parent
881 |
882 | if cgcignore_path:
883 | with open(cgcignore_path) as f:
884 | ignore_patterns = f.read().splitlines()
885 | spec = pathspec.PathSpec.from_lines('gitwildmatch', ignore_patterns)
886 | else:
887 | spec = None
888 |
889 | supported_extensions = self.parsers.keys()
890 | all_files = path.rglob("*") if path.is_dir() else [path]
891 | files = [f for f in all_files if f.is_file() and f.suffix in supported_extensions]
892 |
893 | # Filter default ignored directories
894 | ignore_dirs_str = get_config_value("IGNORE_DIRS") or ""
895 | if ignore_dirs_str and path.is_dir():
896 | ignore_dirs = {d.strip().lower() for d in ignore_dirs_str.split(',') if d.strip()}
897 | if ignore_dirs:
898 | kept_files = []
899 | for f in files:
900 | try:
901 | # Check if any parent directory in the relative path is in ignore list
902 | parts = set(p.lower() for p in f.relative_to(path).parent.parts)
903 | if not parts.intersection(ignore_dirs):
904 | kept_files.append(f)
905 | else:
906 | # debug_log(f"Skipping default ignored file: {f}")
907 | pass
908 | except ValueError:
909 | kept_files.append(f)
910 | files = kept_files
911 |
912 | if spec:
913 | filtered_files = []
914 | for f in files:
915 | try:
916 | # Match relative to the directory containing .cgcignore
917 | rel_path = f.relative_to(ignore_root)
918 | if not spec.match_file(str(rel_path)):
919 | filtered_files.append(f)
920 | else:
921 | debug_log(f"Ignored file based on .cgcignore: {rel_path}")
922 | except ValueError:
923 | # Should not happen if ignore_root is a parent, but safety fallback
924 | filtered_files.append(f)
925 | files = filtered_files
926 | if job_id:
927 | self.job_manager.update_job(job_id, total_files=len(files))
928 |
929 | debug_log("Starting pre-scan to build imports map...")
930 | imports_map = self._pre_scan_for_imports(files)
931 | debug_log(f"Pre-scan complete. Found {len(imports_map)} definitions.")
932 |
933 | all_file_data = []
934 |
935 | processed_count = 0
936 | for file in files:
937 | if file.is_file():
938 | if job_id:
939 | self.job_manager.update_job(job_id, current_file=str(file))
940 | repo_path = path.resolve() if path.is_dir() else file.parent.resolve()
941 | file_data = self.parse_file(repo_path, file, is_dependency)
942 | if "error" not in file_data:
943 | self.add_file_to_graph(file_data, repo_name, imports_map)
944 | all_file_data.append(file_data)
945 | processed_count += 1
946 | if job_id:
947 | self.job_manager.update_job(job_id, processed_files=processed_count)
948 | await asyncio.sleep(0.01)
949 |
950 | self._create_all_inheritance_links(all_file_data, imports_map)
951 | self._create_all_function_calls(all_file_data, imports_map)
952 |
953 | if job_id:
954 | self.job_manager.update_job(job_id, status=JobStatus.COMPLETED, end_time=datetime.now())
955 | except Exception as e:
956 | error_message=str(e)
957 | error_logger(f"Failed to build graph for path {path}: {error_message}")
958 | if job_id:
959 | '''checking if the repo got deleted '''
960 | if "no such file found" in error_message or "deleted" in error_message or "not found" in error_message:
961 | status=JobStatus.CANCELLED
962 |
963 | else:
964 | status=JobStatus.FAILED
965 |
966 | self.job_manager.update_job(
967 | job_id, status=status, end_time=datetime.now(), errors=[str(e)]
968 | )
969 |
```
--------------------------------------------------------------------------------
/docs/site/cookbook/index.html:
--------------------------------------------------------------------------------
```html
1 |
2 | <!doctype html>
3 | <html lang="en" class="no-js">
4 | <head>
5 |
6 | <meta charset="utf-8">
7 | <meta name="viewport" content="width=device-width,initial-scale=1">
8 |
9 |
10 |
11 |
12 | <link rel="prev" href="../tools/">
13 |
14 |
15 | <link rel="next" href="../contributing/">
16 |
17 |
18 |
19 |
20 |
21 | <link rel="icon" href="../assets/images/favicon.png">
22 | <meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.1">
23 |
24 |
25 |
26 | <title>Cookbook - CodeGraphContext</title>
27 |
28 |
29 |
30 | <link rel="stylesheet" href="../assets/stylesheets/main.484c7ddc.min.css">
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
44 | <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">
45 | <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
46 |
47 |
48 |
49 | <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>
50 |
51 |
52 |
53 |
54 |
55 | </head>
56 |
57 |
58 | <body dir="ltr">
59 |
60 |
61 | <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
62 | <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
63 | <label class="md-overlay" for="__drawer"></label>
64 | <div data-md-component="skip">
65 |
66 |
67 | <a href="#mcp-tool-cookbook" class="md-skip">
68 | Skip to content
69 | </a>
70 |
71 | </div>
72 | <div data-md-component="announce">
73 |
74 | </div>
75 |
76 |
77 |
78 |
79 |
80 |
81 | <header class="md-header md-header--shadow" data-md-component="header">
82 | <nav class="md-header__inner md-grid" aria-label="Header">
83 | <a href=".." title="CodeGraphContext" class="md-header__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
84 |
85 |
86 | <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>
87 |
88 | </a>
89 | <label class="md-header__button md-icon" for="__drawer">
90 |
91 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
92 | </label>
93 | <div class="md-header__title" data-md-component="header-title">
94 | <div class="md-header__ellipsis">
95 | <div class="md-header__topic">
96 | <span class="md-ellipsis">
97 | CodeGraphContext
98 | </span>
99 | </div>
100 | <div class="md-header__topic" data-md-component="header-topic">
101 | <span class="md-ellipsis">
102 |
103 | Cookbook
104 |
105 | </span>
106 | </div>
107 | </div>
108 | </div>
109 |
110 |
111 | <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>
112 |
113 |
114 |
115 |
116 |
117 | <label class="md-header__button md-icon" for="__search">
118 |
119 | <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>
120 | </label>
121 | <div class="md-search" data-md-component="search" role="dialog">
122 | <label class="md-search__overlay" for="__search"></label>
123 | <div class="md-search__inner" role="search">
124 | <form class="md-search__form" name="search">
125 | <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>
126 | <label class="md-search__icon md-icon" for="__search">
127 |
128 | <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>
129 |
130 | <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>
131 | </label>
132 | <nav class="md-search__options" aria-label="Search">
133 |
134 | <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
135 |
136 | <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>
137 | </button>
138 | </nav>
139 |
140 | </form>
141 | <div class="md-search__output">
142 | <div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
143 | <div class="md-search-result" data-md-component="search-result">
144 | <div class="md-search-result__meta">
145 | Initializing search
146 | </div>
147 | <ol class="md-search-result__list" role="presentation"></ol>
148 | </div>
149 | </div>
150 | </div>
151 | </div>
152 | </div>
153 |
154 |
155 |
156 | </nav>
157 |
158 | </header>
159 |
160 | <div class="md-container" data-md-component="container">
161 |
162 |
163 |
164 |
165 |
166 |
167 | <main class="md-main" data-md-component="main">
168 | <div class="md-main__inner md-grid">
169 |
170 |
171 |
172 | <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
173 | <div class="md-sidebar__scrollwrap">
174 | <div class="md-sidebar__inner">
175 |
176 |
177 |
178 |
179 | <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
180 | <label class="md-nav__title" for="__drawer">
181 | <a href=".." title="CodeGraphContext" class="md-nav__button md-logo" aria-label="CodeGraphContext" data-md-component="logo">
182 |
183 |
184 | <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>
185 |
186 | </a>
187 | CodeGraphContext
188 | </label>
189 |
190 | <ul class="md-nav__list" data-md-scrollfix>
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | <li class="md-nav__item">
199 | <a href=".." class="md-nav__link">
200 |
201 |
202 |
203 | <span class="md-ellipsis">
204 |
205 |
206 | Home
207 |
208 |
209 |
210 | </span>
211 |
212 |
213 |
214 | </a>
215 | </li>
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 | <li class="md-nav__item">
226 | <a href="../installation/" class="md-nav__link">
227 |
228 |
229 |
230 | <span class="md-ellipsis">
231 |
232 |
233 | Installation
234 |
235 |
236 |
237 | </span>
238 |
239 |
240 |
241 | </a>
242 | </li>
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | <li class="md-nav__item">
253 | <a href="../use_cases/" class="md-nav__link">
254 |
255 |
256 |
257 | <span class="md-ellipsis">
258 |
259 |
260 | Use Cases
261 |
262 |
263 |
264 | </span>
265 |
266 |
267 |
268 | </a>
269 | </li>
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 | <li class="md-nav__item">
280 | <a href="../architecture/" class="md-nav__link">
281 |
282 |
283 |
284 | <span class="md-ellipsis">
285 |
286 |
287 | Architecture
288 |
289 |
290 |
291 | </span>
292 |
293 |
294 |
295 | </a>
296 | </li>
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 | <li class="md-nav__item">
307 | <a href="../cli/" class="md-nav__link">
308 |
309 |
310 |
311 | <span class="md-ellipsis">
312 |
313 |
314 | CLI Reference
315 |
316 |
317 |
318 | </span>
319 |
320 |
321 |
322 | </a>
323 | </li>
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 | <li class="md-nav__item">
334 | <a href="../watching/" class="md-nav__link">
335 |
336 |
337 |
338 | <span class="md-ellipsis">
339 |
340 |
341 | Live Watching
342 |
343 |
344 |
345 | </span>
346 |
347 |
348 |
349 | </a>
350 | </li>
351 |
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 | <li class="md-nav__item">
361 | <a href="../server/" class="md-nav__link">
362 |
363 |
364 |
365 | <span class="md-ellipsis">
366 |
367 |
368 | Server
369 |
370 |
371 |
372 | </span>
373 |
374 |
375 |
376 | </a>
377 | </li>
378 |
379 |
380 |
381 |
382 |
383 |
384 |
385 |
386 |
387 | <li class="md-nav__item">
388 | <a href="../core/" class="md-nav__link">
389 |
390 |
391 |
392 | <span class="md-ellipsis">
393 |
394 |
395 | Core Concepts
396 |
397 |
398 |
399 | </span>
400 |
401 |
402 |
403 | </a>
404 | </li>
405 |
406 |
407 |
408 |
409 |
410 |
411 |
412 |
413 |
414 | <li class="md-nav__item">
415 | <a href="../tools/" class="md-nav__link">
416 |
417 |
418 |
419 | <span class="md-ellipsis">
420 |
421 |
422 | Tools
423 |
424 |
425 |
426 | </span>
427 |
428 |
429 |
430 | </a>
431 | </li>
432 |
433 |
434 |
435 |
436 |
437 |
438 |
439 |
440 |
441 |
442 |
443 | <li class="md-nav__item md-nav__item--active">
444 |
445 | <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
446 |
447 |
448 |
449 |
450 |
451 | <label class="md-nav__link md-nav__link--active" for="__toc">
452 |
453 |
454 |
455 | <span class="md-ellipsis">
456 |
457 |
458 | Cookbook
459 |
460 |
461 |
462 | </span>
463 |
464 |
465 |
466 | <span class="md-nav__icon md-icon"></span>
467 | </label>
468 |
469 | <a href="./" class="md-nav__link md-nav__link--active">
470 |
471 |
472 |
473 | <span class="md-ellipsis">
474 |
475 |
476 | Cookbook
477 |
478 |
479 |
480 | </span>
481 |
482 |
483 |
484 | </a>
485 |
486 |
487 |
488 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
489 |
490 |
491 |
492 |
493 |
494 |
495 | <label class="md-nav__title" for="__toc">
496 | <span class="md-nav__icon md-icon"></span>
497 | Table of contents
498 | </label>
499 | <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
500 |
501 | <li class="md-nav__item">
502 | <a href="#basic-queries" class="md-nav__link">
503 | <span class="md-ellipsis">
504 |
505 | Basic Queries
506 |
507 | </span>
508 | </a>
509 |
510 | <nav class="md-nav" aria-label="Basic Queries">
511 | <ul class="md-nav__list">
512 |
513 | <li class="md-nav__item">
514 | <a href="#1-find-a-specific-function-by-name" class="md-nav__link">
515 | <span class="md-ellipsis">
516 |
517 | 1. Find a specific function by name
518 |
519 | </span>
520 | </a>
521 |
522 | </li>
523 |
524 | <li class="md-nav__item">
525 | <a href="#2-find-all-calls-to-a-specific-function" class="md-nav__link">
526 | <span class="md-ellipsis">
527 |
528 | 2. Find all calls to a specific function
529 |
530 | </span>
531 | </a>
532 |
533 | </li>
534 |
535 | <li class="md-nav__item">
536 | <a href="#3-find-what-a-function-calls" class="md-nav__link">
537 | <span class="md-ellipsis">
538 |
539 | 3. Find what a function calls
540 |
541 | </span>
542 | </a>
543 |
544 | </li>
545 |
546 | <li class="md-nav__item">
547 | <a href="#4-find-all-imports-of-a-specific-module" class="md-nav__link">
548 | <span class="md-ellipsis">
549 |
550 | 4. Find all imports of a specific module
551 |
552 | </span>
553 | </a>
554 |
555 | </li>
556 |
557 | <li class="md-nav__item">
558 | <a href="#5-find-all-methods-of-a-class" class="md-nav__link">
559 | <span class="md-ellipsis">
560 |
561 | 5. Find all methods of a class
562 |
563 | </span>
564 | </a>
565 |
566 | </li>
567 |
568 | <li class="md-nav__item">
569 | <a href="#6-find-all-classes-that-inherit-from-a-specific-class" class="md-nav__link">
570 | <span class="md-ellipsis">
571 |
572 | 6. Find all classes that inherit from a specific class
573 |
574 | </span>
575 | </a>
576 |
577 | </li>
578 |
579 | <li class="md-nav__item">
580 | <a href="#7-find-all-functions-with-a-specific-decorator" class="md-nav__link">
581 | <span class="md-ellipsis">
582 |
583 | 7. Find all functions with a specific decorator
584 |
585 | </span>
586 | </a>
587 |
588 | </li>
589 |
590 | <li class="md-nav__item">
591 | <a href="#8-find-all-dataclasses" class="md-nav__link">
592 | <span class="md-ellipsis">
593 |
594 | 8. Find all dataclasses
595 |
596 | </span>
597 | </a>
598 |
599 | </li>
600 |
601 | </ul>
602 | </nav>
603 |
604 | </li>
605 |
606 | <li class="md-nav__item">
607 | <a href="#code-analysis-quality" class="md-nav__link">
608 | <span class="md-ellipsis">
609 |
610 | Code Analysis & Quality
611 |
612 | </span>
613 | </a>
614 |
615 | <nav class="md-nav" aria-label="Code Analysis & Quality">
616 | <ul class="md-nav__list">
617 |
618 | <li class="md-nav__item">
619 | <a href="#9-find-the-5-most-complex-functions" class="md-nav__link">
620 | <span class="md-ellipsis">
621 |
622 | 9. Find the 5 most complex functions
623 |
624 | </span>
625 | </a>
626 |
627 | </li>
628 |
629 | <li class="md-nav__item">
630 | <a href="#10-calculate-cyclomatic-complexity-of-a-function" class="md-nav__link">
631 | <span class="md-ellipsis">
632 |
633 | 10. Calculate cyclomatic complexity of a function
634 |
635 | </span>
636 | </a>
637 |
638 | </li>
639 |
640 | <li class="md-nav__item">
641 | <a href="#11-find-unused-code" class="md-nav__link">
642 | <span class="md-ellipsis">
643 |
644 | 11. Find unused code
645 |
646 | </span>
647 | </a>
648 |
649 | </li>
650 |
651 | <li class="md-nav__item">
652 | <a href="#12-find-the-call-chain-between-two-functions" class="md-nav__link">
653 | <span class="md-ellipsis">
654 |
655 | 12. Find the call chain between two functions
656 |
657 | </span>
658 | </a>
659 |
660 | </li>
661 |
662 | <li class="md-nav__item">
663 | <a href="#13-find-all-direct-and-indirect-callers-of-a-function" class="md-nav__link">
664 | <span class="md-ellipsis">
665 |
666 | 13. Find all direct and indirect callers of a function
667 |
668 | </span>
669 | </a>
670 |
671 | </li>
672 |
673 | <li class="md-nav__item">
674 | <a href="#14-find-functions-by-argument-name" class="md-nav__link">
675 | <span class="md-ellipsis">
676 |
677 | 14. Find functions by argument name
678 |
679 | </span>
680 | </a>
681 |
682 | </li>
683 |
684 | <li class="md-nav__item">
685 | <a href="#15-list-all-python-package-imports-from-a-directory" class="md-nav__link">
686 | <span class="md-ellipsis">
687 |
688 | 15. List all python package imports from a directory
689 |
690 | </span>
691 | </a>
692 |
693 | </li>
694 |
695 | </ul>
696 | </nav>
697 |
698 | </li>
699 |
700 | <li class="md-nav__item">
701 | <a href="#repository-information-queries" class="md-nav__link">
702 | <span class="md-ellipsis">
703 |
704 | Repository Information Queries
705 |
706 | </span>
707 | </a>
708 |
709 | <nav class="md-nav" aria-label="Repository Information Queries">
710 | <ul class="md-nav__list">
711 |
712 | <li class="md-nav__item">
713 | <a href="#16-list-all-indexed-projects" class="md-nav__link">
714 | <span class="md-ellipsis">
715 |
716 | 16. List all indexed projects
717 |
718 | </span>
719 | </a>
720 |
721 | </li>
722 |
723 | <li class="md-nav__item">
724 | <a href="#17-check-the-status-of-an-indexing-job" class="md-nav__link">
725 | <span class="md-ellipsis">
726 |
727 | 17. Check the status of an indexing job
728 |
729 | </span>
730 | </a>
731 |
732 | </li>
733 |
734 | <li class="md-nav__item">
735 | <a href="#18-list-all-background-jobs" class="md-nav__link">
736 | <span class="md-ellipsis">
737 |
738 | 18. List all background jobs
739 |
740 | </span>
741 | </a>
742 |
743 | </li>
744 |
745 | </ul>
746 | </nav>
747 |
748 | </li>
749 |
750 | <li class="md-nav__item">
751 | <a href="#advanced-cypher-queries" class="md-nav__link">
752 | <span class="md-ellipsis">
753 |
754 | Advanced Cypher Queries
755 |
756 | </span>
757 | </a>
758 |
759 | <nav class="md-nav" aria-label="Advanced Cypher Queries">
760 | <ul class="md-nav__list">
761 |
762 | <li class="md-nav__item">
763 | <a href="#19-find-all-function-definitions" class="md-nav__link">
764 | <span class="md-ellipsis">
765 |
766 | 19. Find all function definitions
767 |
768 | </span>
769 | </a>
770 |
771 | </li>
772 |
773 | <li class="md-nav__item">
774 | <a href="#20-find-all-classes" class="md-nav__link">
775 | <span class="md-ellipsis">
776 |
777 | 20. Find all classes
778 |
779 | </span>
780 | </a>
781 |
782 | </li>
783 |
784 | <li class="md-nav__item">
785 | <a href="#21-find-all-functions-in-a-file" class="md-nav__link">
786 | <span class="md-ellipsis">
787 |
788 | 21. Find all functions in a file
789 |
790 | </span>
791 | </a>
792 |
793 | </li>
794 |
795 | <li class="md-nav__item">
796 | <a href="#22-find-all-classes-in-a-file" class="md-nav__link">
797 | <span class="md-ellipsis">
798 |
799 | 22. Find all classes in a file
800 |
801 | </span>
802 | </a>
803 |
804 | </li>
805 |
806 | <li class="md-nav__item">
807 | <a href="#23-list-all-top-level-functions-and-classes-in-a-file" class="md-nav__link">
808 | <span class="md-ellipsis">
809 |
810 | 23. List all top-level functions and classes in a file
811 |
812 | </span>
813 | </a>
814 |
815 | </li>
816 |
817 | <li class="md-nav__item">
818 | <a href="#24-find-functions-in-one-module-that-call-a-function-in-another" class="md-nav__link">
819 | <span class="md-ellipsis">
820 |
821 | 24. Find functions in one module that call a function in another
822 |
823 | </span>
824 | </a>
825 |
826 | </li>
827 |
828 | <li class="md-nav__item">
829 | <a href="#25-find-circular-file-imports" class="md-nav__link">
830 | <span class="md-ellipsis">
831 |
832 | 25. Find circular file imports
833 |
834 | </span>
835 | </a>
836 |
837 | </li>
838 |
839 | <li class="md-nav__item">
840 | <a href="#26-find-all-functions-with-more-than-5-arguments" class="md-nav__link">
841 | <span class="md-ellipsis">
842 |
843 | 26. Find all functions with more than 5 arguments
844 |
845 | </span>
846 | </a>
847 |
848 | </li>
849 |
850 | <li class="md-nav__item">
851 | <a href="#27-find-all-functions-in-a-file-that-have-a-docstring" class="md-nav__link">
852 | <span class="md-ellipsis">
853 |
854 | 27. Find all functions in a file that have a docstring
855 |
856 | </span>
857 | </a>
858 |
859 | </li>
860 |
861 | <li class="md-nav__item">
862 | <a href="#28-find-all-classes-that-have-a-specific-method" class="md-nav__link">
863 | <span class="md-ellipsis">
864 |
865 | 28. Find all classes that have a specific method
866 |
867 | </span>
868 | </a>
869 |
870 | </li>
871 |
872 | <li class="md-nav__item">
873 | <a href="#29-find-the-depth-of-inheritance-for-all-classes" class="md-nav__link">
874 | <span class="md-ellipsis">
875 |
876 | 29. Find the depth of inheritance for all classes
877 |
878 | </span>
879 | </a>
880 |
881 | </li>
882 |
883 | <li class="md-nav__item">
884 | <a href="#30-find-all-functions-that-have-a-docstring" class="md-nav__link">
885 | <span class="md-ellipsis">
886 |
887 | 30. Find all functions that have a docstring
888 |
889 | </span>
890 | </a>
891 |
892 | </li>
893 |
894 | <li class="md-nav__item">
895 | <a href="#31-find-all-decorated-methods-in-a-class" class="md-nav__link">
896 | <span class="md-ellipsis">
897 |
898 | 31. Find all decorated methods in a class
899 |
900 | </span>
901 | </a>
902 |
903 | </li>
904 |
905 | <li class="md-nav__item">
906 | <a href="#32-find-the-number-of-functions-in-each-file" class="md-nav__link">
907 | <span class="md-ellipsis">
908 |
909 | 32. Find the number of functions in each file
910 |
911 | </span>
912 | </a>
913 |
914 | </li>
915 |
916 | <li class="md-nav__item">
917 | <a href="#33-find-all-methods-that-override-a-parent-method" class="md-nav__link">
918 | <span class="md-ellipsis">
919 |
920 | 33. Find all methods that override a parent method
921 |
922 | </span>
923 | </a>
924 |
925 | </li>
926 |
927 | <li class="md-nav__item">
928 | <a href="#34-find-all-functions-that-call-super" class="md-nav__link">
929 | <span class="md-ellipsis">
930 |
931 | 34. Find all functions that call super()
932 |
933 | </span>
934 | </a>
935 |
936 | </li>
937 |
938 | <li class="md-nav__item">
939 | <a href="#35-find-all-calls-to-a-function-with-a-specific-argument" class="md-nav__link">
940 | <span class="md-ellipsis">
941 |
942 | 35. Find all calls to a function with a specific argument
943 |
944 | </span>
945 | </a>
946 |
947 | </li>
948 |
949 | <li class="md-nav__item">
950 | <a href="#36-find-all-functions-that-are-not-called-by-any-other-function" class="md-nav__link">
951 | <span class="md-ellipsis">
952 |
953 | 36. Find all functions that are not called by any other function
954 |
955 | </span>
956 | </a>
957 |
958 | </li>
959 |
960 | <li class="md-nav__item">
961 | <a href="#37-find-all-functions-that-are-called-with-a-specific-argument" class="md-nav__link">
962 | <span class="md-ellipsis">
963 |
964 | 37. Find all functions that are called with a specific argument
965 |
966 | </span>
967 | </a>
968 |
969 | </li>
970 |
971 | <li class="md-nav__item">
972 | <a href="#38-find-all-direct-and-indirect-callees-of-a-function" class="md-nav__link">
973 | <span class="md-ellipsis">
974 |
975 | 38. Find all direct and indirect callees of a function
976 |
977 | </span>
978 | </a>
979 |
980 | </li>
981 |
982 | <li class="md-nav__item">
983 | <a href="#39-find-all-functions-that-are-overridden" class="md-nav__link">
984 | <span class="md-ellipsis">
985 |
986 | 39. Find all functions that are overridden
987 |
988 | </span>
989 | </a>
990 |
991 | </li>
992 |
993 | <li class="md-nav__item">
994 | <a href="#40-find-all-modules-imported-by-module_a" class="md-nav__link">
995 | <span class="md-ellipsis">
996 |
997 | 40. Find all modules imported by module_a
998 |
999 | </span>
1000 | </a>
1001 |
1002 | </li>
1003 |
1004 | <li class="md-nav__item">
1005 | <a href="#41-find-large-functions-that-should-be-refactored" class="md-nav__link">
1006 | <span class="md-ellipsis">
1007 |
1008 | 41. Find large functions that should be refactored
1009 |
1010 | </span>
1011 | </a>
1012 |
1013 | </li>
1014 |
1015 | <li class="md-nav__item">
1016 | <a href="#42-find-recursive-functions" class="md-nav__link">
1017 | <span class="md-ellipsis">
1018 |
1019 | 42. Find recursive functions
1020 |
1021 | </span>
1022 | </a>
1023 |
1024 | </li>
1025 |
1026 | <li class="md-nav__item">
1027 | <a href="#43-find-most-connected-functions-hub-functions" class="md-nav__link">
1028 | <span class="md-ellipsis">
1029 |
1030 | 43. Find most connected functions (hub functions)
1031 |
1032 | </span>
1033 | </a>
1034 |
1035 | </li>
1036 |
1037 | </ul>
1038 | </nav>
1039 |
1040 | </li>
1041 |
1042 | <li class="md-nav__item">
1043 | <a href="#security-sensitive-data-analysis" class="md-nav__link">
1044 | <span class="md-ellipsis">
1045 |
1046 | Security & Sensitive Data Analysis
1047 |
1048 | </span>
1049 | </a>
1050 |
1051 | <nav class="md-nav" aria-label="Security & Sensitive Data Analysis">
1052 | <ul class="md-nav__list">
1053 |
1054 | <li class="md-nav__item">
1055 | <a href="#44-find-potential-security-vulnerabilities-hardcoded-secrets" class="md-nav__link">
1056 | <span class="md-ellipsis">
1057 |
1058 | 44. Find potential security vulnerabilities (hardcoded secrets)
1059 |
1060 | </span>
1061 | </a>
1062 |
1063 | </li>
1064 |
1065 | </ul>
1066 | </nav>
1067 |
1068 | </li>
1069 |
1070 | </ul>
1071 |
1072 | </nav>
1073 |
1074 | </li>
1075 |
1076 |
1077 |
1078 |
1079 |
1080 |
1081 |
1082 |
1083 |
1084 |
1085 |
1086 |
1087 |
1088 |
1089 | <li class="md-nav__item md-nav__item--nested">
1090 |
1091 |
1092 |
1093 | <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_11" >
1094 |
1095 |
1096 | <label class="md-nav__link" for="__nav_11" id="__nav_11_label" tabindex="0">
1097 |
1098 |
1099 |
1100 | <span class="md-ellipsis">
1101 |
1102 |
1103 | Contributing
1104 |
1105 |
1106 |
1107 | </span>
1108 |
1109 |
1110 |
1111 | <span class="md-nav__icon md-icon"></span>
1112 | </label>
1113 |
1114 | <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_11_label" aria-expanded="false">
1115 | <label class="md-nav__title" for="__nav_11">
1116 | <span class="md-nav__icon md-icon"></span>
1117 |
1118 |
1119 | Contributing
1120 |
1121 |
1122 | </label>
1123 | <ul class="md-nav__list" data-md-scrollfix>
1124 |
1125 |
1126 |
1127 |
1128 |
1129 |
1130 |
1131 | <li class="md-nav__item">
1132 | <a href="../contributing/" class="md-nav__link">
1133 |
1134 |
1135 |
1136 | <span class="md-ellipsis">
1137 |
1138 |
1139 | Overview
1140 |
1141 |
1142 |
1143 | </span>
1144 |
1145 |
1146 |
1147 | </a>
1148 | </li>
1149 |
1150 |
1151 |
1152 |
1153 |
1154 |
1155 |
1156 |
1157 |
1158 |
1159 | <li class="md-nav__item">
1160 | <a href="../contributing_languages/" class="md-nav__link">
1161 |
1162 |
1163 |
1164 | <span class="md-ellipsis">
1165 |
1166 |
1167 | Adding New Languages
1168 |
1169 |
1170 |
1171 | </span>
1172 |
1173 |
1174 |
1175 | </a>
1176 | </li>
1177 |
1178 |
1179 |
1180 |
1181 | </ul>
1182 | </nav>
1183 |
1184 | </li>
1185 |
1186 |
1187 |
1188 |
1189 |
1190 |
1191 |
1192 |
1193 |
1194 | <li class="md-nav__item">
1195 | <a href="../troubleshooting/" class="md-nav__link">
1196 |
1197 |
1198 |
1199 | <span class="md-ellipsis">
1200 |
1201 |
1202 | Troubleshooting
1203 |
1204 |
1205 |
1206 | </span>
1207 |
1208 |
1209 |
1210 | </a>
1211 | </li>
1212 |
1213 |
1214 |
1215 |
1216 |
1217 |
1218 |
1219 |
1220 |
1221 | <li class="md-nav__item">
1222 | <a href="../future_work/" class="md-nav__link">
1223 |
1224 |
1225 |
1226 | <span class="md-ellipsis">
1227 |
1228 |
1229 | Future Work
1230 |
1231 |
1232 |
1233 | </span>
1234 |
1235 |
1236 |
1237 | </a>
1238 | </li>
1239 |
1240 |
1241 |
1242 |
1243 |
1244 |
1245 |
1246 |
1247 |
1248 | <li class="md-nav__item">
1249 | <a href="../license/" class="md-nav__link">
1250 |
1251 |
1252 |
1253 | <span class="md-ellipsis">
1254 |
1255 |
1256 | License
1257 |
1258 |
1259 |
1260 | </span>
1261 |
1262 |
1263 |
1264 | </a>
1265 | </li>
1266 |
1267 |
1268 |
1269 | </ul>
1270 | </nav>
1271 | </div>
1272 | </div>
1273 | </div>
1274 |
1275 |
1276 |
1277 | <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
1278 | <div class="md-sidebar__scrollwrap">
1279 | <div class="md-sidebar__inner">
1280 |
1281 |
1282 | <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
1283 |
1284 |
1285 |
1286 |
1287 |
1288 |
1289 | <label class="md-nav__title" for="__toc">
1290 | <span class="md-nav__icon md-icon"></span>
1291 | Table of contents
1292 | </label>
1293 | <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
1294 |
1295 | <li class="md-nav__item">
1296 | <a href="#basic-queries" class="md-nav__link">
1297 | <span class="md-ellipsis">
1298 |
1299 | Basic Queries
1300 |
1301 | </span>
1302 | </a>
1303 |
1304 | <nav class="md-nav" aria-label="Basic Queries">
1305 | <ul class="md-nav__list">
1306 |
1307 | <li class="md-nav__item">
1308 | <a href="#1-find-a-specific-function-by-name" class="md-nav__link">
1309 | <span class="md-ellipsis">
1310 |
1311 | 1. Find a specific function by name
1312 |
1313 | </span>
1314 | </a>
1315 |
1316 | </li>
1317 |
1318 | <li class="md-nav__item">
1319 | <a href="#2-find-all-calls-to-a-specific-function" class="md-nav__link">
1320 | <span class="md-ellipsis">
1321 |
1322 | 2. Find all calls to a specific function
1323 |
1324 | </span>
1325 | </a>
1326 |
1327 | </li>
1328 |
1329 | <li class="md-nav__item">
1330 | <a href="#3-find-what-a-function-calls" class="md-nav__link">
1331 | <span class="md-ellipsis">
1332 |
1333 | 3. Find what a function calls
1334 |
1335 | </span>
1336 | </a>
1337 |
1338 | </li>
1339 |
1340 | <li class="md-nav__item">
1341 | <a href="#4-find-all-imports-of-a-specific-module" class="md-nav__link">
1342 | <span class="md-ellipsis">
1343 |
1344 | 4. Find all imports of a specific module
1345 |
1346 | </span>
1347 | </a>
1348 |
1349 | </li>
1350 |
1351 | <li class="md-nav__item">
1352 | <a href="#5-find-all-methods-of-a-class" class="md-nav__link">
1353 | <span class="md-ellipsis">
1354 |
1355 | 5. Find all methods of a class
1356 |
1357 | </span>
1358 | </a>
1359 |
1360 | </li>
1361 |
1362 | <li class="md-nav__item">
1363 | <a href="#6-find-all-classes-that-inherit-from-a-specific-class" class="md-nav__link">
1364 | <span class="md-ellipsis">
1365 |
1366 | 6. Find all classes that inherit from a specific class
1367 |
1368 | </span>
1369 | </a>
1370 |
1371 | </li>
1372 |
1373 | <li class="md-nav__item">
1374 | <a href="#7-find-all-functions-with-a-specific-decorator" class="md-nav__link">
1375 | <span class="md-ellipsis">
1376 |
1377 | 7. Find all functions with a specific decorator
1378 |
1379 | </span>
1380 | </a>
1381 |
1382 | </li>
1383 |
1384 | <li class="md-nav__item">
1385 | <a href="#8-find-all-dataclasses" class="md-nav__link">
1386 | <span class="md-ellipsis">
1387 |
1388 | 8. Find all dataclasses
1389 |
1390 | </span>
1391 | </a>
1392 |
1393 | </li>
1394 |
1395 | </ul>
1396 | </nav>
1397 |
1398 | </li>
1399 |
1400 | <li class="md-nav__item">
1401 | <a href="#code-analysis-quality" class="md-nav__link">
1402 | <span class="md-ellipsis">
1403 |
1404 | Code Analysis & Quality
1405 |
1406 | </span>
1407 | </a>
1408 |
1409 | <nav class="md-nav" aria-label="Code Analysis & Quality">
1410 | <ul class="md-nav__list">
1411 |
1412 | <li class="md-nav__item">
1413 | <a href="#9-find-the-5-most-complex-functions" class="md-nav__link">
1414 | <span class="md-ellipsis">
1415 |
1416 | 9. Find the 5 most complex functions
1417 |
1418 | </span>
1419 | </a>
1420 |
1421 | </li>
1422 |
1423 | <li class="md-nav__item">
1424 | <a href="#10-calculate-cyclomatic-complexity-of-a-function" class="md-nav__link">
1425 | <span class="md-ellipsis">
1426 |
1427 | 10. Calculate cyclomatic complexity of a function
1428 |
1429 | </span>
1430 | </a>
1431 |
1432 | </li>
1433 |
1434 | <li class="md-nav__item">
1435 | <a href="#11-find-unused-code" class="md-nav__link">
1436 | <span class="md-ellipsis">
1437 |
1438 | 11. Find unused code
1439 |
1440 | </span>
1441 | </a>
1442 |
1443 | </li>
1444 |
1445 | <li class="md-nav__item">
1446 | <a href="#12-find-the-call-chain-between-two-functions" class="md-nav__link">
1447 | <span class="md-ellipsis">
1448 |
1449 | 12. Find the call chain between two functions
1450 |
1451 | </span>
1452 | </a>
1453 |
1454 | </li>
1455 |
1456 | <li class="md-nav__item">
1457 | <a href="#13-find-all-direct-and-indirect-callers-of-a-function" class="md-nav__link">
1458 | <span class="md-ellipsis">
1459 |
1460 | 13. Find all direct and indirect callers of a function
1461 |
1462 | </span>
1463 | </a>
1464 |
1465 | </li>
1466 |
1467 | <li class="md-nav__item">
1468 | <a href="#14-find-functions-by-argument-name" class="md-nav__link">
1469 | <span class="md-ellipsis">
1470 |
1471 | 14. Find functions by argument name
1472 |
1473 | </span>
1474 | </a>
1475 |
1476 | </li>
1477 |
1478 | <li class="md-nav__item">
1479 | <a href="#15-list-all-python-package-imports-from-a-directory" class="md-nav__link">
1480 | <span class="md-ellipsis">
1481 |
1482 | 15. List all python package imports from a directory
1483 |
1484 | </span>
1485 | </a>
1486 |
1487 | </li>
1488 |
1489 | </ul>
1490 | </nav>
1491 |
1492 | </li>
1493 |
1494 | <li class="md-nav__item">
1495 | <a href="#repository-information-queries" class="md-nav__link">
1496 | <span class="md-ellipsis">
1497 |
1498 | Repository Information Queries
1499 |
1500 | </span>
1501 | </a>
1502 |
1503 | <nav class="md-nav" aria-label="Repository Information Queries">
1504 | <ul class="md-nav__list">
1505 |
1506 | <li class="md-nav__item">
1507 | <a href="#16-list-all-indexed-projects" class="md-nav__link">
1508 | <span class="md-ellipsis">
1509 |
1510 | 16. List all indexed projects
1511 |
1512 | </span>
1513 | </a>
1514 |
1515 | </li>
1516 |
1517 | <li class="md-nav__item">
1518 | <a href="#17-check-the-status-of-an-indexing-job" class="md-nav__link">
1519 | <span class="md-ellipsis">
1520 |
1521 | 17. Check the status of an indexing job
1522 |
1523 | </span>
1524 | </a>
1525 |
1526 | </li>
1527 |
1528 | <li class="md-nav__item">
1529 | <a href="#18-list-all-background-jobs" class="md-nav__link">
1530 | <span class="md-ellipsis">
1531 |
1532 | 18. List all background jobs
1533 |
1534 | </span>
1535 | </a>
1536 |
1537 | </li>
1538 |
1539 | </ul>
1540 | </nav>
1541 |
1542 | </li>
1543 |
1544 | <li class="md-nav__item">
1545 | <a href="#advanced-cypher-queries" class="md-nav__link">
1546 | <span class="md-ellipsis">
1547 |
1548 | Advanced Cypher Queries
1549 |
1550 | </span>
1551 | </a>
1552 |
1553 | <nav class="md-nav" aria-label="Advanced Cypher Queries">
1554 | <ul class="md-nav__list">
1555 |
1556 | <li class="md-nav__item">
1557 | <a href="#19-find-all-function-definitions" class="md-nav__link">
1558 | <span class="md-ellipsis">
1559 |
1560 | 19. Find all function definitions
1561 |
1562 | </span>
1563 | </a>
1564 |
1565 | </li>
1566 |
1567 | <li class="md-nav__item">
1568 | <a href="#20-find-all-classes" class="md-nav__link">
1569 | <span class="md-ellipsis">
1570 |
1571 | 20. Find all classes
1572 |
1573 | </span>
1574 | </a>
1575 |
1576 | </li>
1577 |
1578 | <li class="md-nav__item">
1579 | <a href="#21-find-all-functions-in-a-file" class="md-nav__link">
1580 | <span class="md-ellipsis">
1581 |
1582 | 21. Find all functions in a file
1583 |
1584 | </span>
1585 | </a>
1586 |
1587 | </li>
1588 |
1589 | <li class="md-nav__item">
1590 | <a href="#22-find-all-classes-in-a-file" class="md-nav__link">
1591 | <span class="md-ellipsis">
1592 |
1593 | 22. Find all classes in a file
1594 |
1595 | </span>
1596 | </a>
1597 |
1598 | </li>
1599 |
1600 | <li class="md-nav__item">
1601 | <a href="#23-list-all-top-level-functions-and-classes-in-a-file" class="md-nav__link">
1602 | <span class="md-ellipsis">
1603 |
1604 | 23. List all top-level functions and classes in a file
1605 |
1606 | </span>
1607 | </a>
1608 |
1609 | </li>
1610 |
1611 | <li class="md-nav__item">
1612 | <a href="#24-find-functions-in-one-module-that-call-a-function-in-another" class="md-nav__link">
1613 | <span class="md-ellipsis">
1614 |
1615 | 24. Find functions in one module that call a function in another
1616 |
1617 | </span>
1618 | </a>
1619 |
1620 | </li>
1621 |
1622 | <li class="md-nav__item">
1623 | <a href="#25-find-circular-file-imports" class="md-nav__link">
1624 | <span class="md-ellipsis">
1625 |
1626 | 25. Find circular file imports
1627 |
1628 | </span>
1629 | </a>
1630 |
1631 | </li>
1632 |
1633 | <li class="md-nav__item">
1634 | <a href="#26-find-all-functions-with-more-than-5-arguments" class="md-nav__link">
1635 | <span class="md-ellipsis">
1636 |
1637 | 26. Find all functions with more than 5 arguments
1638 |
1639 | </span>
1640 | </a>
1641 |
1642 | </li>
1643 |
1644 | <li class="md-nav__item">
1645 | <a href="#27-find-all-functions-in-a-file-that-have-a-docstring" class="md-nav__link">
1646 | <span class="md-ellipsis">
1647 |
1648 | 27. Find all functions in a file that have a docstring
1649 |
1650 | </span>
1651 | </a>
1652 |
1653 | </li>
1654 |
1655 | <li class="md-nav__item">
1656 | <a href="#28-find-all-classes-that-have-a-specific-method" class="md-nav__link">
1657 | <span class="md-ellipsis">
1658 |
1659 | 28. Find all classes that have a specific method
1660 |
1661 | </span>
1662 | </a>
1663 |
1664 | </li>
1665 |
1666 | <li class="md-nav__item">
1667 | <a href="#29-find-the-depth-of-inheritance-for-all-classes" class="md-nav__link">
1668 | <span class="md-ellipsis">
1669 |
1670 | 29. Find the depth of inheritance for all classes
1671 |
1672 | </span>
1673 | </a>
1674 |
1675 | </li>
1676 |
1677 | <li class="md-nav__item">
1678 | <a href="#30-find-all-functions-that-have-a-docstring" class="md-nav__link">
1679 | <span class="md-ellipsis">
1680 |
1681 | 30. Find all functions that have a docstring
1682 |
1683 | </span>
1684 | </a>
1685 |
1686 | </li>
1687 |
1688 | <li class="md-nav__item">
1689 | <a href="#31-find-all-decorated-methods-in-a-class" class="md-nav__link">
1690 | <span class="md-ellipsis">
1691 |
1692 | 31. Find all decorated methods in a class
1693 |
1694 | </span>
1695 | </a>
1696 |
1697 | </li>
1698 |
1699 | <li class="md-nav__item">
1700 | <a href="#32-find-the-number-of-functions-in-each-file" class="md-nav__link">
1701 | <span class="md-ellipsis">
1702 |
1703 | 32. Find the number of functions in each file
1704 |
1705 | </span>
1706 | </a>
1707 |
1708 | </li>
1709 |
1710 | <li class="md-nav__item">
1711 | <a href="#33-find-all-methods-that-override-a-parent-method" class="md-nav__link">
1712 | <span class="md-ellipsis">
1713 |
1714 | 33. Find all methods that override a parent method
1715 |
1716 | </span>
1717 | </a>
1718 |
1719 | </li>
1720 |
1721 | <li class="md-nav__item">
1722 | <a href="#34-find-all-functions-that-call-super" class="md-nav__link">
1723 | <span class="md-ellipsis">
1724 |
1725 | 34. Find all functions that call super()
1726 |
1727 | </span>
1728 | </a>
1729 |
1730 | </li>
1731 |
1732 | <li class="md-nav__item">
1733 | <a href="#35-find-all-calls-to-a-function-with-a-specific-argument" class="md-nav__link">
1734 | <span class="md-ellipsis">
1735 |
1736 | 35. Find all calls to a function with a specific argument
1737 |
1738 | </span>
1739 | </a>
1740 |
1741 | </li>
1742 |
1743 | <li class="md-nav__item">
1744 | <a href="#36-find-all-functions-that-are-not-called-by-any-other-function" class="md-nav__link">
1745 | <span class="md-ellipsis">
1746 |
1747 | 36. Find all functions that are not called by any other function
1748 |
1749 | </span>
1750 | </a>
1751 |
1752 | </li>
1753 |
1754 | <li class="md-nav__item">
1755 | <a href="#37-find-all-functions-that-are-called-with-a-specific-argument" class="md-nav__link">
1756 | <span class="md-ellipsis">
1757 |
1758 | 37. Find all functions that are called with a specific argument
1759 |
1760 | </span>
1761 | </a>
1762 |
1763 | </li>
1764 |
1765 | <li class="md-nav__item">
1766 | <a href="#38-find-all-direct-and-indirect-callees-of-a-function" class="md-nav__link">
1767 | <span class="md-ellipsis">
1768 |
1769 | 38. Find all direct and indirect callees of a function
1770 |
1771 | </span>
1772 | </a>
1773 |
1774 | </li>
1775 |
1776 | <li class="md-nav__item">
1777 | <a href="#39-find-all-functions-that-are-overridden" class="md-nav__link">
1778 | <span class="md-ellipsis">
1779 |
1780 | 39. Find all functions that are overridden
1781 |
1782 | </span>
1783 | </a>
1784 |
1785 | </li>
1786 |
1787 | <li class="md-nav__item">
1788 | <a href="#40-find-all-modules-imported-by-module_a" class="md-nav__link">
1789 | <span class="md-ellipsis">
1790 |
1791 | 40. Find all modules imported by module_a
1792 |
1793 | </span>
1794 | </a>
1795 |
1796 | </li>
1797 |
1798 | <li class="md-nav__item">
1799 | <a href="#41-find-large-functions-that-should-be-refactored" class="md-nav__link">
1800 | <span class="md-ellipsis">
1801 |
1802 | 41. Find large functions that should be refactored
1803 |
1804 | </span>
1805 | </a>
1806 |
1807 | </li>
1808 |
1809 | <li class="md-nav__item">
1810 | <a href="#42-find-recursive-functions" class="md-nav__link">
1811 | <span class="md-ellipsis">
1812 |
1813 | 42. Find recursive functions
1814 |
1815 | </span>
1816 | </a>
1817 |
1818 | </li>
1819 |
1820 | <li class="md-nav__item">
1821 | <a href="#43-find-most-connected-functions-hub-functions" class="md-nav__link">
1822 | <span class="md-ellipsis">
1823 |
1824 | 43. Find most connected functions (hub functions)
1825 |
1826 | </span>
1827 | </a>
1828 |
1829 | </li>
1830 |
1831 | </ul>
1832 | </nav>
1833 |
1834 | </li>
1835 |
1836 | <li class="md-nav__item">
1837 | <a href="#security-sensitive-data-analysis" class="md-nav__link">
1838 | <span class="md-ellipsis">
1839 |
1840 | Security & Sensitive Data Analysis
1841 |
1842 | </span>
1843 | </a>
1844 |
1845 | <nav class="md-nav" aria-label="Security & Sensitive Data Analysis">
1846 | <ul class="md-nav__list">
1847 |
1848 | <li class="md-nav__item">
1849 | <a href="#44-find-potential-security-vulnerabilities-hardcoded-secrets" class="md-nav__link">
1850 | <span class="md-ellipsis">
1851 |
1852 | 44. Find potential security vulnerabilities (hardcoded secrets)
1853 |
1854 | </span>
1855 | </a>
1856 |
1857 | </li>
1858 |
1859 | </ul>
1860 | </nav>
1861 |
1862 | </li>
1863 |
1864 | </ul>
1865 |
1866 | </nav>
1867 | </div>
1868 | </div>
1869 | </div>
1870 |
1871 |
1872 |
1873 | <div class="md-content" data-md-component="content">
1874 |
1875 | <article class="md-content__inner md-typeset">
1876 |
1877 |
1878 |
1879 |
1880 |
1881 | <h1 id="mcp-tool-cookbook">MCP Tool Cookbook</h1>
1882 | <p>This cookbook provides examples of how to use the <code>mcp</code> tool to query and understand your Python codebase. The "Tool" indicates which <code>mcp</code> tool to use, and the "JSON Arguments" are what the LLM would provide to that tool.</p>
1883 | <hr />
1884 | <h2 id="basic-queries">Basic Queries</h2>
1885 | <h3 id="1-find-a-specific-function-by-name">1. Find a specific function by name</h3>
1886 | <ul>
1887 | <li><strong>Natural Language:</strong> "Where is the function <code>foo</code> defined?"</li>
1888 | <li><strong>Tool:</strong> <code>find_code</code></li>
1889 | <li><strong>JSON Arguments:</strong></li>
1890 | </ul>
1891 | <pre><code class="language-json">{
1892 | "query": "foo"
1893 | }
1894 | </code></pre>
1895 | <p><img alt="Query 1" src="../images/1.png" /></p>
1896 | <h3 id="2-find-all-calls-to-a-specific-function">2. Find all calls to a specific function</h3>
1897 | <ul>
1898 | <li><strong>Natural Language:</strong> "Find all calls to the <code>helper</code> function."</li>
1899 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1900 | <li><strong>JSON Arguments:</strong></li>
1901 | </ul>
1902 | <pre><code class="language-json">{
1903 | "query_type": "find_callers",
1904 | "target": "helper"
1905 | }
1906 | </code></pre>
1907 | <p><img alt="Query 2" src="../images/2.png" /></p>
1908 | <h3 id="3-find-what-a-function-calls">3. Find what a function calls</h3>
1909 | <ul>
1910 | <li><strong>Natural Language:</strong> "What functions are called inside the <code>foo</code> function?"</li>
1911 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1912 | <li><strong>JSON Arguments:</strong></li>
1913 | </ul>
1914 | <pre><code class="language-json">{
1915 | "query_type": "find_callees",
1916 | "target": "foo",
1917 | "context": "/teamspace/studios/this_studio/demo/CodeGraphContext/tests/sample_project/module_a.py"
1918 | }
1919 | </code></pre>
1920 | <p><img alt="Query 3" src="../images/3.png" /></p>
1921 | <h3 id="4-find-all-imports-of-a-specific-module">4. Find all imports of a specific module</h3>
1922 | <ul>
1923 | <li><strong>Natural Language:</strong> "Where is the <code>math</code> module imported?"</li>
1924 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1925 | <li><strong>JSON Arguments:</strong></li>
1926 | </ul>
1927 | <pre><code class="language-json">{
1928 | "query_type": "find_importers",
1929 | "target": "math"
1930 | }
1931 | </code></pre>
1932 | <p><img alt="Query 4" src="../images/4.png" /></p>
1933 | <h3 id="5-find-all-methods-of-a-class">5. Find all methods of a class</h3>
1934 | <ul>
1935 | <li><strong>Natural Language:</strong> "What are the methods of the <code>A</code> class?"</li>
1936 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1937 | <li><strong>JSON Arguments:</strong></li>
1938 | </ul>
1939 | <pre><code class="language-json">{
1940 | "query_type": "class_hierarchy",
1941 | "target": "A"
1942 | }
1943 | </code></pre>
1944 | <ul>
1945 | <li><strong>Note:</strong> The response for <code>class_hierarchy</code> includes a list of methods.</li>
1946 | </ul>
1947 | <p><img alt="Query 5" src="../images/5.png" /></p>
1948 | <h3 id="6-find-all-classes-that-inherit-from-a-specific-class">6. Find all classes that inherit from a specific class</h3>
1949 | <ul>
1950 | <li><strong>Natural Language:</strong> "Show me all classes that inherit from <code>Base</code>."</li>
1951 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1952 | <li><strong>JSON Arguments:</strong></li>
1953 | </ul>
1954 | <pre><code class="language-json">{
1955 | "query_type": "class_hierarchy",
1956 | "target": "Base"
1957 | }
1958 | </code></pre>
1959 | <ul>
1960 | <li><strong>Note:</strong> The response for <code>class_hierarchy</code> includes a list of child classes.</li>
1961 | </ul>
1962 | <p><img alt="Query 6" src="../images/6.png" /></p>
1963 | <h3 id="7-find-all-functions-with-a-specific-decorator">7. Find all functions with a specific decorator</h3>
1964 | <ul>
1965 | <li><strong>Natural Language:</strong> "Find all functions with the <code>log_decorator</code>."</li>
1966 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
1967 | <li><strong>JSON Arguments:</strong></li>
1968 | </ul>
1969 | <pre><code class="language-json">{
1970 | "query_type": "find_functions_by_decorator",
1971 | "target": "log_decorator"
1972 | }
1973 | </code></pre>
1974 | <p><img alt="Query 7" src="../images/7.png" /></p>
1975 | <h3 id="8-find-all-dataclasses">8. Find all dataclasses</h3>
1976 | <ul>
1977 | <li><strong>Natural Language:</strong> "Find all dataclasses."</li>
1978 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
1979 | <li><strong>JSON Arguments:</strong></li>
1980 | </ul>
1981 | <pre><code class="language-json">{
1982 | "cypher_query": "MATCH (c:Class) WHERE 'dataclass' IN c.decorators RETURN c.name, c.file_path"
1983 | }
1984 | </code></pre>
1985 | <p><img alt="Query 8" src="../images/8.png" /></p>
1986 | <hr />
1987 | <h2 id="code-analysis-quality">Code Analysis & Quality</h2>
1988 | <h3 id="9-find-the-5-most-complex-functions">9. Find the 5 most complex functions</h3>
1989 | <ul>
1990 | <li><strong>Natural Language:</strong> "Find the 5 most complex functions."</li>
1991 | <li><strong>Tool:</strong> <code>find_most_complex_functions</code></li>
1992 | <li><strong>JSON Arguments:</strong></li>
1993 | </ul>
1994 | <pre><code class="language-json">{
1995 | "limit": 5
1996 | }
1997 | </code></pre>
1998 | <p><img alt="Query 9" src="../images/9.png" /></p>
1999 | <h3 id="10-calculate-cyclomatic-complexity-of-a-function">10. Calculate cyclomatic complexity of a function</h3>
2000 | <ul>
2001 | <li><strong>Natural Language:</strong> "What is the cyclomatic complexity of <code>try_except_finally</code>?"</li>
2002 | <li><strong>Tool:</strong> <code>calculate_cyclomatic_complexity</code></li>
2003 | <li><strong>JSON Arguments:</strong></li>
2004 | </ul>
2005 | <pre><code class="language-json">{
2006 | "function_name": "try_except_finally"
2007 | }
2008 | </code></pre>
2009 | <h3 id="11-find-unused-code">11. Find unused code</h3>
2010 | <ul>
2011 | <li><strong>Natural Language:</strong> "Find unused code, but ignore API endpoints decorated with <code>@app.route</code>."</li>
2012 | <li><strong>Tool:</strong> <code>find_dead_code</code></li>
2013 | <li><strong>JSON Arguments:</strong></li>
2014 | </ul>
2015 | <pre><code class="language-json">{
2016 | "exclude_decorated_with": ["@app.route"]
2017 | }
2018 | </code></pre>
2019 | <p><img alt="Query 11" src="../images/11.png" /></p>
2020 | <h3 id="12-find-the-call-chain-between-two-functions">12. Find the call chain between two functions</h3>
2021 | <ul>
2022 | <li><strong>Natural Language:</strong> "What is the call chain from <code>wrapper</code> to <code>helper</code>?"</li>
2023 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
2024 | <li><strong>JSON Arguments:</strong></li>
2025 | </ul>
2026 | <pre><code class="language-json">{
2027 | "query_type": "call_chain",
2028 | "target": "wrapper->helper"
2029 | }
2030 | </code></pre>
2031 | <p><img alt="Query 12" src="../images/12.png" /></p>
2032 | <h3 id="13-find-all-direct-and-indirect-callers-of-a-function">13. Find all direct and indirect callers of a function</h3>
2033 | <ul>
2034 | <li><strong>Natural Language:</strong> "Show me all functions that eventually call the <code>helper</code> function."</li>
2035 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
2036 | <li><strong>JSON Arguments:</strong></li>
2037 | </ul>
2038 | <pre><code class="language-json">{
2039 | "query_type": "find_all_callers",
2040 | "target": "helper"
2041 | }
2042 | </code></pre>
2043 | <p><img alt="Query 13" src="../images/13.png" /></p>
2044 | <h3 id="14-find-functions-by-argument-name">14. Find functions by argument name</h3>
2045 | <ul>
2046 | <li><strong>Natural Language:</strong> "Find all functions that take <code>self</code> as an argument."</li>
2047 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
2048 | <li><strong>JSON Arguments:</strong></li>
2049 | </ul>
2050 | <pre><code class="language-json">{
2051 | "query_type": "find_functions_by_argument",
2052 | "target": "self"
2053 | }
2054 | </code></pre>
2055 | <p><img alt="Query 14" src="../images/14.png" /></p>
2056 | <h3 id="15-list-all-python-package-imports-from-a-directory">15. List all python package imports from a directory</h3>
2057 | <ul>
2058 | <li><strong>Natural Language:</strong> "List all python package imports from my project directory."</li>
2059 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2060 | <li><strong>JSON Arguments:</strong></li>
2061 | </ul>
2062 | <pre><code class="language-json">{
2063 | "cypher_query": "MATCH (f:File)-[:IMPORTS]->(m:Module) WHERE f.path ENDS WITH '.py' RETURN DISTINCT m.name"
2064 | }
2065 | </code></pre>
2066 | <hr />
2067 | <h2 id="repository-information-queries">Repository Information Queries</h2>
2068 | <h3 id="16-list-all-indexed-projects">16. List all indexed projects</h3>
2069 | <ul>
2070 | <li><strong>Natural Language:</strong> "List all projects I have indexed."</li>
2071 | <li><strong>Tool:</strong> <code>list_indexed_repositories</code></li>
2072 | <li><strong>JSON Arguments:</strong></li>
2073 | </ul>
2074 | <pre><code class="language-json"> {}
2075 | </code></pre>
2076 | <p><img alt="Query 16" src="../images/16.png" /></p>
2077 | <h3 id="17-check-the-status-of-an-indexing-job">17. Check the status of an indexing job</h3>
2078 | <ul>
2079 | <li><strong>Natural Language:</strong> "What is the status of job <code>4cb9a60e-c1b1-43a7-9c94-c840771506bc</code>?"</li>
2080 | <li><strong>Tool:</strong> <code>check_job_status</code></li>
2081 | <li><strong>JSON Arguments:</strong></li>
2082 | </ul>
2083 | <pre><code class="language-json">{
2084 | "job_id": "4cb9a60e-c1b1-43a7-9c94-c840771506bc"
2085 | }
2086 | </code></pre>
2087 | <h3 id="18-list-all-background-jobs">18. List all background jobs</h3>
2088 | <ul>
2089 | <li><strong>Natural Language:</strong> "Show me all background jobs."</li>
2090 | <li><strong>Tool:</strong> <code>list_jobs</code></li>
2091 | <li><strong>JSON Arguments:</strong></li>
2092 | </ul>
2093 | <pre><code class="language-json"> {}
2094 | </code></pre>
2095 | <hr />
2096 | <h2 id="advanced-cypher-queries">Advanced Cypher Queries</h2>
2097 | <p>These examples use the <code>execute_cypher_query</code> tool for more specific and complex questions.</p>
2098 | <h3 id="19-find-all-function-definitions">19. Find all function definitions</h3>
2099 | <ul>
2100 | <li><strong>Natural Language:</strong> "Find all function definitions in the codebase."</li>
2101 | <li><strong>JSON Arguments:</strong></li>
2102 | </ul>
2103 | <pre><code class="language-json">{
2104 | "cypher_query": "MATCH (n:Function) RETURN n.name, n.file_path, n.line_number LIMIT 50"
2105 | }
2106 | </code></pre>
2107 | <p><img alt="Query 19" src="../images/19.png" /></p>
2108 | <h3 id="20-find-all-classes">20. Find all classes</h3>
2109 | <ul>
2110 | <li><strong>Natural Language:</strong> "Show me all the classes."</li>
2111 | <li><strong>JSON Arguments:</strong></li>
2112 | </ul>
2113 | <pre><code class="language-json">{
2114 | "cypher_query": "MATCH (n:Class) RETURN n.name, n.file_path, n.line_number LIMIT 50"
2115 | }
2116 | </code></pre>
2117 | <p><img alt="Query 20" src="../images/20.png" /></p>
2118 | <h3 id="21-find-all-functions-in-a-file">21. Find all functions in a file</h3>
2119 | <ul>
2120 | <li><strong>Natural Language:</strong> "Find all functions in <code>module_a.py</code>."</li>
2121 | <li><strong>JSON Arguments:</strong></li>
2122 | </ul>
2123 | <pre><code class="language-json">{
2124 | "cypher_query": "MATCH (f:Function) WHERE f.file_path ENDS WITH 'module_a.py' RETURN f.name"
2125 | }
2126 | </code></pre>
2127 | <p><img alt="Query 21" src="../images/21.png" /></p>
2128 | <h3 id="22-find-all-classes-in-a-file">22. Find all classes in a file</h3>
2129 | <ul>
2130 | <li><strong>Natural Language:</strong> "Find all classes in <code>advanced_classes.py</code>."</li>
2131 | <li><strong>JSON Arguments:</strong></li>
2132 | </ul>
2133 | <pre><code class="language-json">{
2134 | "cypher_query": "MATCH (c:Class) WHERE c.file_path ENDS WITH 'advanced_classes.py' RETURN c.name"
2135 | }
2136 | </code></pre>
2137 | <p><img alt="Query 22" src="../images/22.png" /></p>
2138 | <h3 id="23-list-all-top-level-functions-and-classes-in-a-file">23. List all top-level functions and classes in a file</h3>
2139 | <ul>
2140 | <li><strong>Natural Language:</strong> "List all top-level functions and classes in <code>module_a.py</code>."</li>
2141 | <li><strong>JSON Arguments:</strong></li>
2142 | </ul>
2143 | <pre><code class="language-json">{
2144 | "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"
2145 | }
2146 | </code></pre>
2147 | <p><img alt="Query 23" src="../images/23.png" /></p>
2148 | <h3 id="24-find-functions-in-one-module-that-call-a-function-in-another">24. Find functions in one module that call a function in another</h3>
2149 | <ul>
2150 | <li><strong>Natural Language:</strong> "Find functions in <code>module_a.py</code> that call <code>helper</code> in <code>module_b.py</code>."</li>
2151 | <li><strong>JSON Arguments:</strong></li>
2152 | </ul>
2153 | <pre><code class="language-json">{
2154 | "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"
2155 | }
2156 | </code></pre>
2157 | <p><img alt="Query 24" src="../images/24.png" /></p>
2158 | <h3 id="25-find-circular-file-imports">25. Find circular file imports</h3>
2159 | <ul>
2160 | <li><strong>Natural Language:</strong> "Are there any circular dependencies between files?"</li>
2161 | <li><strong>JSON Arguments:</strong></li>
2162 | </ul>
2163 | <pre><code class="language-json">{
2164 | "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"
2165 | }
2166 | </code></pre>
2167 | <h3 id="26-find-all-functions-with-more-than-5-arguments">26. Find all functions with more than 5 arguments</h3>
2168 | <ul>
2169 | <li><strong>Natural Language:</strong> "Find all functions with a large number of arguments."</li>
2170 | <li><strong>JSON Arguments:</strong></li>
2171 | </ul>
2172 | <pre><code class="language-json">{
2173 | "cypher_query": "MATCH (f:Function) WHERE size(f.args) > 5 RETURN f.name, f.file_path, size(f.args) as arg_count"
2174 | }
2175 | </code></pre>
2176 | <p><img alt="Query 26" src="../images/26.png" /></p>
2177 | <h3 id="27-find-all-functions-in-a-file-that-have-a-docstring">27. Find all functions in a file that have a docstring</h3>
2178 | <ul>
2179 | <li><strong>Natural Language:</strong> "Find all functions in <code>module_a.py</code> that have a docstring."</li>
2180 | <li><strong>JSON Arguments:</strong></li>
2181 | </ul>
2182 | <pre><code class="language-json">{
2183 | "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"
2184 | }
2185 | </code></pre>
2186 | <h3 id="28-find-all-classes-that-have-a-specific-method">28. Find all classes that have a specific method</h3>
2187 | <ul>
2188 | <li><strong>Natural Language:</strong> "Find all classes that have a <code>greet</code> method."</li>
2189 | <li><strong>JSON Arguments:</strong></li>
2190 | </ul>
2191 | <pre><code class="language-json">{
2192 | "cypher_query": "MATCH (c:Class)-[:CONTAINS]->(m:Function {name: 'greet'}) RETURN c.name, c.file_path"
2193 | }
2194 | </code></pre>
2195 | <p><img alt="Query 28" src="../images/28.png" /></p>
2196 | <h3 id="29-find-the-depth-of-inheritance-for-all-classes">29. Find the depth of inheritance for all classes</h3>
2197 | <ul>
2198 | <li><strong>Natural Language:</strong> "How deep are the inheritance chains for all classes?"</li>
2199 | <li><strong>JSON Arguments:</strong></li>
2200 | </ul>
2201 | <pre><code class="language-json">{
2202 | "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"
2203 | }
2204 | </code></pre>
2205 | <p><img alt="Query 29" src="../images/29.png" /></p>
2206 | <h3 id="30-find-all-functions-that-have-a-docstring">30. Find all functions that have a docstring</h3>
2207 | <ul>
2208 | <li><strong>Natural Language:</strong> "Show me all functions that are documented."</li>
2209 | <li><strong>JSON Arguments:</strong></li>
2210 | </ul>
2211 | <pre><code class="language-json">{
2212 | "cypher_query": "MATCH (f:Function) WHERE f.docstring IS NOT NULL AND f.docstring <> '' RETURN f.name, f.file_path LIMIT 50"
2213 | }
2214 | </code></pre>
2215 | <p><img alt="Query 30" src="../images/30.png" /></p>
2216 | <h3 id="31-find-all-decorated-methods-in-a-class">31. Find all decorated methods in a class</h3>
2217 | <ul>
2218 | <li><strong>Natural Language:</strong> "Find all decorated methods in the <code>Child</code> class."</li>
2219 | <li><strong>JSON Arguments:</strong></li>
2220 | </ul>
2221 | <pre><code class="language-json">{
2222 | "cypher_query": "MATCH (c:Class {name: 'Child'})-[:CONTAINS]->(m:Function) WHERE m.decorators IS NOT NULL AND size(m.decorators) > 0 RETURN m.name"
2223 | }
2224 | </code></pre>
2225 | <p><img alt="Query 31" src="../images/31.png" /></p>
2226 | <h3 id="32-find-the-number-of-functions-in-each-file">32. Find the number of functions in each file</h3>
2227 | <ul>
2228 | <li><strong>Natural Language:</strong> "How many functions are in each file?"</li>
2229 | <li><strong>JSON Arguments:</strong></li>
2230 | </ul>
2231 | <pre><code class="language-json">{
2232 | "cypher_query": "MATCH (f:Function) RETURN f.file_path, count(f) AS function_count ORDER BY function_count DESC"
2233 | }
2234 | </code></pre>
2235 | <p><img alt="Query 32" src="../images/32.png" /></p>
2236 | <h3 id="33-find-all-methods-that-override-a-parent-method">33. Find all methods that override a parent method</h3>
2237 | <ul>
2238 | <li><strong>Natural Language:</strong> "Find all methods that are overridden from a parent class."</li>
2239 | <li><strong>JSON Arguments:</strong></li>
2240 | </ul>
2241 | <pre><code class="language-json">{
2242 | "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"
2243 | }
2244 | </code></pre>
2245 | <p><img alt="Query 33" src="../images/33.png" /></p>
2246 | <h3 id="34-find-all-functions-that-call-super">34. Find all functions that call <code>super()</code></h3>
2247 | <ul>
2248 | <li><strong>Natural Language:</strong> "Find all methods that call their parent's method via <code>super()</code>."</li>
2249 | <li><strong>JSON Arguments:</strong></li>
2250 | </ul>
2251 | <pre><code class="language-json">{
2252 | "cypher_query": "MATCH (f:Function)-[r:CALLS]->() WHERE r.full_call_name STARTS WITH 'super(' RETURN f.name, f.file_path"
2253 | }
2254 | </code></pre>
2255 | <p><img alt="Query 34" src="../images/34.png" /></p>
2256 | <h3 id="35-find-all-calls-to-a-function-with-a-specific-argument">35. Find all calls to a function with a specific argument</h3>
2257 | <ul>
2258 | <li><strong>Natural Language:</strong> "Find all calls to <code>helper</code> with the argument <code>x</code>."</li>
2259 | <li><strong>JSON Arguments:</strong></li>
2260 | </ul>
2261 | <pre><code class="language-json">{
2262 | "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"
2263 | }
2264 | </code></pre>
2265 | <p><img alt="Query 35" src="../images/35.png" /></p>
2266 | <h3 id="36-find-all-functions-that-are-not-called-by-any-other-function">36. Find all functions that are not called by any other function</h3>
2267 | <ul>
2268 | <li><strong>Natural Language:</strong> "Find all dead code (functions that are never called)."</li>
2269 | <li><strong>JSON Arguments:</strong></li>
2270 | </ul>
2271 | <pre><code class="language-json">{
2272 | "cypher_query": "MATCH (f:Function) WHERE NOT (()-[:CALLS]->(f)) AND f.is_dependency = false RETURN f.name, f.file_path"
2273 | }
2274 | </code></pre>
2275 | <p><img alt="Query 36" src="../images/36.png" /></p>
2276 | <h3 id="37-find-all-functions-that-are-called-with-a-specific-argument">37. Find all functions that are called with a specific argument</h3>
2277 | <ul>
2278 | <li><strong>Natural Language:</strong> "Find all calls to <code>print</code> with the argument <code>'hello'</code>."</li>
2279 | <li><strong>JSON Arguments:</strong></li>
2280 | </ul>
2281 | <pre><code class="language-json">{
2282 | "cypher_query": "MATCH (c:Call) WHERE c.name = 'print' AND 'hello' IN c.args RETURN c.file, c.lineno"
2283 | }
2284 | </code></pre>
2285 | <h3 id="38-find-all-direct-and-indirect-callees-of-a-function">38. Find all direct and indirect callees of a function</h3>
2286 | <ul>
2287 | <li><strong>Natural Language:</strong> "Show me all functions that are eventually called by the <code>foo</code> function."</li>
2288 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
2289 | <li><strong>JSON Arguments:</strong></li>
2290 | </ul>
2291 | <pre><code class="language-json">{
2292 | "query_type": "find_all_callees",
2293 | "target": "foo",
2294 | "context": "/teamspace/studios/this_studio/demo/CodeGraphContext/tests/sample_project/module_a.py"
2295 | }
2296 | </code></pre>
2297 | <p><img alt="Query 38" src="../images/38.png" /></p>
2298 | <h3 id="39-find-all-functions-that-are-overridden">39. Find all functions that are overridden</h3>
2299 | <ul>
2300 | <li><strong>Natural Language:</strong> "Find all functions that are overridden."</li>
2301 | <li><strong>Tool:</strong> <code>analyze_code_relationships</code></li>
2302 | <li><strong>JSON Arguments:</strong></li>
2303 | </ul>
2304 | <pre><code class="language-json">{
2305 | "query_type": "overrides",
2306 | "target": "foo"
2307 | }
2308 | </code></pre>
2309 | <p><img alt="Query 39" src="../images/39.png" /></p>
2310 | <h3 id="40-find-all-modules-imported-by-module_a">40. Find all modules imported by <code>module_a</code></h3>
2311 | <ul>
2312 | <li><strong>Natural Language:</strong> "Find all modules imported by <code>module_a</code>."</li>
2313 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2314 | <li><strong>JSON Arguments:</strong></li>
2315 | </ul>
2316 | <pre><code class="language-json">{
2317 | "cypher_query": "MATCH (f:File {name: 'module_a.py'})-[:IMPORTS]->(m:Module) RETURN m.name AS imported_module_name"
2318 | }
2319 | </code></pre>
2320 | <p><img alt="Query 40" src="../images/40.png" /></p>
2321 | <h3 id="41-find-large-functions-that-should-be-refactored">41. Find large functions that should be refactored</h3>
2322 | <ul>
2323 | <li><strong>Natural Language:</strong> "Find functions with more than 20 lines of code that might need refactoring."</li>
2324 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2325 | <li><strong>JSON Arguments:</strong></li>
2326 | </ul>
2327 | <pre><code class="language-json">{
2328 | "cypher_query": "MATCH (f:Function)\n WHERE f.end_line - f.line_number > 20\n RETURN f"
2329 | }
2330 | </code></pre>
2331 | <p><img alt="Query 41" src="../images/41.png" /></p>
2332 | <h3 id="42-find-recursive-functions">42. Find recursive functions</h3>
2333 | <ul>
2334 | <li><strong>Natural Language:</strong> "Find all functions that call themselves (recursive functions)."</li>
2335 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2336 | <li><strong>JSON Arguments:</strong></li>
2337 | </ul>
2338 | <pre><code class="language-json">{
2339 | "cypher_query": "MATCH p=(f:Function)-[:CALLS]->(f2:Function)\n WHERE f.name = f2.name AND f.file_path = f2.file_path\n RETURN p"
2340 | }
2341 | </code></pre>
2342 | <p><img alt="Query 42" src="../images/42.png" /></p>
2343 | <h3 id="43-find-most-connected-functions-hub-functions">43. Find most connected functions (hub functions)</h3>
2344 | <ul>
2345 | <li><strong>Natural Language:</strong> "Find the functions that are most central to the codebase (called by many and call many others)."</li>
2346 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2347 | <li><strong>JSON Arguments:</strong></li>
2348 | </ul>
2349 | <pre><code class="language-json">{
2350 | "cypher_query": "MATCH (f:Function)\n OPTIONAL MATCH (f)-[:CALLS]->(callee:Function)\n OPTIONAL MATCH (caller:Function)-[:CALLS]->(f)\n WITH f, count(DISTINCT callee) AS calls_out, count(DISTINCT caller) AS calls_in\n ORDER BY (calls_out + calls_in) DESC\n LIMIT 5\n MATCH p=(f)-[*0..2]-()\n RETURN p"
2351 | }
2352 | </code></pre>
2353 | <p><img alt="Query 43" src="../images/43.png" /></p>
2354 | <h2 id="security-sensitive-data-analysis">Security & Sensitive Data Analysis</h2>
2355 | <h3 id="44-find-potential-security-vulnerabilities-hardcoded-secrets">44. Find potential security vulnerabilities (hardcoded secrets)</h3>
2356 | <ul>
2357 | <li><strong>Natural Language:</strong> "Find potential hardcoded passwords, API keys, or secrets in the codebase."</li>
2358 | <li><strong>Tool:</strong> <code>execute_cypher_query</code></li>
2359 | <li><strong>JSON Arguments:</strong></li>
2360 | </ul>
2361 | <pre><code class="language-json">{
2362 | "cypher_query": "WITH [\"password\", \"api_key\", \"apikey\", \"secret_token\", \"token\", \"auth\", \"access_key\", \"private_key\", \"client_secret\", \"sessionid\", \"jwt\"] AS keywords\n MATCH (f:Function)\n WHERE ANY(word IN keywords WHERE toLower(f.source_code) CONTAINS word)\n RETURN f"
2363 | }
2364 | </code></pre>
2365 |
2366 |
2367 |
2368 |
2369 |
2370 |
2371 |
2372 |
2373 |
2374 |
2375 |
2376 |
2377 |
2378 | </article>
2379 | </div>
2380 |
2381 |
2382 | <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
2383 | </div>
2384 |
2385 | </main>
2386 |
2387 | <footer class="md-footer">
2388 |
2389 | <div class="md-footer-meta md-typeset">
2390 | <div class="md-footer-meta__inner md-grid">
2391 | <div class="md-copyright">
2392 |
2393 |
2394 | Made with
2395 | <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
2396 | Material for MkDocs
2397 | </a>
2398 |
2399 | </div>
2400 |
2401 | </div>
2402 | </div>
2403 | </footer>
2404 |
2405 | </div>
2406 | <div class="md-dialog" data-md-component="dialog">
2407 | <div class="md-dialog__inner md-typeset"></div>
2408 | </div>
2409 |
2410 |
2411 |
2412 |
2413 |
2414 | <script id="__config" type="application/json">{"annotate": null, "base": "..", "features": [], "search": "../assets/javascripts/workers/search.2c215733.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>
2415 |
2416 |
2417 | <script src="../assets/javascripts/bundle.79ae519e.min.js"></script>
2418 |
2419 |
2420 | </body>
2421 | </html>
```