mirror of
https://github.com/dart-lang/sdk
synced 2024-09-21 07:21:29 +00:00
d6db26f912
BUG= R=karlklose@google.com Review URL: https://codereview.chromium.org//1311783012.
123 lines
3.5 KiB
Dart
123 lines
3.5 KiB
Dart
// 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 'package:compiler/src/elements/elements.dart' show
|
|
AbstractFieldElement,
|
|
ClassElement,
|
|
CompilationUnitElement,
|
|
Element,
|
|
ElementCategory,
|
|
FunctionElement,
|
|
LibraryElement,
|
|
ScopeContainerElement;
|
|
|
|
import 'package:compiler/src/elements/modelx.dart' as modelx;
|
|
|
|
import 'package:compiler/src/elements/modelx.dart' show
|
|
DeclarationSite;
|
|
|
|
import 'package:compiler/src/parser/partial_elements.dart' show
|
|
PartialClassElement,
|
|
PartialElement;
|
|
|
|
import 'package:compiler/src/tokens/token.dart' show
|
|
ErrorToken,
|
|
Token;
|
|
|
|
import 'package:compiler/src/tokens/token_constants.dart' show
|
|
EOF_TOKEN,
|
|
IDENTIFIER_TOKEN,
|
|
KEYWORD_TOKEN;
|
|
|
|
class Difference {
|
|
final DeclarationSite before;
|
|
final DeclarationSite after;
|
|
|
|
/// Records the position of first difference between [before] and [after]. If
|
|
/// either [before] or [after] are null, [token] is null.
|
|
Token token;
|
|
|
|
Difference(this.before, this.after) {
|
|
if (before == after) {
|
|
throw '[before] and [after] are the same.';
|
|
}
|
|
}
|
|
|
|
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, DeclarationSite> beforeMap = <String, DeclarationSite>{};
|
|
before.forEachLocalMember((modelx.ElementX element) {
|
|
DeclarationSite site = element.declarationSite;
|
|
assert(site != null || element.isSynthesized);
|
|
if (!element.isSynthesized) {
|
|
beforeMap[element.name] = site;
|
|
}
|
|
});
|
|
List<Difference> modifications = <Difference>[];
|
|
List<Difference> potentiallyChanged = <Difference>[];
|
|
after.forEachLocalMember((modelx.ElementX element) {
|
|
DeclarationSite existing = beforeMap.remove(element.name);
|
|
if (existing == null) {
|
|
modifications.add(new Difference(null, element.declarationSite));
|
|
} else {
|
|
potentiallyChanged.add(new Difference(existing, element.declarationSite));
|
|
}
|
|
});
|
|
|
|
modifications.addAll(
|
|
beforeMap.values.map(
|
|
(DeclarationSite site) => new Difference(site, null)));
|
|
|
|
modifications.addAll(
|
|
potentiallyChanged.where(areDifferentElements));
|
|
|
|
return modifications;
|
|
}
|
|
|
|
bool areDifferentElements(Difference diff) {
|
|
DeclarationSite before = diff.before;
|
|
DeclarationSite after = diff.after;
|
|
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;
|
|
}
|