Skip to content

feat(frameworks): CodeIgniter 3 support#167

Open
darkspock wants to merge 1 commit into
colbymchenry:mainfrom
darkspock:feat/codeigniter-support
Open

feat(frameworks): CodeIgniter 3 support#167
darkspock wants to merge 1 commit into
colbymchenry:mainfrom
darkspock:feat/codeigniter-support

Conversation

@darkspock
Copy link
Copy Markdown

Adds a CodeIgniter 3 framework resolver alongside Laravel. Same shape as the existing PHP support — FrameworkResolver in src/resolution/frameworks/codeigniter.ts, one line in the registry, parameterized tests in the existing framework test file.

What it captures

1. Explicit routes from application/config/routes.php:

  • $route['pattern'] = 'controller/method'
  • HTTP-verb-scoped: $route['x']['POST'] = '...'
  • CI3 wildcards preserved: (:any), (:num)
  • Reserved keys skipped: default_controller, 404_override, translate_uri_dashes

2. Convention routes synthesized from every public method on each controller in application/controllers/**. CI3 routes by convention much more than via routes.php, so without this the graph would be near-empty for typical projects. URLs are lowercased per CI3 routing rules; _-prefixed methods, __construct, __destruct are excluded. Recognized controller bases: CI_Controller, MX_Controller (HMVC), MY_Controller, REST_Controller, plus common project-specific patterns (Admin_Controller, Public_Controller, Frontend_Controller, Backend_Controller).

3. Magic-loaded models and libraries — both $this->load->model('X') / $this->load->library('X') calls and the runtime property accesses that follow ($this->ModelName->method()). This is the part that matters most in practice: on a real ~8k-PHP-file CI3 codebase, only ~0.2% of model usages are explicit load->model() calls; the rest are property accesses on pre-loaded models that pure AST analysis can't see. The resolver filters on PascalCase to keep CI3 built-in properties ($this->load, $this->db, $this->input, …) out — they're all lowercase.

Reference resolution

controller/method strings in routes.php resolve to method nodes in application/controllers/, trying both PascalCase (CI3 file-naming convention) and the literal segment as fallback.

Tests

13 new tests in __tests__/frameworks.test.ts:

  • Explicit routes: tuple syntax, verb-scoped variant, reserved-key filtering
  • Convention routes: visibility filters (public only, _-prefix excluded), index → URL base, subdirectory URL building, non-controller files, HMVC base classes
  • Loader extraction: load->model('X'), load->library('X'), dedup, lowercase → PascalCase normalization
  • Magic property access: $this->Foo->bar() captured, lowercase built-ins ($this->db, $this->session, $this->load) excluded
  • Dedup across both layers when both patterns coexist

All 81 tests across frameworks.test.ts, resolution.test.ts, and frameworks-integration.test.ts pass. tsc --noEmit clean.

Validation on a real CI3 codebase

Indexed an ~8k-PHP-file CI3 project (61k PHP files total before filters):

Metric Value
Cold index time ~52s (~180 files/s)
Incremental sync after 1-file touch ~0.3s
Route nodes emitted 2,528
Files reachable from a specific model (Restomodel) via the graph 465
Same count from grep 467

99.6% recall vs grep, with edges that grep can't give you (resolves through the framework, not just text matches).

Notes

  • Changelog entry placed under ## [Unreleased] rather than a specific version — easier to rename at release time.
  • No version bump in package.json / package-lock.json — leaving release cadence to you.
  • Edit edge kind chosen as imports for consistency with how Laravel emits its handler references; the resolution pipeline routes these through the standard name-matcher.

Test plan

  • npm test — 81/81 framework + resolution + integration tests pass
  • npx tsc --noEmit — clean
  • End-to-end indexing on a real CI3 project, manual verification of route/import counts
  • Manual smoke test on a small Laravel project (no regressions in laravelResolver) — not run here, but the changes are additive and laravel.ts is untouched

Adds a CodeIgniter 3 framework resolver alongside Laravel, so PHP
projects on CI3 (still a sizeable long tail) get the same depth of
indexing.

Three layers of extraction:

1. **Explicit routes** from `application/config/routes.php` —
   `$route['pattern'] = 'controller/method'`, the HTTP-verb-scoped
   `$route['x']['POST'] = '...'` variant, and CI3 wildcards
   (`(:any)`, `(:num)`). Reserved keys (`default_controller`,
   `404_override`, `translate_uri_dashes`) are skipped.

2. **Convention routes** synthesized from every public method on each
   controller in `application/controllers/**`. CI3 routes by
   convention much more than by `routes.php`, so without this the
   graph would be near-empty for typical projects. URLs are lowercased
   per CI3 routing rules; `_`-prefixed methods, `__construct` and
   `__destruct` are excluded. Recognized bases: `CI_Controller`,
   `MX_Controller` (HMVC), `MY_Controller`, `REST_Controller`, plus
   common project-specific patterns.

3. **Magic-loaded models and libraries** — both `$this->load->model('X')`
   / `$this->load->library('X')` calls and the runtime property
   accesses that follow (`$this->ModelName->method()`). On a real
   ~8k-PHP-file CI3 codebase, only ~0.2% of model usages are explicit
   `load->model()` calls; the rest are property accesses on
   pre-loaded models that pure AST analysis can't see. The resolver
   filters on PascalCase to keep CI3 built-in properties (`$this->load`,
   `$this->db`, `$this->input`, …) out — they're all lowercase. False
   positives are limited to PascalCase property names that happen to
   collide with a real class name elsewhere; in practice this catches
   ~99% of real usages with negligible noise.

Reference resolution: `controller/method` strings in routes.php
resolve to method nodes in `application/controllers/`, trying both
PascalCase (CI3 file-naming convention) and the literal segment as
fallback.

## Tests

13 new tests in `__tests__/frameworks.test.ts` covering: explicit
routes, HTTP-verb variants, reserved-key filtering, convention routes
(visibility filters, `index` → URL base), subdirectory URL building,
non-controller files, HMVC base classes, `$this->load->model/library()`
extraction, magic property access, dedup across both patterns, and
PascalCase normalization.

Validated end-to-end on a ~8k-PHP-file CI3 project: 2,528 route nodes
emitted, framework detected, and graph edges to `application/models/`
classes match grep with ~99% recall.

## Changelog

Added under `[Unreleased]` so the maintainer can rename when cutting
the next release.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants