← Reflection
In the worksrole: extensionlicense: BSD-3-Clause

tom_reflector_model

tom_reflector_model · v1.0.0

The pure, serializable object model behind `tom_reflector` — the typed snapshot of a codebase's structure that downstream tools consume. Deliberately analyzer-free (only `collection` + `yaml`), with JSON/YAML round-trip and cycle-safe id references.

See License
Status
In the works
LOC
3.3k
Tests
0
Test LOC
0

Overview

From the module readme.md file:

What it enables

Enables Analysis result data model, JSON/YAML round-trip, Analyzer-free API representation.

Relationships

Standalone — no declared relationships.

tom_reflector_model

> Part of the Tom Framework reflection toolkit — an original analyzer-based > build-time reflection model © 2024–2026 Peter Nicolai Alexis Kyaw > (BSD-3-Clause). Like its sibling tom_reflector, > it shares no lineage or code with the > reflectable package by the Dart team > ("Copyright (c) 2015, Dart", BSD-3-Clause) that engine 1 derives from. See > LICENSE.

The pure, serializable object model behind engine 2 of the Tom reflection toolkit. It is the typed snapshot of a program's structure — libraries, packages, classes, enums, mixins, extensions, functions, members, parameters, types and annotations — that tom_reflector produces and that downstream generators and tools consume.

Crucially, this package has no dependency on the Dart analyzer (only collection and yaml). That is the whole point: the analyzer-heavy work lives in tom_reflector, while the data lives here as plain Dart objects that any tool can read, round-trip through JSON/YAML, and depend on without inheriting an analyzer version constraint.

Overview

A reflection result has to travel: it is produced once (by the analyzer), then read many times by code generators, doc tools and workspace indexers — often in separate processes, sometimes from disk. For that to be stable and cheap, the result must be plain data, not a live analyzer element tree.

tom_reflector_model provides exactly that:

  • A comprehensive object graph rooted at AnalysisResult (packages →

libraries → declarations → members → types/annotations), with full modifiers, type parameters and bounds, annotation arguments, and source locations. - In memory, elements reference each other directly (e.g. ClassInfo.superclass is a TypeReference); on the wire, references are encoded by stable id so cyclic graphs round-trip safely. - JSON and YAML serializers/deserializers plus a validator, so a result can be persisted and later re-read or validated independently of the analyzer.

tom_reflector  ──►  AnalysisResult (this package)  ──►  JSON / YAML on disk
 (analyzer)          plain Dart objects                  ◄── re-read by any tool

Installation

tom_reflector_model is an internal workspace package (publish_to: none); depend on it by path:

dependencies:
  tom_reflector_model:
    path: ../tom_reflector_model

SDK: Dart ^3.10.4. Dependencies are deliberately minimal: collection, yaml. It is also re-exported by tom_reflector, so depending on the engine gives you the model for free.

The model

Roots and containers

TypeRepresents
AnalysisResult The root: packages , libraries , files , plus timestamp , dartSdkVersion , analyzerVersion , schemaVersion , errors .
PackageInfoA package and its libraries.
LibraryInfo A library: its classes, enums, mixins, extensions, functions, variables, getters/setters.
FileInfoA source file (path, package).
ImportInfo / ExportInfoLibrary import/export directives.

Type declarations (extend TypeDeclaration)

TypeRepresents
ClassInfo A class — modifiers ( isAbstract , isSealed , isFinal , isBase , isInterface , isMixin ), superclass , interfaces , mixins , typeParameters , constructors , methods , fields , getters , setters .
EnumInfoAn enum and its EnumValueInfo values.
MixinInfoA mixin declaration.
ExtensionInfoAn extension.
ExtensionTypeInfoAn extension type.
TypeAliasInfoA typedef.

Members

TypeRepresents
MethodInfo A method (isOperator, isStatic, parameters, return type).
ConstructorInfoA constructor (named/factory/const).
FunctionInfoA top-level function.
FieldInfo / VariableInfo An instance field / top-level variable.
GetterInfo / SetterInfoAccessors.

Supporting types

TypeRepresents
ParameterInfoA parameter (named/optional/required, default value).
TypeParameterInfoA generic type parameter with its bound.
TypeReference A reference to a type (name, type arguments, nullability).
FunctionTypeInfoA function-type signature.
AnnotationInfo / ArgumentValue An annotation and its parsed arguments.
SourceLocationOffset/line/column into a source file.
AnalysisErrorA diagnostic captured during analysis.
ElementNotFoundException / AmbiguousElementException Lookup failures.

Navigating a result

result.allClasses;     // flatten classes across all libraries
result.allEnums;       // … enums, allMixins, allFunctions, allGetters, …
result.findClass('package:my/models.dart::Order');   // by qualified name
result.findClassesByName('Order');                   // by simple name
result.findClassesWithAnnotation('Reflectable');     // by annotation
result.findFunctionsWithAnnotation('entryPoint');

Serialization

Serializers and deserializers are static; the validator is an instance.

import 'dart:io';
import 'package:tom_reflector_model/tom_reflector_model.dart';

void main() {
  // A result is normally produced by tom_reflector; here we re-read one
  // saved to disk.
  final jsonText = File('analysis.json').readAsStringSync();

  // Validate untrusted input before decoding.
  final issues = AnalysisResultValidator().validateJson(jsonText);
  if (issues.isNotEmpty) throw StateError('invalid analysis: $issues');

  // Decode into the in-memory graph (id references rewired to objects).
  final AnalysisResult result = JsonDeserializer.decode(jsonText);

  for (final cls in result.allClasses) {
    print('${cls.qualifiedName}: '
        '${cls.methods.length} methods, ${cls.fields.length} fields');
    // package:my/models.dart::Order: 3 methods, 4 fields
  }

  // Round-trip back out — JSON (pretty) or YAML.
  final json = JsonSerializer.encode(result);   // String
  final yaml = YamlSerializer.encode(result);   // String
  final map  = JsonSerializer.toMap(result);    // Map<String, dynamic>

  // YAML re-reads symmetrically.
  final restored = YamlDeserializer.decode(yaml);
  print(restored.allClasses.length == result.allClasses.length); // true
}
APIDirection
JsonSerializer.encode(result) / .toMap(result) model → JSON string / map
JsonDeserializer.decode(source) / .fromMap(map) JSON string / map → model
YamlSerializer.encode(result)model → YAML string
YamlDeserializer.decode(source)YAML string → model
AnalysisResultValidator().validateJson / validateYaml / validateMap check before decoding → List<ValidationIssue>
IdGenerator().nextId(prefix)mint stable element ids

Cycle-safe references

Code graphs are cyclic (a class refers to types that refer back to it). In memory the model uses direct object references; for serialization, every element carries an id and references are emitted by id, so the writer never recurses infinitely and the reader rebuilds the object graph by resolving ids. IdGenerator mints those ids.

Configuration

TomAnalyzerConfig is the plain-data configuration record shared by the engine (barrels, output format/file, re-export following, workspace root):

const config = TomAnalyzerConfig(
  barrels: ['lib/models.dart'],
  outputFormat: 'yaml',           // or 'json'
  followReExports: true,
  skipReExports: ['dart.core'],
);

Architecture

package:tom_reflector_model/tom_reflector_model.dart
├── src/model/           the object graph (AnalysisResult, ClassInfo, …)
├── src/serialization/   JsonSerializer/Deserializer, YamlSerializer/Deserializer,
│                        AnalysisResultValidator, IdGenerator
└── src/config/          TomAnalyzerConfig

No analyzer, no build dependency — just data, serialization and config. This is what keeps downstream tools insulated from analyzer/Dart version churn.

Key types

TypeResponsibility
AnalysisResult Root of the model; flattening getters ( allClasses , …) and lookups ( findClass , …).
ClassInfo / EnumInfo / MixinInfo / ExtensionInfo / TypeAliasInfo Type declarations with full modifiers and members.
MethodInfo / FieldInfo / ParameterInfo / TypeParameterInfo Members and their shape.
TypeReferenceCycle-safe reference to a type.
AnnotationInfo / ArgumentValue Annotations with parsed arguments.
JsonSerializer / JsonDeserializer JSON round-trip (static).
YamlSerializer / YamlDeserializer YAML round-trip (static).
AnalysisResultValidatorValidate serialized input before decoding.
IdGeneratorStable id minting for cycle-safe references.
TomAnalyzerConfigEngine configuration as plain data.

Ecosystem

tom_reflector_model   THIS PACKAGE — pure model + serialization (no analyzer dep)
      ▲ re-exported & produced by
tom_reflector         analyzer engine + `reflector` CLI → AnalysisResult + *.r.dart

tom_reflector_model is the contract; tom_reflector fills it. Tools that only read analysis results can depend on this package alone and stay free of the analyzer dependency. The runtime-mirror engine (tom_reflection) is a separate technology — see the repo README.

The model is exercised end-to-end by the engine-2 parser samples — reflector_parser_introduction_sample (walk + JSON round-trip) and reflector_parser_advanced_sample (type resolution, cycle-safe IDs, YAML).

Status

  • Version: 1.0.0 (publish_to: none, internal workspace package).
  • SDK: Dart ^3.10.4.
  • Dependencies: collection, yaml only — deliberately analyzer-free.
  • Capabilities: comprehensive object model, JSON + YAML round-trip,

validation, cycle-safe id references.

License

BSD 3-Clause — original Tom Framework work (no reflectable lineage). Renamed from tom_analyzer_model. 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.