Skip to content

Commit aeee613

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Extract Id, DataRegistry and DataExtractor from dart2js
This is a step towards sharing tests based on annotated code between the CFE and the analyzer. Change-Id: Ia0f4b78717042af5544d92b0a259d6693547e722 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/108260 Reviewed-by: Paul Berry <[email protected]>
1 parent 708e919 commit aeee613

File tree

12 files changed

+584
-521
lines changed

12 files changed

+584
-521
lines changed

pkg/front_end/lib/src/testing/id.dart

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
enum IdKind {
6+
element,
7+
cls,
8+
node,
9+
invoke,
10+
update,
11+
iterator,
12+
current,
13+
moveNext,
14+
}
15+
16+
/// Id for a code point or element.
17+
abstract class Id {
18+
IdKind get kind;
19+
bool get isGlobal;
20+
21+
/// Display name for this id.
22+
String get descriptor;
23+
}
24+
25+
class IdValue {
26+
final Id id;
27+
final String value;
28+
29+
const IdValue(this.id, this.value);
30+
31+
@override
32+
int get hashCode => id.hashCode * 13 + value.hashCode * 17;
33+
34+
@override
35+
bool operator ==(other) {
36+
if (identical(this, other)) return true;
37+
if (other is! IdValue) return false;
38+
return id == other.id && value == other.value;
39+
}
40+
41+
@override
42+
String toString() => idToString(id, value);
43+
44+
static String idToString(Id id, String value) {
45+
switch (id.kind) {
46+
case IdKind.element:
47+
ElementId elementId = id;
48+
return '$elementPrefix${elementId.name}:$value';
49+
case IdKind.cls:
50+
ClassId classId = id;
51+
return '$classPrefix${classId.name}:$value';
52+
case IdKind.node:
53+
return value;
54+
case IdKind.invoke:
55+
return '$invokePrefix$value';
56+
case IdKind.update:
57+
return '$updatePrefix$value';
58+
case IdKind.iterator:
59+
return '$iteratorPrefix$value';
60+
case IdKind.current:
61+
return '$currentPrefix$value';
62+
case IdKind.moveNext:
63+
return '$moveNextPrefix$value';
64+
}
65+
throw new UnsupportedError("Unexpected id kind: ${id.kind}");
66+
}
67+
68+
static const String globalPrefix = "global#";
69+
static const String elementPrefix = "element: ";
70+
static const String classPrefix = "class: ";
71+
static const String invokePrefix = "invoke: ";
72+
static const String updatePrefix = "update: ";
73+
static const String iteratorPrefix = "iterator: ";
74+
static const String currentPrefix = "current: ";
75+
static const String moveNextPrefix = "moveNext: ";
76+
77+
static IdValue decode(int offset, String text) {
78+
Id id;
79+
String expected;
80+
if (text.startsWith(elementPrefix)) {
81+
text = text.substring(elementPrefix.length);
82+
int colonPos = text.indexOf(':');
83+
if (colonPos == -1) throw "Invalid element id: '$text'";
84+
String name = text.substring(0, colonPos);
85+
bool isGlobal = name.startsWith(globalPrefix);
86+
if (isGlobal) {
87+
name = name.substring(globalPrefix.length);
88+
}
89+
id = new ElementId(name, isGlobal: isGlobal);
90+
expected = text.substring(colonPos + 1);
91+
} else if (text.startsWith(classPrefix)) {
92+
text = text.substring(classPrefix.length);
93+
int colonPos = text.indexOf(':');
94+
if (colonPos == -1) throw "Invalid class id: '$text'";
95+
String name = text.substring(0, colonPos);
96+
bool isGlobal = name.startsWith(globalPrefix);
97+
if (isGlobal) {
98+
name = name.substring(globalPrefix.length);
99+
}
100+
id = new ClassId(name, isGlobal: isGlobal);
101+
expected = text.substring(colonPos + 1);
102+
} else if (text.startsWith(invokePrefix)) {
103+
id = new NodeId(offset, IdKind.invoke);
104+
expected = text.substring(invokePrefix.length);
105+
} else if (text.startsWith(updatePrefix)) {
106+
id = new NodeId(offset, IdKind.update);
107+
expected = text.substring(updatePrefix.length);
108+
} else if (text.startsWith(iteratorPrefix)) {
109+
id = new NodeId(offset, IdKind.iterator);
110+
expected = text.substring(iteratorPrefix.length);
111+
} else if (text.startsWith(currentPrefix)) {
112+
id = new NodeId(offset, IdKind.current);
113+
expected = text.substring(currentPrefix.length);
114+
} else if (text.startsWith(moveNextPrefix)) {
115+
id = new NodeId(offset, IdKind.moveNext);
116+
expected = text.substring(moveNextPrefix.length);
117+
} else {
118+
id = new NodeId(offset, IdKind.node);
119+
expected = text;
120+
}
121+
// Remove newlines.
122+
expected = expected.replaceAll(new RegExp(r'\s*(\n\s*)+\s*'), '');
123+
return new IdValue(id, expected);
124+
}
125+
}
126+
127+
/// Id for an member element.
128+
class ElementId implements Id {
129+
final String className;
130+
final String memberName;
131+
@override
132+
final bool isGlobal;
133+
134+
factory ElementId(String text, {bool isGlobal: false}) {
135+
int dotPos = text.indexOf('.');
136+
if (dotPos != -1) {
137+
return new ElementId.internal(text.substring(dotPos + 1),
138+
className: text.substring(0, dotPos), isGlobal: isGlobal);
139+
} else {
140+
return new ElementId.internal(text, isGlobal: isGlobal);
141+
}
142+
}
143+
144+
ElementId.internal(this.memberName, {this.className, this.isGlobal: false});
145+
146+
@override
147+
int get hashCode => className.hashCode * 13 + memberName.hashCode * 17;
148+
149+
@override
150+
bool operator ==(other) {
151+
if (identical(this, other)) return true;
152+
if (other is! ElementId) return false;
153+
return className == other.className && memberName == other.memberName;
154+
}
155+
156+
@override
157+
IdKind get kind => IdKind.element;
158+
159+
String get name => className != null ? '$className.$memberName' : memberName;
160+
161+
@override
162+
String get descriptor => 'member $name';
163+
164+
@override
165+
String toString() => 'element:$name';
166+
}
167+
168+
/// Id for a class.
169+
class ClassId implements Id {
170+
final String className;
171+
@override
172+
final bool isGlobal;
173+
174+
ClassId(this.className, {this.isGlobal: false});
175+
176+
@override
177+
int get hashCode => className.hashCode * 13;
178+
179+
@override
180+
bool operator ==(other) {
181+
if (identical(this, other)) return true;
182+
if (other is! ClassId) return false;
183+
return className == other.className;
184+
}
185+
186+
@override
187+
IdKind get kind => IdKind.cls;
188+
189+
String get name => className;
190+
191+
@override
192+
String get descriptor => 'class $name';
193+
194+
@override
195+
String toString() => 'class:$name';
196+
}
197+
198+
/// Id for a code point.
199+
class NodeId implements Id {
200+
final int value;
201+
@override
202+
final IdKind kind;
203+
204+
const NodeId(this.value, this.kind);
205+
206+
@override
207+
bool get isGlobal => false;
208+
209+
@override
210+
int get hashCode => value.hashCode * 13 + kind.hashCode * 17;
211+
212+
@override
213+
bool operator ==(other) {
214+
if (identical(this, other)) return true;
215+
if (other is! NodeId) return false;
216+
return value == other.value && kind == other.kind;
217+
}
218+
219+
@override
220+
String get descriptor => 'offset $value ($kind)';
221+
222+
@override
223+
String toString() => '$kind:$value';
224+
}
225+
226+
class ActualData<T> {
227+
final Id id;
228+
final T value;
229+
final Uri uri;
230+
final int _offset;
231+
final Object object;
232+
233+
ActualData(this.id, this.value, this.uri, this._offset, this.object);
234+
235+
int get offset {
236+
if (id is NodeId) {
237+
NodeId nodeId = id;
238+
return nodeId.value;
239+
} else {
240+
return _offset;
241+
}
242+
}
243+
244+
String get objectText {
245+
return 'object `${'$object'.replaceAll('\n', '')}` (${object.runtimeType})';
246+
}
247+
248+
@override
249+
String toString() => 'ActualData(id=$id,value=$value,uri=$uri,'
250+
'offset=$offset,object=$objectText)';
251+
}
252+
253+
abstract class DataRegistry<T> {
254+
Map<Id, ActualData<T>> get actualMap;
255+
256+
void registerValue(Uri uri, int offset, Id id, T value, Object object) {
257+
if (actualMap.containsKey(id)) {
258+
ActualData<T> existingData = actualMap[id];
259+
report(uri, offset, "Duplicate id ${id}, value=$value, object=$object");
260+
report(
261+
uri,
262+
offset,
263+
"Duplicate id ${id}, value=${existingData.value}, "
264+
"object=${existingData.object}");
265+
fail("Duplicate id $id.");
266+
}
267+
if (value != null) {
268+
actualMap[id] = new ActualData<T>(id, value, uri, offset, object);
269+
}
270+
}
271+
272+
void report(Uri uri, int offset, String message);
273+
274+
void fail(String message);
275+
}

0 commit comments

Comments
 (0)