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

Side by Side Diff: pkg/compiler/lib/src/js_backend/no_such_method_registry.dart

Issue 2857943002: Implement KernelNoSuchMethodResolver. (Closed)
Patch Set: Updated cf. comments Created 3 years, 7 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/kernel/element_map.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 import '../common.dart'; 5 import '../common.dart';
6 import '../common_elements.dart' show CommonElements; 6 import '../common_elements.dart' show CommonElements;
7 import '../common/names.dart' show Identifiers, Names, Selectors; 7 import '../common/names.dart' show Identifiers, Selectors;
8 import '../elements/elements.dart';
9 import '../elements/entities.dart'; 8 import '../elements/entities.dart';
10 import '../types/types.dart'; 9 import '../types/types.dart';
11 import '../tree/tree.dart';
12 10
13 /** 11 /**
14 * Categorizes `noSuchMethod` implementations. 12 * Categorizes `noSuchMethod` implementations.
15 * 13 *
16 * If user code includes `noSuchMethod` implementations, type inference is 14 * If user code includes `noSuchMethod` implementations, type inference is
17 * hindered because (for instance) any selector where the type of the 15 * hindered because (for instance) any selector where the type of the
18 * receiver is not known all implementations of `noSuchMethod` must be taken 16 * receiver is not known all implementations of `noSuchMethod` must be taken
19 * into account when inferring the return type. 17 * into account when inferring the return type.
20 * 18 *
21 * The situation can be ameliorated with some heuristics for disregarding some 19 * The situation can be ameliorated with some heuristics for disregarding some
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 final Set<FunctionEntity> complexReturningImpls = new Set<FunctionEntity>(); 65 final Set<FunctionEntity> complexReturningImpls = new Set<FunctionEntity>();
68 66
69 /// The implementations that have not yet been categorized. 67 /// The implementations that have not yet been categorized.
70 final Set<FunctionEntity> _uncategorizedImpls = new Set<FunctionEntity>(); 68 final Set<FunctionEntity> _uncategorizedImpls = new Set<FunctionEntity>();
71 69
72 final CommonElements _commonElements; 70 final CommonElements _commonElements;
73 final NoSuchMethodResolver _resolver; 71 final NoSuchMethodResolver _resolver;
74 72
75 NoSuchMethodRegistry(this._commonElements, this._resolver); 73 NoSuchMethodRegistry(this._commonElements, this._resolver);
76 74
75 NoSuchMethodResolver get internalResolverForTesting => _resolver;
76
77 bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty; 77 bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
78 bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty; 78 bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
79 79
80 void registerNoSuchMethod(FunctionEntity noSuchMethodElement) { 80 void registerNoSuchMethod(FunctionEntity noSuchMethodElement) {
81 _uncategorizedImpls.add(noSuchMethodElement); 81 _uncategorizedImpls.add(noSuchMethodElement);
82 } 82 }
83 83
84 void onQueueEmpty() { 84 void onQueueEmpty() {
85 _uncategorizedImpls.forEach(_categorizeImpl); 85 _uncategorizedImpls.forEach(_categorizeImpl);
86 _uncategorizedImpls.clear(); 86 _uncategorizedImpls.clear();
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 199
200 /// Computes whether [method] is of the form 200 /// Computes whether [method] is of the form
201 /// 201 ///
202 /// noSuchMethod(i) => throw new Error(); 202 /// noSuchMethod(i) => throw new Error();
203 /// 203 ///
204 bool hasThrowingSyntax(FunctionEntity method); 204 bool hasThrowingSyntax(FunctionEntity method);
205 205
206 /// Returns the `noSuchMethod` that [method] overrides. 206 /// Returns the `noSuchMethod` that [method] overrides.
207 FunctionEntity getSuperNoSuchMethod(FunctionEntity method); 207 FunctionEntity getSuperNoSuchMethod(FunctionEntity method);
208 } 208 }
209
210 /// AST-based implementation of [NoSuchMethodResolver].
211 class NoSuchMethodResolverImpl implements NoSuchMethodResolver {
212 bool hasForwardingSyntax(MethodElement element) {
213 // At this point we know that this is signature-compatible with
214 // Object.noSuchMethod, but it may have more than one argument as long as
215 // it only has one required argument.
216 if (!element.hasResolvedAst) {
217 // TODO(johnniwinther): Why do we see unresolved elements here?
218 return false;
219 }
220 ResolvedAst resolvedAst = element.resolvedAst;
221 if (resolvedAst.kind != ResolvedAstKind.PARSED) {
222 return false;
223 }
224 String param = element.parameters.first.name;
225 Statement body = resolvedAst.body;
226 Expression expr;
227 if (body is Return && body.isArrowBody) {
228 expr = body.expression;
229 } else if (body is Block &&
230 !body.statements.isEmpty &&
231 body.statements.nodes.tail.isEmpty) {
232 Statement stmt = body.statements.nodes.head;
233 if (stmt is Return && stmt.hasExpression) {
234 expr = stmt.expression;
235 }
236 }
237 if (expr is Send && expr.isTypeCast) {
238 Send sendExpr = expr;
239 var typeAnnotation = sendExpr.typeAnnotationFromIsCheckOrCast;
240 var typeName = typeAnnotation.asNominalTypeAnnotation()?.typeName;
241 if (typeName is Identifier && typeName.source == "dynamic") {
242 expr = sendExpr.receiver;
243 }
244 }
245 if (expr is Send &&
246 expr.isSuperCall &&
247 expr.selector is Identifier &&
248 (expr.selector as Identifier).source == Identifiers.noSuchMethod_) {
249 var arg = expr.arguments.head;
250 if (expr.arguments.tail.isEmpty &&
251 arg is Send &&
252 arg.argumentsNode == null &&
253 arg.receiver == null &&
254 arg.selector is Identifier &&
255 arg.selector.source == param) {
256 return true;
257 }
258 }
259 return false;
260 }
261
262 bool hasThrowingSyntax(MethodElement element) {
263 if (!element.hasResolvedAst) {
264 // TODO(johnniwinther): Why do we see unresolved elements here?
265 return false;
266 }
267 ResolvedAst resolvedAst = element.resolvedAst;
268 if (resolvedAst.kind != ResolvedAstKind.PARSED) {
269 return false;
270 }
271 Statement body = resolvedAst.body;
272 if (body is Return && body.isArrowBody) {
273 if (body.expression is Throw) {
274 return true;
275 }
276 } else if (body is Block &&
277 !body.statements.isEmpty &&
278 body.statements.nodes.tail.isEmpty) {
279 if (body.statements.nodes.head is ExpressionStatement) {
280 ExpressionStatement stmt = body.statements.nodes.head;
281 return stmt.expression is Throw;
282 }
283 }
284 return false;
285 }
286
287 MethodElement getSuperNoSuchMethod(MethodElement method) {
288 return method.enclosingClass.lookupSuperByName(Names.noSuchMethod_);
289 }
290 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/kernel/element_map.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698