|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This file provides guidance to AI coding agents when working with code in this repository. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +CodeCompass is a pluginable code comprehension tool. A C++17 backend parses |
| 8 | +projects into an SQL database (via ODB) and a webserver serves the results over |
| 9 | +Thrift RPC to a web frontend. Two frontends exist: the legacy Dojo-based |
| 10 | +`webgui/` (served at `/`) and the React/Next.js `webgui-new/` (served at |
| 11 | +`/new`). |
| 12 | + |
| 13 | +## Build |
| 14 | + |
| 15 | +Out-of-source CMake build (see `doc/deps.md` for dependencies: LLVM/Clang 15, |
| 16 | +ODB built via build2, Thrift, Boost, GTest, etc.): |
| 17 | + |
| 18 | +```bash |
| 19 | +mkdir build && cd build |
| 20 | +cmake .. \ |
| 21 | + -DCMAKE_INSTALL_PREFIX=<install_dir> \ |
| 22 | + -DDATABASE=<sqlite|pgsql> \ |
| 23 | + -DCMAKE_BUILD_TYPE=<Debug|Release|RelWithDebInfo> \ |
| 24 | + -DLLVM_DIR=/usr/lib/llvm-15/cmake \ |
| 25 | + -DClang_DIR=/usr/lib/cmake/clang-15 \ |
| 26 | + -DCMAKE_EXPORT_COMPILE_COMMANDS=1 \ |
| 27 | + -DTEST_DB="<connection_string>" # optional, enables functional tests |
| 28 | +make -j $(nproc) |
| 29 | +make install |
| 30 | +``` |
| 31 | + |
| 32 | +Notable CMake variables: |
| 33 | +- `DATABASE` (default `sqlite`) is a **compile-time** choice: it drives ODB code |
| 34 | + generation and defines `DATABASE_SQLITE`/`DATABASE_PGSQL`. Switching backend |
| 35 | + requires a separate build directory. |
| 36 | +- `WITH_PLUGIN` / `WITHOUT_PLUGIN` (mutually exclusive), e.g. |
| 37 | + `-DWITH_PLUGIN="cpp;git"`. The `search` plugin is always built. |
| 38 | +- `WITH_AUTH="plain;ldap"` selects authentication plugins. |
| 39 | +- `CODECOMPASS_LINKER` overrides the default `gold` linker. |
| 40 | + |
| 41 | +ODB/GTest from a custom prefix need `CMAKE_PREFIX_PATH`, `PATH` (for the `odb` |
| 42 | +binary) and `GTEST_ROOT` set before running CMake. |
| 43 | + |
| 44 | +## Tests |
| 45 | + |
| 46 | +Tests are GTest binaries registered with CTest, living in `plugins/<name>/test/`. |
| 47 | +Functional tests are only generated when `TEST_DB` is set at configure time, and |
| 48 | +its scheme must match `DATABASE` (e.g. `sqlite:database=/path/test.sqlite` or |
| 49 | +`pgsql:host=localhost;port=5432;user=...;password=...;database=...`). |
| 50 | + |
| 51 | +**Tests run against the installed binaries**: each test first builds a small |
| 52 | +sample project from `test/sources/` with CMake, then runs |
| 53 | +`${CMAKE_INSTALL_PREFIX}/bin/CodeCompass_parser` on it, then runs GTest queries |
| 54 | +against `TEST_DB`. So always `make install` before `make test`. |
| 55 | + |
| 56 | +```bash |
| 57 | +make install && make test ARGS=-V # all tests (as in CI) |
| 58 | +ctest -V -R cppparser # single CTest test (from build dir) |
| 59 | +``` |
| 60 | + |
| 61 | +Registered test names: `cppparser`, `cppservice`, `cppmetricsparser`, |
| 62 | +`cppmetricsservice`, `pythonparser`, `pythonservice`. To filter individual |
| 63 | +GTest cases, pass `--gtest_filter=...` after the three positional args the test |
| 64 | +binary expects (build command, parser command, DB string) — easiest to copy |
| 65 | +them from `ctest -V -N` / `CTestTestfile.cmake`. |
| 66 | + |
| 67 | +## Running |
| 68 | + |
| 69 | +```bash |
| 70 | +CodeCompass_parser -w <workspace> -n <project_name> -d <conn_string> \ |
| 71 | + -i <compile_commands.json> -i <source_dir> [-j N] [--force|--dry-run] |
| 72 | +CodeCompass_webserver -w <workspace> -p <port> |
| 73 | +``` |
| 74 | + |
| 75 | +The workspace must not be inside the parsed source tree. Without `--force`, |
| 76 | +re-parsing an existing project is incremental (only C++ and metrics parsers |
| 77 | +truly support it). `CodeCompass_logger` produces a compilation database for |
| 78 | +non-CMake builds. See `doc/usage.md`. |
| 79 | + |
| 80 | +## Frontend (webgui-new) |
| 81 | + |
| 82 | +```bash |
| 83 | +cd webgui-new |
| 84 | +npm install |
| 85 | +./thrift-codegen.sh --thrift-source ../ # regenerate TS stubs from all *.thrift |
| 86 | +npm run dev # dev server on :3000, proxies to BACKEND_URL |
| 87 | +npm run lint # run in CI |
| 88 | +``` |
| 89 | + |
| 90 | +Configure `BACKEND_URL`, `DEVSERVER_PORT`, `PUBLIC_URL` in `.env.local`. The |
| 91 | +generated Thrift TS stubs land in `webgui-new/generated/`; rerun codegen after |
| 92 | +changing any `.thrift` file. |
| 93 | + |
| 94 | +## Architecture |
| 95 | + |
| 96 | +Everything beyond the core is a **plugin loaded at runtime as a shared library** |
| 97 | +with `extern "C"` entry points: |
| 98 | + |
| 99 | +- **Parser plugins** (`plugins/<p>/parser`) subclass `cc::parser::AbstractParser` |
| 100 | + (`parser/include/parser/abstractparser.h`) and export `getOptions()` and |
| 101 | + `make(ParserContext&)`. Installed to `lib/parserplugin/`; `CodeCompass_parser` |
| 102 | + (`parser/src/parser.cpp`) dlopens every library there, runs |
| 103 | + `markModifiedFiles()` / `cleanupDatabase()` for incremental parsing, then |
| 104 | + `parse()` (parsers returning `isDatabaseIndexRequired()` run after DB indexes |
| 105 | + are created). Inputs (`-i`) are offered to every parser, which decide what |
| 106 | + they consume. |
| 107 | +- **Service plugins** (`plugins/<p>/service`, `service/*`) implement Thrift |
| 108 | + services and export `getOptions()` and `registerPlugin(ServerContext, |
| 109 | + PluginHandler*)` (see `plugins/dummy/service/src/plugin.cpp`). Installed to |
| 110 | + `lib/serviceplugin/`; `CodeCompass_webserver` (`webserver/`, embedded Mongoose |
| 111 | + HTTP server) loads them and routes requests per project in the workspace. |
| 112 | +- **Auth plugins** (`webserver/authenticators/`) installed to `lib/authplugin/`. |
| 113 | + |
| 114 | +Core modules: |
| 115 | +- `model/` — core ODB persistent classes (`File`, `FileContent`, `BuildAction`, |
| 116 | + …). Plugins add their own `model/` directories; headers are run through ODB |
| 117 | + via `generate_odb_files()` / `add_odb_library()` (`Functions.cmake`), |
| 118 | + producing `*-odb.hxx/.cxx` and `.sql` schema files (installed to |
| 119 | + `share/codecompass/sql`) in the build tree. |
| 120 | +- `service/` — shared Thrift APIs: `project.thrift` / `common.thrift` (files, |
| 121 | + build logs), `language.thrift` (the common interface that language plugins |
| 122 | + such as `cpp` and `python` implement), `workspace`, `plugin`, |
| 123 | + `authentication`, and the LSP bridge. |
| 124 | +- `util/` — DB connection/transaction helpers (`odbtransaction.h`, `dbutil.h`), |
| 125 | + logging, thread pool, graph (GraphViz) helpers, dynamic library loading. |
| 126 | +- `logger/` — `CodeCompass_logger` (LD_PRELOAD-based build command logger). |
| 127 | + |
| 128 | +A typical plugin (`plugins/dummy` is the template) has `model/`, `parser/`, |
| 129 | +`service/` (with a `.thrift` file), `test/` and `webgui/` (JS/CSS/images for the |
| 130 | +legacy GUI, installed by `install_webplugin()`; the new GUI lives entirely in |
| 131 | +`webgui-new/src`). Plugin-to-plugin model dependencies are passed as extra args |
| 132 | +to `generate_odb_files()`. |
| 133 | + |
| 134 | +The Python plugin's parser is itself written in Python (`plugins/python/parser/pyparser/`) |
| 135 | +and embedded via Boost.Python; see `doc/pythonplugin.md`. |
| 136 | + |
| 137 | +## Coding conventions (C++, from `doc/coding_conventions.md`) |
| 138 | + |
| 139 | +- 80-column lines, 2-space indent, no tabs; braces on their own line (Allman); |
| 140 | + namespaces not indented, closed with `} // name`. |
| 141 | +- Namespaces: two levels, `cc::<module>` (e.g. `cc::parser`, `cc::model`); |
| 142 | + services nest further (`cc::service::language`). |
| 143 | +- Naming: files lowercase without dashes (`.h`/`.cpp`); types `CamelCase`; |
| 144 | + functions `camelCase`; members `_camelCase`; parameters `camelCase_`; |
| 145 | + smart-pointer typedefs end in `Ptr`. |
| 146 | +- `int* ptr`, `const T& ref` — qualifier attached to the type. |
| 147 | +- Include guards `CC_<MODULE>_<FILE>_H`. Public headers under |
| 148 | + `include/<submodule>/` included with `<>`; private headers in `src/` with `""`. |
| 149 | + Include order: std, Boost, other third-party (LLVM/ODB/…), project headers. |
| 150 | +- One `public`/`protected`/`private` section each, in that order; friends first. |
| 151 | +- Never `using namespace` in headers. |
0 commit comments