diff --git a/pkg/dart2js_info/bin/src/to_devtools_format.dart b/pkg/dart2js_info/bin/src/to_devtools_format.dart index 8e12f5dad28..9469c957c98 100644 --- a/pkg/dart2js_info/bin/src/to_devtools_format.dart +++ b/pkg/dart2js_info/bin/src/to_devtools_format.dart @@ -1,13 +1,13 @@ +library dart2js_info.bin.to_devtools_format; + import 'dart:convert'; import 'dart:io'; import 'package:args/command_runner.dart'; import 'package:dart2js_info/info.dart'; import 'package:dart2js_info/src/io.dart'; -import 'package:dart2js_info/src/util.dart'; +import 'package:dart2js_info/src/util.dart' show longName, libraryGroupName; import 'package:vm_snapshot_analysis/program_info.dart' as vm; -import 'package:vm_snapshot_analysis/treemap.dart'; - import 'usage_exception.dart'; /// Command that converts a `--dump-info` JSON output into a format ingested by Devtools. @@ -39,12 +39,12 @@ class DevtoolsFormatCommand extends Command with PrintUsageException { final AllInfo allInfo = await infoFromFile(args.rest.first); final builder = ProgramInfoBuilder(allInfo); vm.ProgramInfo programInfo = builder.build(allInfo); - Map treeMap = treemapFromInfo(programInfo); - var treeMapJson = jsonEncode(treeMap); + Map programInfoTree = programInfo.toJson(); + // TODO: convert the programInfo tree to a treemap if (outputPath == null) { - print(treeMapJson); + print(jsonEncode(programInfoTree)); } else { - await File(outputPath).writeAsString(treeMapJson); + await File(outputPath).writeAsString(jsonEncode(programInfoTree)); } } } @@ -61,17 +61,34 @@ class ProgramInfoBuilder extends VMProgramInfoVisitor { final List outputInfo = []; + /// Mapping between the filename of the outputUnit and the [vm.ProgramInfo] + /// subtree representing a program unit (main or deferred). + final Map outputUnits = {}; + + /// Mapping between the name of the library [vm.ProgramInfoNode] + /// object and its corresponding outputUnit [vm.ProgramInfo] tree. + final Map libraryUnits = {}; + + /// Mapping between the name of an [Info] object and the corresponding + /// [vm.ProgramInfoNode] object. + /// + /// For packages and libraries, since their children can be split among + /// different outputUnits, a composite name is used instead to differentiate + /// between [vm.ProgramInfoNode] in different outputUnits. + final Map infoNodesByName = {}; + + /// A unique key composed of the name of an [Info] object and the + /// filename of the outputUnit. + String compositeName(String name, String outputUnitName) => + "$name/$outputUnitName"; + /// Mapping between the name of a [Info] object and the corresponding /// [vm.ProgramInfoNode] object. - Map infoNodesByName = {}; - - /// Mapping between the id (aka coverageId) of an [AllInfo] node and the - /// corresponding [vm.ProgramInfoNode] object. final Map infoNodesById = {}; - /// Mapping between package names and the corresponding [vm.ProgramInfoNode] - /// objects of [vm.NodeType.packageNode]. - final Map packageInfoNodes = {}; + /// Mapping between the composite name of a package and the corresponding + /// [vm.ProgramInfoNode] objects of [vm.NodeType.packageNode]. + final Map packageInfoNodes = {}; /// Mapping between an [LibraryInfo] object and the name of the /// corresponding [vm.ProgramInfoNode] object. @@ -79,33 +96,289 @@ class ProgramInfoBuilder extends VMProgramInfoVisitor { ProgramInfoBuilder(this.info); + /// Collect libraries into packages and aggregate their sizes. + void makePackage(LibraryInfo libraryInfo, String outputUnitName) { + vm.ProgramInfo outputUnit = outputUnits[outputUnitName]!; + String libraryName = libraryInfo.name; + if (libraryInfo.name == '') { + libraryName = longName(libraryInfo, useLibraryUri: true, forId: true); + } + String packageName = libraryGroupName(libraryInfo) ?? libraryName; + vm.ProgramInfoNode? packageInfoNode = packageInfoNodes[packageName]; + if (packageInfoNode == null) { + String compositePackageName = compositeName(packageName, outputUnitName); + vm.ProgramInfoNode newPackage = outputUnit.makeNode( + name: compositePackageName, + parent: outputUnit.root, + type: vm.NodeType.packageNode); + newPackage.size = libraryInfo.size; + packageInfoNodes[compositePackageName] = newPackage; + outputUnit.root.children[compositePackageName] = newPackage; + outputInfo.add(newPackage); + var packageNode = infoNodesByName[compositePackageName]; + assert(packageNode == null, + "encountered package with duplicated name: $compositePackageName"); + infoNodesByName[compositePackageName] = newPackage; + } else { + packageInfoNode.size = (packageInfoNode.size ?? 0) + libraryInfo.size; + } + } + + void makeLibrary(LibraryInfo libraryInfo, String outputUnitName) { + vm.ProgramInfo outputUnit = outputUnits[outputUnitName]!; + String libraryName = libraryInfo.name; + if (libraryName == '') { + libraryName = longName(libraryInfo, useLibraryUri: true, forId: true); + unnamedLibraries[libraryInfo] = libraryName; + } + String packageName = libraryGroupName(libraryInfo) ?? libraryName; + String compositePackageName = compositeName(packageName, outputUnitName); + vm.ProgramInfoNode parentNode = infoNodesByName[compositePackageName]!; + String compositeLibraryName = compositeName(libraryName, outputUnitName); + vm.ProgramInfoNode newLibrary = outputUnit.makeNode( + name: compositeLibraryName, + parent: parentNode, + type: vm.NodeType.libraryNode); + newLibrary.size = libraryInfo.size; + parentNode.children[newLibrary.name] = newLibrary; + vm.ProgramInfoNode? libraryNode = infoNodesByName[compositeLibraryName]; + assert(libraryNode == null, + "encountered library with duplicated name: $compositeLibraryName"); + infoNodesByName[compositeLibraryName] = newLibrary; + outputInfo.add(newLibrary); + } + + void makeFunction(FunctionInfo functionInfo) { + Info? parent = functionInfo.parent; + String outputUnitName = functionInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + if (parent != null && outputUnit != null) { + assert(parent.kind == kindFromString('library')); + vm.ProgramInfoNode parentNode; + if (parent.kind == kindFromString('library')) { + if (parent.name == "") { + var tempName = + compositeName(unnamedLibraries[parent]!, outputUnitName); + parentNode = infoNodesByName[tempName]!; + } else { + parentNode = + infoNodesByName[compositeName(parent.name, outputUnitName)]!; + } + } else { + parentNode = infoNodesByName[parent.name]!; + } + vm.ProgramInfoNode newFunction = outputUnit.makeNode( + name: functionInfo.name, + parent: parentNode, + type: vm.NodeType.functionNode); + newFunction.size = functionInfo.size; + parentNode.children[newFunction.name] = newFunction; + vm.ProgramInfoNode? functionNode = infoNodesByName[newFunction.name]; + assert(functionNode == null, + "encountered function with duplicated name: $newFunction.name"); + infoNodesByName[newFunction.name] = newFunction; + outputInfo.add(newFunction); + } + } + + void makeClass(ClassInfo classInfo) { + Info? parent = classInfo.parent; + String outputUnitName = classInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + if (parent != null && outputUnit != null) { + vm.ProgramInfoNode parentNode; + if (parent.kind == kindFromString('library')) { + if (parent.name == "") { + var tempName = + compositeName(unnamedLibraries[parent]!, outputUnitName); + parentNode = infoNodesByName[tempName]!; + } else { + parentNode = + infoNodesByName[compositeName(parent.name, outputUnitName)]!; + } + } else { + parentNode = infoNodesByName[parent.name]!; + } + vm.ProgramInfoNode newClass = outputUnit.makeNode( + name: classInfo.name, + parent: parentNode, + type: vm.NodeType.classNode); + newClass.size = classInfo.size; + parentNode.children[newClass.name] = newClass; + vm.ProgramInfoNode? classNode = infoNodesByName[newClass.name]; + assert(classNode == null, + "encountered class with duplicated name: $newClass.name"); + infoNodesByName[newClass.name] = newClass; + outputInfo.add(newClass); + } + } + + /// Fields are currently assigned [vm.NodeType.other]. + /// + /// Note: we might want to create a separate [vm.NodeType.fieldNode] to + /// differentiate fields from other miscellaneous nodes for constructing + /// the call graph. + void makeField(FieldInfo fieldInfo) { + Info? parent = fieldInfo.parent; + String outputUnitName = fieldInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + if (parent != null && outputUnit != null) { + vm.ProgramInfoNode parentNode; + if (parent.kind == kindFromString('library')) { + if (parent.name == "") { + var tempName = + compositeName(unnamedLibraries[parent]!, outputUnitName); + parentNode = infoNodesByName[tempName]!; + } else { + parentNode = + infoNodesByName[compositeName(parent.name, outputUnitName)]!; + } + } else { + parentNode = infoNodesByName[parent.name]!; + } + vm.ProgramInfoNode newField = outputUnit.makeNode( + name: fieldInfo.name, parent: parentNode, type: vm.NodeType.other); + newField.size = fieldInfo.size; + parentNode.children[newField.name] = newField; + vm.ProgramInfoNode? fieldNode = infoNodesByName[newField.name]; + assert(fieldNode == null, + "encountered field with duplicated name: $newField.name"); + infoNodesByName[newField.name] = newField; + outputInfo.add(newField); + } + } + + void makeConstant(ConstantInfo constantInfo) { + String? constantName = constantInfo.code.first.text ?? + "${constantInfo.code.first.start}/${constantInfo.code.first.end}"; + String outputUnitName = constantInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + vm.ProgramInfoNode newConstant = outputUnit!.makeNode( + name: constantName, parent: outputUnit.root, type: vm.NodeType.other); + newConstant.size = constantInfo.size; + outputUnit.root.children[newConstant.name] = newConstant; + vm.ProgramInfoNode? constantNode = infoNodesByName[newConstant.name]; + assert(constantNode == null, + "encountered constant with duplicated name: $newConstant.name"); + infoNodesByName[newConstant.name] = newConstant; + outputInfo.add(newConstant); + } + + void makeTypedef(TypedefInfo typedefInfo) { + String outputUnitName = typedefInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + vm.ProgramInfoNode newTypedef = outputUnit!.makeNode( + name: typedefInfo.name, + parent: outputUnit.root, + type: vm.NodeType.other); + newTypedef.size = typedefInfo.size; + vm.ProgramInfoNode? typedefNode = infoNodesByName[newTypedef.name]; + assert(typedefNode == null, + "encountered constant with duplicated name: $newTypedef.name"); + outputInfo.add(newTypedef); + } + + void makeClassType(ClassTypeInfo classTypeInfo) { + Info? parent = classTypeInfo.parent; + String outputUnitName = classTypeInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + if (parent != null && outputUnit != null) { + assert(parent.kind == kindFromString('library')); + vm.ProgramInfoNode parentNode; + if (parent.name == "") { + var tempName = compositeName(unnamedLibraries[parent]!, outputUnitName); + parentNode = infoNodesByName[tempName]!; + } else { + parentNode = + infoNodesByName[compositeName(parent.name, outputUnitName)]!; + } + vm.ProgramInfoNode newClassType = outputUnit.makeNode( + name: classTypeInfo.name, + parent: parentNode, + type: vm.NodeType.other); + newClassType.size = classTypeInfo.size; + vm.ProgramInfoNode? classTypeNode = infoNodesByName[newClassType.name]; + assert(classTypeNode == null, + "encountered classType with duplicated name: $newClassType.name"); + infoNodesByName[newClassType.name] = newClassType; + outputInfo.add(newClassType); + } + } + + void makeClosure(ClosureInfo closureInfo) { + Info? parent = closureInfo.parent; + String outputUnitName = closureInfo.outputUnit!.filename; + vm.ProgramInfo? outputUnit = outputUnits[outputUnitName]; + if (parent != null && outputUnit != null) { + vm.ProgramInfoNode parentNode; + if (parent.kind == kindFromString('library')) { + if (parent.name == "") { + var tempName = + compositeName(unnamedLibraries[parent]!, outputUnitName); + parentNode = infoNodesByName[tempName]!; + } else { + parentNode = + infoNodesByName[compositeName(parent.name, outputUnitName)]!; + } + } else { + parentNode = infoNodesByName[parent.name]!; + } + vm.ProgramInfoNode newClosure = outputUnit.makeNode( + name: closureInfo.name, + parent: parentNode, + // ProgramInfo trees consider closures and functions to both be of the functionNode type. + type: vm.NodeType.functionNode); + newClosure.size = closureInfo.size; + parentNode.children[newClosure.name] = newClosure; + vm.ProgramInfoNode? closureNode = infoNodesByName[newClosure.name]; + assert(closureNode == null, + "encountered closure with duplicated name: $newClosure.name"); + infoNodesByName[newClosure.name] = newClosure; + outputInfo.add(newClosure); + } + } + @override - vm.ProgramInfoNode visitAll(AllInfo info) { - outputInfo.add(program.root); - info.libraries.forEach(makePackage); - info.packages.forEach(visitPackage); - info.libraries.forEach(makeLibrary); - info.libraries.forEach(visitLibrary); + vm.ProgramInfoNode visitAll(AllInfo info, String outputUnitName) { + outputInfo.add(outputUnits[outputUnitName]!.root); + visitProgram(info.program!); + for (var package in info.packages) { + visitPackage(package, outputUnitName); + } + for (var library in info.libraries) { + visitLibrary(library, outputUnitName); + } info.constants.forEach(makeConstant); info.constants.forEach(visitConstant); - return program.root; + return outputUnits[outputUnitName]!.root; + } + + @override + vm.ProgramInfoNode visitOutput(OutputUnitInfo info) { + vm.ProgramInfo? outputUnit = outputUnits[info.filename]; + assert(outputUnit == null, "encountered outputUnit with duplicated name"); + var newUnit = vm.ProgramInfo(); + outputUnits[info.filename] = newUnit; + outputUnits[info.filename]!.root.size = info.size; + return outputUnits[info.filename]!.root; } @override vm.ProgramInfoNode visitProgram(ProgramInfo info) { - throw Exception('Not supported for devtools format.'); + program.root.size = info.size; + return program.root; } @override - vm.ProgramInfoNode visitPackage(PackageInfo info) { - info.libraries.forEach(makePackage); - info.libraries.forEach(makeLibrary); - info.libraries.forEach(visitLibrary); - return infoNodesByName[info.name]!; + vm.ProgramInfoNode visitPackage(PackageInfo info, String outputUnitName) { + for (var library in info.libraries) { + visitLibrary(library, outputUnitName); + } + return infoNodesByName[compositeName(info.name, outputUnitName)]!; } @override - vm.ProgramInfoNode visitLibrary(LibraryInfo info) { + vm.ProgramInfoNode visitLibrary(LibraryInfo info, String outputUnitName) { info.topLevelFunctions.forEach(makeFunction); info.topLevelFunctions.forEach(visitFunction); info.topLevelVariables.forEach(makeField); @@ -116,8 +389,9 @@ class ProgramInfoBuilder extends VMProgramInfoVisitor { info.classTypes.forEach(visitClassType); info.typedefs.forEach(makeTypedef); info.typedefs.forEach(visitTypedef); - return infoNodesByName[info.name] ?? - infoNodesByName[unnamedLibraries[info]]!; + return infoNodesByName[compositeName(info.name, outputUnitName)] ?? + infoNodesByName[ + compositeName(unnamedLibraries[info]!, outputUnitName)]!; } @override @@ -157,7 +431,8 @@ class ProgramInfoBuilder extends VMProgramInfoVisitor { @override vm.ProgramInfoNode visitConstant(ConstantInfo info) { - return infoNodesByName[info.code.first.text!]!; + return infoNodesByName[info.code.first.text] ?? + infoNodesByName["${info.code.first.start}/${info.code.first.end}"]!; } @override @@ -165,191 +440,18 @@ class ProgramInfoBuilder extends VMProgramInfoVisitor { return infoNodesByName[info.name]!; } - @override - vm.ProgramInfoNode visitOutput(OutputUnitInfo info) { - throw Exception("For deferred loading."); - } - vm.ProgramInfo build(AllInfo info) { - visitAll(info); + info.outputUnits.forEach(visitOutput); + for (var outputUnitName in outputUnits.keys) { + for (var library in info.libraries) { + makePackage(library, outputUnitName); + makeLibrary(library, outputUnitName); + } + } + for (var outputUnitName in outputUnits.keys) { + visitAll(info, outputUnitName); + program.root.children[outputUnitName] = outputUnits[outputUnitName]!.root; + } return program; } - - /// Collect libraries into packages and aggregate their sizes. - void makePackage(LibraryInfo libraryInfo) { - String packageName = libraryGroupName(libraryInfo) ?? libraryInfo.name; - vm.ProgramInfoNode? packageInfoNode = packageInfoNodes[packageName]; - if (packageInfoNode == null) { - vm.ProgramInfoNode newPackage = program.makeNode( - name: packageName, - parent: program.root, - type: vm.NodeType.packageNode); - newPackage.size = libraryInfo.size; - packageInfoNodes[packageName] = newPackage; - program.root.children[packageName] = newPackage; - outputInfo.add(newPackage); - var packageNode = infoNodesByName[newPackage.name]; - assert(packageNode == null, "encountered package with duplicated name"); - infoNodesByName[newPackage.name] = newPackage; - } else { - packageInfoNode.size = (packageInfoNode.size ?? 0) + libraryInfo.size; - } - } - - void makeLibrary(LibraryInfo libraryInfo) { - String packageName = libraryGroupName(libraryInfo) ?? libraryInfo.name; - vm.ProgramInfoNode parentNode = infoNodesByName[packageName]!; - String libraryName = libraryInfo.name; - if (libraryName == '') { - libraryName = longName(libraryInfo, useLibraryUri: true, forId: true); - unnamedLibraries[libraryInfo] = libraryName; - } - vm.ProgramInfoNode newLibrary = program.makeNode( - name: libraryName, parent: parentNode, type: vm.NodeType.libraryNode); - newLibrary.size = libraryInfo.size; - parentNode.children[newLibrary.name] = newLibrary; - vm.ProgramInfoNode? libraryNode = infoNodesByName[newLibrary.name]; - assert(libraryNode == null, "encountered library with duplicated name"); - infoNodesByName[newLibrary.name] = newLibrary; - outputInfo.add(newLibrary); - } - - void makeFunction(FunctionInfo functionInfo) { - Info? parent = functionInfo.parent; - if (parent != null) { - vm.ProgramInfoNode parentNode; - if (parent.name == "" && - parent.kind == kindFromString('library')) { - parentNode = infoNodesByName[unnamedLibraries[parent]]!; - } else { - parentNode = infoNodesByName[parent.name]!; - } - vm.ProgramInfoNode newFunction = program.makeNode( - name: functionInfo.name, - parent: parentNode, - type: vm.NodeType.functionNode); - newFunction.size = functionInfo.size; - parentNode.children[newFunction.name] = newFunction; - vm.ProgramInfoNode? functionNode = infoNodesByName[newFunction.name]; - assert(functionNode == null, "encountered function with duplicated name"); - infoNodesByName[newFunction.name] = newFunction; - outputInfo.add(newFunction); - } - } - - void makeClass(ClassInfo classInfo) { - Info? parent = classInfo.parent; - if (parent != null) { - vm.ProgramInfoNode parentNode; - if (parent.name == "" && - parent.kind == kindFromString('library')) { - parentNode = infoNodesByName[unnamedLibraries[parent]]!; - } else { - parentNode = infoNodesByName[parent.name]!; - } - vm.ProgramInfoNode newClass = program.makeNode( - name: classInfo.name, - parent: parentNode, - type: vm.NodeType.classNode); - newClass.size = classInfo.size; - parentNode.children[newClass.name] = newClass; - vm.ProgramInfoNode? classNode = infoNodesByName[newClass.name]; - assert(classNode == null, "encountered class with duplicated name"); - infoNodesByName[newClass.name] = newClass; - outputInfo.add(newClass); - } - } - - /// Fields are currently assigned [vm.NodeType.other]. - /// - /// Note: we might want to create a separate [vm.NodeType.fieldNode] to - /// differentiate fields from other miscellaneous nodes for constructing - /// the call graph. - void makeField(FieldInfo fieldInfo) { - Info? parent = fieldInfo.parent; - if (parent != null) { - vm.ProgramInfoNode parentNode; - if (parent.name == "" && - parent.kind == kindFromString('library')) { - parentNode = infoNodesByName[unnamedLibraries[parent]]!; - } else { - parentNode = infoNodesByName[parent.name]!; - } - vm.ProgramInfoNode newField = program.makeNode( - name: fieldInfo.name, parent: parentNode, type: vm.NodeType.other); - newField.size = fieldInfo.size; - parentNode.children[newField.name] = newField; - vm.ProgramInfoNode? fieldNode = infoNodesByName[newField.name]; - assert(fieldNode == null, "encountered field with duplicated name"); - infoNodesByName[newField.name] = newField; - outputInfo.add(newField); - } - } - - void makeConstant(ConstantInfo constantInfo) { - String constantName = constantInfo.code.first.text!; - vm.ProgramInfoNode newConstant = program.makeNode( - name: constantName, parent: program.root, type: vm.NodeType.other); - newConstant.size = constantInfo.size; - program.root.children[newConstant.name] = newConstant; - vm.ProgramInfoNode? constantNode = infoNodesByName[newConstant.name]; - assert(constantNode == null, "encountered constant with duplicated name"); - infoNodesByName[newConstant.name] = newConstant; - outputInfo.add(newConstant); - } - - void makeTypedef(TypedefInfo typedefInfo) { - vm.ProgramInfoNode newTypedef = program.makeNode( - name: typedefInfo.name, parent: program.root, type: vm.NodeType.other); - newTypedef.size = typedefInfo.size; - infoNodesByName[newTypedef.name] = newTypedef; - outputInfo.add(newTypedef); - } - - void makeClassType(ClassTypeInfo classTypeInfo) { - Info? parent = classTypeInfo.parent; - if (parent != null) { - vm.ProgramInfoNode parentNode; - if (parent.name == "" && - parent.kind == kindFromString('library')) { - parentNode = infoNodesByName[unnamedLibraries[parent]]!; - } else { - parentNode = infoNodesByName[parent.name]!; - } - vm.ProgramInfoNode newClassType = program.makeNode( - name: classTypeInfo.name, - parent: parentNode, - type: vm.NodeType.other); - newClassType.size = classTypeInfo.size; - vm.ProgramInfoNode? classTypeNode = infoNodesByName[newClassType.name]; - assert( - classTypeNode == null, "encountered classType with duplicated name"); - infoNodesByName[newClassType.name] = newClassType; - outputInfo.add(newClassType); - } - } - - void makeClosure(ClosureInfo closureInfo) { - Info? parent = closureInfo.parent; - if (parent != null) { - vm.ProgramInfoNode parentNode; - if (parent.name == "" && - parent.kind == kindFromString('library')) { - parentNode = infoNodesByName[unnamedLibraries[parent]]!; - } else { - parentNode = infoNodesByName[parent.name]!; - } - vm.ProgramInfoNode newClosure = program.makeNode( - name: closureInfo.name, - parent: parentNode, - // ProgramInfo trees consider closures and functions to both be of the functionNode type. - type: vm.NodeType.functionNode); - newClosure.size = closureInfo.size; - parentNode.children[newClosure.name] = newClosure; - vm.ProgramInfoNode? closureNode = infoNodesByName[newClosure.name]; - assert(closureNode == null, "encountered closure with duplicated name"); - infoNodesByName[newClosure.name] = newClosure; - outputInfo.add(newClosure); - } - } } diff --git a/pkg/dart2js_info/lib/info.dart b/pkg/dart2js_info/lib/info.dart index 051d75a660e..7c14f743bcb 100644 --- a/pkg/dart2js_info/lib/info.dart +++ b/pkg/dart2js_info/lib/info.dart @@ -203,14 +203,8 @@ class PackageInfo extends BasicInfo { : super(InfoKind.package, name, outputUnit, size, null); @override - T accept(InfoVisitor visitor) { - if (visitor is VMProgramInfoVisitor) { - return visitor.visitPackage(this); - } else { - throw ArgumentError( - "PackageInfo can only be visited by a VMProgramInfoVisitor"); - } - } + T accept(InfoVisitor visitor) => + throw Exception("PackageInfo is not supported by InfoVisitor."); } /// Info associated with a library element. @@ -620,8 +614,19 @@ abstract class InfoVisitor { /// A visitor that adds implementation for PackageInfo specifically for building /// the VM ProgramInfo Tree from a Dart2js info tree. -abstract class VMProgramInfoVisitor extends InfoVisitor { - T visitPackage(PackageInfo info); +abstract class VMProgramInfoVisitor { + T visitAll(AllInfo info, String outputUnit); + T visitProgram(ProgramInfo info); + T visitPackage(PackageInfo info, String outputUnit); + T visitLibrary(LibraryInfo info, String outputUnit); + T visitClass(ClassInfo info); + T visitClassType(ClassTypeInfo info); + T visitField(FieldInfo info); + T visitConstant(ConstantInfo info); + T visitFunction(FunctionInfo info); + T visitTypedef(TypedefInfo info); + T visitClosure(ClosureInfo info); + T visitOutput(OutputUnitInfo info); } /// A visitor that recursively walks each portion of the program. Because the @@ -642,6 +647,11 @@ class RecursiveInfoVisitor extends InfoVisitor { @override void visitProgram(ProgramInfo info) {} + void visitPackage(PackageInfo info) { + throw Exception( + "PackageInfo objects are only defined for the VM Devtools format."); + } + @override void visitLibrary(LibraryInfo info) { info.topLevelFunctions.forEach(visitFunction);