The attached Java file shows a rough sketch of what the CompilationAnalysis API might look like. The basic idea is to map J(s)Nodes, SourceInfos, and Correlations onto a simplified API suitable for building reports from. The inner interfaces would likely be top-level types in a separate package, but are in the one Java file for ease of transmission.
The "byte-accounting" use cases would generally start with getStories(), which returns a Map of non-overlapping Ranges onto the applicable Story. Each Story can then provide a collection of Members that should be charged for those bytes. The "reachability" use case would use getClasses() and proceed to extract the fields and methods that have been retained (if somewhat mangled) in the JS output. The "dependency" use case is an extension and would crawl the Members that implement HasDependency. The "inspection" use case (similar to the JS-normal view) would be an extension of the byte-accounting interface, but would add in the additional mutation metadata from the Story. I'd expect that this is only really useful for compiler developers to look at the output with this much detail. Points for discussion: - Are simple HTML reports generated from the API (by a SoycReportLinker) or by processing an all-inclusive XML file after the fact? - There's going to be a _lot_ of data in the XML file [1]. It will likely be necessary to break the data up over several files, but I think that if we start with a single XML file and try to build some XSLT reports from it, we'll have a better idea of where the hotspots are. - If the data is broken up across several XML files, do we just start with a manifest XML file that says "for dependency data for this permutation, see this file"? - I don't really expect that anyone would use the Linker API directly, so I'm not really concerned with having that API perform any kind of aggregation or computations on behalf of the consumer. It's there in case anyone wants to use a different export format or to do something crazy like submit the data to a database as part of the build process. [1] A graphviz / .dot file showing dependencies for Dynatable weighs in at about 600k. It's mainly full of text label and lines that look like (56 -> 182); Showcase dependency files are just under a meg. -- Bob Vawter Google Web Toolkit Team --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
CompilationAnalysis.java
Description: Binary data
<?xml version="1.0" encoding="UTF-8"?> <soyc> <!-- Assume that the children of the soyc node could be split up among several files to allow report-writers to reduce to total amount of XML used when generating simple reports. --> <!-- Members are functional units that humans like to use --> <members> <class id="com.google.Class" name="Class" package="com.google"> <!-- Preserve some amount of the type hierarchy, even if the superclass or superinterface doesn't contribute anything directly. --> <overrides idref="com.google.AbstractClass" /> <!-- We could move depends to a top-level construct --> <depends> <on idref="com.google.Foo.methodUsedInPrototypeSetup" /> </depends> <!-- After inlining, many things are related only through direct field accesses. --> <field id="com.google.Class.field" name="field" /> <!-- Methods may or may not be directly preserved in the JS ouput, but we still want to be able to talk about the chunk of code the JS originated from. --> <method id="com.google.Class.method" name="method"> <depends> <on idref="com.google.Other.method" /> <on idref="com.google.Other.field" /> <on idref="com.google.ThirdClass" /> </depends> <overrides idref="com.google.AbstractClass.method" /> </method> </class> <!-- Prototype setup function --> <function id="com_google_Class" name="com_google_Class"> <depends> <on idref="com.google.Class" /> </depends> </function> </members> <stories> <!-- Stories have a counter-based ID --> <story id="story1"> <!-- The primary list of mutations, following the parent chain --> <mutations> <mutation>Class seed and function prototype setup</mutation> <mutation>Frobnicator frobbed this function</mutation> <!-- Shows ancestor SourceInfos --> <ancestor> <mutation>Additional ancestor's mutation</mutation> <mutation>Additional ancestar's mutation</mutation> </ancestor> <ancestor> <mutation>Some other ancester's mutation</mutation> </ancestor> </mutations> <!-- Shows references to member tags / functional units; getPrimaryCorrelations() --> <correlations> <by idref="com.google.Class" /> <by idref="com.google.Class.method" /> <by idref="com_google_Class" /> </correlations> </story> </stories> <!-- Big block of annotated JS, with nested story references OR we could just store the start-end ranges in the story nodes or some other map-like structure. Keeping the JS in the XML allows the XML reports to be self-contained and archived. --> <js> <story idref="story1">function com_google_Class() {}</story> <story idref="story2"> 1 + 1 + <story idref="story3">'randomness'</story> </story> </js> </soyc>