blob: 9e7302a0612a2895ae0bf146031e5d0fb4bfdf10 [file] [log] [blame]
import 'package:dart2js_info/info.dart';
import 'package:dart2js_info/src/util.dart';
class MaskDiff {
final BasicInfo info;
final String oldMask;
final String newMask;
MaskDiff(this.info, this.oldMask, this.newMask);
}
List<MaskDiff> diff(AllInfo oldInfo, AllInfo newInfo) {
var differ = new _InfoDiffer(oldInfo, newInfo);
differ.diff();
return differ.diffs;
}
class _InfoDiffer extends InfoVisitor<Null> {
final AllInfo _old;
final AllInfo _new;
BasicInfo _other;
List<MaskDiff> diffs = <MaskDiff>[];
_InfoDiffer(this._old, this._new);
void diff() {
_diffList(_old.libraries, _new.libraries);
}
@override
visitAll(AllInfo info) {
throw new StateError('should not diff AllInfo');
}
@override
visitProgram(ProgramInfo info) {
throw new StateError('should not diff ProgramInfo');
}
@override
visitOutput(OutputUnitInfo info) {
throw new StateError('should not diff OutputUnitInfo');
}
// TODO(het): diff constants
@override
visitConstant(ConstantInfo info) {
throw new StateError('should not diff ConstantInfo');
}
@override
visitLibrary(LibraryInfo info) {
var other = _other as LibraryInfo;
_diffList(info.topLevelVariables, other.topLevelVariables);
_diffList(info.topLevelFunctions, other.topLevelFunctions);
_diffList(info.classes, other.classes);
}
@override
visitClass(ClassInfo info) {
var other = _other as ClassInfo;
_diffList(info.fields, other.fields);
_diffList(info.functions, other.functions);
}
@override
visitClosure(ClosureInfo info) {
var other = _other as ClosureInfo;
_diffList([info.function], [other.function]);
}
@override
visitField(FieldInfo info) {
var other = _other as FieldInfo;
if (info.type != other.type) {
diffs.add(new MaskDiff(info, info.type, other.type));
}
_diffList(info.closures, other.closures);
}
String _signature(FunctionInfo info) {
var sb = new StringBuffer();
sb.write(info.returnType);
sb.write("(");
for (var parameter in info.parameters) {
sb.write(parameter.type);
sb.write(" ");
sb.write(parameter.name);
sb.write(",");
}
sb.write(")");
return '$sb';
}
@override
visitFunction(FunctionInfo info) {
var other = _other as FunctionInfo;
var infoSignature = _signature(info);
var otherSignature = _signature(other);
if (infoSignature != otherSignature) {
diffs.add(new MaskDiff(info, infoSignature, otherSignature));
}
_diffList(info.closures, other.closures);
}
@override
visitTypedef(TypedefInfo info) {}
void _diffList(List<BasicInfo> oldInfos, List<BasicInfo> newInfos) {
var oldNames = <String, BasicInfo>{};
var newNames = <String, BasicInfo>{};
for (var oldInfo in oldInfos) {
oldNames[longName(oldInfo, useLibraryUri: true)] = oldInfo;
}
for (var newInfo in newInfos) {
newNames[longName(newInfo, useLibraryUri: true)] = newInfo;
}
for (var oldName in oldNames.keys) {
if (newNames[oldName] == null) {
diffs.add(new MaskDiff(oldNames[oldName], "removed", ""));
} else {
_other = newNames[oldName];
oldNames[oldName].accept(this);
}
}
for (var newName in newNames.keys) {
if (oldNames[newName] == null) {
diffs.add(new MaskDiff(newNames[newName], "", "added"));
}
}
}
}