blob: a2e17eb420156146bf4600b96cd7d64d4d8fe94e [file] [log] [blame]
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library trydart.poi.diff;
import 'dart:async' show
Completer,
Future,
Stream;
import 'dart:convert' show
LineSplitter,
UTF8;
import 'package:compiler/compiler.dart' as api;
import 'package:compiler/implementation/dart2jslib.dart' show
Compiler,
Enqueuer,
QueueFilter,
Script,
WorkItem;
import 'package:compiler/implementation/elements/visitor.dart' show
ElementVisitor;
import 'package:compiler/implementation/elements/elements.dart' show
AbstractFieldElement,
ClassElement,
CompilationUnitElement,
Element,
ElementCategory,
FunctionElement,
LibraryElement,
ScopeContainerElement;
import 'package:compiler/implementation/elements/modelx.dart' as modelx;
import 'package:compiler/implementation/dart_types.dart' show
DartType;
import 'package:compiler/implementation/scanner/scannerlib.dart' show
EOF_TOKEN,
ErrorToken,
IDENTIFIER_TOKEN,
KEYWORD_TOKEN,
PartialClassElement,
PartialElement,
Token;
import 'package:compiler/implementation/source_file.dart' show
StringSourceFile;
class Difference {
final Element before;
final Element after;
Token token;
Difference(this.before, this.after);
String toString() {
if (before == null) return 'Added($after)';
if (after == null) return 'Removed($before)';
return 'Modified($after -> $before)';
}
}
List<Difference> computeDifference(
ScopeContainerElement before,
ScopeContainerElement after) {
Map<String, Element> beforeMap = <String, Element>{};
before.forEachLocalMember((Element element) {
beforeMap[element.name] = element;
});
List<Difference> modifications = <Difference>[];
List<Difference> potentiallyChanged = <Difference>[];
after.forEachLocalMember((Element element) {
Element existing = beforeMap.remove(element.name);
if (existing == null) {
modifications.add(new Difference(null, element));
} else {
potentiallyChanged.add(new Difference(existing, element));
}
});
modifications.addAll(
beforeMap.values.map((Element element) => new Difference(element, null)));
modifications.addAll(
potentiallyChanged.where(areDifferentElements));
return modifications;
}
bool areDifferentElements(Difference diff) {
Element beforeElement = diff.before;
Element afterElement = diff.after;
var before = (beforeElement is modelx.VariableElementX)
? beforeElement.variables : beforeElement;
var after = (afterElement is modelx.VariableElementX)
? afterElement.variables : afterElement;
if (before is PartialElement && after is PartialElement) {
Token beforeToken = before.beginToken;
Token afterToken = after.beginToken;
Token stop = before.endToken;
int beforeKind = beforeToken.kind;
int afterKind = afterToken.kind;
while (beforeKind != EOF_TOKEN && afterKind != EOF_TOKEN) {
if (beforeKind != afterKind) {
diff.token = afterToken;
return true;
}
if (beforeToken is! ErrorToken && afterToken is! ErrorToken) {
if (beforeToken.value != afterToken.value) {
diff.token = afterToken;
return true;
}
}
if (beforeToken == stop) return false;
beforeToken = beforeToken.next;
afterToken = afterToken.next;
beforeKind = beforeToken.kind;
afterKind = afterToken.kind;
}
return beforeKind != afterKind;
}
print("$before isn't a PartialElement");
return true;
}