Add a compiler-backed exporter that produces deterministic, machine-readable descriptions of the public Apache Royale API. The output must be complete enough for clients to determine how to use every public class, interface, package function, field, accessor, method, event, style, effect, and MXML component, including all referenced types.
The exporter belongs in royale-compiler. Project orchestration and release packaging belong in the sibling royale-asjs repository and should be handled only after the compiler exporter is stable.
Do not parse ActionScript or MXML with regular expressions. The exporter must use resolved compiler definitions because Royale APIs may depend on:
COMPILE::JS and COMPILE::SWF conditional compilation.@copy and @private.Event, Style, Effect, Bindable, DefaultProperty, and Inspectable.UIBase in royale-asjs/frameworks/projects/Basic is an important eventual integration case. Its typeNames field is simple, while width, parent, and transformElement demonstrate target-specific declarations and inheritance behavior.
Start by reading these files:
compiler-jx/src/main/java/org/apache/royale/compiler/clients/MXMLJSCRoyale.javacompiler-jx/src/main/java/org/apache/royale/compiler/internal/driver/mxml/royale/MXMLRoyaleSWCBackend.javacompiler-jx/src/main/java/org/apache/royale/compiler/internal/projects/RoyaleJSProject.javacompiler-jx/src/main/java/org/apache/royale/compiler/internal/targets/RoyaleSWCTarget.javacompiler-jx/src/main/java/org/apache/royale/compiler/asdoc/royale/ASDocComment.javacompiler-jx/src/main/java/org/apache/royale/compiler/internal/parsing/as/RoyaleASDocDelegate.javaThe compiler infrastructure already provides:
RoyaleSWCTarget construction.getReachableCompilationUnits(...).Do not create an unrelated parser or duplicate compiler setup. Reuse the lower-level compiler lifecycle where appropriate, but keep the code graph client independent from the ASDoc client and output model. CODEGRAPH is not a kind of ASDOCJSC; any shared behavior is incidental compiler infrastructure and does not justify inheritance. The code graph path must not require ASDoc-specific configuration, emitters, or exclusions unless a rule is independently part of the code graph contract.
Keep the first implementation in compiler-jx because that module contains the Royale compiler client, SWC backend, project, and target infrastructure needed by the exporter.
The standalone client should extend the common compiler client infrastructure, use the normal Royale SWC backend, and own its target setup, reachable-unit selection, and graph output. Existing clients such as ASDOCJSC should remain unchanged unless a genuinely shared lower-level abstraction is introduced for multiple compiler clients.
Suggested classes are names, not mandatory API decisions:
org.apache.royale.compiler.clients.CODEGRAPH org.apache.royale.compiler.internal.codegen.graph.CodeGraphExporter org.apache.royale.compiler.internal.codegen.graph.CodeGraphModel org.apache.royale.compiler.internal.codegen.graph.CodeGraphWriter
Prefer a small model and writer over embedding JSON calls throughout AST visitors. Compiler traversal should populate the model; serialization should be deterministic and independently testable.
The initial command should resemble existing compiler clients:
java -cp ... org.apache.royale.compiler.clients.CODEGRAPH \ -load-config+=path/to/config.xml \ -compiler.define+=COMPILE::JS,true \ -compiler.define+=COMPILE::SWF,false \ -output=target/codegraph/graph.js.json
One invocation exports one resolved target. Merging JS and SWF into one logical release index can come later. Keeping target runs separate matches current compiler and Maven behavior and avoids inventing a second conditional-compilation evaluator.
The first pull request should prove semantic extraction, not solve release packaging.
Add a compiler test fixture containing:
Event, Bindable, and DefaultProperty metadata.Build the fixture through the normal compiler target.
Enumerate only reachable AS/MXML compilation units using the normal SWC target, extern configuration, and external-linkage rules owned by the code graph client.
Export public top-level definitions and their directly declared public members.
Resolve every referenced type through ICompilerProject. Emit a stable symbol reference even when the definition belongs to an external library.
Serialize a deterministic JSON document.
Assert the complete output as a golden fixture and run the export twice to verify byte-identical output.
Do not begin with inherited-member materialization, Maven attachment, graph compression, npm packaging, or all Royale framework projects. Those are follow-up slices.
The exact JSON shape should be finalized with tests, but version 1 needs these concepts.
{ "schemaVersion": "1.0", "target": "js", "module": "UIBase", "symbols": [], "externalSymbols": [] }
Do not include timestamps or absolute machine paths. They break deterministic release artifacts.
Use qualified semantic identities rather than source locations:
as3://org.apache.royale.core/UIBase as3://org.apache.royale.core/UIBase#typeNames as3://org.apache.royale.core/UIBase#width:get as3://org.apache.royale.core/UIBase#setWidth(Number,Boolean) as3://org.apache.royale.utils/sendEvent
Overloads are uncommon in AS3 but IDs must still distinguish callable signatures. Constructors, getters, setters, methods, fields, constants, and package functions need unambiguous IDs.
For each public type or package-level definition, include:
For members, include:
For external references, emit at least:
Never silently replace an unresolved type with a simple string. Emit an explicit unresolved reference and a compiler problem so validation can find it.
Use public definition and scope interfaces where possible:
IDefinitionITypeDefinitionIClassDefinitionIInterfaceDefinitionIFunctionDefinitionIAccessorDefinitionIVariableDefinitionIConstantDefinitionIParameterDefinitionIMetaTag and metadata attribute APIsICompilerProjectICompilationUnitResolve types with the active compiler project. Do not infer qualification from source imports manually.
Use AST nodes only for facts absent from definitions, such as preserving a source-level default expression. Keep semantic identity and type resolution definition-based.
Initially include:
Initially exclude:
@private.The objective is a public API/type graph, not a whole-program call graph.
Use RoyaleASDocDelegate and the existing parsed comment model for documentation extraction only. This does not make the exporter an ASDoc client and must not require the ASDoc backend or ASDoc configuration class. Preserve descriptions and tags structurally.
For the first slice, retain @copy as a structured tag/reference. Resolve and materialize copied text in a follow-up only after direct comments are correct. Similarly, preserve unknown tags rather than dropping them.
Treat @private consistently with the compiler's parsed documentation semantics.
Run the exporter once per target configuration:
COMPILE::JS=true, COMPILE::SWF=false -> graph.js.json COMPILE::JS=false, COMPILE::SWF=true -> graph.swf.json
Each graph describes what the compiler actually sees for that target. A later merger may combine matching stable IDs and mark availability as js, swf, or both.
Do not make the exporter inspect inactive conditional branches itself.
/.Place focused tests under compiler-jx/src/test/java and fixtures under the existing compiler-jx test resource conventions.
Required first tests:
typeNames-style public field: type, default value, docs, metadata, owner.The tests must also cover the standalone client path, not only graph model helpers:
create-target-with-errors explicitly permits it.Use explicit assertions in test helpers so a missing symbol or member reports its semantic identity instead of failing later with a null-pointer exception. Exact JSON golden assertions are appropriate because byte-level stability is part of the exporter contract.
Run the narrow module tests first:
./mvnw -pl compiler-jx -am test
Follow repository conventions if the existing compiler test harness requires additional environment properties.
Before considering the first compiler PR review-ready:
Test* naming, JUnit 4, and compiler test-base patterns.create-target-with-errors.ASDOCJSC unchanged. The code graph client must not inherit from it or use MXMLRoyaleASDocBackend.compiler-jx reactor tests before review.Passing the existing suite is necessary but not sufficient: the new client must have direct regression coverage for configuration, target setup, filtering, error handling, and output generation.
Status as of August 1, 2026: the compiler exporter, build-tool integration, SDK orchestration, and release packaging described by this plan are implemented and validated on the codegraph branches of royale-compiler and royale-asjs.
Implemented and covered by focused compiler-backed tests:
@private exclusion, structured metadata, metadata ASDoc, and type-bearing metadata references.@copy targets remain structured, opaque tag values, matching Royale's existing parser and emitter semantics. Effective inherited-member views remain derivable from explicit base/interface edges.
Implemented and validated in royale-asjs:
index.json, and mxml.json.index.json records module coordinates, target dependencies, relative paths, symbol/class counts, and SHA-256 hashes.mxml.json records target-specific namespace and manifest tag mappings.frameworks/codegraphs.org.apache.royale.framework:distribution:zip:codegraphs:<version> when the codegraphs profile is active.mvn verify -Pcodegraphs unpacks the attached classifier and validates package membership, graph identity, counts, schema versions, and indexed SHA-256 hashes.The compiler test reactor passes 1,375 tests with zero failures and zero errors (one skipped). Full Ant and Maven framework generation both pass for 37 modules and both targets.
schemaVersion uses major.minor numbering and identifies the graph contract, independently of compiler releases.codegraph-<major>.<minor>.schema.json beside the graph model classes.compiler-jx.@copy is preserved as an opaque structured tag, matching Royale parser and emitter behavior.compile-codegraph goal in royale-maven-plugin. Implemented with dedicated graph configs and separate JS/SWF outputs.codegraph.jar entry point and Unix/Windows launchers.CompileASDocMojo without invoking the ASDoc compiler.royale-asjs integration (complete)Implemented in the sibling repository:
index.json.mxml.json.codegraphs classifier, SDK downloads, and the existing @apache-royale/royale-js and @apache-royale/royale-js-swf npm packages.royale-asjsThe compiler exporter should accept normal compiler configuration and produce one graph file. It should not need to know the Royale reactor, npm package layout, or release staging paths.
royale-asjs supplies:
The graph format must allow royale-asjs to add module metadata without rewriting semantic symbol records.
compiler-jx unchanged and record the working test command.RoyaleSWCTarget to its resolved top-level definition.CODEGRAPH client.The compiler phase is complete. The following criteria are satisfied:
compiler-jx test suite passes.royale-asjs project list is hard-coded in the exporter.The implementation is complete on the codegraph branches. After merge into develop:
mvn verify -Pcodegraphs in the appropriate CI/release job.Keep the first change narrow: resolved public compiler facts in deterministic JSON.