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

Side by Side Diff: pkg/analyzer/lib/src/task/strong_mode.dart

Issue 2352433002: support `@virtual` fields, fix #27384 (Closed)
Patch Set: Created 4 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) 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 library analyzer.src.task.strong_mode; 5 library analyzer.src.task.strong_mode;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/visitor.dart'; 10 import 'package:analyzer/dart/ast/visitor.dart';
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 } 299 }
300 } 300 }
301 // 301 //
302 // Infer the parameter types. 302 // Infer the parameter types.
303 // 303 //
304 List<ParameterElement> parameters = element.parameters; 304 List<ParameterElement> parameters = element.parameters;
305 int length = parameters.length; 305 int length = parameters.length;
306 for (int i = 0; i < length; ++i) { 306 for (int i = 0; i < length; ++i) {
307 ParameterElement parameter = parameters[i]; 307 ParameterElement parameter = parameters[i];
308 if (parameter is ParameterElementImpl) { 308 if (parameter is ParameterElementImpl) {
309 // If a parameter is covariant, any parameters that override it are too. 309 _inferParameterCovariance(parameter, i, overriddenTypes);
310 parameter.inheritsCovariant = overriddenTypes.any((f) {
311 var param = _getCorrespondingParameter(parameter, i, f.parameters);
312 return param != null && param.isCovariant;
313 });
314 310
315 if (parameter.hasImplicitType) { 311 if (parameter.hasImplicitType) {
316 parameter.type = _computeParameterType(parameter, i, overriddenTypes); 312 parameter.type = _computeParameterType(parameter, i, overriddenTypes);
317 if (element is PropertyAccessorElement) { 313 if (element is PropertyAccessorElement) {
318 _updateSyntheticVariableType(element); 314 _updateSyntheticVariableType(element);
319 } 315 }
320 } 316 }
321 } 317 }
322 } 318 }
323 } 319 }
324 320
325 /** 321 /**
326 * If the given [fieldElement] represents a non-synthetic instance field for 322 * If the given [fieldElement] represents a non-synthetic instance field for
327 * which no type was provided, infer the type of the field. 323 * which no type was provided, infer the type of the field.
328 */ 324 */
329 void _inferField(FieldElement fieldElement) { 325 void _inferField(FieldElement fieldElement) {
330 if (!fieldElement.isSynthetic && 326 if (fieldElement.isSynthetic || fieldElement.isStatic) {
331 !fieldElement.isStatic && 327 return;
332 fieldElement.hasImplicitType) { 328 }
329 List<ExecutableElement> overriddenSetters =
330 inheritanceManager.lookupOverrides(
331 fieldElement.enclosingElement, fieldElement.name + '=');
332 var setter = fieldElement.setter;
333 if (setter != null && overriddenSetters.isNotEmpty) {
334 _inferParameterCovariance(
335 setter.parameters[0], 0, overriddenSetters.map((s) => s.type));
336 }
337
338 if (fieldElement.hasImplicitType) {
333 // 339 //
334 // First look for overridden getters with the same name as the field. 340 // First look for overridden getters with the same name as the field.
335 // 341 //
336 List<ExecutableElement> overriddenGetters = inheritanceManager 342 List<ExecutableElement> overriddenGetters = inheritanceManager
337 .lookupOverrides(fieldElement.enclosingElement, fieldElement.name); 343 .lookupOverrides(fieldElement.enclosingElement, fieldElement.name);
338 DartType newType = null; 344 DartType newType = null;
339 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) { 345 if (overriddenGetters.isNotEmpty && _onlyGetters(overriddenGetters)) {
340 newType = 346 newType =
341 _computeReturnType(overriddenGetters.map((e) => e.returnType)); 347 _computeReturnType(overriddenGetters.map((e) => e.returnType));
342 List<ExecutableElement> overriddenSetters = 348
343 inheritanceManager.lookupOverrides(
344 fieldElement.enclosingElement, fieldElement.name + '=');
345 if (!_isCompatible(newType, overriddenSetters)) { 349 if (!_isCompatible(newType, overriddenSetters)) {
346 newType = null; 350 newType = null;
347 } 351 }
348 } 352 }
349 // 353 //
350 // If there is no overridden getter or if the overridden getter's type is 354 // If there is no overridden getter or if the overridden getter's type is
351 // dynamic, then we can infer the type from the initialization expression 355 // dynamic, then we can infer the type from the initialization expression
352 // without breaking subtype rules. We could potentially infer a consistent 356 // without breaking subtype rules. We could potentially infer a consistent
353 // return type even if the overridden getter's type was not dynamic, but 357 // return type even if the overridden getter's type was not dynamic, but
354 // choose not to for simplicity. The field is required to be final to 358 // choose not to for simplicity. The field is required to be final to
(...skipping 14 matching lines...) Expand all
369 } 373 }
370 374
371 void _inferFieldFormalParameter(FieldFormalParameterElement element) { 375 void _inferFieldFormalParameter(FieldFormalParameterElement element) {
372 FieldElement field = element.field; 376 FieldElement field = element.field;
373 if (field != null && element.hasImplicitType) { 377 if (field != null && element.hasImplicitType) {
374 (element as FieldFormalParameterElementImpl).type = field.type; 378 (element as FieldFormalParameterElementImpl).type = field.type;
375 } 379 }
376 } 380 }
377 381
378 /** 382 /**
383 * If a parameter is covariant, any parameters that override it are too.
384 */
385 void _inferParameterCovariance(ParameterElementImpl parameter, int index,
386 Iterable<FunctionType> overriddenTypes) {
387 parameter.inheritsCovariant = overriddenTypes.any((f) {
388 var param = _getCorrespondingParameter(parameter, index, f.parameters);
389 return param != null && param.isCovariant;
390 });
391 }
392
393 /**
379 * Infer type information for all of the instance members in the given 394 * Infer type information for all of the instance members in the given
380 * interface [type]. 395 * interface [type].
381 */ 396 */
382 void _inferType(InterfaceType type) { 397 void _inferType(InterfaceType type) {
383 if (type != null) { 398 if (type != null) {
384 ClassElement element = type.element; 399 ClassElement element = type.element;
385 if (element != null) { 400 if (element != null) {
386 _inferClass(element); 401 _inferClass(element);
387 } 402 }
388 } 403 }
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 results.add(element); 495 results.add(element);
481 } 496 }
482 } 497 }
483 } 498 }
484 } 499 }
485 500
486 /** 501 /**
487 * A class of exception that is not used anywhere else. 502 * A class of exception that is not used anywhere else.
488 */ 503 */
489 class _CycleException implements Exception {} 504 class _CycleException implements Exception {}
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/task/strong/checker.dart ('k') | pkg/analyzer/test/src/task/strong/checker_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698