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

Side by Side Diff: lib/src/checker/checker.dart

Issue 957013002: Typecheck map and list literals (Closed) Base URL: git@github.com:dart-lang/dart-dev-compiler.git@master
Patch Set: Add flag to reject casts in const contexts Created 5 years, 9 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 | lib/src/checker/rules.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 library ddc.src.checker.checker; 5 library ddc.src.checker.checker;
6 6
7 import 'package:analyzer/analyzer.dart'; 7 import 'package:analyzer/analyzer.dart';
8 import 'package:analyzer/src/generated/ast.dart'; 8 import 'package:analyzer/src/generated/ast.dart';
9 import 'package:analyzer/src/generated/element.dart'; 9 import 'package:analyzer/src/generated/element.dart';
10 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType; 10 import 'package:analyzer/src/generated/scanner.dart' show Token, TokenType;
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
330 if (info.level >= logger.Level.SEVERE) _failure = true; 330 if (info.level >= logger.Level.SEVERE) _failure = true;
331 _reporter.log(info); 331 _reporter.log(info);
332 } 332 }
333 } 333 }
334 334
335 /// Checks the body of functions and properties. 335 /// Checks the body of functions and properties.
336 class CodeChecker extends RecursiveAstVisitor { 336 class CodeChecker extends RecursiveAstVisitor {
337 final TypeRules _rules; 337 final TypeRules _rules;
338 final CheckerReporter _reporter; 338 final CheckerReporter _reporter;
339 final _OverrideChecker _overrideChecker; 339 final _OverrideChecker _overrideChecker;
340 bool _constantContext = false;
340 bool _failure = false; 341 bool _failure = false;
341 bool get failure => _failure || _overrideChecker._failure; 342 bool get failure => _failure || _overrideChecker._failure;
342 343
343 CodeChecker( 344 CodeChecker(
344 TypeRules rules, CheckerReporter reporter, CompilerOptions options) 345 TypeRules rules, CheckerReporter reporter, CompilerOptions options)
345 : _rules = rules, 346 : _rules = rules,
346 _reporter = reporter, 347 _reporter = reporter,
347 _overrideChecker = new _OverrideChecker(rules, reporter, options); 348 _overrideChecker = new _OverrideChecker(rules, reporter, options);
348 349
350 _visitMaybeConst(AstNode n, visitNode(AstNode n)) {
vsm 2015/02/27 00:20:16 Would be nice if we had generic methods. :-)
Leaf 2015/02/27 00:44:21 Acknowledged.
351 var o = _constantContext;
352 if (!o) {
353 if (n is VariableDeclarationList) {
354 _constantContext = o || n.isConst;
355 } else if (n is VariableDeclaration) {
356 _constantContext = o || n.isConst;
357 } else if (n is FormalParameter) {
358 _constantContext = o || n.isConst;
359 } else if (n is InstanceCreationExpression) {
360 _constantContext = o || n.isConst;
361 } else if (n is ConstructorDeclaration) {
362 _constantContext = o || n.element.isConst;
363 }
364 }
365 visitNode(n);
366 _constantContext = o;
367 }
368
349 visitComment(Comment node) { 369 visitComment(Comment node) {
350 // skip, no need to do typechecking inside comments (they may contain 370 // skip, no need to do typechecking inside comments (they may contain
351 // comment references which would require resolution). 371 // comment references which would require resolution).
352 } 372 }
353 373
354 visitClassDeclaration(ClassDeclaration node) { 374 visitClassDeclaration(ClassDeclaration node) {
355 _overrideChecker.check(node); 375 _overrideChecker.check(node);
356 super.visitClassDeclaration(node); 376 super.visitClassDeclaration(node);
357 } 377 }
358 378
359 visitAssignmentExpression(AssignmentExpression node) { 379 visitAssignmentExpression(AssignmentExpression node) {
360 var token = node.operator; 380 var token = node.operator;
361 if (token.type != TokenType.EQ) { 381 if (token.type != TokenType.EQ) {
362 _checkCompoundAssignment(node); 382 _checkCompoundAssignment(node);
363 } else { 383 } else {
364 DartType staticType = _rules.getStaticType(node.leftHandSide); 384 DartType staticType = _rules.getStaticType(node.leftHandSide);
365 node.rightHandSide = checkAssignment(node.rightHandSide, staticType); 385 node.rightHandSide = checkAssignment(node.rightHandSide, staticType);
366 } 386 }
367 node.visitChildren(this); 387 node.visitChildren(this);
368 } 388 }
369 389
370 /// Check constructor declaration to ensure correct super call placement. 390 _visitConstructorDeclaration(ConstructorDeclaration node) {
371 @override
372 visitConstructorDeclaration(ConstructorDeclaration node) {
373 node.visitChildren(this); 391 node.visitChildren(this);
374 392
375 final init = node.initializers; 393 final init = node.initializers;
376 for (int i = 0, last = init.length - 1; i < last; i++) { 394 for (int i = 0, last = init.length - 1; i < last; i++) {
377 final node = init[i]; 395 final node = init[i];
378 if (node is SuperConstructorInvocation) { 396 if (node is SuperConstructorInvocation) {
379 _recordMessage(new InvalidSuperInvocation(node)); 397 _recordMessage(new InvalidSuperInvocation(node));
380 } 398 }
381 } 399 }
382 } 400 }
383 401
402 /// Check constructor declaration to ensure correct super call placement.
403 @override
404 visitConstructorDeclaration(ConstructorDeclaration node) {
405 _visitMaybeConst(node, _visitConstructorDeclaration);
vsm 2015/02/27 00:20:16 Perhaps just inline the closure here instead of a
Leaf 2015/02/27 00:44:21 Done.
406 }
407
408 @override
409 visitInstanceCreationExpression(InstanceCreationExpression node) {
410 _visitMaybeConst(node, super.visitInstanceCreationExpression);
411 }
412
413 @override visitListLiteral(ListLiteral node) {
414 var type = _rules.provider.dynamicType;
415 if (node.typeArguments != null) {
416 var targs = node.typeArguments.arguments;
417 if (targs.length > 0) type = targs[0].type;
418 }
419 var elements = node.elements;
420 for (int i = 0; i < elements.length; i++) {
421 elements[i] = checkArgument(elements[i], type);
422 }
423 super.visitListLiteral(node);
424 }
425
426 @override visitMapLiteral(MapLiteral node) {
427 var ktype = _rules.provider.dynamicType;
428 var vtype = _rules.provider.dynamicType;
429 if (node.typeArguments != null) {
430 var targs = node.typeArguments.arguments;
431 if (targs.length > 0) ktype = targs[0].type;
432 if (targs.length > 1) vtype = targs[1].type;
433 }
434 var entries = node.entries;
435 for (int i = 0; i < entries.length; i++) {
436 var entry = entries[i];
437 entry.key = checkArgument(entry.key, ktype);
438 entry.value = checkArgument(entry.value, vtype);
439 }
440 super.visitMapLiteral(node);
441 }
442
384 // Check invocations 443 // Check invocations
385 bool checkArgumentList(ArgumentList node, FunctionType type) { 444 bool checkArgumentList(ArgumentList node, FunctionType type) {
386 NodeList<Expression> list = node.arguments; 445 NodeList<Expression> list = node.arguments;
387 int len = list.length; 446 int len = list.length;
388 for (int i = 0; i < len; ++i) { 447 for (int i = 0; i < len; ++i) {
389 Expression arg = list[i]; 448 Expression arg = list[i];
390 ParameterElement element = node.getStaticParameterElementFor(arg); 449 ParameterElement element = node.getStaticParameterElementFor(arg);
391 if (element == null) { 450 if (element == null) {
392 if (type.parameters.length < len) { 451 if (type.parameters.length < len) {
393 // We found an argument mismatch, the analyzer will report this too, 452 // We found an argument mismatch, the analyzer will report this too,
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 visitPrefixedIdentifier(PrefixedIdentifier node) { 560 visitPrefixedIdentifier(PrefixedIdentifier node) {
502 final target = node.prefix; 561 final target = node.prefix;
503 // Check if the prefix is a library - PrefixElement denotes a library 562 // Check if the prefix is a library - PrefixElement denotes a library
504 // access. 563 // access.
505 if (target.staticElement is! PrefixElement && _rules.isDynamicGet(target)) { 564 if (target.staticElement is! PrefixElement && _rules.isDynamicGet(target)) {
506 _recordDynamicInvoke(node); 565 _recordDynamicInvoke(node);
507 } 566 }
508 node.visitChildren(this); 567 node.visitChildren(this);
509 } 568 }
510 569
511 visitDefaultFormalParameter(DefaultFormalParameter node) { 570 _visitDefaultFormalParameter(DefaultFormalParameter node) {
512 // Check that defaults have the proper subtype. 571 // Check that defaults have the proper subtype.
513 var parameter = node.parameter; 572 var parameter = node.parameter;
514 var parameterType = _rules.elementType(parameter.element); 573 var parameterType = _rules.elementType(parameter.element);
515 assert(parameterType != null); 574 assert(parameterType != null);
516 var defaultValue = node.defaultValue; 575 var defaultValue = node.defaultValue;
517 var defaultType; 576 var defaultType;
518 if (defaultValue == null) { 577 if (defaultValue == null) {
519 // TODO(vsm): Should this be null? 578 // TODO(vsm): Should this be null?
520 defaultType = _rules.provider.bottomType; 579 defaultType = _rules.provider.bottomType;
521 } else { 580 } else {
522 defaultType = _rules.getStaticType(defaultValue); 581 defaultType = _rules.getStaticType(defaultValue);
523 } 582 }
524 583
525 // If defaultType is bottom, this enforces that parameterType is not 584 // If defaultType is bottom, this enforces that parameterType is not
526 // non-nullable. 585 // non-nullable.
527 if (!_rules.isSubTypeOf(defaultType, parameterType)) { 586 if (!_rules.isSubTypeOf(defaultType, parameterType)) {
528 var staticInfo = (defaultValue == null) 587 var staticInfo = (defaultValue == null)
529 ? new InvalidVariableDeclaration( 588 ? new InvalidVariableDeclaration(
530 _rules, node.identifier, parameterType) 589 _rules, node.identifier, parameterType)
531 : new StaticTypeError(_rules, defaultValue, parameterType); 590 : new StaticTypeError(_rules, defaultValue, parameterType);
532 _recordMessage(staticInfo); 591 _recordMessage(staticInfo);
533 } 592 }
534 node.visitChildren(this); 593 node.visitChildren(this);
535 } 594 }
536 595
537 visitVariableDeclarationList(VariableDeclarationList node) { 596 @override visitDefaultFormalParameter(DefaultFormalParameter node) {
597 _visitMaybeConst(node, _visitDefaultFormalParameter);
598 }
599
600 _visitVariableDeclarationList(VariableDeclarationList node) {
538 TypeName type = node.type; 601 TypeName type = node.type;
539 if (type == null) { 602 if (type == null) {
540 // No checks are needed when the type is var. Although internally the 603 // No checks are needed when the type is var. Although internally the
541 // typing rules may have inferred a more precise type for the variable 604 // typing rules may have inferred a more precise type for the variable
542 // based on the initializer. 605 // based on the initializer.
543 } else { 606 } else {
544 var dartType = getType(type); 607 var dartType = getType(type);
545 for (VariableDeclaration variable in node.variables) { 608 for (VariableDeclaration variable in node.variables) {
546 var initializer = variable.initializer; 609 var initializer = variable.initializer;
547 if (initializer != null) { 610 if (initializer != null) {
(...skipping 10 matching lines...) Expand all
558 var staticInfo = 621 var staticInfo =
559 new InvalidVariableDeclaration(_rules, variable, dartType); 622 new InvalidVariableDeclaration(_rules, variable, dartType);
560 _recordMessage(staticInfo); 623 _recordMessage(staticInfo);
561 } 624 }
562 } 625 }
563 } 626 }
564 } 627 }
565 node.visitChildren(this); 628 node.visitChildren(this);
566 } 629 }
567 630
631 @override
632 visitVariableDeclarationList(VariableDeclarationList node) {
633 _visitMaybeConst(node, _visitVariableDeclarationList);
634 }
635
636 @override
637 visitVariableDeclaration(VariableDeclaration node) {
638 _visitMaybeConst(node, super.visitVariableDeclaration);
639 }
640
568 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { 641 void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) {
569 var type = getType(typeName); 642 var type = getType(typeName);
570 if (!_rules.isGroundType(type)) { 643 if (!_rules.isGroundType(type)) {
571 _recordMessage(new InvalidRuntimeCheckError(node, type)); 644 _recordMessage(new InvalidRuntimeCheckError(node, type));
572 } 645 }
573 } 646 }
574 647
575 visitAsExpression(AsExpression node) { 648 visitAsExpression(AsExpression node) {
576 node.visitChildren(this); 649 node.visitChildren(this);
577 } 650 }
578 651
579 visitIsExpression(IsExpression node) { 652 visitIsExpression(IsExpression node) {
580 _checkRuntimeTypeCheck(node, node.type); 653 _checkRuntimeTypeCheck(node, node.type);
581 node.visitChildren(this); 654 node.visitChildren(this);
582 } 655 }
583 656
584 DartType getType(TypeName name) { 657 DartType getType(TypeName name) {
585 return (name == null) ? _rules.provider.dynamicType : name.type; 658 return (name == null) ? _rules.provider.dynamicType : name.type;
586 } 659 }
587 660
588 Expression checkAssignment(Expression expr, DartType type) { 661 Expression checkAssignment(Expression expr, DartType type) {
589 final staticInfo = _rules.checkAssignment(expr, type); 662 final staticInfo = _rules.checkAssignment(expr, type, _constantContext);
590 _recordMessage(staticInfo); 663 _recordMessage(staticInfo);
591 if (staticInfo is Conversion) expr = staticInfo; 664 if (staticInfo is Conversion) expr = staticInfo;
592 return expr; 665 return expr;
593 } 666 }
594 667
595 DartType _specializedBinaryReturnType( 668 DartType _specializedBinaryReturnType(
596 TokenType op, DartType t1, DartType t2, DartType normalReturnType) { 669 TokenType op, DartType t1, DartType t2, DartType normalReturnType) {
597 // This special cases binary return types as per 16.26 and 16.27 of the 670 // This special cases binary return types as per 16.26 and 16.27 of the
598 // Dart language spec. 671 // Dart language spec.
599 switch (op) { 672 switch (op) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 } else { 726 } else {
654 // Static type error 727 // Static type error
655 staticInfo = new StaticTypeError(_rules, expr, lhsType); 728 staticInfo = new StaticTypeError(_rules, expr, lhsType);
656 } 729 }
657 _recordMessage(staticInfo); 730 _recordMessage(staticInfo);
658 } 731 }
659 732
660 // Check the rhs type 733 // Check the rhs type
661 if (staticInfo is! Conversion) { 734 if (staticInfo is! Conversion) {
662 var paramType = paramTypes.first; 735 var paramType = paramTypes.first;
663 staticInfo = _rules.checkAssignment(expr.rightHandSide, paramType); 736 staticInfo = _rules.checkAssignment(
737 expr.rightHandSide, paramType, _constantContext);
664 _recordMessage(staticInfo); 738 _recordMessage(staticInfo);
665 if (staticInfo is Conversion) expr.rightHandSide = staticInfo; 739 if (staticInfo is Conversion) expr.rightHandSide = staticInfo;
666 } 740 }
667 } 741 }
668 } 742 }
669 743
670 void _recordDynamicInvoke(AstNode node) { 744 void _recordDynamicInvoke(AstNode node) {
671 _reporter.log(new DynamicInvoke(_rules, node)); 745 _reporter.log(new DynamicInvoke(_rules, node));
672 } 746 }
673 747
674 void _recordMessage(StaticInfo info) { 748 void _recordMessage(StaticInfo info) {
675 if (info == null) return; 749 if (info == null) return;
676 if (info.level >= logger.Level.SEVERE) _failure = true; 750 if (info.level >= logger.Level.SEVERE) _failure = true;
677 _reporter.log(info); 751 _reporter.log(info);
678 } 752 }
679 } 753 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/checker/rules.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698