Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_outline_shaker.dart

Issue 3009803002: Mark types of Constructor parameters and preserve referenced typedefs. (Closed)
Patch Set: Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// A transformation to create a self-contained modular kernel without 5 /// A transformation to create a self-contained modular kernel without
6 /// unnecessary references to other libraries. 6 /// unnecessary references to other libraries.
7 library fasta.kernel.kernel_outline_shaker; 7 library fasta.kernel.kernel_outline_shaker;
8 8
9 import 'package:kernel/ast.dart'; 9 import 'package:kernel/ast.dart';
10 import 'package:kernel/core_types.dart'; 10 import 'package:kernel/core_types.dart';
(...skipping 24 matching lines...) Expand all
35 /// the [KernelOutlineShaker] when tree-shaking. 35 /// the [KernelOutlineShaker] when tree-shaking.
36 abstract class RetainedData { 36 abstract class RetainedData {
37 /// Whether a library should be preserved and mark as external. 37 /// Whether a library should be preserved and mark as external.
38 bool isLibraryUsed(Library library); 38 bool isLibraryUsed(Library library);
39 39
40 /// Whether a class should be preserved. If a class is preserved, its 40 /// Whether a class should be preserved. If a class is preserved, its
41 /// supertypes will be preserved too, but some of it members may not be 41 /// supertypes will be preserved too, but some of it members may not be
42 /// included. 42 /// included.
43 bool isClassUsed(Class cls); 43 bool isClassUsed(Class cls);
44 44
45 /// Whether a typedef should be preserved. If a typedef is preserved, its
46 /// return type and types of parameters will be preserved too.
47 bool isTypedefUsed(Typedef node);
48
45 /// Whether a member should be preserved. If so, its enclosing class/library 49 /// Whether a member should be preserved. If so, its enclosing class/library
46 /// will be preserved too. 50 /// will be preserved too.
47 bool isMemberUsed(Member member); 51 bool isMemberUsed(Member member);
48 } 52 }
49 53
50 /// A builder of [RetainedData] that recursively marks transitive dependencies. 54 /// A builder of [RetainedData] that recursively marks transitive dependencies.
51 /// 55 ///
52 /// This builder contains APIs to mark the roots that are needed (e.g. 56 /// This builder contains APIs to mark the roots that are needed (e.g.
53 /// [markClass] and [markMember]). Note this builder does not determine what 57 /// [markClass] and [markMember]). Note this builder does not determine what
54 /// roots to keep, that is done either directly by fasta while it is parsing, or 58 /// roots to keep, that is done either directly by fasta while it is parsing, or
55 /// by using a visitor like the [RootsMarker] below. 59 /// by using a visitor like the [RootsMarker] below.
56 class RetainedDataBuilder extends RetainedData { 60 class RetainedDataBuilder extends RetainedData {
57 /// Libraries that contained code that is transitively reachable from the 61 /// Libraries that contained code that is transitively reachable from the
58 /// included libraries. 62 /// included libraries.
59 final Set<Library> libraries = new Set<Library>(); 63 final Set<Library> libraries = new Set<Library>();
60 64
61 /// Classes that are transitively reachable from the included libraries. 65 /// Classes that are transitively reachable from the included libraries.
62 final Set<Class> classes = new Set<Class>(); 66 final Set<Class> classes = new Set<Class>();
63 67
68 /// Typedefs that are transitively reachable from the included libraries.
69 final Set<Typedef> typedefs = new Set<Typedef>();
70
64 /// Members that are transitively reachable from the included libraries. 71 /// Members that are transitively reachable from the included libraries.
65 final Set<Member> members = new Set<Member>(); 72 final Set<Member> members = new Set<Member>();
66 73
67 TypeMarker typeMarker; 74 TypeMarker typeMarker;
68 75
69 @override 76 @override
70 bool isLibraryUsed(Library library) => libraries.contains(library); 77 bool isLibraryUsed(Library library) => libraries.contains(library);
71 78
72 @override 79 @override
73 bool isClassUsed(Class cls) => classes.contains(cls); 80 bool isClassUsed(Class cls) => classes.contains(cls);
74 81
75 @override 82 @override
83 bool isTypedefUsed(Typedef node) => typedefs.contains(node);
84
85 @override
76 bool isMemberUsed(Member m) => members.contains(m); 86 bool isMemberUsed(Member m) => members.contains(m);
77 87
78 RetainedDataBuilder() { 88 RetainedDataBuilder() {
79 typeMarker = new TypeMarker(this); 89 typeMarker = new TypeMarker(this);
80 } 90 }
81 91
82 /// Mark a library as used. 92 /// Mark a library as used.
83 void markLibrary(Library lib) { 93 void markLibrary(Library lib) {
84 libraries.add(lib); 94 libraries.add(lib);
85 } 95 }
86 96
87 /// Mark a class and it's supertypes as used. 97 /// Mark a class and it's supertypes as used.
88 void markClass(Class cls) { 98 void markClass(Class cls) {
89 if (cls == null || !classes.add(cls)) return; 99 if (cls == null || !classes.add(cls)) return;
90 markLibrary(cls.parent); 100 markLibrary(cls.parent);
91 // TODO(sigmund): retain annotations? 101 // TODO(sigmund): retain annotations?
92 // visitList(cls.annotations, this); 102 // visitList(cls.annotations, this);
93 markSupertype(cls.supertype); 103 markSupertype(cls.supertype);
94 markSupertype(cls.mixedInType); 104 markSupertype(cls.mixedInType);
95 cls.implementedTypes.forEach(markSupertype); 105 cls.implementedTypes.forEach(markSupertype);
96 cls.typeParameters.forEach((t) => t.bound.accept(typeMarker)); 106 cls.typeParameters.forEach((t) => t.bound.accept(typeMarker));
97 } 107 }
98 108
109 /// Mark the typedef.
110 void markTypedef(Typedef node) {
111 if (node == null || !typedefs.add(node)) return;
112 markLibrary(node.parent);
113 }
114
99 /// Mark the class and type arguments of [node]. 115 /// Mark the class and type arguments of [node].
100 void markSupertype(Supertype node) { 116 void markSupertype(Supertype node) {
101 if (node == null) return; 117 if (node == null) return;
102 markClass(node.classNode); 118 markClass(node.classNode);
103 node.typeArguments.forEach((t) => t.accept(typeMarker)); 119 node.typeArguments.forEach((t) => t.accept(typeMarker));
104 } 120 }
105 121
106 /// Mark a member and types mentioned on its interface. 122 /// Mark a member and types mentioned on its interface.
107 void markMember(Member m) { 123 void markMember(Member m) {
108 if (m == null || !members.add(m)) return; 124 if (m == null || !members.add(m)) return;
109 markMemberInterface(m); 125 markMemberInterface(m);
110 var parent = m.parent; 126 var parent = m.parent;
111 if (parent is Library) { 127 if (parent is Library) {
112 markLibrary(parent); 128 markLibrary(parent);
113 } else if (parent is Class) { 129 } else if (parent is Class) {
114 markClass(parent); 130 markClass(parent);
115 } 131 }
116 } 132 }
117 133
118 void markMemberInterface(Member node) { 134 void markMemberInterface(Member node) {
119 if (node is Field) { 135 if (node is Field) {
120 node.type.accept(typeMarker); 136 node.type.accept(typeMarker);
137 } else if (node is Constructor) {
138 var function = node.function;
139 function.positionalParameters.forEach((p) => p.type.accept(typeMarker));
140 function.namedParameters.forEach((p) => p.type.accept(typeMarker));
121 } else if (node is Procedure) { 141 } else if (node is Procedure) {
122 var function = node.function; 142 var function = node.function;
123 function.typeParameters.forEach((p) => p.bound.accept(typeMarker)); 143 function.typeParameters.forEach((p) => p.bound.accept(typeMarker));
124 function.positionalParameters.forEach((p) => p.type.accept(typeMarker)); 144 function.positionalParameters.forEach((p) => p.type.accept(typeMarker));
125 function.namedParameters.forEach((p) => p.type.accept(typeMarker)); 145 function.namedParameters.forEach((p) => p.type.accept(typeMarker));
126 function.returnType.accept(typeMarker); 146 function.returnType.accept(typeMarker);
127 } 147 }
128 } 148 }
129 } 149 }
130 150
131 /// A helper visitor used to mark transitive types by the [RetainedDataBuilder]. 151 /// A helper visitor used to mark transitive types by the [RetainedDataBuilder].
132 class TypeMarker extends DartTypeVisitor { 152 class TypeMarker extends DartTypeVisitor {
133 RetainedDataBuilder data; 153 RetainedDataBuilder data;
134 154
135 TypeMarker(this.data); 155 TypeMarker(this.data);
136 156
137 visitInterfaceType(InterfaceType node) { 157 visitInterfaceType(InterfaceType node) {
138 data.markClass(node.classNode); 158 data.markClass(node.classNode);
139 node.typeArguments.forEach((t) => t.accept(this)); 159 node.typeArguments.forEach((t) => t.accept(this));
140 } 160 }
141 161
142 visitFunctionType(FunctionType node) { 162 visitFunctionType(FunctionType node) {
143 node.typeParameters.forEach((t) => t.bound.accept(this)); 163 node.typeParameters.forEach((t) => t.bound.accept(this));
144 node.positionalParameters.forEach((t) => t.accept(this)); 164 node.positionalParameters.forEach((t) => t.accept(this));
145 node.namedParameters.forEach((t) => t.type.accept(this)); 165 node.namedParameters.forEach((t) => t.type.accept(this));
146 node.returnType.accept(this); 166 node.returnType.accept(this);
167 data.markTypedef(node.typedefReference?.asTypedef);
147 } 168 }
148 169
149 visitTypeParameterType(TypeParameterType node) { 170 visitTypeParameterType(TypeParameterType node) {
150 // Note: node.parameter is marked by marking the enclosing element. 171 // Note: node.parameter is marked by marking the enclosing element.
151 } 172 }
152 173
153 visitTypedefType(TypedefType node) { 174 visitTypedefType(TypedefType node) {
154 node.typeArguments.forEach((t) => t.accept(this)); 175 node.typeArguments.forEach((t) => t.accept(this));
155 } 176 }
156 } 177 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 data.markMember(coreTypes.awaitHelperProcedure); 243 data.markMember(coreTypes.awaitHelperProcedure);
223 244
224 // These are needed by the mixin transformer 245 // These are needed by the mixin transformer
225 data.markMember(coreTypes.invocationMirrorDefaultConstructor); 246 data.markMember(coreTypes.invocationMirrorDefaultConstructor);
226 data.markMember(coreTypes.listFromConstructor); 247 data.markMember(coreTypes.listFromConstructor);
227 } 248 }
228 249
229 visitConstructor(Constructor node) { 250 visitConstructor(Constructor node) {
230 if (!node.initializers.any((i) => i is SuperInitializer)) { 251 if (!node.initializers.any((i) => i is SuperInitializer)) {
231 // super() is currently implicit. 252 // super() is currently implicit.
232 for (var ctor in node.enclosingClass.supertype.classNode.constructors) { 253 var supertype = node.enclosingClass.supertype;
233 if (ctor.name.name == '') data.markMember(ctor); 254 if (supertype != null) {
255 for (var constructor in supertype.classNode.constructors) {
256 if (constructor.name.name == '') data.markMember(constructor);
257 }
234 } 258 }
235 } 259 }
236 node.visitChildren(this); 260 node.visitChildren(this);
237 } 261 }
238 262
239 @override 263 @override
240 visitSuperInitializer(SuperInitializer node) { 264 visitSuperInitializer(SuperInitializer node) {
241 data.markMember(node.target); 265 data.markMember(node.target);
242 node.visitChildren(this); 266 node.visitChildren(this);
243 } 267 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 node.visitChildren(this); 341 node.visitChildren(this);
318 } 342 }
319 343
320 @override 344 @override
321 visitPropertySet(PropertySet node) { 345 visitPropertySet(PropertySet node) {
322 data.markMember(node.interfaceTarget); 346 data.markMember(node.interfaceTarget);
323 node.visitChildren(this); 347 node.visitChildren(this);
324 } 348 }
325 349
326 @override 350 @override
351 visitFunctionType(FunctionType node) {
352 data.markTypedef(node.typedefReference?.asTypedef);
353 super.visitFunctionType(node);
354 }
355
356 @override
327 visitInterfaceType(InterfaceType node) { 357 visitInterfaceType(InterfaceType node) {
328 data.markClass(node.classNode); 358 data.markClass(node.classNode);
329 node.visitChildren(this); 359 node.visitChildren(this);
330 } 360 }
331 361
332 @override 362 @override
333 visitSupertype(Supertype node) { 363 visitSupertype(Supertype node) {
334 data.markClass(node.classNode); 364 data.markClass(node.classNode);
335 node.visitChildren(this); 365 node.visitChildren(this);
336 } 366 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 } 407 }
378 408
379 Member defaultMember(Member node) { 409 Member defaultMember(Member node) {
380 if (!data.isMemberUsed(node)) { 410 if (!data.isMemberUsed(node)) {
381 node.canonicalName?.unbind(); 411 node.canonicalName?.unbind();
382 return null; 412 return null;
383 } else { 413 } else {
384 if (node is Procedure) { 414 if (node is Procedure) {
385 node.function.body = null; 415 node.function.body = null;
386 } else if (node is Field) { 416 } else if (node is Field) {
417 if (node.name.name == '_exports#') return null;
387 node.initializer = null; 418 node.initializer = null;
388 } else if (node is Constructor) { 419 } else if (node is Constructor) {
389 node.initializers.clear(); 420 node.initializers.clear();
390 node.function.body = null; 421 node.function.body = null;
391 } 422 }
392 return node; 423 return node;
393 } 424 }
394 } 425 }
395 426
396 /// Types appear to be encoded directly, so we have no need to preserve 427 Typedef visitTypedef(Typedef node) {
397 /// typedefs. 428 if (!data.isTypedefUsed(node)) {
398 // TODO(sigmund): revisit if this is not the case, the `inputError` in 429 node.canonicalName?.unbind();
399 // [RootsMarker] is meant to detect this. 430 return null; // Remove the typedef.
400 Typedef visitTypedef(Typedef node) => null; 431 } else {
432 node.transformChildren(this);
433 return node;
434 }
435 }
401 436
402 TreeNode defaultTreeNode(TreeNode node) => node; 437 TreeNode defaultTreeNode(TreeNode node) => node;
403 } 438 }
404 439
405 typedef bool Filter(Uri uri); 440 typedef bool Filter(Uri uri);
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/src/incremental/mock_sdk.dart » ('j') | pkg/front_end/testcases/shaker/typedefs_in_types.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698