Skip to content

Commit 7fce125

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe,kernel] Add AstPrinter
This CL adds a Node.toText method together with an AstPrinter. These facility and better toString implementation on AST nodes while allowing for toString independent printing of AST to use in testing. This also add support for an integrated toString of custom/internal nodes. Some work is still needed in bringing the toString implementation on all nodes to the old quality, and not all internal nodes have customized textual representations yet. This work is left for future CLs. Change-Id: Ib0bf8a0bc02f489dfacdc8aa5f96da9c52f26058 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150923 Commit-Queue: Johnni Winther <[email protected]> Reviewed-by: Alexander Markov <[email protected]> Reviewed-by: Jens Johansen <[email protected]>
1 parent b2d41ab commit 7fce125

File tree

92 files changed

+4578
-1414
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+4578
-1414
lines changed

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ class IdValue {
125125
static const String stmtPrefix = "stmt: ";
126126
static const String errorPrefix = "error: ";
127127

128-
static IdValue decode(Uri sourceUri, Annotation annotation, String text) {
128+
static IdValue decode(Uri sourceUri, Annotation annotation, String text,
129+
{bool preserveWhitespaceInAnnotations: false,
130+
bool preserveInfixWhitespace: false}) {
129131
int offset = annotation.offset;
130132
Id id;
131133
String expected;
@@ -182,8 +184,15 @@ class IdValue {
182184
id = new NodeId(offset, IdKind.node);
183185
expected = text;
184186
}
185-
// Remove newlines.
186-
expected = expected.replaceAll(new RegExp(r'\s*(\n\s*)+\s*'), '');
187+
if (preserveWhitespaceInAnnotations) {
188+
// Keep all whitespace.
189+
} else if (preserveInfixWhitespace) {
190+
// Remove heading and trailing whitespace.
191+
expected = expected.trim();
192+
} else {
193+
// Remove unneeded whitespace.
194+
expected = expected.replaceAll(new RegExp(r'\s*(\n\s*)+\s*'), '');
195+
}
187196
return new IdValue(id, annotation, expected);
188197
}
189198
}

pkg/_fe_analyzer_shared/lib/src/testing/id_testing.dart

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ class MemberAnnotations<DataType> {
219219
// TODO(johnniwinther): Support an empty marker set.
220220
void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
221221
Map<String, MemberAnnotations<IdValue>> maps,
222-
{void onFailure(String message)}) {
222+
{void onFailure(String message),
223+
bool preserveWhitespaceInAnnotations: false,
224+
bool preserveInfixWhitespaceInAnnotations: false}) {
223225
List<String> mapKeys = maps.keys.toList();
224226
Map<String, AnnotatedCode> split = splitByPrefixes(code, mapKeys);
225227

@@ -229,7 +231,9 @@ void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
229231
Map<Id, IdValue> expectedValues = fileAnnotations[sourceUri];
230232
for (Annotation annotation in code.annotations) {
231233
String text = annotation.text;
232-
IdValue idValue = IdValue.decode(sourceUri, annotation, text);
234+
IdValue idValue = IdValue.decode(sourceUri, annotation, text,
235+
preserveWhitespaceInAnnotations: preserveWhitespaceInAnnotations,
236+
preserveInfixWhitespace: preserveInfixWhitespaceInAnnotations);
233237
if (idValue.id.isGlobal) {
234238
if (fileAnnotations.globalData.containsKey(idValue.id)) {
235239
onFailure("Error in test '$filename': "
@@ -259,7 +263,9 @@ void computeExpectedMap(Uri sourceUri, String filename, AnnotatedCode code,
259263
TestData computeTestData(FileSystemEntity testFile,
260264
{Iterable<String> supportedMarkers,
261265
Uri createTestUri(Uri uri, String fileName),
262-
void onFailure(String message)}) {
266+
void onFailure(String message),
267+
bool preserveWhitespaceInAnnotations: false,
268+
bool preserveInfixWhitespaceInAnnotations: false}) {
263269
Uri entryPoint;
264270

265271
String testName;
@@ -300,7 +306,10 @@ TestData computeTestData(FileSystemEntity testFile,
300306
}
301307
computeExpectedMap(entryPoint, testFile.uri.pathSegments.last,
302308
code[entryPoint], expectedMaps,
303-
onFailure: onFailure);
309+
onFailure: onFailure,
310+
preserveWhitespaceInAnnotations: preserveWhitespaceInAnnotations,
311+
preserveInfixWhitespaceInAnnotations:
312+
preserveInfixWhitespaceInAnnotations);
304313
Map<String, String> memorySourceFiles = {
305314
entryPoint.path: code[entryPoint].sourceCode
306315
};
@@ -317,7 +326,10 @@ TestData computeTestData(FileSystemEntity testFile,
317326
code[libFileUri] = annotatedLibCode;
318327
computeExpectedMap(
319328
libFileUri, libFileName, annotatedLibCode, expectedMaps,
320-
onFailure: onFailure);
329+
onFailure: onFailure,
330+
preserveWhitespaceInAnnotations: preserveWhitespaceInAnnotations,
331+
preserveInfixWhitespaceInAnnotations:
332+
preserveInfixWhitespaceInAnnotations);
321333
}
322334
}
323335

@@ -713,7 +725,9 @@ Future<void> runTests<T>(Directory dataDir,
713725
void onFailure(String message),
714726
RunTestFunction<T> runTest,
715727
List<String> skipList,
716-
Map<String, List<String>> skipMap}) async {
728+
Map<String, List<String>> skipMap,
729+
bool preserveWhitespaceInAnnotations: false,
730+
bool preserveInfixWhitespaceInAnnotations: false}) async {
717731
MarkerOptions markerOptions =
718732
new MarkerOptions.fromDataDir(dataDir, shouldFindScript: shards == 1);
719733
// TODO(johnniwinther): Support --show to show actual data for an input.
@@ -775,7 +789,10 @@ Future<void> runTests<T>(Directory dataDir,
775789
TestData testData = computeTestData(entity,
776790
supportedMarkers: markerOptions.supportedMarkers,
777791
createTestUri: createTestUri,
778-
onFailure: onFailure);
792+
onFailure: onFailure,
793+
preserveWhitespaceInAnnotations: preserveWhitespaceInAnnotations,
794+
preserveInfixWhitespaceInAnnotations:
795+
preserveInfixWhitespaceInAnnotations);
779796
print('Test: ${testData.testFileUri}');
780797

781798
Map<String, TestResult<T>> results = await runTest(testData,

pkg/compiler/lib/src/ir/closure.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:kernel/ast.dart' as ir;
6+
import 'package:kernel/src/printer.dart' as ir;
67
import 'package:kernel/text/ast_to_text.dart' as ir show debugNodeToString;
78

89
/// Collection of scope data collected for a single member.
@@ -419,6 +420,12 @@ class TypeVariableTypeWithContext implements ir.Node {
419420
'type=${type.toStringInternal()},context=${context.toStringInternal()},'
420421
'kind=$kind,typeDeclaration=${typeDeclaration.toStringInternal()}';
421422

423+
@override
424+
String toText(ir.AstTextStrategy strategy) => type.toText(strategy);
425+
426+
@override
427+
void toTextInternal(ir.AstPrinter printer) => type.toTextInternal(printer);
428+
422429
@override
423430
String leakingDebugToString() => ir.debugNodeToString(this);
424431
}

pkg/compiler/lib/src/ir/constants.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:kernel/ast.dart' as ir;
6+
import 'package:kernel/src/printer.dart' as ir;
67
import 'package:kernel/type_environment.dart' as ir;
78
import 'package:front_end/src/api_prototype/constant_evaluator.dart' as ir;
89
import 'package:front_end/src/api_unstable/dart2js.dart' as ir;
@@ -204,4 +205,11 @@ class ConstantReference extends ir.TreeNode {
204205

205206
@override
206207
String toStringInternal() => 'constant=${constant.toStringInternal()}';
208+
209+
@override
210+
String toText(ir.AstTextStrategy strategy) => constant.toText(strategy);
211+
212+
@override
213+
void toTextInternal(ir.AstPrinter printer) =>
214+
constant.toTextInternal(printer);
207215
}

pkg/dev_compiler/test/nullable_inference_test.dart

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:kernel/core_types.dart';
99
import 'package:kernel/kernel.dart';
1010
import 'package:kernel/class_hierarchy.dart';
1111
import 'package:kernel/type_environment.dart';
12+
import 'package:kernel/src/printer.dart';
1213
import 'package:kernel/target/targets.dart';
1314
import 'package:test/test.dart';
1415

@@ -17,6 +18,11 @@ import 'package:dev_compiler/src/kernel/nullable_inference.dart';
1718
import 'package:dev_compiler/src/kernel/js_typerep.dart';
1819
import 'package:dev_compiler/src/kernel/target.dart';
1920

21+
const AstTextStrategy astTextStrategy = AstTextStrategy(
22+
includeLibraryNamesInTypes: true,
23+
includeLibraryNamesInMembers: true,
24+
useMultiline: false);
25+
2026
void main() {
2127
test('empty main', () async {
2228
await expectNotNull('main() {}', '');
@@ -72,7 +78,7 @@ void main() {
7278

7379
test('constructor', () async {
7480
await expectNotNull(
75-
'library a; class C {} main() { new C(); }', 'new a::C::•()');
81+
'library a; class C {} main() { new C(); }', 'new a::C()');
7682
});
7783

7884
group('operator', () {
@@ -249,8 +255,8 @@ void main() {
249255
});
250256

251257
test('function expression', () async {
252-
await expectNotNull('main() { () => null; f() {}; f; }',
253-
'() dart.core::Null? => null, f');
258+
await expectNotNull(
259+
'main() { () => null; f() {}; f; }', 'dart.core::Null? () => null, f');
254260
});
255261

256262
test('cascades (kernel BlockExpression)', () async {
@@ -302,7 +308,7 @@ void main() {
302308
var y = (x = null) == null;
303309
print(x);
304310
print(y);
305-
}''', '1, (x = null).{dart.core::Object::==}(null), y');
311+
}''', '1, (x = null).{dart.core::Object.==}(null), y');
306312
});
307313
test('declaration from variable transitive', () async {
308314
await expectNotNull('''main() {
@@ -339,8 +345,8 @@ void main() {
339345
}''',
340346
// arithmetic operation results on `i` are themselves not null, even
341347
// though `i` is nullable.
342-
'0, i.{dart.core::num::<}(10), 10, i = i.{dart.core::num::+}(1), '
343-
'i.{dart.core::num::+}(1), 1, i.{dart.core::num::>=}(10), 10');
348+
'0, i.{dart.core::num.<}(10), 10, i = i.{dart.core::num.+}(1), '
349+
'i.{dart.core::num.+}(1), 1, i.{dart.core::num.>=}(10), 10');
344350
});
345351
test('for-in', () async {
346352
await expectNotNull('''main() {
@@ -362,7 +368,7 @@ void main() {
362368
print(z);
363369
}
364370
f(42);
365-
}''', '0, () → void => dart.core::print("g"), "g", g, y, 1, z, f, 42');
371+
}''', '0, void () => dart.core::print("g"), "g", g, y, 1, z, f, 42');
366372
});
367373
test('assignment to closure variable', () async {
368374
await expectNotNull('''main() {
@@ -391,8 +397,7 @@ void main() {
391397
await expectNotNull('''main() {
392398
var x = () => 42;
393399
var y = (() => x = null);
394-
}''',
395-
'() → dart.core::int* => 42, 42, () → dart.core::Null? => x = null');
400+
}''', 'dart.core::int* () => 42, 42, dart.core::Null? () => x = null');
396401
});
397402
test('do not depend on unrelated variables', () async {
398403
await expectNotNull('''main() {
@@ -481,7 +486,7 @@ void main() {
481486
await expectNotNull(
482487
'library b; $imports class C { @notNull m() {} } '
483488
'main() { var c = new C(); c.m(); }',
484-
'new b::C::•(), c.{b::C::m}(), c');
489+
'new b::C(), c.{b::C.m}(), c');
485490
});
486491
});
487492
}
@@ -505,9 +510,9 @@ Future expectNotNull(String code, String expectedNotNull) async {
505510
// Print integer values as integers
506511
return BigInt.from(c.value).toString();
507512
}
508-
return c.toConstantText();
513+
return c.toText(astTextStrategy);
509514
}
510-
return e.leakingDebugToString();
515+
return e.toText(astTextStrategy);
511516
})
512517
// Filter out our own NotNull annotations. The library prefix changes
513518
// per test, so just filter on the suffix.

pkg/front_end/lib/src/fasta/kernel/collections.dart

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import 'package:kernel/ast.dart'
1919
transformList,
2020
visitList;
2121

22+
import 'package:kernel/src/printer.dart';
23+
2224
import 'package:kernel/type_environment.dart' show StaticTypeContext;
2325

2426
import 'package:kernel/visitor.dart'
@@ -106,8 +108,8 @@ class SpreadElement extends Expression with ControlFlowElement {
106108
}
107109

108110
@override
109-
String toStringInternal() {
110-
return "";
111+
void toTextInternal(AstPrinter state) {
112+
// TODO(johnniwinther): Implement this.
111113
}
112114
}
113115

@@ -172,8 +174,8 @@ class IfElement extends Expression with ControlFlowElement {
172174
}
173175

174176
@override
175-
String toStringInternal() {
176-
return "";
177+
void toTextInternal(AstPrinter state) {
178+
// TODO(johnniwinther): Implement this.
177179
}
178180
}
179181

@@ -234,8 +236,8 @@ class ForElement extends Expression with ControlFlowElement {
234236
}
235237

236238
@override
237-
String toStringInternal() {
238-
return "";
239+
void toTextInternal(AstPrinter state) {
240+
// TODO(johnniwinther): Implement this.
239241
}
240242
}
241243

@@ -323,8 +325,8 @@ class ForInElement extends Expression with ControlFlowElement {
323325
}
324326

325327
@override
326-
String toStringInternal() {
327-
return "";
328+
void toTextInternal(AstPrinter state) {
329+
// TODO(johnniwinther): Implement this.
328330
}
329331
}
330332

@@ -351,6 +353,16 @@ mixin ControlFlowMapEntry implements MapEntry {
351353

352354
@override
353355
R accept<R>(TreeVisitor<R> v) => v.defaultTreeNode(this);
356+
357+
@override
358+
String toStringInternal() => toText(defaultAstTextStrategy);
359+
360+
@override
361+
String toText(AstTextStrategy strategy) {
362+
AstPrinter state = new AstPrinter(strategy);
363+
toTextInternal(state);
364+
return state.getText();
365+
}
354366
}
355367

356368
/// A spread element in a map literal.
@@ -387,8 +399,8 @@ class SpreadMapEntry extends TreeNode with ControlFlowMapEntry {
387399
}
388400

389401
@override
390-
String toStringInternal() {
391-
return "";
402+
void toTextInternal(AstPrinter state) {
403+
// TODO(johnniwinther): Implement this.
392404
}
393405
}
394406

@@ -433,8 +445,8 @@ class IfMapEntry extends TreeNode with ControlFlowMapEntry {
433445
}
434446

435447
@override
436-
String toStringInternal() {
437-
return "";
448+
void toTextInternal(AstPrinter state) {
449+
// TODO(johnniwinther): Implement this.
438450
}
439451
}
440452

@@ -480,8 +492,8 @@ class ForMapEntry extends TreeNode with ControlFlowMapEntry {
480492
}
481493

482494
@override
483-
String toStringInternal() {
484-
return "";
495+
void toTextInternal(AstPrinter state) {
496+
// TODO(johnniwinther): Implement this.
485497
}
486498
}
487499

@@ -554,8 +566,8 @@ class ForInMapEntry extends TreeNode with ControlFlowMapEntry {
554566
}
555567

556568
@override
557-
String toStringInternal() {
558-
return "";
569+
void toTextInternal(AstPrinter state) {
570+
// TODO(johnniwinther): Implement this.
559571
}
560572
}
561573

pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1899,7 +1899,7 @@ class ConstantEvaluator extends RecursiveVisitor<Constant> {
18991899
if (constant is DoubleConstant && intFolder.isInt(constant)) {
19001900
value = new BigInt.from(constant.value).toString();
19011901
} else {
1902-
value = constant.toString();
1902+
value = constant.value.toString();
19031903
}
19041904
Object last = concatenated.last;
19051905
if (last is StringBuffer) {

pkg/front_end/lib/src/fasta/kernel/forest.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ library fasta.fangorn;
77
import 'dart:core' hide MapEntry;
88

99
import 'package:kernel/ast.dart';
10+
import 'package:kernel/src/printer.dart';
1011

1112
import '../problems.dart' show unsupported;
1213

@@ -761,7 +762,14 @@ class _VariablesDeclaration extends Statement {
761762
}
762763

763764
@override
764-
String toStringInternal() {
765-
return "";
765+
void toTextInternal(AstPrinter printer) {
766+
for (int index = 0; index < declarations.length; index++) {
767+
if (index > 0) {
768+
printer.write(', ');
769+
}
770+
printer.writeVariableDeclaration(declarations[index],
771+
includeModifiersAndType: index == 0);
772+
}
773+
printer.write(';');
766774
}
767775
}

0 commit comments

Comments
 (0)