tom_reflector
Analyzer-based code reflection engine for the Tom framework. It walks Dart sources with the Dart analyzer and produces a structured snapshot of a codebase's API.
Overview
From the module readme.md file:
What it enables
Enables API extraction, *.r.dart reflection output, Stable downstream API surface.
Relationships
Standalone โ no declared relationships.
tom_reflector
> Part of the Tom Framework reflection toolkit โ an original analyzer-based > build-time reflection engine ยฉ 2024โ2026 Peter Nicolai Alexis Kyaw > (BSD-3-Clause). Unlike its engine-1 siblings >
tom_reflection / > tom_reflection_generator
โ which are > derived from the reflectable
package > by the Dart team ("Copyright (c) 2015, Dart", BSD-3-Clause) โ tom_reflector
> shares no lineage or code with reflectable. See LICENSE.
Build-time, structural reflection for Dart. tom_reflector is engine 2
of the Tom reflection toolkit: instead of mirrors on live objects, it walks the Dart analyzer
element model and produces a serializable object graph of your code's shape โ classes, methods, parameters, types, annotations โ plus optional
*.r.dart reflection output that tooling consumes at build time.
This is original work (renamed from tom_analyzer), with no shared lineage with
reflectable. For runtime mirrors on real instances, use the sibling engine tom_reflection
instead โ see the repo README
for how to choose.
Overview
A code generator or workspace tool often needs to know the shape of code โ "what classes are here, what do they implement, what are their members and annotations?" โ without running that code.
dart:mirrors can't help (it's runtime and unavailable in AOT), and re-running the analyzer in every downstream tool is slow and couples you to a specific analyzer/Dart version.
tom_reflector solves this by analyzing once and emitting a stable, pre-resolved model
(tom_reflector_model) that any tool can read as plain data. The model is comprehensive (modifiers, type parameters with bounds, annotations with arguments, source locations), round-trips through JSON/YAML, and uses cycle-safe ID references when serialized. That stability is the point: downstream generators are insulated from analyzer churn.
your sources tom_reflector (analyzer) outputs
lib/models.dart โโโโโโบ reachability / barrel analysis โโบ models.r.dart
lib/app.dart + element walking + AnalysisResult graph
(tom_reflector_model)
Installation
tom_reflector is an internal workspace package (publish_to: none); depend on it by path from within the workspace:
dependencies:
tom_reflector:
path: ../tom_reflector
SDK: Dart ^3.10.4; uses analyzer ^8. The compiled reflector
binary is produced by the workspace build (~/.tom/bin/<platform>/reflector) and is also reachable as
buildkit :reflector.
Two generation modes
| Mode | Driven by | Use it when |
|---|---|---|
| Legacy (barrel) | a barrel file whose exports are all analyzed | you want reflection for everything a package exports. |
| Entry-point (reachability) | entry points + include/exclude filters | you want precise control โ reflect only what's reachable and wanted. |
Legacy (barrel) mode
# buildkit.yaml
tom_reflector:
barrels:
- lib/my_package.dart
follow_re_exports: true
skip_re_exports:
- dart.core
Generates lib/my_package.r.dart for all exports of the barrel.
Entry-point (reachability) mode
Performs reachability analysis from entry points, with rich filters, configurable transitive dependency resolution, and fine-grained coverage:
# buildkit.yaml
tom_reflector:
entry_points:
- lib/my_app.dart
output: lib/generated/reflection.r.dart
defaults:
exclude_packages: ['dart.*']
include_annotations: ['Reflectable']
filters:
- include: { packages: ['my_package'] }
- exclude: { annotations: ['DoNotReflect'] }
dependency_config:
superclasses: { enabled: true, depth: -1 }
interfaces: { enabled: true }
mixins: { enabled: true }
type_arguments: { enabled: true }
code_bodies: { enabled: false }
coverage_config:
instance_members: { enabled: true }
static_members: { enabled: true }
constructors: { enabled: true }
metadata: { enabled: true }
Configuration reference (entry-point mode):
| Section | Key | Default | Purpose |
|---|---|---|---|
| top-level | entry_points |
[] |
Roots for reachability analysis. |
output |
(derived) | Output path; .r.dart appended automatically. |
|
include_private |
false |
Include private members. | |
defaults |
exclude_packages / include_packages |
[] |
Package globs always excluded / included. |
include_annotations |
[] |
Annotations that auto-include their target. | |
filters |
include / exclude selectors |
[] |
Ordered rules by
packages
,
annotations
,
paths
,
types
,
elements
.
|
dependency_config |
superclasses
,
interfaces
,
mixins
,
type_arguments
,
code_bodies
|
varies |
Transitive resolution (
enabled
,
depth
,
external_depth
,
exclude_types
).
|
coverage_config |
instance_members
,
static_members
,
constructors
,
metadata
|
enabled: true |
Which invokers/data to generate. |
CLI
Run over a configured project, or scan the whole workspace:
reflector # generate for the current project (reads buildkit.yaml)
reflector -R # recursively scan the workspace for tom_reflector: projects
reflector -e lib/app.dart # entry-point mode (bypasses barrel config)
reflector --list # list projects that would be processed (no action)
buildkit :reflector # equivalent, nested under buildkit
dart run bin/reflector.dart [options] is equivalent before the binary is compiled.
Options (navigation flags like -R, -s, -p come from
tom_build_base):
| Option | Short | Default | Description |
|---|---|---|---|
--config=<path> |
-c |
buildkit.yaml |
Config file path. |
--entry=<file> |
-e |
Entry point(s), repeatable/comma-separated โ switches to entry-point mode. | |
--barrel=<path> |
(from config) | Barrel for legacy mode (overrides config). | |
--output=<path> |
(auto) | Output file path. | |
--list |
-l |
false |
List target projects, take no action. |
--verbose |
-v |
false |
Verbose output. |
Override precedence: buildkit.yaml tom_reflector: loads first โ
--barrel overrides barrels โ --output overrides the derived path โ
--entry bypasses barrel config entirely and switches to entry-point mode.
Programmatic usage
Barrel analysis โ model
import 'package:tom_reflector/tom_reflector.dart';
Future<void> main() async {
final runner = AnalyzerRunner();
final AnalysisResult result = await runner.analyzeBarrel(
barrelPath: 'lib/models.dart',
skipReExports: const ['dart.core'],
);
for (final cls in result.allClasses) {
print('${cls.name}: ${cls.methods.length} methods'); // Order: 3 methods
}
}
Entry-point reachability โ model
import 'package:tom_reflector/tom_reflector.dart';
Future<void> main() async {
final config = ReflectionConfig(
entryPoints: const ['lib/my_app.dart'],
defaults: const ReflectionDefaults(includeAnnotations: ['Reflectable']),
);
final analyzer = EntryPointAnalyzer(config);
final result = await analyzer.analyze();
// result holds the reachable, filtered set; feed it to ReflectionGenerator.
}
.r.dart output
In either mode the ReflectionGenerator emits a *.r.dart file holding the reflection data alongside the source. Treat
*.r.dart as a build output โ never hand-edit it; fix the generator/config and regenerate.
Architecture
package:tom_reflector/tom_reflector.dart (public API; re-exports tom_reflector_model)
โโโ src/analyzer/ drive the analyzer & build the model
โ โโโ AnalyzerRunner barrel analysis โ AnalysisResult
โ โโโ AnalyzerContextBuilder analysis context setup
โ โโโ BarrelAnalyzer legacy barrel mode
โ โโโ ElementVisitor / TypeResolver, AnnotationParser
โโโ src/reflection/generator/ entry-point reachability
โ โโโ EntryPointAnalyzer reachability + filters โ ReflectionAnalysisResult
โ โโโ ReflectionConfig filters, dependency & coverage config
โ โโโ ReflectionGenerator emits *.r.dart
โโโ src/v2/ reflectorTool + ReflectorExecutor (tom_build_base CLI)
bin/reflector.dart โ ToolRunner(reflectorTool) โ `reflector` / `buildkit :reflector`
Key types
| Type | Responsibility |
|---|---|
AnalyzerRunner |
Entry point for
barrel
analysis (
analyzeBarrel
) โ
AnalysisResult
.
|
AnalyzerContextBuilder |
Builds the analyzer AnalysisContextCollection. |
BarrelAnalyzer | Legacy barrel-export walking. |
EntryPointAnalyzer |
Reachability analysis from entry points (analyze()). |
ReflectionConfig |
Entry-point configuration:
entryPoints
,
filters
,
dependencyConfig
,
coverageConfig
,
includePrivate
;
load()
/
fromMap()
.
|
ReflectionGenerator |
Emits *.r.dart from the analyzed model. |
ReflectionModel | In-memory reflection model for generation. |
reflectorTool / ReflectorExecutor |
tom_build_base CLI surface (reflector). |
The pure data model itself (AnalysisResult, ClassInfo, โฆ) lives in tom_reflector_model
and is re-exported here.
Ecosystem
tom_reflector_model pure serializable model (AnalysisResult, ClassInfo, โฆ)
โฒ re-exports
tom_reflector THIS PACKAGE โ analyzer engine + `reflector` CLI โ *.r.dart
โ builds on
โโโ tom_build_base v2 tool framework (CLI, navigation, version flags)
โโโ tom_d4rt_ast AST modelling (cross-repo: tom_ai/d4rt/)
> tom_d4rt_ast lives in the d4rt repo; changes there can affect this > package โ coordinate with the d4rt quest on breaking changes.
This is the engine-2 generator. The runtime mirror engine (tom_reflection) is a separate technology with its own generator emitting
*.reflection.dart.
Further documentation
-
CLI usage:
doc/reflector_usage_guide.md -
Reflection guide:
doc/reflection_user_guide.md -
Analyzer usage & config reference:
doc/analyzer_usage_guide.md -
Implementation notes:
doc/reflection_implementation.md -
Design (pre-rename
tom_analyzer):doc/tom_analyzer_design.md -
Analyzer element API:
doc/analyzer_element_api.md
Runnable samples (engine 2)
-
Parser mode (no codegen):
reflector_parser_introduction_sample
โ reflector_parser_advanced_sample
- Codegen mode (*.r.dart): reflector_reflection_introduction_sample
โ reflector_reflection_advanced_sample
> Naming note: some doc/ files predate the tom_analyzer โ tom_reflector
> rename and still say "tom_analyzer"/"tom_analyzer_model". Read those names as > the pre-rename identity of
tom_reflector/tom_reflector_model.
Status
- Version: 1.0.0 (
publish_to: none, internal workspace package). - SDK: Dart
^3.10.4;analyzer ^8. - Modes: legacy barrel + entry-point reachability, both implemented.
-
CLI:
reflectorstandalone andbuildkit :reflector, ontom_build_base
navigation.
License
BSD 3-Clause โ original Tom Framework work (no reflectable lineage). See LICENSE.
License
BSD 3-Clause License Copyright (c) 2024-2026, Peter Nicolai Alexis Kyaw Find me on LinkedIn under Alexis Kyaw All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.