elixir-lsp/elixir_sense
68.0
Adequate · 3 October 2026
28.9k
lines of production code
Elixir
primary language
2
measurements over time
What this system is
ElixirSense is a stateless library that provides code intelligence capabilities for Elixir and Erlang, including type inference, documentation retrieval, and symbol navigation. It powers IDE features such as code completion, hover tooltips, and go-to-definition by analyzing code structure and context. The system supports specific frameworks like Ecto and Phoenix through a plugin architecture and maintains compatibility across various Elixir versions via normalized APIs and backports.
How it got here
2016–2019 — Version 2.0 architecture and type inference
11 changes.
The project underwent a major architectural shift to version 2.0, transitioning from an OTP application to a stateless library and raising the minimum Elixir requirement to 1.16. This period focused on implementing a comprehensive structural type-algebra engine for precise type inference and introspection, supported by normalized shims for Elixir's internal APIs. Extensive test coverage and project hygiene improvements, including modernized configuration and static analysis tooling, were integrated to support these core changes.
2023–2024 — completion engine rewrite and type inference
21 changes.
The project overhauled the completion subsystem with a new reducer-based architecture and added plugin support for Ecto and Phoenix frameworks. Significant improvements were made to type inference, introducing occurrence typing and guard handling for more accurate variable narrowing. The codebase was also refactored for Elixir 1.20+ compatibility, expanded to support Erlang navigation, and strengthened with comprehensive test coverage.
2026 — Navigation accuracy and test coverage
5 changes.
This period focused on improving navigation accuracy by replacing lexical analysis with an AST-based classifier in the SurroundContext module, fixing edge cases around symbol boundaries and operator captures. Concurrently, extensive test suites were added to verify the correctness of the completion engine, definition lookup in macros, and the new navigation logic against Elixir's standard library behavior.
Features
Added Erlang source location provider
Introduced a new location provider for Erlang files (\lib/elixir\_sense/providers/location/erl.ex\) that enables the IDE to locate type definitions, function definitions, and module declarations within \.erl\ files. This allows users to navigate to definitions and view symbol locations in Erlang codebases, extending the existing location capabilities beyond Elixir.
_lib/elixir\sense/providers/location · high confidence
Added utility modules for field type extraction and fuzzy name matching
New utility modules have been introduced to support provider functionality: \ElixirSense.Providers.Utils.Field\ now extracts field types from module metadata or via introspection, handling both public and private fields based on configuration, while \ElixirSense.Providers.Utils.Matcher\ implements a naive sequential fuzzy matching algorithm that requires the first character to match, improving how suggestions are filtered and ranked for users.
_lib/elixir\sense/providers/utils · high confidence
Ecto query and schema completion support
Added new completion providers for Ecto that enhance code intelligence when writing queries and defining schemas. The new \Ecto.Query\ provider offers suggestions for query clauses (such as \from\, \join\, and their options) and resolves field completions for bindings, including associations. The \Ecto.Schema\ provider provides autocomplete for schema field options (like \:default\, \:virtual\, \:primary\_key\) and association definitions (\belongs\_to\, \has\_one\, \has\_many\), including detailed documentation for options like \:on\_replace\ and \:on\_delete\. Additionally, the \Ecto.Types\ provider suggests built-in Ecto types (e.g., \:string\, \:integer\, \:utc\_datetime\) and custom types implementing \Ecto.Type\, with support for snippet insertion for complex types like arrays and maps.
_lib/elixir\sense/providers/plugins/ecto · high confidence
Hover provider now surfaces inferred types for variables
The hover provider in \lib/elixir\_sense/providers/hover/docs.ex\ has been updated to include inferred type information for variables. When hovering over a variable, the provider now attempts to render its best-effort inferred type using \TypePresentation.render\_hint\, displaying this type alongside the variable's name in the hover documentation. This enhances the developer experience by providing immediate type context for local variables without requiring explicit type annotations.
_lib/elixir\sense/providers/hover · high confidence
Introduce core type inference and introspection modules
This change adds a comprehensive set of new core modules to ElixirSense, including \Binding\, \Compiler\, \ElixirTypes\, \Introspection\, and \ExCkReader\. These modules implement a structural type-algebra engine for precise type inference, pattern matching refinement, and variable binding tracking. The update also integrates Elixir's native \Module.Types\ backend (where available) for enhanced expression typing and adds support for reading ExCk signature chunks from BEAM files to improve completion and hover accuracy.
_lib/elixir\sense/core · high confidence
New plugin-based completion providers for Ecto and Phoenix
The completion engine now uses a new plugin architecture to provide context-aware suggestions for Ecto and Phoenix code. A new \ModuleStore\ caches loaded modules and their behaviors to speed up lookups. The Ecto plugin offers completions for schema fields, associations, and query bindings, while the Phoenix plugin suggests controllers and actions within router definitions. These changes replace previous completion logic with a more modular, plugin-driven approach.
_lib/elixir\sense/providers/plugins · high confidence
Behavioural changes
Backports Elixir 1.17+ macro environment APIs for older versions
The library now supports macro expansion and aliasing APIs (such as \expand\_require\, \expand\_alias\, \define\_alias\, \define\_require\, and \define\_import\) on Elixir versions prior to 1.17. Previously, these operations relied on native \Macro.Env\ functions that were only available in Elixir 1.17 and later; the diff introduces a compatibility layer that delegates to the native implementation on Elixir 1.17+ but provides a custom, backported implementation for earlier versions. This ensures consistent behavior for code analysis and expansion across a wider range of Elixir versions, including specific handling for alias expansion and import definition logic that mirrors upstream changes.
_lib/elixir\sense/core/normalized/macro · high confidence
Compiler core refactored into modular components with Elixir 1.20+ support
The monolithic compiler implementation has been split into distinct modules (Bitstring, Clauses, Dispatch, Fn, Macro, Map, Quote, Rewrite, State, Typespec) to improve maintainability and align with upstream Elixir changes. This update adds support for Elixir 1.20, including version-specific behavior for \fn\ and \with\ expressions, and fixes crashes related to missing column information in \end\_of\_expression\ and undefined optional callbacks. It also improves type inference accuracy by preventing alias reference emission during typespec expansion and correctly handling bitstring alignment and size inference.
_lib/elixir\sense/core/compiler · high confidence
Completion engine ported from elixir-ls with state-based bitstring filtering
The completion subsystem has been replaced with a wholesale port from elixir-ls, introducing a new reducer-based architecture (CompletionEngine, GenericReducer, Suggestion) that processes cursor context to generate suggestions. This change restores state-based filtering for bitstring modifier suggestions, ensuring that only valid combinations (e.g., preventing \signed\ after \binary\) are offered to users. The engine also delegates cursor parsing to the host compiler's Code.Fragment to automatically inherit token-level fixes from the running Elixir version, and surfaces inferred types via TypePresentation for both hover and completion contexts.
_lib/elixir\sense/providers/completion · high confidence
Configurable logging and migration to new config syntax
The application now supports environment-specific configuration files (dev, prod, test) and has migrated from the legacy Mix.Config syntax to the modern import Config style. Users can now control logging behavior via the :elixir\_sense application's :logging\_enabled setting, which defaults to true in general configuration but is explicitly set to false in the production environment. Additionally, default settings for :use\_elixir\_types and :exck\_cache\_ttl are established in the base configuration.
config · high confidence
ElixirSense transitions from OTP application to stateless library
The ElixirSense module no longer starts as an OTP application; the \Application\ behavior and supervisor logic have been removed, making the library stateless and easier to integrate without managing a supervision tree. The public API has been refactored to delegate core functions (docs, definition, implementations, suggestions, signature, references) to specific provider modules, and a new \all\_modules/0\ function was added to list available modules. Additionally, the \string\_to\_quoted/5\ function now exposes an error-tolerant parser with configurable options, replacing the previous implementation.
lib · high confidence
Improved Phoenix scope resolution for nested routes
The Phoenix provider now correctly resolves module aliases within nested \scope\ blocks in Phoenix router files. By analyzing the AST path to the cursor, the tool can now accurately determine the full module name (e.g., \ExampleWeb.Router\ -\> \ExampleWeb.MyController\) even when scopes are wrapped or nested, ensuring that code completion and navigation work correctly inside complex routing definitions.
_lib/elixir\sense/providers/plugins/phoenix · high confidence
Improved navigation accuracy at symbol boundaries and for specific Elixir constructs
Navigation providers (definition, references, hover, etc.) now use a new AST-based classifier in \SurroundContext.Toxic\ instead of relying solely on lexical analysis. This change fixes two specific issues: it correctly resolves the module name when the cursor is placed immediately after an alias (e.g., at the end of \Foo\ in \Foo.bar()\), and it correctly identifies symbols when the cursor is positioned one column past the last character of a bare name. Additionally, the classifier provides more precise navigation for operator arity captures (like \&+/2\) and unary operators, while falling back to the standard library for cases where AST metadata is insufficient.
_lib/elixir\_sense/core/surround\context · high confidence
Improved type inference for guards and occurrence typing in control flow
The type inference engine now provides more precise type narrowing in \case\, \with\, and \cond\ expressions through a new occurrence typing system. This system narrows variable types based on matched patterns (e.g., recognizing that a variable is a specific struct or tuple within a branch) and leverages guard expressions to refine types further. Specifically, the new guard handling supports negative facts like \not is\_map\_key/2\ (marking keys as \:not\_set\ to prevent completion suggestions) and recognizes non-empty list shapes via \length(x) \> 0\. These changes result in more accurate type information for variables in conditional branches, leading to better code completion and error detection.
_lib/elixir\_sense/core/type\inference · high confidence
Introduce dedicated info structs for tracking code elements
The state management layer now uses specific data structures to track definitions and variables, replacing or supplementing previous generic storage. New modules include VarInfo for variables (tracking scope, version, and inferred types), AttributeInfo for module attributes, CallInfo for function calls, and ModFunInfo for module and function definitions (including parameters, positions, and type signatures). Additionally, RecordInfo, StructInfo, TypeInfo, and SpecInfo are introduced to capture details for records, structs, type definitions, and specs respectively. The Env struct has been updated to hold lists of these new info types, enabling more precise introspection and context tracking for features like variable type inference and documentation consumption.
_lib/elixir\sense/core/state · high confidence
Introduce normalized code and typespec shims for improved compatibility
Added new modules \ElixirSense.Core.Normalized.Code\ and \ElixirSense.Core.Normalized.Typespec\ to provide a stable, portable API layer over Elixir's internal \Code\ and \Code.Typespec\ modules. The \Code\ shim replicates the behavior of the deprecated \Code.get\_docs/2\, handling various documentation categories (functions, callbacks, types, module docs) and supporting multiple MIME types including Erlang HTML. The \Typespec\ shim wraps \Code.Typespec\ functions like \fetch\_specs\, \fetch\_types\, and \fetch\_callbacks\, ensuring consistent return formats and exposing helper functions for converting types and specs to quoted forms.
_lib/elixir\sense/core/normalized · high confidence
New definition locator implementation with toxic context support
The definition provider now uses a new \Locator\ module that routes navigation requests through the \SurroundContext.Toxic\ seam, enabling more accurate symbol location resolution. This change introduces support for finding definitions of variables, attributes, and functions defined within \\_\using\\_\ macros, including handling \defdelegate\ and \defguard\ constructs. The implementation also passes cursor position to binding resolution and includes fixes for multi-line use site detection, improving the reliability of 'go-to-definition' features for complex macro-generated code.
_lib/elixir\sense/providers/definition · high confidence
New implementation locator with cursor-aware context resolution
The implementation provider now uses a new \Locator\ module that determines symbol implementations by analyzing the surrounding code context at the cursor position. This change introduces a 'Toxic seam' via \SurroundContext.Toxic\ to route navigation locators, allowing the system to distinguish between different binding types (such as variables, attributes, or module functions) and resolve behavior implementations more accurately based on the specific cursor location rather than just the module scope.
_lib/elixir\sense/providers/implementation · high confidence
Project hygiene and documentation overhaul
The repository now includes formalized development standards and tooling: a \.credo.exs\ configuration enforces code style and refactoring checks, a \.dialyzer\_ignore.exs\ file manages static analysis warnings for version-gated code paths, and a \.formatter.exs\ standardizes code formatting. Additionally, the project is now MIT-licensed (replacing previous unspecified terms), includes a Code of Conduct, and features updated documentation with a supported Elixir/Erlang version matrix, installation instructions, and contributor credits.
(repo-wide) · high confidence
Refactored references locator to use SurroundContext.Toxic for context detection
The references provider now routes navigation location detection through the new SurroundContext.Toxic seam, replacing the previous logic for determining the context (variable, attribute, or module/function) at a cursor position. This change introduces a new Locator module that leverages this context to more accurately resolve references, including specific handling for variables via find\_var and improved binding resolution through the updated SurroundContext integration.
_lib/elixir\sense/providers/references · high confidence
Reimplemented completion engine with new reducer-based architecture
The completion subsystem has been replaced with a new reducer-based architecture that provides more accurate and context-aware suggestions. This change introduces dedicated reducers for specific completion types, including callbacks, overridable functions, protocol functions, record fields, parameter options, return values, and type specs. The new \CompleteEngine\ reducer populates context with grouped suggestions (modules, functions, macros, variables, attributes, and fields) which are then consumed by specialized reducers. Users will see improved completion for callbacks (including macrocallbacks), overridable functions, protocol functions, record fields (with support for Elixir 1.18+ record definitions), keyword parameter options, return value suggestions, and type specs. The system now also provides snippet suggestions for module attributes like @doc, @moduledoc, and @typedoc.
_lib/elixir\sense/providers/completion/reducers · high confidence
Test coverage
Added comprehensive test coverage for core type inference and binding logic; Added mock Elixir String module for testing; Added test coverage for completion engine, field type specs, and hover documentation; Added test coverage for metadata builder alias, import, require, and error recovery logic; Added test fixtures for Elixir language server capabilities; Added test fixtures for alias and require handling; Added test fixtures for import behavior; Added tests for Ecto query binding extraction with join associations; Added tests for SurroundContext.Toxic parity with Code.Fragment; Added tests for definition lookup in \_\using\\_ macros; Added tests for guard and occurrence type inference; Added tests for module listing and logging configuration; Added tests for normalized code and typespec documentation retrieval; Added tests for typespec expansion; Refactor test suite configuration and remove obsolete test file.
Dependencies
Major version bump to 2.0.0 with Elixir 1.16 requirement and new dev tooling
The project has been upgraded to version 2.0.0, raising the minimum supported Elixir version from 1.3 to 1.16. This change introduces a new dependency on the \toxic2\ parser (via git), replaces the legacy \mix.exs\ structure with a modern \Mix.Project\ module, and adds development dependencies for \credo\ (1.7), \dialyxir\ (1.0), \ex\_doc\ (0.18), and \stream\_data\ (1.1). The configuration also enables dialyzer flags for stricter type checking and updates the package metadata for Hex publishing.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 68 → 68 (-0.2)
- Rubric changed (rubric-2026.09.15 → rubric-2026.10.1) — scores are not directly comparable.
Lenses
- Code Health 87 → 87 (-0.0)
- Architecture 100 → 85 (-14.7)
- Maturity 51 → 52 (+0.9)
- Readiness 76 → 78 (+1.7)
- Security 96 → 97 (+0.8)
Resolved (12)
- Duplicated block (12 lines × 2) (lib/elixir_sense/providers/definition/locator.ex)
- Duplicated block (22 lines × 2) (lib/elixir_sense/core/compiler/dispatch.ex)
- Duplicated block (6 lines × 3) (lib/elixir_sense/core/binding.ex)
- Duplicated block (6 lines × 3) (lib/elixir_sense/core/binding.ex)
- Hotspot: lib/elixir_sense/core/binding.ex (lib/elixir_sense/core/binding.ex)
- Hotspot: lib/elixir_sense/core/compiler.ex (lib/elixir_sense/core/compiler.ex)
- Hotspot: lib/elixir_sense/core/compiler/state.ex (lib/elixir_sense/core/compiler/state.ex)
- Hotspot: lib/elixir_sense/core/elixir_types.ex (lib/elixir_sense/core/elixir_types.ex)
- Hotspot: lib/elixir_sense/core/metadata.ex (lib/elixir_sense/core/metadata.ex)
- Hotspot: lib/elixir_sense/core/surround_context/toxic.ex (lib/elixir_sense/core/surround_context/toxic.ex)
- Hotspot: lib/elixir_sense/providers/completion/completion_engine.ex (lib/elixir_sense/providers/completion/completion_engine.ex)
- Members sharing a duplicated core (4 members, 50+ identical tokens) (lib/elixir_sense/core/binding.ex)
New (9)
- Duplicated block (10 lines × 2) (lib/elixir_sense/core/state/env.ex)
- Duplicated block (14 lines × 2) (lib/elixir_sense/providers/definition/locator.ex)
- Duplicated block (24 lines × 2) (lib/elixir_sense/core/compiler/dispatch.ex)
- Duplicated block (6 lines × 3) (lib/elixir_sense/core/binding.ex)
- Duplicated block (6 lines × 3) (lib/elixir_sense/core/binding.ex)
- Duplicated block (8 lines × 2) (lib/elixir_sense/core/binding.ex)
- Low cohesion: State (LCOM4 5) (lib/elixir_sense/core/compiler/state.ex)
- Members sharing a duplicated core (4 members, 50+ identical tokens) (lib/elixir_sense/core/binding.ex)
- Projects may be oversized for their cohesion
Changes since last survey
- 1 commits — 0 feature/other, 1 fixes
By area
- (repo) — 1 commit
Notable commits
- fix: Merge pull request #343 from elixir-lsp/codex/fix-bitstring-completion-in
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
elixir-lsp/elixir_sense was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 3 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit da9f5b9148fa3b7f1bc0fda1b44d5e9efba1cac7 — the exact code this score is about.
- Scored under rubric-2026.10.1 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-24c657e50118.