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

Side by Side Diff: pkg/analyzer_experimental/lib/src/generated/resolver.dart

Issue 22285004: New analyzer_experimental snapshot. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // This code was auto-generated, is not intended to be edited, and is subject to 1 // This code was auto-generated, is not intended to be edited, and is subject to
2 // significant change. Please see the README file for more information. 2 // significant change. Please see the README file for more information.
3 library engine.resolver; 3 library engine.resolver;
4 import 'dart:collection'; 4 import 'dart:collection';
5 import 'java_core.dart'; 5 import 'java_core.dart';
6 import 'java_engine.dart'; 6 import 'java_engine.dart';
7 import 'instrumentation.dart'; 7 import 'instrumentation.dart';
8 import 'source.dart'; 8 import 'source.dart';
9 import 'error.dart'; 9 import 'error.dart';
10 import 'scanner.dart' as sc; 10 import 'scanner.dart' as sc;
(...skipping 1230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1241 * @param errorCode the error code of the error to be reported 1241 * @param errorCode the error code of the error to be reported
1242 * @param offset the offset of the first character to be highlighted 1242 * @param offset the offset of the first character to be highlighted
1243 * @param length the number of characters to be highlighted 1243 * @param length the number of characters to be highlighted
1244 * @param arguments the arguments used to compose the error message 1244 * @param arguments the arguments used to compose the error message
1245 */ 1245 */
1246 void reportError(ErrorCode errorCode, int offset, int length, List<Object> arg uments) { 1246 void reportError(ErrorCode errorCode, int offset, int length, List<Object> arg uments) {
1247 _errorListener.onError(new AnalysisError.con2(_htmlElement.source, offset, l ength, errorCode, arguments)); 1247 _errorListener.onError(new AnalysisError.con2(_htmlElement.source, offset, l ength, errorCode, arguments));
1248 } 1248 }
1249 } 1249 }
1250 /** 1250 /**
1251 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f or cases of
1252 * [HintCode#DEAD_CODE].
1253 *
1254 * @coverage dart.engine.resolver
1255 */
1256 class DeadCodeVerifier extends RecursiveASTVisitor<Object> {
1257
1258 /**
1259 * The error reporter by which errors will be reported.
1260 */
1261 ErrorReporter _errorReporter;
1262
1263 /**
1264 * Create a new instance of the [DeadCodeVerifier].
1265 *
1266 * @param errorReporter the error reporter
1267 */
1268 DeadCodeVerifier(ErrorReporter errorReporter) {
1269 this._errorReporter = errorReporter;
1270 }
1271 Object visitBinaryExpression(BinaryExpression node) {
1272 sc.Token operator = node.operator;
1273 bool isAmpAmp = identical(operator.type, sc.TokenType.AMPERSAND_AMPERSAND);
1274 bool isBarBar = identical(operator.type, sc.TokenType.BAR_BAR);
1275 if (isAmpAmp || isBarBar) {
1276 Expression lhsCondition = node.leftOperand;
1277 ValidResult lhsResult = getConstantBooleanValue(lhsCondition);
1278 if (lhsResult != null) {
1279 if (identical(lhsResult, ValidResult.RESULT_TRUE) && isBarBar) {
1280 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, []) ;
1281 safelyVisit(lhsCondition);
1282 return null;
1283 } else if (identical(lhsResult, ValidResult.RESULT_FALSE) && isAmpAmp) {
1284 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, []) ;
1285 safelyVisit(lhsCondition);
1286 return null;
1287 }
1288 }
1289 }
1290 return super.visitBinaryExpression(node);
1291 }
1292
1293 /**
1294 * For each [Block], this method reports and error on all statements between t he end of the
1295 * block and the first return statement (assuming there it is not at the end o f the block.)
1296 *
1297 * @param node the block to evaluate
1298 */
1299 Object visitBlock(Block node) {
1300 NodeList<Statement> statements = node.statements;
1301 int size = statements.length;
1302 for (int i = 0; i < size; i++) {
1303 Statement currentStatement = statements[i];
1304 safelyVisit(currentStatement);
1305 if (currentStatement is ReturnStatement && i != size - 1) {
1306 Statement nextStatement = statements[i + 1];
1307 Statement lastStatement = statements[size - 1];
1308 int offset = nextStatement.offset;
1309 int length = lastStatement.end - offset;
1310 _errorReporter.reportError3(HintCode.DEAD_CODE, offset, length, []);
1311 return null;
1312 }
1313 }
1314 return null;
1315 }
1316 Object visitConditionalExpression(ConditionalExpression node) {
1317 Expression conditionExpression = node.condition;
1318 ValidResult result = getConstantBooleanValue(conditionExpression);
1319 if (result != null) {
1320 if (identical(result, ValidResult.RESULT_TRUE)) {
1321 _errorReporter.reportError2(HintCode.DEAD_CODE, node.elseExpression, []) ;
1322 safelyVisit(node.thenExpression);
1323 return null;
1324 } else {
1325 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenExpression, []) ;
1326 safelyVisit(node.elseExpression);
1327 return null;
1328 }
1329 }
1330 return super.visitConditionalExpression(node);
1331 }
1332 Object visitIfStatement(IfStatement node) {
1333 Expression conditionExpression = node.condition;
1334 ValidResult result = getConstantBooleanValue(conditionExpression);
1335 if (result != null) {
1336 if (identical(result, ValidResult.RESULT_TRUE)) {
1337 Statement elseStatement = node.elseStatement;
1338 if (elseStatement != null) {
1339 _errorReporter.reportError2(HintCode.DEAD_CODE, elseStatement, []);
1340 safelyVisit(node.thenStatement);
1341 return null;
1342 }
1343 } else {
1344 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenStatement, []);
1345 safelyVisit(node.elseStatement);
1346 return null;
1347 }
1348 }
1349 return super.visitIfStatement(node);
1350 }
1351 Object visitTryStatement(TryStatement node) {
1352 safelyVisit(node.body);
1353 safelyVisit(node.finallyClause);
1354 NodeList<CatchClause> catchClauses = node.catchClauses;
1355 int numOfCatchClauses = catchClauses.length;
1356 List<Type2> visitedTypes = new List<Type2>();
1357 for (int i = 0; i < numOfCatchClauses; i++) {
1358 CatchClause catchClause = catchClauses[i];
1359 if (catchClause.onKeyword != null) {
1360 TypeName typeName = catchClause.exceptionType;
1361 if (typeName != null && typeName.type != null) {
1362 Type2 currentType = typeName.type;
1363 if (currentType.isObject) {
1364 safelyVisit(catchClause);
1365 if (i + 1 != numOfCatchClauses) {
1366 CatchClause nextCatchClause = catchClauses[i + 1];
1367 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1368 int offset = nextCatchClause.offset;
1369 int length = lastCatchClause.end - offset;
1370 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CAT CH, offset, length, []);
1371 return null;
1372 }
1373 }
1374 for (Type2 type in visitedTypes) {
1375 if (currentType.isSubtypeOf(type)) {
1376 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1377 int offset = catchClause.offset;
1378 int length = lastCatchClause.end - offset;
1379 _errorReporter.reportError3(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, o ffset, length, [currentType.displayName, type.displayName]);
1380 return null;
1381 }
1382 }
1383 visitedTypes.add(currentType);
1384 }
1385 safelyVisit(catchClause);
1386 } else {
1387 safelyVisit(catchClause);
1388 if (i + 1 != numOfCatchClauses) {
1389 CatchClause nextCatchClause = catchClauses[i + 1];
1390 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1];
1391 int offset = nextCatchClause.offset;
1392 int length = lastCatchClause.end - offset;
1393 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length, []);
1394 return null;
1395 }
1396 }
1397 }
1398 return null;
1399 }
1400 Object visitWhileStatement(WhileStatement node) {
1401 Expression conditionExpression = node.condition;
1402 safelyVisit(conditionExpression);
1403 ValidResult result = getConstantBooleanValue(conditionExpression);
1404 if (result != null) {
1405 if (identical(result, ValidResult.RESULT_FALSE)) {
1406 _errorReporter.reportError2(HintCode.DEAD_CODE, node.body, []);
1407 return null;
1408 }
1409 }
1410 safelyVisit(node.body);
1411 return null;
1412 }
1413
1414 /**
1415 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i t is
1416 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the
1417 * expression is not a constant boolean value.
1418 *
1419 * @param expression the expression to evaluate
1420 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS E]
1421 * if it is `false`, or `null` if the expression is not a constant boo lean
1422 * value
1423 */
1424 ValidResult getConstantBooleanValue(Expression expression) {
1425 if (expression is BooleanLiteral) {
1426 if (((expression as BooleanLiteral)).value) {
1427 return ValidResult.RESULT_TRUE;
1428 } else {
1429 return ValidResult.RESULT_FALSE;
1430 }
1431 } else {
1432 EvaluationResultImpl result = expression.accept(new ConstantVisitor());
1433 if (identical(result, ValidResult.RESULT_TRUE)) {
1434 return ValidResult.RESULT_TRUE;
1435 } else if (identical(result, ValidResult.RESULT_FALSE)) {
1436 return ValidResult.RESULT_FALSE;
1437 }
1438 return null;
1439 }
1440 }
1441
1442 /**
1443 * If the given node is not `null`, visit this instance of the dead code verif ier.
1444 *
1445 * @param node the node to be visited
1446 */
1447 void safelyVisit(ASTNode node) {
1448 if (node != null) {
1449 node.accept(this);
1450 }
1451 }
1452 }
1453 /**
1454 * Instances of the class `HintGenerator` traverse a library's worth of dart cod e at a time to
1455 * generate hints over the set of sources.
1456 *
1457 * @see HintCode
1458 * @coverage dart.engine.resolver
1459 */
1460 class HintGenerator {
1461 List<CompilationUnit> _compilationUnits;
1462 AnalysisContext _context;
1463 AnalysisErrorListener _errorListener;
1464 ImportsVerifier _importsVerifier;
1465 DeadCodeVerifier _deadCodeVerifier;
1466 HintGenerator(List<CompilationUnit> compilationUnits, AnalysisContext context, AnalysisErrorListener errorListener) {
1467 this._compilationUnits = compilationUnits;
1468 this._context = context;
1469 this._errorListener = errorListener;
1470 LibraryElement library = compilationUnits[0].element.library;
1471 _importsVerifier = new ImportsVerifier(library);
1472 }
1473 void generateForLibrary() {
1474 for (int i = 0; i < _compilationUnits.length; i++) {
1475 CompilationUnitElement element = _compilationUnits[i].element;
1476 if (element != null) {
1477 if (i == 0) {
1478 _importsVerifier.inDefiningCompilationUnit = true;
1479 generateForCompilationUnit(_compilationUnits[i], element.source);
1480 _importsVerifier.inDefiningCompilationUnit = false;
1481 } else {
1482 generateForCompilationUnit(_compilationUnits[i], element.source);
1483 }
1484 }
1485 }
1486 _importsVerifier.generateUnusedImportHints(new ErrorReporter(_errorListener, _compilationUnits[0].element.source));
1487 }
1488 void generateForCompilationUnit(CompilationUnit unit, Source source) {
1489 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
1490 _importsVerifier.visitCompilationUnit(unit);
1491 _deadCodeVerifier = new DeadCodeVerifier(errorReporter);
1492 _deadCodeVerifier.visitCompilationUnit(unit);
1493 }
1494 }
1495 /**
1496 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the
1497 * source code verifying that all of the imports are used, otherwise a
1498 * [HintCode#UNUSED_IMPORT] is generated with
1499 * [generateUnusedImportHints].
1500 *
1501 * While this class does not yet have support for an "Organize Imports" action, this logic built up
1502 * in this class could be used for such an action in the future.
1503 *
1504 * @coverage dart.engine.resolver
1505 */
1506 class ImportsVerifier extends RecursiveASTVisitor<Object> {
1507
1508 /**
1509 * This is set to `true` if the current compilation unit which is being visite d is the
1510 * defining compilation unit for the library, its value can be set with
1511 * [setInDefiningCompilationUnit].
1512 */
1513 bool _inDefiningCompilationUnit = false;
1514
1515 /**
1516 * The current library.
1517 */
1518 LibraryElement _currentLibrary;
1519
1520 /**
1521 * A list of [ImportDirective]s that the current library imports, as identifie rs are visited
1522 * by this visitor and an import has been identified as being used by the libr ary, the
1523 * [ImportDirective] is removed from this list. After all the sources in the l ibrary have
1524 * been evaluated, this list represents the set of unused imports.
1525 *
1526 * @see ImportsVerifier#generateUnusedImportErrors(ErrorReporter)
1527 */
1528 List<ImportDirective> _unusedImports;
1529
1530 /**
1531 * This is a map between the set of [LibraryElement]s that the current library imports, and
1532 * a list of [ImportDirective]s that imports the library. In cases where the c urrent library
1533 * imports a library with a single directive (such as `import lib1.dart;`), th e library
1534 * element will map to a list of one [ImportDirective], which will then be rem oved from the
1535 * [unusedImports] list. In cases where the current library imports a library with multiple
1536 * directives (such as `import lib1.dart; import lib1.dart show C;`), the
1537 * [LibraryElement] will be mapped to a list of the import directives, and the namespace
1538 * will need to be used to compute the correct [ImportDirective] being used, s ee
1539 * [namespaceMap].
1540 */
1541 Map<LibraryElement, List<ImportDirective>> _libraryMap;
1542
1543 /**
1544 * In cases where there is more than one import directive per library element, this mapping is
1545 * used to determine which of the multiple import directives are used by gener ating a
1546 * [Namespace] for each of the imports to do lookups in the same way that they are done from
1547 * the [ElementResolver].
1548 */
1549 Map<ImportDirective, Namespace> _namespaceMap;
1550
1551 /**
1552 * This is a map between prefix elements and the import directive from which t hey are derived. In
1553 * cases where a type is referenced via a prefix element, the import directive can be marked as
1554 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`,
1555 * instead of looking at which library the `lib.X` resolves.
1556 */
1557 Map<PrefixElement, ImportDirective> _prefixElementMap;
1558
1559 /**
1560 * Create a new instance of the [ImportsVerifier].
1561 *
1562 * @param errorReporter the error reporter
1563 */
1564 ImportsVerifier(LibraryElement library) {
1565 this._currentLibrary = library;
1566 this._unusedImports = new List<ImportDirective>();
1567 this._libraryMap = new Map<LibraryElement, List<ImportDirective>>();
1568 this._namespaceMap = new Map<ImportDirective, Namespace>();
1569 this._prefixElementMap = new Map<PrefixElement, ImportDirective>();
1570 }
1571
1572 /**
1573 * After all of the compilation units have been visited by this visitor, this method can be called
1574 * to report an [HintCode#UNUSED_IMPORT] hint for each of the import directive s in the
1575 * [unusedImports] list.
1576 *
1577 * @param errorReporter the error reporter to report the set of [HintCode#UNUS ED_IMPORT]
1578 * hints to
1579 */
1580 void generateUnusedImportHints(ErrorReporter errorReporter) {
1581 for (ImportDirective unusedImport in _unusedImports) {
1582 errorReporter.reportError2(HintCode.UNUSED_IMPORT, unusedImport.uri, []);
1583 }
1584 }
1585 Object visitCompilationUnit(CompilationUnit node) {
1586 if (_inDefiningCompilationUnit) {
1587 NodeList<Directive> directives = node.directives;
1588 for (Directive directive in directives) {
1589 if (directive is ImportDirective) {
1590 ImportDirective importDirective = directive as ImportDirective;
1591 LibraryElement libraryElement = importDirective.uriElement;
1592 if (libraryElement != null) {
1593 _unusedImports.add(importDirective);
1594 if (importDirective.asToken != null) {
1595 SimpleIdentifier prefixIdentifier = importDirective.prefix;
1596 if (prefixIdentifier != null) {
1597 Element element = prefixIdentifier.element;
1598 if (element is PrefixElement) {
1599 PrefixElement prefixElementKey = element as PrefixElement;
1600 _prefixElementMap[prefixElementKey] = importDirective;
1601 }
1602 }
1603 }
1604 putIntoLibraryMap(libraryElement, importDirective);
1605 addAdditionalLibrariesForExports(_libraryMap, libraryElement, import Directive, new List<LibraryElement>());
1606 }
1607 }
1608 }
1609 }
1610 if (_unusedImports.isEmpty) {
1611 return null;
1612 }
1613 return super.visitCompilationUnit(node);
1614 }
1615 Object visitExportDirective(ExportDirective node) => null;
1616 Object visitImportDirective(ImportDirective node) => null;
1617 Object visitLibraryDirective(LibraryDirective node) => null;
1618 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
1619 SimpleIdentifier prefixIdentifier = node.prefix;
1620 Element element = prefixIdentifier.element;
1621 if (element is PrefixElement) {
1622 _unusedImports.remove(_prefixElementMap[element]);
1623 return null;
1624 }
1625 return visitIdentifier(element, prefixIdentifier.name);
1626 }
1627 Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.el ement, node.name);
1628 void set inDefiningCompilationUnit(bool inDefiningCompilationUnit2) {
1629 this._inDefiningCompilationUnit = inDefiningCompilationUnit2;
1630 }
1631
1632 /**
1633 * Recursively add any exported library elements into the [libraryMap].
1634 */
1635 void addAdditionalLibrariesForExports(Map<LibraryElement, List<ImportDirective >> map, LibraryElement library, ImportDirective importDirective, List<LibraryEle ment> exportPath) {
1636 if (exportPath.contains(library)) {
1637 return;
1638 }
1639 for (LibraryElement exportedLibraryElt in library.exportedLibraries) {
1640 putIntoLibraryMap(exportedLibraryElt, importDirective);
1641 exportPath.add(exportedLibraryElt);
1642 addAdditionalLibrariesForExports(map, exportedLibraryElt, importDirective, exportPath);
1643 }
1644 }
1645
1646 /**
1647 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not
1648 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not
1649 * resolved or is not resolvable, `null` is returned.
1650 *
1651 * @param importDirective the import directive used to compute the returned na mespace
1652 * @return the computed or looked up [Namespace]
1653 */
1654 Namespace computeNamespace(ImportDirective importDirective) {
1655 Namespace namespace = _namespaceMap[importDirective];
1656 if (namespace == null) {
1657 ImportElement importElement = importDirective.element as ImportElement;
1658 if (importElement != null) {
1659 NamespaceBuilder builder = new NamespaceBuilder();
1660 namespace = builder.createImportNamespace(importElement);
1661 _namespaceMap[importDirective] = namespace;
1662 }
1663 }
1664 return namespace;
1665 }
1666
1667 /**
1668 * The [libraryMap] is a mapping between a library elements and a list of impo rt
1669 * directives, but when adding these mappings into the [libraryMap], this meth od can be
1670 * used to simply add the mapping between the library element an an import dir ective without
1671 * needing to check to see if a list needs to be created.
1672 */
1673 void putIntoLibraryMap(LibraryElement libraryElement, ImportDirective importDi rective) {
1674 List<ImportDirective> importList = _libraryMap[libraryElement];
1675 if (importList == null) {
1676 importList = new List<ImportDirective>();
1677 _libraryMap[libraryElement] = importList;
1678 }
1679 importList.add(importDirective);
1680 }
1681 Object visitIdentifier(Element element, String name) {
1682 if (element == null) {
1683 return null;
1684 }
1685 if (element is MultiplyDefinedElement) {
1686 MultiplyDefinedElement multiplyDefinedElement = element as MultiplyDefined Element;
1687 for (Element elt in multiplyDefinedElement.conflictingElements) {
1688 visitIdentifier(elt, name);
1689 }
1690 return null;
1691 }
1692 LibraryElement containingLibrary = element.library;
1693 if (containingLibrary == null) {
1694 return null;
1695 }
1696 if (_currentLibrary == containingLibrary) {
1697 return null;
1698 }
1699 List<ImportDirective> importsFromSameLibrary = _libraryMap[containingLibrary ];
1700 if (importsFromSameLibrary == null) {
1701 return null;
1702 }
1703 if (importsFromSameLibrary.length == 1) {
1704 ImportDirective usedImportDirective = importsFromSameLibrary[0];
1705 _unusedImports.remove(usedImportDirective);
1706 } else {
1707 for (ImportDirective importDirective in importsFromSameLibrary) {
1708 Namespace namespace = computeNamespace(importDirective);
1709 if (namespace != null && namespace.get(name) != null) {
1710 _unusedImports.remove(importDirective);
1711 }
1712 }
1713 }
1714 return null;
1715 }
1716 }
1717 /**
1718 * Instances of the class `PubVerifier` traverse an AST structure looking for de viations from
1719 * pub best practices.
1720 */
1721 class PubVerifier extends RecursiveASTVisitor<Object> {
1722 static String _PUBSPEC_YAML = "pubspec.yaml";
1723
1724 /**
1725 * The analysis context containing the sources to be analyzed
1726 */
1727 AnalysisContext _context;
1728
1729 /**
1730 * The error reporter by which errors will be reported.
1731 */
1732 ErrorReporter _errorReporter;
1733 PubVerifier(AnalysisContext context, ErrorReporter errorReporter) {
1734 this._context = context;
1735 this._errorReporter = errorReporter;
1736 }
1737 Object visitImportDirective(ImportDirective directive) {
1738 return null;
1739 }
1740
1741 /**
1742 * This verifies that the passed file import directive is not contained in a s ource inside a
1743 * package "lib" directory hierarchy referencing a source outside that package "lib" directory
1744 * hierarchy.
1745 *
1746 * @param uriLiteral the import URL (not `null`)
1747 * @param path the file path being verified (not `null`)
1748 * @return `true` if and only if an error code is generated on the passed node
1749 * @see PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE
1750 */
1751 bool checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLiteral , String path) {
1752 Source source = getSource(uriLiteral);
1753 String fullName = getSourceFullName(source);
1754 if (fullName != null) {
1755 int pathIndex = 0;
1756 int fullNameIndex = fullName.length;
1757 while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) {
1758 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex);
1759 if (fullNameIndex < 4) {
1760 return false;
1761 }
1762 if (JavaString.startsWithBefore(fullName, "/lib", fullNameIndex - 4)) {
1763 String relativePubspecPath = path.substring(0, pathIndex + 3) + _PUBSP EC_YAML;
1764 Source pubspecSource = _context.sourceFactory.resolveUri(source, relat ivePubspecPath);
1765 if (pubspecSource.exists()) {
1766 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_INSIDE_LIB _REFERENCES_FILE_OUTSIDE, uriLiteral, []);
1767 }
1768 return true;
1769 }
1770 pathIndex += 3;
1771 }
1772 }
1773 return false;
1774 }
1775
1776 /**
1777 * This verifies that the passed file import directive is not contained in a s ource outside a
1778 * package "lib" directory hierarchy referencing a source inside that package "lib" directory
1779 * hierarchy.
1780 *
1781 * @param uriLiteral the import URL (not `null`)
1782 * @param path the file path being verified (not `null`)
1783 * @return `true` if and only if an error code is generated on the passed node
1784 * @see PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE
1785 */
1786 bool checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLiteral , String path) {
1787 if (path.startsWith("lib/")) {
1788 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, 0) ) {
1789 return true;
1790 }
1791 }
1792 int pathIndex = path.indexOf("/lib/");
1793 while (pathIndex != -1) {
1794 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, pa thIndex + 1)) {
1795 return true;
1796 }
1797 pathIndex = JavaString.indexOf(path, "/lib/", pathIndex + 4);
1798 }
1799 return false;
1800 }
1801 bool checkForFileImportOutsideLibReferencesFileInside2(StringLiteral uriLitera l, String path, int pathIndex) {
1802 Source source = getSource(uriLiteral);
1803 String relativePubspecPath = path.substring(0, pathIndex) + _PUBSPEC_YAML;
1804 Source pubspecSource = _context.sourceFactory.resolveUri(source, relativePub specPath);
1805 if (!pubspecSource.exists()) {
1806 return false;
1807 }
1808 String fullName = getSourceFullName(source);
1809 if (fullName != null) {
1810 if (!fullName.contains("/lib/")) {
1811 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_RE FERENCES_FILE_INSIDE, uriLiteral, []);
1812 return true;
1813 }
1814 }
1815 return false;
1816 }
1817
1818 /**
1819 * This verifies that the passed package import directive does not contain ".. "
1820 *
1821 * @param uriLiteral the import URL (not `null`)
1822 * @param path the path to be validated (not `null`)
1823 * @return `true` if and only if an error code is generated on the passed node
1824 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
1825 */
1826 bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path ) {
1827 if (path.startsWith("../") || path.contains("/../")) {
1828 _errorReporter.reportError2(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_ DOT, uriLiteral, []);
1829 return true;
1830 }
1831 return false;
1832 }
1833
1834 /**
1835 * Answer the source associated with the compilation unit containing the given AST node.
1836 *
1837 * @param node the node (not `null`)
1838 * @return the source or `null` if it could not be determined
1839 */
1840 Source getSource(ASTNode node) {
1841 Source source = null;
1842 CompilationUnit unit = node.getAncestor(CompilationUnit);
1843 if (unit != null) {
1844 CompilationUnitElement element = unit.element;
1845 if (element != null) {
1846 source = element.source;
1847 }
1848 }
1849 return source;
1850 }
1851
1852 /**
1853 * Answer the full name of the given source. The returned value will have all
1854 * [File#separatorChar] replace by '/'.
1855 *
1856 * @param source the source
1857 * @return the full name or `null` if it could not be determined
1858 */
1859 String getSourceFullName(Source source) {
1860 if (source != null) {
1861 String fullName = source.fullName;
1862 if (fullName != null) {
1863 return fullName.replaceAll(r'\', '/');
1864 }
1865 }
1866 return null;
1867 }
1868 }
1869 /**
1251 * Instances of the class `DeclarationResolver` are used to resolve declarations in an AST 1870 * Instances of the class `DeclarationResolver` are used to resolve declarations in an AST
1252 * structure to already built elements. 1871 * structure to already built elements.
1253 */ 1872 */
1254 class DeclarationResolver extends RecursiveASTVisitor<Object> { 1873 class DeclarationResolver extends RecursiveASTVisitor<Object> {
1255 1874
1256 /** 1875 /**
1257 * The compilation unit containing the AST nodes being visited. 1876 * The compilation unit containing the AST nodes being visited.
1258 */ 1877 */
1259 CompilationUnitElement _enclosingUnit; 1878 CompilationUnitElement _enclosingUnit;
1260 1879
(...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after
1882 /** 2501 /**
1883 * The name of the method that can be implemented by a class to allow its inst ances to be invoked 2502 * The name of the method that can be implemented by a class to allow its inst ances to be invoked
1884 * as if they were a function. 2503 * as if they were a function.
1885 */ 2504 */
1886 static String CALL_METHOD_NAME = "call"; 2505 static String CALL_METHOD_NAME = "call";
1887 2506
1888 /** 2507 /**
1889 * The name of the method that will be invoked if an attempt is made to invoke an undefined method 2508 * The name of the method that will be invoked if an attempt is made to invoke an undefined method
1890 * on an object. 2509 * on an object.
1891 */ 2510 */
1892 static String _NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod"; 2511 static String NO_SUCH_METHOD_METHOD_NAME = "noSuchMethod";
1893 2512
1894 /** 2513 /**
1895 * Initialize a newly created visitor to resolve the nodes in a compilation un it. 2514 * Initialize a newly created visitor to resolve the nodes in a compilation un it.
1896 * 2515 *
1897 * @param resolver the resolver driving this participant 2516 * @param resolver the resolver driving this participant
1898 */ 2517 */
1899 ElementResolver(ResolverVisitor resolver) { 2518 ElementResolver(ResolverVisitor resolver) {
1900 this._resolver = resolver; 2519 this._resolver = resolver;
1901 _strictMode = resolver.definingLibrary.context.analysisOptions.strictMode; 2520 _strictMode = resolver.definingLibrary.context.analysisOptions.strictMode;
1902 } 2521 }
1903 Object visitAssignmentExpression(AssignmentExpression node) { 2522 Object visitAssignmentExpression(AssignmentExpression node) {
1904 sc.Token operator = node.operator; 2523 sc.Token operator = node.operator;
1905 sc.TokenType operatorType = operator.type; 2524 sc.TokenType operatorType = operator.type;
1906 if (operatorType != sc.TokenType.EQ) { 2525 if (operatorType != sc.TokenType.EQ) {
1907 operatorType = operatorFromCompoundAssignment(operatorType); 2526 operatorType = operatorFromCompoundAssignment(operatorType);
1908 Expression leftHandSide = node.leftHandSide; 2527 Expression leftHandSide = node.leftHandSide;
1909 if (leftHandSide != null) { 2528 if (leftHandSide != null) {
1910 String methodName = operatorType.lexeme; 2529 String methodName = operatorType.lexeme;
1911 Type2 staticType = getStaticType(leftHandSide); 2530 Type2 staticType = getStaticType(leftHandSide);
1912 MethodElement staticMethod = lookUpMethod(leftHandSide, staticType, meth odName); 2531 MethodElement staticMethod = lookUpMethod(leftHandSide, staticType, meth odName);
1913 node.staticElement = staticMethod; 2532 node.staticElement = staticMethod;
1914 Type2 propagatedType = getPropagatedType(leftHandSide); 2533 Type2 propagatedType = getPropagatedType(leftHandSide);
1915 MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedTy pe, methodName); 2534 MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedTy pe, methodName);
1916 node.element = select2(staticMethod, propagatedMethod); 2535 node.propagatedElement = propagatedMethod;
1917 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagate dMethod))) { 2536 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagate dMethod))) {
1918 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_METHOD, operato r, [methodName, staticType.displayName]); 2537 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_METHOD, operato r, [methodName, staticType.displayName]);
1919 } 2538 }
1920 } 2539 }
1921 } 2540 }
1922 return null; 2541 return null;
1923 } 2542 }
1924 Object visitBinaryExpression(BinaryExpression node) { 2543 Object visitBinaryExpression(BinaryExpression node) {
1925 sc.Token operator = node.operator; 2544 sc.Token operator = node.operator;
1926 if (operator.isUserDefinableOperator) { 2545 if (operator.isUserDefinableOperator) {
1927 Expression leftOperand = node.leftOperand; 2546 Expression leftOperand = node.leftOperand;
1928 if (leftOperand != null) { 2547 if (leftOperand != null) {
1929 String methodName = operator.lexeme; 2548 String methodName = operator.lexeme;
1930 Type2 staticType = getStaticType(leftOperand); 2549 Type2 staticType = getStaticType(leftOperand);
1931 MethodElement staticMethod = lookUpMethod(leftOperand, staticType, metho dName); 2550 MethodElement staticMethod = lookUpMethod(leftOperand, staticType, metho dName);
1932 node.staticElement = staticMethod; 2551 node.staticElement = staticMethod;
1933 Type2 propagatedType = getPropagatedType(leftOperand); 2552 Type2 propagatedType = getPropagatedType(leftOperand);
1934 MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedTyp e, methodName); 2553 MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedTyp e, methodName);
1935 node.element = select2(staticMethod, propagatedMethod); 2554 node.propagatedElement = propagatedMethod;
1936 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagate dMethod))) { 2555 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagate dMethod))) {
1937 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, opera tor, [methodName, staticType.displayName]); 2556 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, opera tor, [methodName, staticType.displayName]);
1938 } 2557 }
1939 } 2558 }
1940 } 2559 }
1941 return null; 2560 return null;
1942 } 2561 }
1943 Object visitBreakStatement(BreakStatement node) { 2562 Object visitBreakStatement(BreakStatement node) {
1944 SimpleIdentifier labelNode = node.label; 2563 SimpleIdentifier labelNode = node.label;
1945 LabelElementImpl labelElement = lookupLabel(node, labelNode); 2564 LabelElementImpl labelElement = lookupLabel(node, labelNode);
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 } else { 2847 } else {
2229 Type2 targetType = getStaticType(target); 2848 Type2 targetType = getStaticType(target);
2230 staticElement = resolveInvokedElement(target, targetType, methodName); 2849 staticElement = resolveInvokedElement(target, targetType, methodName);
2231 propagatedElement = resolveInvokedElement(target, getPropagatedType(target ), methodName); 2850 propagatedElement = resolveInvokedElement(target, getPropagatedType(target ), methodName);
2232 } 2851 }
2233 staticElement = convertSetterToGetter(staticElement); 2852 staticElement = convertSetterToGetter(staticElement);
2234 propagatedElement = convertSetterToGetter(propagatedElement); 2853 propagatedElement = convertSetterToGetter(propagatedElement);
2235 recordResolution2(methodName, staticElement, propagatedElement); 2854 recordResolution2(methodName, staticElement, propagatedElement);
2236 ArgumentList argumentList = node.argumentList; 2855 ArgumentList argumentList = node.argumentList;
2237 if (staticElement != null) { 2856 if (staticElement != null) {
2238 List<ParameterElement> parameters = computePropagatedParameters(argumentLi st, staticElement); 2857 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, staticElement);
2239 if (parameters != null) { 2858 if (parameters != null) {
2240 argumentList.correspondingStaticParameters = parameters; 2859 argumentList.correspondingStaticParameters = parameters;
2241 } 2860 }
2242 } 2861 }
2243 if (propagatedElement != null) { 2862 if (propagatedElement != null) {
2244 List<ParameterElement> parameters = computePropagatedParameters(argumentLi st, propagatedElement); 2863 List<ParameterElement> parameters = computeCorrespondingParameters(argumen tList, propagatedElement);
2245 if (parameters != null) { 2864 if (parameters != null) {
2246 argumentList.correspondingParameters = parameters; 2865 argumentList.correspondingPropagatedParameters = parameters;
2247 } 2866 }
2248 } 2867 }
2249 ErrorCode errorCode = checkForInvocationError(target, staticElement); 2868 ErrorCode errorCode = checkForInvocationError(target, staticElement);
2250 if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) { 2869 if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) {
2251 _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, me thodName, [methodName.name]); 2870 _resolver.reportError(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, me thodName, [methodName.name]);
2252 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) { 2871 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_FUNCTION)) {
2253 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_FUNCTION, methodName , [methodName.name]); 2872 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_FUNCTION, methodName , [methodName.name]);
2254 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) { 2873 } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_METHOD)) {
2255 String targetTypeName; 2874 String targetTypeName;
2256 if (target == null) { 2875 if (target == null) {
(...skipping 26 matching lines...) Expand all
2283 return null; 2902 return null;
2284 } 2903 }
2285 Object visitPostfixExpression(PostfixExpression node) { 2904 Object visitPostfixExpression(PostfixExpression node) {
2286 Expression operand = node.operand; 2905 Expression operand = node.operand;
2287 String methodName = getPostfixOperator(node); 2906 String methodName = getPostfixOperator(node);
2288 Type2 staticType = getStaticType(operand); 2907 Type2 staticType = getStaticType(operand);
2289 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName); 2908 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName);
2290 node.staticElement = staticMethod; 2909 node.staticElement = staticMethod;
2291 Type2 propagatedType = getPropagatedType(operand); 2910 Type2 propagatedType = getPropagatedType(operand);
2292 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, metho dName); 2911 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, metho dName);
2293 node.element = select2(staticMethod, propagatedMethod); 2912 node.propagatedElement = propagatedMethod;
2294 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || p ropagatedType == null || shouldReportMissingMember(propagatedType, propagatedMet hod))) { 2913 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || p ropagatedType == null || shouldReportMissingMember(propagatedType, propagatedMet hod))) {
2295 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, node.oper ator, [methodName, staticType.displayName]); 2914 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, node.oper ator, [methodName, staticType.displayName]);
2296 } 2915 }
2297 return null; 2916 return null;
2298 } 2917 }
2299 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 2918 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
2300 SimpleIdentifier prefix = node.prefix; 2919 SimpleIdentifier prefix = node.prefix;
2301 SimpleIdentifier identifier = node.identifier; 2920 SimpleIdentifier identifier = node.identifier;
2302 Element prefixElement = prefix.element; 2921 Element prefixElement = prefix.element;
2303 if (prefixElement is PrefixElement) { 2922 if (prefixElement is PrefixElement) {
(...skipping 30 matching lines...) Expand all
2334 sc.Token operator = node.operator; 2953 sc.Token operator = node.operator;
2335 sc.TokenType operatorType = operator.type; 2954 sc.TokenType operatorType = operator.type;
2336 if (operatorType.isUserDefinableOperator || identical(operatorType, sc.Token Type.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) { 2955 if (operatorType.isUserDefinableOperator || identical(operatorType, sc.Token Type.PLUS_PLUS) || identical(operatorType, sc.TokenType.MINUS_MINUS)) {
2337 Expression operand = node.operand; 2956 Expression operand = node.operand;
2338 String methodName = getPrefixOperator(node); 2957 String methodName = getPrefixOperator(node);
2339 Type2 staticType = getStaticType(operand); 2958 Type2 staticType = getStaticType(operand);
2340 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName) ; 2959 MethodElement staticMethod = lookUpMethod(operand, staticType, methodName) ;
2341 node.staticElement = staticMethod; 2960 node.staticElement = staticMethod;
2342 Type2 propagatedType = getPropagatedType(operand); 2961 Type2 propagatedType = getPropagatedType(operand);
2343 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, met hodName); 2962 MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, met hodName);
2344 node.element = select2(staticMethod, propagatedMethod); 2963 node.propagatedElement = propagatedMethod;
2345 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedM ethod))) { 2964 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedM ethod))) {
2346 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, operato r, [methodName, staticType.displayName]); 2965 _resolver.reportError6(StaticTypeWarningCode.UNDEFINED_OPERATOR, operato r, [methodName, staticType.displayName]);
2347 } 2966 }
2348 } 2967 }
2349 return null; 2968 return null;
2350 } 2969 }
2351 Object visitPropertyAccess(PropertyAccess node) { 2970 Object visitPropertyAccess(PropertyAccess node) {
2352 Expression target = node.realTarget; 2971 Expression target = node.realTarget;
2353 if (target is SuperExpression && !isSuperInValidContext((target as SuperExpr ession))) { 2972 if (target is SuperExpression && !isSuperInValidContext((target as SuperExpr ession))) {
2354 return null; 2973 return null;
(...skipping 23 matching lines...) Expand all
2378 node.staticElement = element; 2997 node.staticElement = element;
2379 node.element = element; 2998 node.element = element;
2380 ArgumentList argumentList = node.argumentList; 2999 ArgumentList argumentList = node.argumentList;
2381 List<ParameterElement> parameters = resolveArgumentsToParameters(false, argu mentList, element); 3000 List<ParameterElement> parameters = resolveArgumentsToParameters(false, argu mentList, element);
2382 if (parameters != null) { 3001 if (parameters != null) {
2383 argumentList.correspondingStaticParameters = parameters; 3002 argumentList.correspondingStaticParameters = parameters;
2384 } 3003 }
2385 return null; 3004 return null;
2386 } 3005 }
2387 Object visitSimpleIdentifier(SimpleIdentifier node) { 3006 Object visitSimpleIdentifier(SimpleIdentifier node) {
2388 if (node.element != null) { 3007 if (node.staticElement != null || node.element != null) {
2389 return null; 3008 return null;
2390 } 3009 }
2391 Element element = resolveSimpleIdentifier(node); 3010 Element element = resolveSimpleIdentifier(node);
2392 if (isFactoryConstructorReturnType(node) && element != _resolver.enclosingCl ass) { 3011 if (isFactoryConstructorReturnType(node) && element != _resolver.enclosingCl ass) {
2393 _resolver.reportError(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLAS S, node, []); 3012 _resolver.reportError(CompileTimeErrorCode.INVALID_FACTORY_NAME_NOT_A_CLAS S, node, []);
2394 } else if (element == null) { 3013 } else if (element == null || (element is PrefixElement && !isValidAsPrefix( node))) {
2395 if (isConstructorReturnType(node)) { 3014 if (isConstructorReturnType(node)) {
2396 _resolver.reportError(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, nod e, []); 3015 _resolver.reportError(CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, nod e, []);
2397 } else if (!classDeclaresNoSuchMethod(_resolver.enclosingClass)) { 3016 } else {
2398 _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, node, [nod e.name]); 3017 _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, node, [nod e.name]);
2399 } 3018 }
2400 } 3019 }
2401 recordResolution(node, element); 3020 recordResolution(node, element);
2402 if (node.parent is Annotation) { 3021 if (node.parent is Annotation) {
2403 Annotation annotation = node.parent as Annotation; 3022 Annotation annotation = node.parent as Annotation;
2404 resolveAnnotationElement(annotation, element, null); 3023 resolveAnnotationElement(annotation, element, null);
2405 } 3024 }
2406 return null; 3025 return null;
2407 } 3026 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2484 } 3103 }
2485 3104
2486 /** 3105 /**
2487 * Given that we have found code to invoke the given element, return the error code that should be 3106 * Given that we have found code to invoke the given element, return the error code that should be
2488 * reported, or `null` if no error should be reported. 3107 * reported, or `null` if no error should be reported.
2489 * 3108 *
2490 * @param target the target of the invocation, or `null` if there was no targe t 3109 * @param target the target of the invocation, or `null` if there was no targe t
2491 * @param element the element to be invoked 3110 * @param element the element to be invoked
2492 * @return the error code that should be reported 3111 * @return the error code that should be reported
2493 */ 3112 */
2494 ErrorCode checkForInvocationError(Expression target, Element element2) { 3113 ErrorCode checkForInvocationError(Expression target, Element element) {
2495 if (element2 is PropertyAccessorElement) { 3114 if (element is PropertyAccessorElement) {
2496 FunctionType getterType = ((element2 as PropertyAccessorElement)).type; 3115 FunctionType getterType = ((element as PropertyAccessorElement)).type;
2497 if (getterType != null) { 3116 if (getterType != null) {
2498 Type2 returnType = getterType.returnType; 3117 Type2 returnType = getterType.returnType;
2499 if (!isExecutableType(returnType)) { 3118 if (!isExecutableType(returnType)) {
2500 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 3119 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
2501 } 3120 }
2502 } 3121 }
2503 } else if (element2 is ExecutableElement) { 3122 } else if (element is ExecutableElement) {
2504 return null; 3123 return null;
2505 } else if (element2 == null && target is SuperExpression) { 3124 } else if (element == null && target is SuperExpression) {
2506 return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD; 3125 return StaticTypeWarningCode.UNDEFINED_SUPER_METHOD;
2507 } else { 3126 } else {
2508 if (element2 is PropertyInducingElement) { 3127 if (element is PropertyInducingElement) {
2509 PropertyAccessorElement getter = ((element2 as PropertyInducingElement)) .getter; 3128 PropertyAccessorElement getter = ((element as PropertyInducingElement)). getter;
2510 FunctionType getterType = getter.type; 3129 FunctionType getterType = getter.type;
2511 if (getterType != null) { 3130 if (getterType != null) {
2512 Type2 returnType = getterType.returnType; 3131 Type2 returnType = getterType.returnType;
2513 if (!isExecutableType(returnType)) { 3132 if (!isExecutableType(returnType)) {
2514 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 3133 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
2515 } 3134 }
2516 } 3135 }
2517 } else if (element2 is VariableElement) { 3136 } else if (element is VariableElement) {
2518 Type2 variableType = ((element2 as VariableElement)).type; 3137 Type2 variableType = ((element as VariableElement)).type;
2519 if (!isExecutableType(variableType)) { 3138 if (!isExecutableType(variableType)) {
2520 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 3139 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
2521 } 3140 }
2522 } else { 3141 } else {
2523 if (target == null) { 3142 if (target == null) {
2524 ClassElement enclosingClass = _resolver.enclosingClass; 3143 ClassElement enclosingClass = _resolver.enclosingClass;
2525 if (enclosingClass == null) { 3144 if (enclosingClass == null) {
2526 return StaticTypeWarningCode.UNDEFINED_FUNCTION; 3145 return StaticTypeWarningCode.UNDEFINED_FUNCTION;
2527 } else if (element2 == null) { 3146 } else if (element == null) {
2528 if (!classDeclaresNoSuchMethod(enclosingClass)) { 3147 return StaticTypeWarningCode.UNDEFINED_METHOD;
2529 return StaticTypeWarningCode.UNDEFINED_METHOD;
2530 }
2531 } else { 3148 } else {
2532 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; 3149 return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION;
2533 } 3150 }
2534 } else { 3151 } else {
2535 Type2 targetType = getStaticType(target); 3152 Type2 targetType = getStaticType(target);
2536 if (targetType == null) { 3153 if (targetType == null) {
2537 return StaticTypeWarningCode.UNDEFINED_FUNCTION; 3154 return StaticTypeWarningCode.UNDEFINED_FUNCTION;
2538 } else if (!targetType.isDynamic && !classDeclaresNoSuchMethod2(target Type.element)) { 3155 } else if (!targetType.isDynamic) {
2539 return StaticTypeWarningCode.UNDEFINED_METHOD; 3156 return StaticTypeWarningCode.UNDEFINED_METHOD;
2540 } 3157 }
2541 } 3158 }
2542 } 3159 }
2543 } 3160 }
2544 return null; 3161 return null;
2545 } 3162 }
2546 3163
2547 /** 3164 /**
2548 * Return `true` if the given class declares a method named "noSuchMethod" and is not the
2549 * class 'Object'.
2550 *
2551 * @param element the class being tested
2552 * @return `true` if the given class declares a method named "noSuchMethod"
2553 */
2554 bool classDeclaresNoSuchMethod(ClassElement classElement) {
2555 if (classElement == null) {
2556 return false;
2557 }
2558 MethodElement methodElement = classElement.lookUpMethod(_NO_SUCH_METHOD_METH OD_NAME, _resolver.definingLibrary);
2559 return methodElement != null && methodElement.enclosingElement.supertype != null;
2560 }
2561
2562 /**
2563 * Return `true` if the given element represents a class that declares a metho d named
2564 * "noSuchMethod" and is not the class 'Object'.
2565 *
2566 * @param element the element being tested
2567 * @return `true` if the given element represents a class that declares a meth od named
2568 * "noSuchMethod"
2569 */
2570 bool classDeclaresNoSuchMethod2(Element element) {
2571 if (element is ClassElement) {
2572 return classDeclaresNoSuchMethod((element as ClassElement));
2573 }
2574 return false;
2575 }
2576
2577 /**
2578 * Given a list of arguments and the element that will be invoked using those argument, compute 3165 * Given a list of arguments and the element that will be invoked using those argument, compute
2579 * the list of parameters that correspond to the list of arguments. Return the parameters that 3166 * the list of parameters that correspond to the list of arguments. Return the parameters that
2580 * correspond to the arguments, or `null` if no correspondence could be comput ed. 3167 * correspond to the arguments, or `null` if no correspondence could be comput ed.
2581 * 3168 *
2582 * @param argumentList the list of arguments being passed to the element 3169 * @param argumentList the list of arguments being passed to the element
2583 * @param executableElement the element that will be invoked with the argument s 3170 * @param executableElement the element that will be invoked with the argument s
2584 * @return the parameters that correspond to the arguments 3171 * @return the parameters that correspond to the arguments
2585 */ 3172 */
2586 List<ParameterElement> computePropagatedParameters(ArgumentList argumentList, Element element2) { 3173 List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentLis t, Element element2) {
2587 if (element2 is PropertyAccessorElement) { 3174 if (element2 is PropertyAccessorElement) {
2588 FunctionType getterType = ((element2 as PropertyAccessorElement)).type; 3175 FunctionType getterType = ((element2 as PropertyAccessorElement)).type;
2589 if (getterType != null) { 3176 if (getterType != null) {
2590 Type2 getterReturnType = getterType.returnType; 3177 Type2 getterReturnType = getterType.returnType;
2591 if (getterReturnType is InterfaceType) { 3178 if (getterReturnType is InterfaceType) {
2592 MethodElement callMethod = ((getterReturnType as InterfaceType)).lookU pMethod(CALL_METHOD_NAME, _resolver.definingLibrary); 3179 MethodElement callMethod = ((getterReturnType as InterfaceType)).lookU pMethod(CALL_METHOD_NAME, _resolver.definingLibrary);
2593 if (callMethod != null) { 3180 if (callMethod != null) {
2594 return resolveArgumentsToParameters(false, argumentList, callMethod) ; 3181 return resolveArgumentsToParameters(false, argumentList, callMethod) ;
2595 } 3182 }
2596 } else if (getterReturnType is FunctionType) { 3183 } else if (getterReturnType is FunctionType) {
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
2773 bool isStatic(Element element) { 3360 bool isStatic(Element element) {
2774 if (element is ExecutableElement) { 3361 if (element is ExecutableElement) {
2775 return ((element as ExecutableElement)).isStatic; 3362 return ((element as ExecutableElement)).isStatic;
2776 } else if (element is PropertyInducingElement) { 3363 } else if (element is PropertyInducingElement) {
2777 return ((element as PropertyInducingElement)).isStatic; 3364 return ((element as PropertyInducingElement)).isStatic;
2778 } 3365 }
2779 return false; 3366 return false;
2780 } 3367 }
2781 3368
2782 /** 3369 /**
3370 * Return `true` if the given node can validly be resolved to a prefix:
3371 *
3372 * * it is the prefix in an import directive, or
3373 * * it is the prefix in a prefixed identifier.
3374 *
3375 *
3376 * @param node the node being tested
3377 * @return `true` if the given node is the prefix in an import directive
3378 */
3379 bool isValidAsPrefix(SimpleIdentifier node) {
3380 ASTNode parent = node.parent;
3381 if (parent is ImportDirective) {
3382 return identical(((parent as ImportDirective)).prefix, node);
3383 } else if (parent is PrefixedIdentifier) {
3384 return true;
3385 } else if (parent is MethodInvocation) {
3386 return identical(((parent as MethodInvocation)).target, node);
3387 }
3388 return false;
3389 }
3390
3391 /**
2783 * Looks up the method element with the given name for index expression, repor ts 3392 * Looks up the method element with the given name for index expression, repor ts
2784 * [StaticWarningCode#UNDEFINED_OPERATOR] if not found. 3393 * [StaticWarningCode#UNDEFINED_OPERATOR] if not found.
2785 * 3394 *
2786 * @param node the index expression to resolve 3395 * @param node the index expression to resolve
2787 * @param target the target of the expression 3396 * @param target the target of the expression
2788 * @param methodName the name of the operator associated with the context of u sing of the given 3397 * @param methodName the name of the operator associated with the context of u sing of the given
2789 * index expression 3398 * index expression
2790 * @return `true` if and only if an error code is generated on the passed node 3399 * @return `true` if and only if an error code is generated on the passed node
2791 */ 3400 */
2792 bool lookUpCheckIndexOperator(IndexExpression node, Expression target, String methodName, Type2 staticType, Type2 propagatedType) { 3401 bool lookUpCheckIndexOperator(IndexExpression node, Expression target, String methodName, Type2 staticType, Type2 propagatedType) {
2793 MethodElement staticMethod = lookUpMethod(target, staticType, methodName); 3402 MethodElement staticMethod = lookUpMethod(target, staticType, methodName);
2794 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, method Name); 3403 MethodElement propagatedMethod = lookUpMethod(target, propagatedType, method Name);
2795 node.staticElement = staticMethod; 3404 node.staticElement = staticMethod;
2796 node.element = select2(staticMethod, propagatedMethod); 3405 node.propagatedElement = propagatedMethod;
2797 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || p ropagatedType == null || shouldReportMissingMember(propagatedType, propagatedMet hod))) { 3406 if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || p ropagatedType == null || shouldReportMissingMember(propagatedType, propagatedMet hod))) {
2798 sc.Token leftBracket = node.leftBracket; 3407 sc.Token leftBracket = node.leftBracket;
2799 sc.Token rightBracket = node.rightBracket; 3408 sc.Token rightBracket = node.rightBracket;
2800 if (leftBracket == null || rightBracket == null) { 3409 if (leftBracket == null || rightBracket == null) {
2801 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_OPERATOR, node, [m ethodName, staticType.displayName]); 3410 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_OPERATOR, node, [m ethodName, staticType.displayName]);
2802 return true; 3411 return true;
2803 } else { 3412 } else {
2804 int offset = leftBracket.offset; 3413 int offset = leftBracket.offset;
2805 int length = rightBracket.offset - offset + 1; 3414 int length = rightBracket.offset - offset + 1;
2806 _resolver.reportError5(StaticTypeWarningCode.UNDEFINED_OPERATOR, offset, length, [methodName, staticType.displayName]); 3415 _resolver.reportError5(StaticTypeWarningCode.UNDEFINED_OPERATOR, offset, length, [methodName, staticType.displayName]);
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
3308 List<ParameterElement> resolvedParameters = new List<ParameterElement>(argum entCount); 3917 List<ParameterElement> resolvedParameters = new List<ParameterElement>(argum entCount);
3309 int positionalArgumentCount = 0; 3918 int positionalArgumentCount = 0;
3310 Set<String> usedNames = new Set<String>(); 3919 Set<String> usedNames = new Set<String>();
3311 for (int i = 0; i < argumentCount; i++) { 3920 for (int i = 0; i < argumentCount; i++) {
3312 Expression argument = arguments[i]; 3921 Expression argument = arguments[i];
3313 if (argument is NamedExpression) { 3922 if (argument is NamedExpression) {
3314 SimpleIdentifier nameNode = ((argument as NamedExpression)).name.label; 3923 SimpleIdentifier nameNode = ((argument as NamedExpression)).name.label;
3315 String name = nameNode.name; 3924 String name = nameNode.name;
3316 ParameterElement element = namedParameters[name]; 3925 ParameterElement element = namedParameters[name];
3317 if (element == null) { 3926 if (element == null) {
3318 ErrorCode errorCode = reportError2 ? CompileTimeErrorCode.UNDEFINED_NA MED_PARAMETER : StaticWarningCode.UNDEFINED_NAMED_PARAMETER; 3927 ErrorCode errorCode = (reportError2 ? CompileTimeErrorCode.UNDEFINED_N AMED_PARAMETER : StaticWarningCode.UNDEFINED_NAMED_PARAMETER) as ErrorCode;
3319 _resolver.reportError(errorCode, nameNode, [name]); 3928 _resolver.reportError(errorCode, nameNode, [name]);
3320 } else { 3929 } else {
3321 resolvedParameters[i] = element; 3930 resolvedParameters[i] = element;
3322 recordResolution(nameNode, element); 3931 recordResolution(nameNode, element);
3323 } 3932 }
3324 if (!javaSetAdd(usedNames, name)) { 3933 if (!javaSetAdd(usedNames, name)) {
3325 _resolver.reportError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, n ameNode, [name]); 3934 _resolver.reportError(CompileTimeErrorCode.DUPLICATE_NAMED_ARGUMENT, n ameNode, [name]);
3326 } 3935 }
3327 } else { 3936 } else {
3328 positionalArgumentCount++; 3937 positionalArgumentCount++;
3329 if (unnamedIndex < unnamedParameterCount) { 3938 if (unnamedIndex < unnamedParameterCount) {
3330 resolvedParameters[i] = unnamedParameters[unnamedIndex++]; 3939 resolvedParameters[i] = unnamedParameters[unnamedIndex++];
3331 } 3940 }
3332 } 3941 }
3333 } 3942 }
3334 if (positionalArgumentCount < requiredParameters.length) { 3943 if (positionalArgumentCount < requiredParameters.length) {
3335 ErrorCode errorCode = reportError2 ? CompileTimeErrorCode.NOT_ENOUGH_REQUI RED_ARGUMENTS : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS; 3944 ErrorCode errorCode = (reportError2 ? CompileTimeErrorCode.NOT_ENOUGH_REQU IRED_ARGUMENTS : StaticWarningCode.NOT_ENOUGH_REQUIRED_ARGUMENTS) as ErrorCode;
3336 _resolver.reportError(errorCode, argumentList, [requiredParameters.length, positionalArgumentCount]); 3945 _resolver.reportError(errorCode, argumentList, [requiredParameters.length, positionalArgumentCount]);
3337 } else if (positionalArgumentCount > unnamedParameterCount) { 3946 } else if (positionalArgumentCount > unnamedParameterCount) {
3338 ErrorCode errorCode = reportError2 ? CompileTimeErrorCode.EXTRA_POSITIONAL _ARGUMENTS : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS; 3947 ErrorCode errorCode = (reportError2 ? CompileTimeErrorCode.EXTRA_POSITIONA L_ARGUMENTS : StaticWarningCode.EXTRA_POSITIONAL_ARGUMENTS) as ErrorCode;
3339 _resolver.reportError(errorCode, argumentList, [unnamedParameterCount, pos itionalArgumentCount]); 3948 _resolver.reportError(errorCode, argumentList, [unnamedParameterCount, pos itionalArgumentCount]);
3340 } 3949 }
3341 return resolvedParameters; 3950 return resolvedParameters;
3342 } 3951 }
3343 3952
3344 /** 3953 /**
3345 * Resolve the names in the given combinators in the scope of the given librar y. 3954 * Resolve the names in the given combinators in the scope of the given librar y.
3346 * 3955 *
3347 * @param library the library that defines the names 3956 * @param library the library that defines the names
3348 * @param combinators the combinators containing the names to be resolved 3957 * @param combinators the combinators containing the names to be resolved
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3455 recordResolution(propertyName, staticElement); 4064 recordResolution(propertyName, staticElement);
3456 } 4065 }
3457 return; 4066 return;
3458 } 4067 }
3459 propertyName.staticElement = staticElement; 4068 propertyName.staticElement = staticElement;
3460 Type2 propagatedType = getPropagatedType(target); 4069 Type2 propagatedType = getPropagatedType(target);
3461 ExecutableElement propagatedElement = resolveProperty(target, propagatedType , propertyName); 4070 ExecutableElement propagatedElement = resolveProperty(target, propagatedType , propertyName);
3462 Element selectedElement = select(staticElement, propagatedElement); 4071 Element selectedElement = select(staticElement, propagatedElement);
3463 propertyName.element = selectedElement; 4072 propertyName.element = selectedElement;
3464 if (shouldReportMissingMember(staticType, staticElement) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedEl ement))) { 4073 if (shouldReportMissingMember(staticType, staticElement) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedEl ement))) {
3465 bool staticNoSuchMethod = staticType != null && classDeclaresNoSuchMethod2 (staticType.element); 4074 bool isStaticProperty = isStatic(selectedElement);
3466 bool propagatedNoSuchMethod = propagatedType != null && classDeclaresNoSuc hMethod2(propagatedType.element); 4075 if (propertyName.inSetterContext()) {
3467 if (!staticNoSuchMethod && (_strictMode || !propagatedNoSuchMethod)) { 4076 if (isStaticProperty) {
3468 bool isStaticProperty = isStatic(selectedElement); 4077 _resolver.reportError(StaticWarningCode.UNDEFINED_SETTER, propertyName , [propertyName.name, staticType.displayName]);
3469 if (propertyName.inSetterContext()) {
3470 if (isStaticProperty) {
3471 _resolver.reportError(StaticWarningCode.UNDEFINED_SETTER, propertyNa me, [propertyName.name, staticType.displayName]);
3472 } else {
3473 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_SETTER, proper tyName, [propertyName.name, staticType.displayName]);
3474 }
3475 } else if (propertyName.inGetterContext()) {
3476 if (isStaticProperty) {
3477 _resolver.reportError(StaticWarningCode.UNDEFINED_GETTER, propertyNa me, [propertyName.name, staticType.displayName]);
3478 } else {
3479 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_GETTER, proper tyName, [propertyName.name, staticType.displayName]);
3480 }
3481 } else { 4078 } else {
3482 _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, property Name, [propertyName.name]); 4079 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_SETTER, property Name, [propertyName.name, staticType.displayName]);
3483 } 4080 }
4081 } else if (propertyName.inGetterContext()) {
4082 if (isStaticProperty) {
4083 _resolver.reportError(StaticWarningCode.UNDEFINED_GETTER, propertyName , [propertyName.name, staticType.displayName]);
4084 } else {
4085 _resolver.reportError(StaticTypeWarningCode.UNDEFINED_GETTER, property Name, [propertyName.name, staticType.displayName]);
4086 }
4087 } else {
4088 _resolver.reportError(StaticWarningCode.UNDEFINED_IDENTIFIER, propertyNa me, [propertyName.name]);
3484 } 4089 }
3485 } 4090 }
3486 } 4091 }
3487 4092
3488 /** 4093 /**
3489 * Resolve the given simple identifier if possible. Return the element to whic h it could be 4094 * Resolve the given simple identifier if possible. Return the element to whic h it could be
3490 * resolved, or `null` if it could not be resolved. This does not record the r esults of the 4095 * resolved, or `null` if it could not be resolved. This does not record the r esults of the
3491 * resolution. 4096 * resolution.
3492 * 4097 *
3493 * @param node the identifier to be resolved 4098 * @param node the identifier to be resolved
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3600 * given type and not finding any member. 4205 * given type and not finding any member.
3601 * 4206 *
3602 * @param type the type in which we attempted to perform the look-up 4207 * @param type the type in which we attempted to perform the look-up
3603 * @param member the result of the look-up 4208 * @param member the result of the look-up
3604 * @return `true` if we should report an error 4209 * @return `true` if we should report an error
3605 */ 4210 */
3606 bool shouldReportMissingMember(Type2 type, ExecutableElement member) { 4211 bool shouldReportMissingMember(Type2 type, ExecutableElement member) {
3607 if (member != null || type == null || type.isDynamic) { 4212 if (member != null || type == null || type.isDynamic) {
3608 return false; 4213 return false;
3609 } 4214 }
3610 if (type is InterfaceType) {
3611 return !classDeclaresNoSuchMethod(((type as InterfaceType)).element);
3612 }
3613 return true; 4215 return true;
3614 } 4216 }
3615 } 4217 }
3616 /** 4218 /**
3617 * Instances of the class `SyntheticIdentifier` implement an identifier that can be used to 4219 * Instances of the class `SyntheticIdentifier` implement an identifier that can be used to
3618 * look up names in the lexical scope when there is no identifier in the AST str ucture. There is 4220 * look up names in the lexical scope when there is no identifier in the AST str ucture. There is
3619 * no identifier in the AST when the parser could not distinguish between a meth od invocation and 4221 * no identifier in the AST when the parser could not distinguish between a meth od invocation and
3620 * an invocation of a top-level function imported with a prefix. 4222 * an invocation of a top-level function imported with a prefix.
3621 */ 4223 */
3622 class ElementResolver_SyntheticIdentifier extends Identifier { 4224 class ElementResolver_SyntheticIdentifier extends Identifier {
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
3919 */ 4521 */
3920 Map<String, ExecutableElement> computeInterfaceLookupMap(ClassElement classElt , Set<ClassElement> visitedInterfaces) { 4522 Map<String, ExecutableElement> computeInterfaceLookupMap(ClassElement classElt , Set<ClassElement> visitedInterfaces) {
3921 Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt]; 4523 Map<String, ExecutableElement> resultMap = _interfaceLookup[classElt];
3922 if (resultMap != null) { 4524 if (resultMap != null) {
3923 return resultMap; 4525 return resultMap;
3924 } else { 4526 } else {
3925 resultMap = new Map<String, ExecutableElement>(); 4527 resultMap = new Map<String, ExecutableElement>();
3926 } 4528 }
3927 InterfaceType supertype = classElt.supertype; 4529 InterfaceType supertype = classElt.supertype;
3928 ClassElement superclassElement = supertype != null ? supertype.element : nul l; 4530 ClassElement superclassElement = supertype != null ? supertype.element : nul l;
4531 List<InterfaceType> mixins = classElt.mixins;
3929 List<InterfaceType> interfaces = classElt.interfaces; 4532 List<InterfaceType> interfaces = classElt.interfaces;
3930 if ((superclassElement == null || supertype.isObject) && interfaces.length = = 0) { 4533 if ((superclassElement == null || supertype.isObject) && mixins.length == 0 && interfaces.length == 0) {
3931 _interfaceLookup[classElt] = resultMap; 4534 _interfaceLookup[classElt] = resultMap;
3932 return resultMap; 4535 return resultMap;
3933 } 4536 }
3934 List<Map<String, ExecutableElement>> lookupMaps = new List<Map<String, Execu tableElement>>(); 4537 List<Map<String, ExecutableElement>> lookupMaps = new List<Map<String, Execu tableElement>>();
3935 if (superclassElement != null) { 4538 if (superclassElement != null) {
3936 if (!visitedInterfaces.contains(superclassElement)) { 4539 if (!visitedInterfaces.contains(superclassElement)) {
3937 try { 4540 try {
3938 javaSetAdd(visitedInterfaces, superclassElement); 4541 javaSetAdd(visitedInterfaces, superclassElement);
3939 lookupMaps.add(computeInterfaceLookupMap(superclassElement, visitedInt erfaces)); 4542 lookupMaps.add(computeInterfaceLookupMap(superclassElement, visitedInt erfaces));
3940 } finally { 4543 } finally {
3941 visitedInterfaces.remove(superclassElement); 4544 visitedInterfaces.remove(superclassElement);
3942 } 4545 }
3943 } else { 4546 } else {
3944 Map<String, ExecutableElement> map = _interfaceLookup[classElt]; 4547 Map<String, ExecutableElement> map = _interfaceLookup[classElt];
3945 if (map != null) { 4548 if (map != null) {
3946 lookupMaps.add(map); 4549 lookupMaps.add(map);
3947 } else { 4550 } else {
3948 _interfaceLookup[superclassElement] = resultMap; 4551 _interfaceLookup[superclassElement] = resultMap;
3949 return resultMap; 4552 return resultMap;
3950 } 4553 }
3951 } 4554 }
3952 } 4555 }
4556 for (InterfaceType mixinType in mixins) {
4557 ClassElement mixinElement = mixinType.element;
4558 if (mixinElement == null) {
4559 continue;
4560 }
4561 Map<String, ExecutableElement> mapWithMixinMembers = new Map<String, Execu tableElement>();
4562 recordMapWithClassMembers(mapWithMixinMembers, mixinElement);
4563 lookupMaps.add(mapWithMixinMembers);
4564 }
3953 for (InterfaceType interfaceType in interfaces) { 4565 for (InterfaceType interfaceType in interfaces) {
3954 ClassElement interfaceElement = interfaceType.element; 4566 ClassElement interfaceElement = interfaceType.element;
3955 if (interfaceElement != null) { 4567 if (interfaceElement != null) {
3956 if (!visitedInterfaces.contains(interfaceElement)) { 4568 if (!visitedInterfaces.contains(interfaceElement)) {
3957 try { 4569 try {
3958 javaSetAdd(visitedInterfaces, interfaceElement); 4570 javaSetAdd(visitedInterfaces, interfaceElement);
3959 lookupMaps.add(computeInterfaceLookupMap(interfaceElement, visitedIn terfaces)); 4571 lookupMaps.add(computeInterfaceLookupMap(interfaceElement, visitedIn terfaces));
3960 } finally { 4572 } finally {
3961 visitedInterfaces.remove(interfaceElement); 4573 visitedInterfaces.remove(interfaceElement);
3962 } 4574 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
4134 return accessor; 4746 return accessor;
4135 } 4747 }
4136 } 4748 }
4137 return null; 4749 return null;
4138 } 4750 }
4139 4751
4140 /** 4752 /**
4141 * Record the passed map with the set of all members (methods, getters and set ters) in the class 4753 * Record the passed map with the set of all members (methods, getters and set ters) in the class
4142 * into the passed map. 4754 * into the passed map.
4143 * 4755 *
4144 * @param map some non-`null` 4756 * @param map some non-`null` map to put the methods and accessors from the pa ssed
4757 * [ClassElement] into
4145 * @param classElt the class element that will be recorded into the passed map 4758 * @param classElt the class element that will be recorded into the passed map
4146 */ 4759 */
4147 void recordMapWithClassMembers(Map<String, ExecutableElement> map, ClassElemen t classElt) { 4760 void recordMapWithClassMembers(Map<String, ExecutableElement> map, ClassElemen t classElt) {
4148 List<MethodElement> methods = classElt.methods; 4761 List<MethodElement> methods = classElt.methods;
4149 for (MethodElement method in methods) { 4762 for (MethodElement method in methods) {
4150 if (method.isAccessibleIn(_library) && !method.isStatic) { 4763 if (method.isAccessibleIn(_library) && !method.isStatic) {
4151 map[method.name] = method; 4764 map[method.name] = method;
4152 } 4765 }
4153 } 4766 }
4154 List<PropertyAccessorElement> accessors = classElt.accessors; 4767 List<PropertyAccessorElement> accessors = classElt.accessors;
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
4273 CompilationUnit getAST(Source source) { 4886 CompilationUnit getAST(Source source) {
4274 CompilationUnit unit = _astMap[source]; 4887 CompilationUnit unit = _astMap[source];
4275 if (unit == null) { 4888 if (unit == null) {
4276 unit = _analysisContext.computeResolvableCompilationUnit(source); 4889 unit = _analysisContext.computeResolvableCompilationUnit(source);
4277 _astMap[source] = unit; 4890 _astMap[source] = unit;
4278 } 4891 }
4279 return unit; 4892 return unit;
4280 } 4893 }
4281 4894
4282 /** 4895 /**
4896 * Return an array of the [CompilationUnit]s that make up the library. The fir st unit is
4897 * always the defining unit.
4898 *
4899 * @return an array of the [CompilationUnit]s that make up the library. The fi rst unit is
4900 * always the defining unit
4901 */
4902 List<CompilationUnit> get compilationUnits {
4903 List<CompilationUnit> unitArrayList = new List<CompilationUnit>();
4904 unitArrayList.add(definingCompilationUnit);
4905 for (Source source in _astMap.keys.toSet()) {
4906 if (_librarySource != source) {
4907 unitArrayList.add(getAST(source));
4908 }
4909 }
4910 return new List.from(unitArrayList);
4911 }
4912
4913 /**
4283 * Return a collection containing the sources for the compilation units in thi s library, including 4914 * Return a collection containing the sources for the compilation units in thi s library, including
4284 * the defining compilation unit. 4915 * the defining compilation unit.
4285 * 4916 *
4286 * @return the sources for the compilation units in this library 4917 * @return the sources for the compilation units in this library
4287 */ 4918 */
4288 Set<Source> get compilationUnitSources => _astMap.keys.toSet(); 4919 Set<Source> get compilationUnitSources => _astMap.keys.toSet();
4289 4920
4290 /** 4921 /**
4291 * Return the AST structure associated with the defining compilation unit for this library. 4922 * Return the AST structure associated with the defining compilation unit for this library.
4292 * 4923 *
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
4389 * @return the result of resolving the URI against the URI of the library 5020 * @return the result of resolving the URI against the URI of the library
4390 */ 5021 */
4391 Source getSource(UriBasedDirective directive) { 5022 Source getSource(UriBasedDirective directive) {
4392 StringLiteral uriLiteral = directive.uri; 5023 StringLiteral uriLiteral = directive.uri;
4393 if (uriLiteral is StringInterpolation) { 5024 if (uriLiteral is StringInterpolation) {
4394 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.o ffset, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION, [])); 5025 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.o ffset, uriLiteral.length, CompileTimeErrorCode.URI_WITH_INTERPOLATION, []));
4395 return null; 5026 return null;
4396 } 5027 }
4397 String uriContent = uriLiteral.stringValue.trim(); 5028 String uriContent = uriLiteral.stringValue.trim();
4398 _directiveUris[directive] = uriContent; 5029 _directiveUris[directive] = uriContent;
5030 uriContent = Uri.encodeFull(uriContent);
4399 try { 5031 try {
4400 parseUriWithException(uriContent); 5032 parseUriWithException(uriContent);
4401 Source source = getSource2(uriContent); 5033 Source source = getSource2(uriContent);
4402 if (source == null || !source.exists()) { 5034 if (source == null || !source.exists()) {
4403 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral .offset, uriLiteral.length, CompileTimeErrorCode.URI_DOES_NOT_EXIST, [uriContent ])); 5035 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral .offset, uriLiteral.length, CompileTimeErrorCode.URI_DOES_NOT_EXIST, [uriContent ]));
4404 } 5036 }
4405 return source; 5037 return source;
4406 } on URISyntaxException catch (exception) { 5038 } on URISyntaxException catch (exception) {
4407 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.o ffset, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent])); 5039 _errorListener.onError(new AnalysisError.con2(_librarySource, uriLiteral.o ffset, uriLiteral.length, CompileTimeErrorCode.INVALID_URI, [uriContent]));
4408 } 5040 }
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
4962 } 5594 }
4963 SimpleIdentifier prefixNode = ((directive as ImportDirective)).pre fix; 5595 SimpleIdentifier prefixNode = ((directive as ImportDirective)).pre fix;
4964 if (prefixNode != null) { 5596 if (prefixNode != null) {
4965 String prefixName = prefixNode.name; 5597 String prefixName = prefixNode.name;
4966 PrefixElementImpl prefix = nameToPrefixMap[prefixName]; 5598 PrefixElementImpl prefix = nameToPrefixMap[prefixName];
4967 if (prefix == null) { 5599 if (prefix == null) {
4968 prefix = new PrefixElementImpl(prefixNode); 5600 prefix = new PrefixElementImpl(prefixNode);
4969 nameToPrefixMap[prefixName] = prefix; 5601 nameToPrefixMap[prefixName] = prefix;
4970 } 5602 }
4971 importElement.prefix = prefix; 5603 importElement.prefix = prefix;
5604 prefixNode.staticElement = prefix;
4972 } 5605 }
4973 directive.element = importElement; 5606 directive.element = importElement;
4974 imports.add(importElement); 5607 imports.add(importElement);
4975 if (doesCompilationUnitHavePartOfDirective(importedLibrary.getAST( importedSource))) { 5608 if (doesCompilationUnitHavePartOfDirective(importedLibrary.getAST( importedSource))) {
4976 StringLiteral uriLiteral = importDirective.uri; 5609 StringLiteral uriLiteral = importDirective.uri;
4977 _errorListener.onError(new AnalysisError.con2(library.librarySou rce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LI BRARY, [uriLiteral.toSource()])); 5610 _errorListener.onError(new AnalysisError.con2(library.librarySou rce, uriLiteral.offset, uriLiteral.length, CompileTimeErrorCode.IMPORT_OF_NON_LI BRARY, [uriLiteral.toSource()]));
4978 } 5611 }
4979 } 5612 }
4980 } 5613 }
4981 } else if (directive is ExportDirective) { 5614 } else if (directive is ExportDirective) {
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
5306 */ 5939 */
5307 Source resolveSource(Source librarySource, UriBasedDirective directive) { 5940 Source resolveSource(Source librarySource, UriBasedDirective directive) {
5308 StringLiteral uriLiteral = directive.uri; 5941 StringLiteral uriLiteral = directive.uri;
5309 if (uriLiteral is StringInterpolation) { 5942 if (uriLiteral is StringInterpolation) {
5310 return null; 5943 return null;
5311 } 5944 }
5312 String uriContent = uriLiteral.stringValue.trim(); 5945 String uriContent = uriLiteral.stringValue.trim();
5313 if (uriContent == null) { 5946 if (uriContent == null) {
5314 return null; 5947 return null;
5315 } 5948 }
5949 uriContent = Uri.encodeFull(uriContent);
5316 try { 5950 try {
5317 parseUriWithException(uriContent); 5951 parseUriWithException(uriContent);
5318 return _analysisContext.sourceFactory.resolveUri(librarySource, uriContent ); 5952 return _analysisContext.sourceFactory.resolveUri(librarySource, uriContent );
5319 } on URISyntaxException catch (exception) { 5953 } on URISyntaxException catch (exception) {
5320 return null; 5954 return null;
5321 } 5955 }
5322 } 5956 }
5323 5957
5324 /** 5958 /**
5325 * Run additional analyses, such as the [ConstantVerifier] and [ErrorVerifier] 5959 * Run additional analyses, such as the [ConstantVerifier] and [ErrorVerifier]
(...skipping 17 matching lines...) Expand all
5343 * the library cannot be analyzed 5977 * the library cannot be analyzed
5344 */ 5978 */
5345 void runAdditionalAnalyses2(Library library) { 5979 void runAdditionalAnalyses2(Library library) {
5346 for (Source source in library.compilationUnitSources) { 5980 for (Source source in library.compilationUnitSources) {
5347 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); 5981 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source);
5348 CompilationUnit unit = library.getAST(source); 5982 CompilationUnit unit = library.getAST(source);
5349 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, _t ypeProvider); 5983 ConstantVerifier constantVerifier = new ConstantVerifier(errorReporter, _t ypeProvider);
5350 unit.accept(constantVerifier); 5984 unit.accept(constantVerifier);
5351 ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, library.lib raryElement, _typeProvider, library.inheritanceManager); 5985 ErrorVerifier errorVerifier = new ErrorVerifier(errorReporter, library.lib raryElement, _typeProvider, library.inheritanceManager);
5352 unit.accept(errorVerifier); 5986 unit.accept(errorVerifier);
5353 if (_enableHints) { 5987 }
5354 new HintVerifier(_analysisContext, errorReporter).visitCompilationUnit(u nit); 5988 if (_enableHints) {
5355 } 5989 HintGenerator hintGenerator = new HintGenerator(library.compilationUnits, _analysisContext, _errorListener);
5990 hintGenerator.generateForLibrary();
5356 } 5991 }
5357 } 5992 }
5358 } 5993 }
5359 /** 5994 /**
5360 * Instances of the class `ResolverVisitor` are used to resolve the nodes within a single 5995 * Instances of the class `ResolverVisitor` are used to resolve the nodes within a single
5361 * compilation unit. 5996 * compilation unit.
5362 * 5997 *
5363 * @coverage dart.engine.resolver 5998 * @coverage dart.engine.resolver
5364 */ 5999 */
5365 class ResolverVisitor extends ScopedVisitor { 6000 class ResolverVisitor extends ScopedVisitor {
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
5667 Object visitHideCombinator(HideCombinator node) => null; 6302 Object visitHideCombinator(HideCombinator node) => null;
5668 Object visitIfStatement(IfStatement node) { 6303 Object visitIfStatement(IfStatement node) {
5669 Expression condition = node.condition; 6304 Expression condition = node.condition;
5670 safelyVisit(condition); 6305 safelyVisit(condition);
5671 Map<Element, Type2> thenOverrides = null; 6306 Map<Element, Type2> thenOverrides = null;
5672 Statement thenStatement = node.thenStatement; 6307 Statement thenStatement = node.thenStatement;
5673 if (thenStatement != null) { 6308 if (thenStatement != null) {
5674 try { 6309 try {
5675 _overrideManager.enterScope(); 6310 _overrideManager.enterScope();
5676 propagateTrueState(condition); 6311 propagateTrueState(condition);
5677 thenStatement.accept(this); 6312 visitStatementInScope(thenStatement);
5678 } finally { 6313 } finally {
5679 thenOverrides = _overrideManager.captureLocalOverrides(); 6314 thenOverrides = _overrideManager.captureLocalOverrides();
5680 _overrideManager.exitScope(); 6315 _overrideManager.exitScope();
5681 } 6316 }
5682 } 6317 }
5683 Map<Element, Type2> elseOverrides = null; 6318 Map<Element, Type2> elseOverrides = null;
5684 Statement elseStatement = node.elseStatement; 6319 Statement elseStatement = node.elseStatement;
5685 if (elseStatement != null) { 6320 if (elseStatement != null) {
5686 try { 6321 try {
5687 _overrideManager.enterScope(); 6322 _overrideManager.enterScope();
5688 propagateFalseState(condition); 6323 propagateFalseState(condition);
5689 elseStatement.accept(this); 6324 visitStatementInScope(elseStatement);
5690 } finally { 6325 } finally {
5691 elseOverrides = _overrideManager.captureLocalOverrides(); 6326 elseOverrides = _overrideManager.captureLocalOverrides();
5692 _overrideManager.exitScope(); 6327 _overrideManager.exitScope();
5693 } 6328 }
5694 } 6329 }
5695 node.accept(_elementResolver); 6330 node.accept(_elementResolver);
5696 node.accept(_typeAnalyzer); 6331 node.accept(_typeAnalyzer);
5697 bool thenIsAbrupt = isAbruptTermination2(thenStatement); 6332 bool thenIsAbrupt = isAbruptTermination2(thenStatement);
5698 bool elseIsAbrupt = isAbruptTermination2(elseStatement); 6333 bool elseIsAbrupt = isAbruptTermination2(elseStatement);
5699 if (elseIsAbrupt && !thenIsAbrupt) { 6334 if (elseIsAbrupt && !thenIsAbrupt) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
5791 } 6426 }
5792 Object visitTypeName(TypeName node) => null; 6427 Object visitTypeName(TypeName node) => null;
5793 Object visitWhileStatement(WhileStatement node) { 6428 Object visitWhileStatement(WhileStatement node) {
5794 Expression condition = node.condition; 6429 Expression condition = node.condition;
5795 safelyVisit(condition); 6430 safelyVisit(condition);
5796 Statement body = node.body; 6431 Statement body = node.body;
5797 if (body != null) { 6432 if (body != null) {
5798 try { 6433 try {
5799 _overrideManager.enterScope(); 6434 _overrideManager.enterScope();
5800 propagateTrueState(condition); 6435 propagateTrueState(condition);
5801 body.accept(this); 6436 visitStatementInScope(body);
5802 } finally { 6437 } finally {
5803 _overrideManager.exitScope(); 6438 _overrideManager.exitScope();
5804 } 6439 }
5805 } 6440 }
5806 node.accept(_elementResolver); 6441 node.accept(_elementResolver);
5807 node.accept(_typeAnalyzer); 6442 node.accept(_typeAnalyzer);
5808 return null; 6443 return null;
5809 } 6444 }
5810 6445
5811 /** 6446 /**
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
5879 try { 6514 try {
5880 _overrideManager.enterScope(); 6515 _overrideManager.enterScope();
5881 if (loopVariable != null && iterator != null) { 6516 if (loopVariable != null && iterator != null) {
5882 LocalVariableElement loopElement = loopVariable.element; 6517 LocalVariableElement loopElement = loopVariable.element;
5883 if (loopElement != null) { 6518 if (loopElement != null) {
5884 Type2 iteratorElementType = getIteratorElementType(iterator); 6519 Type2 iteratorElementType = getIteratorElementType(iterator);
5885 override(loopElement, iteratorElementType); 6520 override(loopElement, iteratorElementType);
5886 recordPropagatedType(loopVariable.identifier, iteratorElementType); 6521 recordPropagatedType(loopVariable.identifier, iteratorElementType);
5887 } 6522 }
5888 } 6523 }
5889 body.accept(this); 6524 visitStatementInScope(body);
5890 } finally { 6525 } finally {
5891 _overrideManager.exitScope(); 6526 _overrideManager.exitScope();
5892 } 6527 }
5893 } 6528 }
5894 node.accept(_elementResolver); 6529 node.accept(_elementResolver);
5895 node.accept(_typeAnalyzer); 6530 node.accept(_typeAnalyzer);
5896 } 6531 }
5897 void visitForStatementInScope(ForStatement node) { 6532 void visitForStatementInScope(ForStatement node) {
5898 safelyVisit(node.variables); 6533 safelyVisit(node.variables);
5899 safelyVisit(node.initialization); 6534 safelyVisit(node.initialization);
5900 safelyVisit(node.condition); 6535 safelyVisit(node.condition);
5901 _overrideManager.enterScope(); 6536 _overrideManager.enterScope();
5902 try { 6537 try {
5903 propagateTrueState(node.condition); 6538 propagateTrueState(node.condition);
5904 safelyVisit(node.body); 6539 visitStatementInScope(node.body);
5905 node.updaters.accept(this); 6540 node.updaters.accept(this);
5906 } finally { 6541 } finally {
5907 _overrideManager.exitScope(); 6542 _overrideManager.exitScope();
5908 } 6543 }
5909 } 6544 }
5910 6545
5911 /** 6546 /**
5912 * Return the best type information available for the given element. If the ty pe of the element 6547 * Return the best type information available for the given element. If the ty pe of the element
5913 * has been overridden, then return the overriding type. Otherwise, return the static type. 6548 * has been overridden, then return the overriding type. Otherwise, return the static type.
5914 * 6549 *
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
5981 _overrideManager.setType(element, expectedType); 6616 _overrideManager.setType(element, expectedType);
5982 } 6617 }
5983 } 6618 }
5984 } 6619 }
5985 6620
5986 /** 6621 /**
5987 * Try to infer types of parameters of the [FunctionExpression] arguments. 6622 * Try to infer types of parameters of the [FunctionExpression] arguments.
5988 */ 6623 */
5989 void inferFunctionExpressionsParametersTypes(ArgumentList argumentList) { 6624 void inferFunctionExpressionsParametersTypes(ArgumentList argumentList) {
5990 for (Expression argument in argumentList.arguments) { 6625 for (Expression argument in argumentList.arguments) {
5991 ParameterElement parameter = argument.parameterElement; 6626 ParameterElement parameter = argument.propagatedParameterElement;
5992 if (parameter == null) { 6627 if (parameter == null) {
5993 parameter = argument.staticParameterElement; 6628 parameter = argument.staticParameterElement;
5994 } 6629 }
5995 if (parameter != null) { 6630 if (parameter != null) {
5996 inferFunctionExpressionParametersTypes(argument, parameter.type); 6631 inferFunctionExpressionParametersTypes(argument, parameter.type);
5997 } 6632 }
5998 } 6633 }
5999 } 6634 }
6000 6635
6001 /** 6636 /**
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
6209 LibraryElement get definingLibrary => _definingLibrary; 6844 LibraryElement get definingLibrary => _definingLibrary;
6210 6845
6211 /** 6846 /**
6212 * Return the object used to access the types from the core library. 6847 * Return the object used to access the types from the core library.
6213 * 6848 *
6214 * @return the object used to access the types from the core library 6849 * @return the object used to access the types from the core library
6215 */ 6850 */
6216 TypeProvider get typeProvider => _typeProvider; 6851 TypeProvider get typeProvider => _typeProvider;
6217 Object visitBlock(Block node) { 6852 Object visitBlock(Block node) {
6218 Scope outerScope = _nameScope; 6853 Scope outerScope = _nameScope;
6219 _nameScope = new EnclosedScope(_nameScope);
6220 try { 6854 try {
6855 _nameScope = new EnclosedScope(_nameScope);
6221 super.visitBlock(node); 6856 super.visitBlock(node);
6222 } finally { 6857 } finally {
6223 _nameScope = outerScope; 6858 _nameScope = outerScope;
6224 } 6859 }
6225 return null; 6860 return null;
6226 } 6861 }
6227 Object visitCatchClause(CatchClause node) { 6862 Object visitCatchClause(CatchClause node) {
6228 SimpleIdentifier exception = node.exceptionParameter; 6863 SimpleIdentifier exception = node.exceptionParameter;
6229 if (exception != null) { 6864 if (exception != null) {
6230 Scope outerScope = _nameScope; 6865 Scope outerScope = _nameScope;
6231 _nameScope = new EnclosedScope(_nameScope);
6232 try { 6866 try {
6867 _nameScope = new EnclosedScope(_nameScope);
6233 _nameScope.define(exception.element); 6868 _nameScope.define(exception.element);
6234 SimpleIdentifier stackTrace = node.stackTraceParameter; 6869 SimpleIdentifier stackTrace = node.stackTraceParameter;
6235 if (stackTrace != null) { 6870 if (stackTrace != null) {
6236 _nameScope.define(stackTrace.element); 6871 _nameScope.define(stackTrace.element);
6237 } 6872 }
6238 super.visitCatchClause(node); 6873 super.visitCatchClause(node);
6239 } finally { 6874 } finally {
6240 _nameScope = outerScope; 6875 _nameScope = outerScope;
6241 } 6876 }
6242 } 6877 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
6274 } 6909 }
6275 Object visitDeclaredIdentifier(DeclaredIdentifier node) { 6910 Object visitDeclaredIdentifier(DeclaredIdentifier node) {
6276 VariableElement element = node.element; 6911 VariableElement element = node.element;
6277 if (element != null) { 6912 if (element != null) {
6278 _nameScope.define(element); 6913 _nameScope.define(element);
6279 } 6914 }
6280 super.visitDeclaredIdentifier(node); 6915 super.visitDeclaredIdentifier(node);
6281 return null; 6916 return null;
6282 } 6917 }
6283 Object visitDoStatement(DoStatement node) { 6918 Object visitDoStatement(DoStatement node) {
6284 LabelScope outerScope = _labelScope; 6919 LabelScope outerLabelScope = _labelScope;
6285 _labelScope = new LabelScope.con1(outerScope, false, false);
6286 try { 6920 try {
6287 super.visitDoStatement(node); 6921 _labelScope = new LabelScope.con1(_labelScope, false, false);
6922 visitStatementInScope(node.body);
6923 safelyVisit(node.condition);
6288 } finally { 6924 } finally {
6289 _labelScope = outerScope; 6925 _labelScope = outerLabelScope;
6290 } 6926 }
6291 return null; 6927 return null;
6292 } 6928 }
6293 Object visitForEachStatement(ForEachStatement node) { 6929 Object visitForEachStatement(ForEachStatement node) {
6930 Scope outerNameScope = _nameScope;
6294 LabelScope outerLabelScope = _labelScope; 6931 LabelScope outerLabelScope = _labelScope;
6295 _labelScope = new LabelScope.con1(outerLabelScope, false, false);
6296 Scope outerNameScope = _nameScope;
6297 _nameScope = new EnclosedScope(_nameScope);
6298 try { 6932 try {
6933 _nameScope = new EnclosedScope(_nameScope);
6934 _labelScope = new LabelScope.con1(outerLabelScope, false, false);
6299 visitForEachStatementInScope(node); 6935 visitForEachStatementInScope(node);
6300 } finally { 6936 } finally {
6937 _labelScope = outerLabelScope;
6301 _nameScope = outerNameScope; 6938 _nameScope = outerNameScope;
6302 _labelScope = outerLabelScope;
6303 } 6939 }
6304 return null; 6940 return null;
6305 } 6941 }
6306 Object visitForStatement(ForStatement node) { 6942 Object visitForStatement(ForStatement node) {
6943 Scope outerNameScope = _nameScope;
6307 LabelScope outerLabelScope = _labelScope; 6944 LabelScope outerLabelScope = _labelScope;
6308 _labelScope = new LabelScope.con1(outerLabelScope, false, false);
6309 Scope outerNameScope = _nameScope;
6310 _nameScope = new EnclosedScope(_nameScope);
6311 try { 6945 try {
6946 _nameScope = new EnclosedScope(_nameScope);
6947 _labelScope = new LabelScope.con1(outerLabelScope, false, false);
6312 visitForStatementInScope(node); 6948 visitForStatementInScope(node);
6313 } finally { 6949 } finally {
6950 _labelScope = outerLabelScope;
6314 _nameScope = outerNameScope; 6951 _nameScope = outerNameScope;
6315 _labelScope = outerLabelScope;
6316 } 6952 }
6317 return null; 6953 return null;
6318 } 6954 }
6319 Object visitFunctionDeclaration(FunctionDeclaration node) { 6955 Object visitFunctionDeclaration(FunctionDeclaration node) {
6320 ExecutableElement function = node.element; 6956 ExecutableElement function = node.element;
6321 Scope outerScope = _nameScope; 6957 Scope outerScope = _nameScope;
6322 try { 6958 try {
6323 _nameScope = new FunctionScope(_nameScope, function); 6959 _nameScope = new FunctionScope(_nameScope, function);
6324 super.visitFunctionDeclaration(node); 6960 super.visitFunctionDeclaration(node);
6325 } finally { 6961 } finally {
(...skipping 25 matching lines...) Expand all
6351 Object visitFunctionTypeAlias(FunctionTypeAlias node) { 6987 Object visitFunctionTypeAlias(FunctionTypeAlias node) {
6352 Scope outerScope = _nameScope; 6988 Scope outerScope = _nameScope;
6353 try { 6989 try {
6354 _nameScope = new FunctionTypeScope(_nameScope, node.element); 6990 _nameScope = new FunctionTypeScope(_nameScope, node.element);
6355 super.visitFunctionTypeAlias(node); 6991 super.visitFunctionTypeAlias(node);
6356 } finally { 6992 } finally {
6357 _nameScope = outerScope; 6993 _nameScope = outerScope;
6358 } 6994 }
6359 return null; 6995 return null;
6360 } 6996 }
6997 Object visitIfStatement(IfStatement node) {
6998 safelyVisit(node.condition);
6999 visitStatementInScope(node.thenStatement);
7000 visitStatementInScope(node.elseStatement);
7001 return null;
7002 }
6361 Object visitLabeledStatement(LabeledStatement node) { 7003 Object visitLabeledStatement(LabeledStatement node) {
6362 LabelScope outerScope = addScopesFor(node.labels); 7004 LabelScope outerScope = addScopesFor(node.labels);
6363 try { 7005 try {
6364 super.visitLabeledStatement(node); 7006 super.visitLabeledStatement(node);
6365 } finally { 7007 } finally {
6366 _labelScope = outerScope; 7008 _labelScope = outerScope;
6367 } 7009 }
6368 return null; 7010 return null;
6369 } 7011 }
6370 Object visitMethodDeclaration(MethodDeclaration node) { 7012 Object visitMethodDeclaration(MethodDeclaration node) {
6371 Scope outerScope = _nameScope; 7013 Scope outerScope = _nameScope;
6372 try { 7014 try {
6373 _nameScope = new FunctionScope(_nameScope, node.element); 7015 _nameScope = new FunctionScope(_nameScope, node.element);
6374 super.visitMethodDeclaration(node); 7016 super.visitMethodDeclaration(node);
6375 } finally { 7017 } finally {
6376 _nameScope = outerScope; 7018 _nameScope = outerScope;
6377 } 7019 }
6378 return null; 7020 return null;
6379 } 7021 }
6380 Object visitSwitchCase(SwitchCase node) { 7022 Object visitSwitchCase(SwitchCase node) {
6381 node.expression.accept(this); 7023 node.expression.accept(this);
6382 Scope outerNameScope = _nameScope; 7024 Scope outerNameScope = _nameScope;
6383 _nameScope = new EnclosedScope(_nameScope);
6384 try { 7025 try {
7026 _nameScope = new EnclosedScope(_nameScope);
6385 node.statements.accept(this); 7027 node.statements.accept(this);
6386 } finally { 7028 } finally {
6387 _nameScope = outerNameScope; 7029 _nameScope = outerNameScope;
6388 } 7030 }
6389 return null; 7031 return null;
6390 } 7032 }
6391 Object visitSwitchDefault(SwitchDefault node) { 7033 Object visitSwitchDefault(SwitchDefault node) {
6392 Scope outerNameScope = _nameScope; 7034 Scope outerNameScope = _nameScope;
6393 _nameScope = new EnclosedScope(_nameScope);
6394 try { 7035 try {
7036 _nameScope = new EnclosedScope(_nameScope);
6395 node.statements.accept(this); 7037 node.statements.accept(this);
6396 } finally { 7038 } finally {
6397 _nameScope = outerNameScope; 7039 _nameScope = outerNameScope;
6398 } 7040 }
6399 return null; 7041 return null;
6400 } 7042 }
6401 Object visitSwitchStatement(SwitchStatement node) { 7043 Object visitSwitchStatement(SwitchStatement node) {
6402 LabelScope outerScope = _labelScope; 7044 LabelScope outerScope = _labelScope;
6403 _labelScope = new LabelScope.con1(outerScope, true, false); 7045 try {
6404 for (SwitchMember member in node.members) { 7046 _labelScope = new LabelScope.con1(outerScope, true, false);
6405 for (Label label in member.labels) { 7047 for (SwitchMember member in node.members) {
6406 SimpleIdentifier labelName = label.label; 7048 for (Label label in member.labels) {
6407 LabelElement labelElement = labelName.element as LabelElement; 7049 SimpleIdentifier labelName = label.label;
6408 _labelScope = new LabelScope.con2(_labelScope, labelName.name, labelElem ent); 7050 LabelElement labelElement = labelName.element as LabelElement;
7051 _labelScope = new LabelScope.con2(_labelScope, labelName.name, labelEl ement);
7052 }
6409 } 7053 }
6410 }
6411 try {
6412 super.visitSwitchStatement(node); 7054 super.visitSwitchStatement(node);
6413 } finally { 7055 } finally {
6414 _labelScope = outerScope; 7056 _labelScope = outerScope;
6415 } 7057 }
6416 return null; 7058 return null;
6417 } 7059 }
6418 Object visitVariableDeclaration(VariableDeclaration node) { 7060 Object visitVariableDeclaration(VariableDeclaration node) {
6419 if (node.parent.parent is! TopLevelVariableDeclaration && node.parent.parent is! FieldDeclaration) { 7061 if (node.parent.parent is! TopLevelVariableDeclaration && node.parent.parent is! FieldDeclaration) {
6420 VariableElement element = node.element; 7062 VariableElement element = node.element;
6421 if (element != null) { 7063 if (element != null) {
6422 _nameScope.define(element); 7064 _nameScope.define(element);
6423 } 7065 }
6424 } 7066 }
6425 super.visitVariableDeclaration(node); 7067 super.visitVariableDeclaration(node);
6426 return null; 7068 return null;
6427 } 7069 }
6428 Object visitWhileStatement(WhileStatement node) { 7070 Object visitWhileStatement(WhileStatement node) {
6429 LabelScope outerScope = _labelScope; 7071 LabelScope outerScope = _labelScope;
6430 _labelScope = new LabelScope.con1(outerScope, false, false);
6431 try { 7072 try {
6432 super.visitWhileStatement(node); 7073 _labelScope = new LabelScope.con1(outerScope, false, false);
7074 safelyVisit(node.condition);
7075 visitStatementInScope(node.body);
6433 } finally { 7076 } finally {
6434 _labelScope = outerScope; 7077 _labelScope = outerScope;
6435 } 7078 }
6436 return null; 7079 return null;
6437 } 7080 }
6438 7081
6439 /** 7082 /**
6440 * Return the label scope in which the current node is being resolved. 7083 * Return the label scope in which the current node is being resolved.
6441 * 7084 *
6442 * @return the label scope in which the current node is being resolved 7085 * @return the label scope in which the current node is being resolved
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
6498 /** 7141 /**
6499 * Visit the given statement after it's scope has been created. This replaces the normal call to 7142 * Visit the given statement after it's scope has been created. This replaces the normal call to
6500 * the inherited visit method so that ResolverVisitor can intervene when type propagation is 7143 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
6501 * enabled. 7144 * enabled.
6502 * 7145 *
6503 * @param node the statement to be visited 7146 * @param node the statement to be visited
6504 */ 7147 */
6505 void visitForEachStatementInScope(ForEachStatement node) { 7148 void visitForEachStatementInScope(ForEachStatement node) {
6506 safelyVisit(node.iterator); 7149 safelyVisit(node.iterator);
6507 safelyVisit(node.loopVariable); 7150 safelyVisit(node.loopVariable);
6508 safelyVisit(node.body); 7151 visitStatementInScope(node.body);
6509 } 7152 }
6510 7153
6511 /** 7154 /**
6512 * Visit the given statement after it's scope has been created. This replaces the normal call to 7155 * Visit the given statement after it's scope has been created. This replaces the normal call to
6513 * the inherited visit method so that ResolverVisitor can intervene when type propagation is 7156 * the inherited visit method so that ResolverVisitor can intervene when type propagation is
6514 * enabled. 7157 * enabled.
6515 * 7158 *
6516 * @param node the statement to be visited 7159 * @param node the statement to be visited
6517 */ 7160 */
6518 void visitForStatementInScope(ForStatement node) { 7161 void visitForStatementInScope(ForStatement node) {
6519 super.visitForStatement(node); 7162 safelyVisit(node.variables);
7163 safelyVisit(node.initialization);
7164 safelyVisit(node.condition);
7165 node.updaters.accept(this);
7166 visitStatementInScope(node.body);
6520 } 7167 }
6521 7168
6522 /** 7169 /**
7170 * Visit the given statement after it's scope has been created. This is used b y ResolverVisitor to
7171 * correctly visit the 'then' and 'else' statements of an 'if' statement.
7172 *
7173 * @param node the statement to be visited
7174 */
7175 void visitStatementInScope(Statement node) {
7176 if (node is Block) {
7177 visitBlock((node as Block));
7178 } else if (node != null) {
7179 Scope outerNameScope = _nameScope;
7180 try {
7181 _nameScope = new EnclosedScope(_nameScope);
7182 node.accept(this);
7183 } finally {
7184 _nameScope = outerNameScope;
7185 }
7186 }
7187 }
7188
7189 /**
6523 * Add scopes for each of the given labels. 7190 * Add scopes for each of the given labels.
6524 * 7191 *
6525 * @param labels the labels for which new scopes are to be added 7192 * @param labels the labels for which new scopes are to be added
6526 * @return the scope that was in effect before the new scopes were added 7193 * @return the scope that was in effect before the new scopes were added
6527 */ 7194 */
6528 LabelScope addScopesFor(NodeList<Label> labels) { 7195 LabelScope addScopesFor(NodeList<Label> labels) {
6529 LabelScope outerScope = _labelScope; 7196 LabelScope outerScope = _labelScope;
6530 for (Label label in labels) { 7197 for (Label label in labels) {
6531 SimpleIdentifier labelNameNode = label.label; 7198 SimpleIdentifier labelNameNode = label.label;
6532 String labelName = labelNameNode.name; 7199 String labelName = labelNameNode.name;
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
6746 * e<sub>2</sub>)</i> where <i>a</i> and <i>i</i> are a variables that are not used in 7413 * e<sub>2</sub>)</i> where <i>a</i> and <i>i</i> are a variables that are not used in
6747 * <i>e<sub>3</sub></i>.</blockquote> 7414 * <i>e<sub>3</sub></i>.</blockquote>
6748 */ 7415 */
6749 Object visitAssignmentExpression(AssignmentExpression node) { 7416 Object visitAssignmentExpression(AssignmentExpression node) {
6750 sc.TokenType operator = node.operator.type; 7417 sc.TokenType operator = node.operator.type;
6751 if (identical(operator, sc.TokenType.EQ)) { 7418 if (identical(operator, sc.TokenType.EQ)) {
6752 Expression rightHandSide = node.rightHandSide; 7419 Expression rightHandSide = node.rightHandSide;
6753 Type2 staticType = getStaticType(rightHandSide); 7420 Type2 staticType = getStaticType(rightHandSide);
6754 recordStaticType(node, staticType); 7421 recordStaticType(node, staticType);
6755 Type2 overrideType = staticType; 7422 Type2 overrideType = staticType;
6756 Type2 propagatedType = getPropagatedType(rightHandSide); 7423 Type2 propagatedType = rightHandSide.propagatedType;
6757 if (propagatedType != null) { 7424 if (propagatedType != null) {
6758 if (propagatedType.isMoreSpecificThan(staticType)) { 7425 if (propagatedType.isMoreSpecificThan(staticType)) {
6759 recordPropagatedType2(node, propagatedType); 7426 recordPropagatedType2(node, propagatedType);
6760 } 7427 }
6761 overrideType = propagatedType; 7428 overrideType = propagatedType;
6762 } 7429 }
6763 VariableElement element = _resolver.getOverridableElement(node.leftHandSid e); 7430 VariableElement element = _resolver.getOverridableElement(node.leftHandSid e);
6764 if (element != null) { 7431 if (element != null) {
6765 _resolver.override(element, overrideType); 7432 _resolver.override(element, overrideType);
6766 } 7433 }
6767 } else { 7434 } else {
6768 ExecutableElement staticMethodElement = node.staticElement; 7435 ExecutableElement staticMethodElement = node.staticElement;
6769 Type2 staticType = computeStaticReturnType(staticMethodElement); 7436 Type2 staticType = computeStaticReturnType(staticMethodElement);
6770 recordStaticType(node, staticType); 7437 recordStaticType(node, staticType);
6771 MethodElement propagatedMethodElement = node.element; 7438 MethodElement propagatedMethodElement = node.propagatedElement;
6772 if (propagatedMethodElement != staticMethodElement) { 7439 if (propagatedMethodElement != staticMethodElement) {
6773 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement); 7440 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
6774 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) { 7441 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
6775 recordPropagatedType2(node, propagatedType); 7442 recordPropagatedType2(node, propagatedType);
6776 } 7443 }
6777 } 7444 }
6778 } 7445 }
6779 return null; 7446 return null;
6780 } 7447 }
6781 7448
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
6814 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n 7481 * <i>e<sub>1</sub> op e<sub>2</sub></i> is equivalent to the method invocatio n
6815 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A multiplicative expression of the form <i>super op 7482 * <i>e<sub>1</sub>.op(e<sub>2</sub>)</i>. A multiplicative expression of the form <i>super op
6816 * e<sub>2</sub></i> is equivalent to the method invocation 7483 * e<sub>2</sub></i> is equivalent to the method invocation
6817 * <i>super.op(e<sub>2</sub>)</i>.</blockquote> 7484 * <i>super.op(e<sub>2</sub>)</i>.</blockquote>
6818 */ 7485 */
6819 Object visitBinaryExpression(BinaryExpression node) { 7486 Object visitBinaryExpression(BinaryExpression node) {
6820 ExecutableElement staticMethodElement = node.staticElement; 7487 ExecutableElement staticMethodElement = node.staticElement;
6821 Type2 staticType = computeStaticReturnType(staticMethodElement); 7488 Type2 staticType = computeStaticReturnType(staticMethodElement);
6822 staticType = refineBinaryExpressionType(node, staticType); 7489 staticType = refineBinaryExpressionType(node, staticType);
6823 recordStaticType(node, staticType); 7490 recordStaticType(node, staticType);
6824 MethodElement propagatedMethodElement = node.element; 7491 MethodElement propagatedMethodElement = node.propagatedElement;
6825 if (propagatedMethodElement != staticMethodElement) { 7492 if (propagatedMethodElement != staticMethodElement) {
6826 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement); 7493 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
6827 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) { 7494 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) {
6828 recordPropagatedType2(node, propagatedType); 7495 recordPropagatedType2(node, propagatedType);
6829 } 7496 }
6830 } 7497 }
6831 return null; 7498 return null;
6832 } 7499 }
6833 7500
6834 /** 7501 /**
6835 * The Dart Language Specification, 12.4: <blockquote>The static type of a boo lean literal is 7502 * The Dart Language Specification, 12.4: <blockquote>The static type of a boo lean literal is
6836 * bool.</blockquote> 7503 * bool.</blockquote>
6837 */ 7504 */
6838 Object visitBooleanLiteral(BooleanLiteral node) { 7505 Object visitBooleanLiteral(BooleanLiteral node) {
6839 recordStaticType(node, _typeProvider.boolType); 7506 recordStaticType(node, _typeProvider.boolType);
6840 return null; 7507 return null;
6841 } 7508 }
6842 7509
6843 /** 7510 /**
6844 * The Dart Language Specification, 12.15.2: <blockquote>A cascaded method inv ocation expression 7511 * The Dart Language Specification, 12.15.2: <blockquote>A cascaded method inv ocation expression
6845 * of the form <i>e..suffix</i> is equivalent to the expression <i>(t) {t.suff ix; return 7512 * of the form <i>e..suffix</i> is equivalent to the expression <i>(t) {t.suff ix; return
6846 * t;}(e)</i>.</blockquote> 7513 * t;}(e)</i>.</blockquote>
6847 */ 7514 */
6848 Object visitCascadeExpression(CascadeExpression node) { 7515 Object visitCascadeExpression(CascadeExpression node) {
6849 recordStaticType(node, getStaticType(node.target)); 7516 recordStaticType(node, getStaticType(node.target));
6850 recordPropagatedType2(node, getPropagatedType(node.target)); 7517 recordPropagatedType2(node, node.target.propagatedType);
6851 return null; 7518 return null;
6852 } 7519 }
6853 7520
6854 /** 7521 /**
6855 * The Dart Language Specification, 12.19: <blockquote> ... a conditional expr ession <i>c</i> of 7522 * The Dart Language Specification, 12.19: <blockquote> ... a conditional expr ession <i>c</i> of
6856 * the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> ... 7523 * the form <i>e<sub>1</sub> ? e<sub>2</sub> : e<sub>3</sub></i> ...
6857 * 7524 *
6858 * It is a static type warning if the type of e<sub>1</sub> may not be assigne d to `bool`. 7525 * It is a static type warning if the type of e<sub>1</sub> may not be assigne d to `bool`.
6859 * 7526 *
6860 * The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i> 7527 * The static type of <i>c</i> is the least upper bound of the static type of <i>e<sub>2</sub></i>
6861 * and the static type of <i>e<sub>3</sub></i>.</blockquote> 7528 * and the static type of <i>e<sub>3</sub></i>.</blockquote>
6862 */ 7529 */
6863 Object visitConditionalExpression(ConditionalExpression node) { 7530 Object visitConditionalExpression(ConditionalExpression node) {
6864 Type2 staticThenType = getStaticType(node.thenExpression); 7531 Type2 staticThenType = getStaticType(node.thenExpression);
6865 Type2 staticElseType = getStaticType(node.elseExpression); 7532 Type2 staticElseType = getStaticType(node.elseExpression);
6866 if (staticThenType == null) { 7533 if (staticThenType == null) {
6867 staticThenType = _dynamicType; 7534 staticThenType = _dynamicType;
6868 } 7535 }
6869 if (staticElseType == null) { 7536 if (staticElseType == null) {
6870 staticElseType = _dynamicType; 7537 staticElseType = _dynamicType;
6871 } 7538 }
6872 Type2 staticType = staticThenType.getLeastUpperBound(staticElseType); 7539 Type2 staticType = staticThenType.getLeastUpperBound(staticElseType);
6873 if (staticType == null) { 7540 if (staticType == null) {
6874 staticType = _dynamicType; 7541 staticType = _dynamicType;
6875 } 7542 }
6876 recordStaticType(node, staticType); 7543 recordStaticType(node, staticType);
6877 Type2 propagatedThenType = getPropagatedType(node.thenExpression); 7544 Type2 propagatedThenType = node.thenExpression.propagatedType;
6878 Type2 propagatedElseType = getPropagatedType(node.elseExpression); 7545 Type2 propagatedElseType = node.elseExpression.propagatedType;
6879 if (propagatedThenType != null || propagatedElseType != null) { 7546 if (propagatedThenType != null || propagatedElseType != null) {
6880 if (propagatedThenType == null) { 7547 if (propagatedThenType == null) {
6881 propagatedThenType = staticThenType; 7548 propagatedThenType = staticThenType;
6882 } 7549 }
6883 if (propagatedElseType == null) { 7550 if (propagatedElseType == null) {
6884 propagatedElseType = staticElseType; 7551 propagatedElseType = staticElseType;
6885 } 7552 }
6886 Type2 propagatedType = propagatedThenType.getLeastUpperBound(propagatedEls eType); 7553 Type2 propagatedType = propagatedThenType.getLeastUpperBound(propagatedEls eType);
6887 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) { 7554 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticType )) {
6888 recordPropagatedType2(node, propagatedType); 7555 recordPropagatedType2(node, propagatedType);
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
6962 * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquot e> 7629 * static type of <i>i</i> is the declared return type of <i>F</i>.</blockquot e>
6963 */ 7630 */
6964 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { 7631 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
6965 ExecutableElement staticMethodElement = node.staticElement; 7632 ExecutableElement staticMethodElement = node.staticElement;
6966 Type2 staticStaticType = computeStaticReturnType(staticMethodElement); 7633 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
6967 recordStaticType(node, staticStaticType); 7634 recordStaticType(node, staticStaticType);
6968 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement ); 7635 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
6969 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) { 7636 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
6970 recordPropagatedType2(node, staticPropagatedType); 7637 recordPropagatedType2(node, staticPropagatedType);
6971 } 7638 }
6972 ExecutableElement propagatedMethodElement = node.element; 7639 ExecutableElement propagatedMethodElement = node.propagatedElement;
6973 if (propagatedMethodElement != staticMethodElement) { 7640 if (propagatedMethodElement != staticMethodElement) {
6974 Type2 propagatedStaticType = computeStaticReturnType(propagatedMethodEleme nt); 7641 Type2 propagatedStaticType = computeStaticReturnType(propagatedMethodEleme nt);
6975 if (propagatedStaticType != null && (staticStaticType == null || propagate dStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == nu ll || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) { 7642 if (propagatedStaticType != null && (staticStaticType == null || propagate dStaticType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedType == nu ll || propagatedStaticType.isMoreSpecificThan(staticPropagatedType))) {
6976 recordPropagatedType2(node, propagatedStaticType); 7643 recordPropagatedType2(node, propagatedStaticType);
6977 } 7644 }
6978 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedMet hodElement); 7645 Type2 propagatedPropagatedType = computePropagatedReturnType(propagatedMet hodElement);
6979 if (propagatedPropagatedType != null && (staticStaticType == null || propa gatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedTy pe == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType)) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificThan (propagatedStaticType))) { 7646 if (propagatedPropagatedType != null && (staticStaticType == null || propa gatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagatedTy pe == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType)) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificThan (propagatedStaticType))) {
6980 recordPropagatedType2(node, propagatedPropagatedType); 7647 recordPropagatedType2(node, propagatedPropagatedType);
6981 } 7648 }
6982 } 7649 }
6983 return null; 7650 return null;
6984 } 7651 }
6985 7652
6986 /** 7653 /**
6987 * The Dart Language Specification, 12.29: <blockquote>An assignable expressio n of the form 7654 * The Dart Language Specification, 12.29: <blockquote>An assignable expressio n of the form
6988 * <i>e<sub>1</sub>[e<sub>2</sub>]</i> is evaluated as a method invocation of the operator method 7655 * <i>e<sub>1</sub>[e<sub>2</sub>]</i> is evaluated as a method invocation of the operator method
6989 * <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</bloc kquote> 7656 * <i>[]</i> on <i>e<sub>1</sub></i> with argument <i>e<sub>2</sub></i>.</bloc kquote>
6990 */ 7657 */
6991 Object visitIndexExpression(IndexExpression node) { 7658 Object visitIndexExpression(IndexExpression node) {
6992 if (node.inSetterContext()) { 7659 if (node.inSetterContext()) {
6993 ExecutableElement staticMethodElement = node.staticElement; 7660 ExecutableElement staticMethodElement = node.staticElement;
6994 Type2 staticType = computeArgumentType(staticMethodElement); 7661 Type2 staticType = computeArgumentType(staticMethodElement);
6995 recordStaticType(node, staticType); 7662 recordStaticType(node, staticType);
6996 MethodElement propagatedMethodElement = node.element; 7663 MethodElement propagatedMethodElement = node.propagatedElement;
6997 if (propagatedMethodElement != staticMethodElement) { 7664 if (propagatedMethodElement != staticMethodElement) {
6998 Type2 propagatedType = computeArgumentType(propagatedMethodElement); 7665 Type2 propagatedType = computeArgumentType(propagatedMethodElement);
6999 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) { 7666 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
7000 recordPropagatedType2(node, propagatedType); 7667 recordPropagatedType2(node, propagatedType);
7001 } 7668 }
7002 } 7669 }
7003 } else { 7670 } else {
7004 ExecutableElement staticMethodElement = node.staticElement; 7671 ExecutableElement staticMethodElement = node.staticElement;
7005 Type2 staticType = computeStaticReturnType(staticMethodElement); 7672 Type2 staticType = computeStaticReturnType(staticMethodElement);
7006 recordStaticType(node, staticType); 7673 recordStaticType(node, staticType);
7007 MethodElement propagatedMethodElement = node.element; 7674 MethodElement propagatedMethodElement = node.propagatedElement;
7008 if (propagatedMethodElement != staticMethodElement) { 7675 if (propagatedMethodElement != staticMethodElement) {
7009 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement); 7676 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
7010 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) { 7677 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
7011 recordPropagatedType2(node, propagatedType); 7678 recordPropagatedType2(node, propagatedType);
7012 } 7679 }
7013 } 7680 }
7014 } 7681 }
7015 return null; 7682 return null;
7016 } 7683 }
7017 7684
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
7088 Type2 argumentType = getType2(argumentTypeName); 7755 Type2 argumentType = getType2(argumentTypeName);
7089 if (argumentType != null) { 7756 if (argumentType != null) {
7090 staticType = argumentType; 7757 staticType = argumentType;
7091 } 7758 }
7092 } 7759 }
7093 } 7760 }
7094 recordStaticType(node, _typeProvider.listType.substitute4(<Type2> [staticTyp e])); 7761 recordStaticType(node, _typeProvider.listType.substitute4(<Type2> [staticTyp e]));
7095 NodeList<Expression> elements = node.elements; 7762 NodeList<Expression> elements = node.elements;
7096 int count = elements.length; 7763 int count = elements.length;
7097 if (count > 0) { 7764 if (count > 0) {
7098 Type2 propagatedType = getBestType(elements[0]); 7765 Type2 propagatedType = elements[0].bestType;
7099 for (int i = 1; i < count; i++) { 7766 for (int i = 1; i < count; i++) {
7100 Type2 elementType = getBestType(elements[i]); 7767 Type2 elementType = elements[i].bestType;
7101 if (propagatedType != elementType) { 7768 if (propagatedType != elementType) {
7102 propagatedType = _dynamicType; 7769 propagatedType = _dynamicType;
7103 } else { 7770 } else {
7104 propagatedType = propagatedType.getLeastUpperBound(elementType); 7771 propagatedType = propagatedType.getLeastUpperBound(elementType);
7105 if (propagatedType == null) { 7772 if (propagatedType == null) {
7106 propagatedType = _dynamicType; 7773 propagatedType = _dynamicType;
7107 } 7774 }
7108 } 7775 }
7109 } 7776 }
7110 if (propagatedType.isMoreSpecificThan(staticType)) { 7777 if (propagatedType.isMoreSpecificThan(staticType)) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
7143 if (entryValueType != null) { 7810 if (entryValueType != null) {
7144 staticValueType = entryValueType; 7811 staticValueType = entryValueType;
7145 } 7812 }
7146 } 7813 }
7147 } 7814 }
7148 recordStaticType(node, _typeProvider.mapType.substitute4(<Type2> [staticKeyT ype, staticValueType])); 7815 recordStaticType(node, _typeProvider.mapType.substitute4(<Type2> [staticKeyT ype, staticValueType]));
7149 NodeList<MapLiteralEntry> entries = node.entries; 7816 NodeList<MapLiteralEntry> entries = node.entries;
7150 int count = entries.length; 7817 int count = entries.length;
7151 if (count > 0) { 7818 if (count > 0) {
7152 MapLiteralEntry entry = entries[0]; 7819 MapLiteralEntry entry = entries[0];
7153 Type2 propagatedKeyType = getBestType(entry.key); 7820 Type2 propagatedKeyType = entry.key.bestType;
7154 Type2 propagatedValueType = getBestType(entry.value); 7821 Type2 propagatedValueType = entry.value.bestType;
7155 for (int i = 1; i < count; i++) { 7822 for (int i = 1; i < count; i++) {
7156 entry = entries[i]; 7823 entry = entries[i];
7157 Type2 elementKeyType = getBestType(entry.key); 7824 Type2 elementKeyType = entry.key.bestType;
7158 if (propagatedKeyType != elementKeyType) { 7825 if (propagatedKeyType != elementKeyType) {
7159 propagatedKeyType = _dynamicType; 7826 propagatedKeyType = _dynamicType;
7160 } else { 7827 } else {
7161 propagatedKeyType = propagatedKeyType.getLeastUpperBound(elementKeyTyp e); 7828 propagatedKeyType = propagatedKeyType.getLeastUpperBound(elementKeyTyp e);
7162 if (propagatedKeyType == null) { 7829 if (propagatedKeyType == null) {
7163 propagatedKeyType = _dynamicType; 7830 propagatedKeyType = _dynamicType;
7164 } 7831 }
7165 } 7832 }
7166 Type2 elementValueType = getBestType(entry.value); 7833 Type2 elementValueType = entry.value.bestType;
7167 if (propagatedValueType != elementValueType) { 7834 if (propagatedValueType != elementValueType) {
7168 propagatedValueType = _dynamicType; 7835 propagatedValueType = _dynamicType;
7169 } else { 7836 } else {
7170 propagatedValueType = propagatedValueType.getLeastUpperBound(elementVa lueType); 7837 propagatedValueType = propagatedValueType.getLeastUpperBound(elementVa lueType);
7171 if (propagatedValueType == null) { 7838 if (propagatedValueType == null) {
7172 propagatedValueType = _dynamicType; 7839 propagatedValueType = _dynamicType;
7173 } 7840 }
7174 } 7841 }
7175 } 7842 }
7176 bool betterKey = propagatedKeyType != null && propagatedKeyType.isMoreSpec ificThan(staticKeyType); 7843 bool betterKey = propagatedKeyType != null && propagatedKeyType.isMoreSpec ificThan(staticKeyType);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
7232 } 7899 }
7233 Type2 staticStaticType = computeStaticReturnType(staticMethodElement); 7900 Type2 staticStaticType = computeStaticReturnType(staticMethodElement);
7234 recordStaticType(node, staticStaticType); 7901 recordStaticType(node, staticStaticType);
7235 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement ); 7902 Type2 staticPropagatedType = computePropagatedReturnType(staticMethodElement );
7236 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) { 7903 if (staticPropagatedType != null && (staticStaticType == null || staticPropa gatedType.isMoreSpecificThan(staticStaticType))) {
7237 recordPropagatedType2(node, staticPropagatedType); 7904 recordPropagatedType2(node, staticPropagatedType);
7238 } 7905 }
7239 String methodName = methodNameNode.name; 7906 String methodName = methodNameNode.name;
7240 if (methodName == "then") { 7907 if (methodName == "then") {
7241 Expression target = node.realTarget; 7908 Expression target = node.realTarget;
7242 Type2 targetType = target == null ? null : getBestType(target); 7909 Type2 targetType = target == null ? null : target.bestType;
7243 if (isAsyncFutureType(targetType)) { 7910 if (isAsyncFutureType(targetType)) {
7244 NodeList<Expression> arguments = node.argumentList.arguments; 7911 NodeList<Expression> arguments = node.argumentList.arguments;
7245 if (arguments.length == 1) { 7912 if (arguments.length == 1) {
7246 Expression closureArg = arguments[0]; 7913 Expression closureArg = arguments[0];
7247 if (closureArg is FunctionExpression) { 7914 if (closureArg is FunctionExpression) {
7248 FunctionExpression closureExpr = closureArg as FunctionExpression; 7915 FunctionExpression closureExpr = closureArg as FunctionExpression;
7249 Type2 returnType = computePropagatedReturnType(closureExpr.element); 7916 Type2 returnType = computePropagatedReturnType(closureExpr.element);
7250 if (returnType != null) { 7917 if (returnType != null) {
7251 InterfaceTypeImpl newFutureType; 7918 InterfaceTypeImpl newFutureType;
7252 if (isAsyncFutureType(returnType)) { 7919 if (isAsyncFutureType(returnType)) {
7253 newFutureType = returnType as InterfaceTypeImpl; 7920 newFutureType = returnType as InterfaceTypeImpl;
7254 } else { 7921 } else {
7255 InterfaceType futureType = targetType as InterfaceType; 7922 InterfaceType futureType = targetType as InterfaceType;
7256 newFutureType = new InterfaceTypeImpl.con1(futureType.element); 7923 newFutureType = new InterfaceTypeImpl.con1(futureType.element);
7257 newFutureType.typeArguments = <Type2> [returnType]; 7924 newFutureType.typeArguments = <Type2> [returnType];
7258 } 7925 }
7259 recordPropagatedType2(node, newFutureType); 7926 recordPropagatedType2(node, newFutureType);
7260 return null; 7927 return null;
7261 } 7928 }
7262 } 7929 }
7263 } 7930 }
7264 } 7931 }
7265 } 7932 }
7266 if (methodName == "\$dom_createEvent") { 7933 if (methodName == "\$dom_createEvent") {
7267 Expression target = node.realTarget; 7934 Expression target = node.realTarget;
7268 if (target != null) { 7935 if (target != null) {
7269 Type2 targetType = getBestType(target); 7936 Type2 targetType = target.bestType;
7270 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) { 7937 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) {
7271 LibraryElement library = targetType.element.library; 7938 LibraryElement library = targetType.element.library;
7272 if (isHtmlLibrary(library)) { 7939 if (isHtmlLibrary(library)) {
7273 Type2 returnType = getFirstArgumentAsType(library, node.argumentList ); 7940 Type2 returnType = getFirstArgumentAsType(library, node.argumentList );
7274 if (returnType != null) { 7941 if (returnType != null) {
7275 recordPropagatedType2(node, returnType); 7942 recordPropagatedType2(node, returnType);
7276 } 7943 }
7277 } 7944 }
7278 } 7945 }
7279 } 7946 }
7280 } else if (methodName == "query") { 7947 } else if (methodName == "query") {
7281 Expression target = node.realTarget; 7948 Expression target = node.realTarget;
7282 if (target == null) { 7949 if (target == null) {
7283 Element methodElement = methodNameNode.element; 7950 Element methodElement = methodNameNode.element;
7284 if (methodElement != null) { 7951 if (methodElement != null) {
7285 LibraryElement library = methodElement.library; 7952 LibraryElement library = methodElement.library;
7286 if (isHtmlLibrary(library)) { 7953 if (isHtmlLibrary(library)) {
7287 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t); 7954 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t);
7288 if (returnType != null) { 7955 if (returnType != null) {
7289 recordPropagatedType2(node, returnType); 7956 recordPropagatedType2(node, returnType);
7290 } 7957 }
7291 } 7958 }
7292 } 7959 }
7293 } else { 7960 } else {
7294 Type2 targetType = getBestType(target); 7961 Type2 targetType = target.bestType;
7295 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) { 7962 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || targetType.name == "Document")) {
7296 LibraryElement library = targetType.element.library; 7963 LibraryElement library = targetType.element.library;
7297 if (isHtmlLibrary(library)) { 7964 if (isHtmlLibrary(library)) {
7298 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t); 7965 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentLis t);
7299 if (returnType != null) { 7966 if (returnType != null) {
7300 recordPropagatedType2(node, returnType); 7967 recordPropagatedType2(node, returnType);
7301 } 7968 }
7302 } 7969 }
7303 } 7970 }
7304 } 7971 }
7305 } else if (methodName == "\$dom_createElement") { 7972 } else if (methodName == "\$dom_createElement") {
7306 Expression target = node.realTarget; 7973 Expression target = node.realTarget;
7307 Type2 targetType = getBestType(target); 7974 Type2 targetType = target.bestType;
7308 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || t argetType.name == "Document")) { 7975 if (targetType is InterfaceType && (targetType.name == "HtmlDocument" || t argetType.name == "Document")) {
7309 LibraryElement library = targetType.element.library; 7976 LibraryElement library = targetType.element.library;
7310 if (isHtmlLibrary(library)) { 7977 if (isHtmlLibrary(library)) {
7311 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentList) ; 7978 Type2 returnType = getFirstArgumentAsQuery(library, node.argumentList) ;
7312 if (returnType != null) { 7979 if (returnType != null) {
7313 recordPropagatedType2(node, returnType); 7980 recordPropagatedType2(node, returnType);
7314 } 7981 }
7315 } 7982 }
7316 } 7983 }
7317 } else if (methodName == "JS") { 7984 } else if (methodName == "JS") {
(...skipping 12 matching lines...) Expand all
7330 if (propagatedPropagatedType != null && (staticStaticType == null || pro pagatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagated Type == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType )) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificTh an(propagatedStaticType))) { 7997 if (propagatedPropagatedType != null && (staticStaticType == null || pro pagatedPropagatedType.isMoreSpecificThan(staticStaticType)) && (staticPropagated Type == null || propagatedPropagatedType.isMoreSpecificThan(staticPropagatedType )) && (propagatedStaticType == null || propagatedPropagatedType.isMoreSpecificTh an(propagatedStaticType))) {
7331 recordPropagatedType2(node, propagatedPropagatedType); 7998 recordPropagatedType2(node, propagatedPropagatedType);
7332 } 7999 }
7333 } 8000 }
7334 } 8001 }
7335 return null; 8002 return null;
7336 } 8003 }
7337 Object visitNamedExpression(NamedExpression node) { 8004 Object visitNamedExpression(NamedExpression node) {
7338 Expression expression = node.expression; 8005 Expression expression = node.expression;
7339 recordStaticType(node, getStaticType(expression)); 8006 recordStaticType(node, getStaticType(expression));
7340 recordPropagatedType2(node, getPropagatedType(expression)); 8007 recordPropagatedType2(node, expression.propagatedType);
7341 return null; 8008 return null;
7342 } 8009 }
7343 8010
7344 /** 8011 /**
7345 * The Dart Language Specification, 12.2: <blockquote>The static type of `null ` is bottom. 8012 * The Dart Language Specification, 12.2: <blockquote>The static type of `null ` is bottom.
7346 * </blockquote> 8013 * </blockquote>
7347 */ 8014 */
7348 Object visitNullLiteral(NullLiteral node) { 8015 Object visitNullLiteral(NullLiteral node) {
7349 recordStaticType(node, _typeProvider.bottomType); 8016 recordStaticType(node, _typeProvider.bottomType);
7350 return null; 8017 return null;
7351 } 8018 }
7352 Object visitParenthesizedExpression(ParenthesizedExpression node) { 8019 Object visitParenthesizedExpression(ParenthesizedExpression node) {
7353 Expression expression = node.expression; 8020 Expression expression = node.expression;
7354 recordStaticType(node, getStaticType(expression)); 8021 recordStaticType(node, getStaticType(expression));
7355 recordPropagatedType2(node, getPropagatedType(expression)); 8022 recordPropagatedType2(node, expression.propagatedType);
7356 return null; 8023 return null;
7357 } 8024 }
7358 8025
7359 /** 8026 /**
7360 * The Dart Language Specification, 12.28: <blockquote>A postfix expression of the form 8027 * The Dart Language Specification, 12.28: <blockquote>A postfix expression of the form
7361 * <i>v++</i>, where <i>v</i> is an identifier, is equivalent to <i>(){var r = v; v = r + 1; 8028 * <i>v++</i>, where <i>v</i> is an identifier, is equivalent to <i>(){var r = v; v = r + 1;
7362 * return r}()</i>. 8029 * return r}()</i>.
7363 * 8030 *
7364 * A postfix expression of the form <i>C.v++</i> is equivalent to <i>(){var r = C.v; C.v = r + 1; 8031 * A postfix expression of the form <i>C.v++</i> is equivalent to <i>(){var r = C.v; C.v = r + 1;
7365 * return r}()</i>. 8032 * return r}()</i>.
(...skipping 20 matching lines...) Expand all
7386 Expression operand = node.operand; 8053 Expression operand = node.operand;
7387 Type2 staticType = getStaticType(operand); 8054 Type2 staticType = getStaticType(operand);
7388 sc.TokenType operator = node.operator.type; 8055 sc.TokenType operator = node.operator.type;
7389 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, sc. TokenType.PLUS_PLUS)) { 8056 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, sc. TokenType.PLUS_PLUS)) {
7390 Type2 intType = _typeProvider.intType; 8057 Type2 intType = _typeProvider.intType;
7391 if (identical(getStaticType(node.operand), intType)) { 8058 if (identical(getStaticType(node.operand), intType)) {
7392 staticType = intType; 8059 staticType = intType;
7393 } 8060 }
7394 } 8061 }
7395 recordStaticType(node, staticType); 8062 recordStaticType(node, staticType);
7396 recordPropagatedType2(node, getPropagatedType(operand)); 8063 recordPropagatedType2(node, operand.propagatedType);
7397 return null; 8064 return null;
7398 } 8065 }
7399 8066
7400 /** 8067 /**
7401 * See [visitSimpleIdentifier]. 8068 * See [visitSimpleIdentifier].
7402 */ 8069 */
7403 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 8070 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
7404 SimpleIdentifier prefixedIdentifier = node.identifier; 8071 SimpleIdentifier prefixedIdentifier = node.identifier;
7405 Element element = prefixedIdentifier.element; 8072 Element element = prefixedIdentifier.element;
7406 Type2 staticType = _dynamicType; 8073 Type2 staticType = _dynamicType;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
7445 } else { 8112 } else {
7446 ExecutableElement staticMethodElement = node.staticElement; 8113 ExecutableElement staticMethodElement = node.staticElement;
7447 Type2 staticType = computeStaticReturnType(staticMethodElement); 8114 Type2 staticType = computeStaticReturnType(staticMethodElement);
7448 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, s c.TokenType.PLUS_PLUS)) { 8115 if (identical(operator, sc.TokenType.MINUS_MINUS) || identical(operator, s c.TokenType.PLUS_PLUS)) {
7449 Type2 intType = _typeProvider.intType; 8116 Type2 intType = _typeProvider.intType;
7450 if (identical(getStaticType(node.operand), intType)) { 8117 if (identical(getStaticType(node.operand), intType)) {
7451 staticType = intType; 8118 staticType = intType;
7452 } 8119 }
7453 } 8120 }
7454 recordStaticType(node, staticType); 8121 recordStaticType(node, staticType);
7455 MethodElement propagatedMethodElement = node.element; 8122 MethodElement propagatedMethodElement = node.propagatedElement;
7456 if (propagatedMethodElement != staticMethodElement) { 8123 if (propagatedMethodElement != staticMethodElement) {
7457 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement); 8124 Type2 propagatedType = computeStaticReturnType(propagatedMethodElement);
7458 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) { 8125 if (propagatedType != null && propagatedType.isMoreSpecificThan(staticTy pe)) {
7459 recordPropagatedType2(node, propagatedType); 8126 recordPropagatedType2(node, propagatedType);
7460 } 8127 }
7461 } 8128 }
7462 } 8129 }
7463 return null; 8130 return null;
7464 } 8131 }
7465 8132
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
7628 return null; 8295 return null;
7629 } 8296 }
7630 Object visitSuperExpression(SuperExpression node) { 8297 Object visitSuperExpression(SuperExpression node) {
7631 if (_thisType == null) { 8298 if (_thisType == null) {
7632 recordStaticType(node, _dynamicType); 8299 recordStaticType(node, _dynamicType);
7633 } else { 8300 } else {
7634 recordStaticType(node, _thisType); 8301 recordStaticType(node, _thisType);
7635 } 8302 }
7636 return null; 8303 return null;
7637 } 8304 }
8305 Object visitSymbolLiteral(SymbolLiteral node) {
8306 recordStaticType(node, _typeProvider.symbolType);
8307 return null;
8308 }
7638 8309
7639 /** 8310 /**
7640 * The Dart Language Specification, 12.10: <blockquote>The static type of `thi s` is the 8311 * The Dart Language Specification, 12.10: <blockquote>The static type of `thi s` is the
7641 * interface of the immediately enclosing class.</blockquote> 8312 * interface of the immediately enclosing class.</blockquote>
7642 */ 8313 */
7643 Object visitThisExpression(ThisExpression node) { 8314 Object visitThisExpression(ThisExpression node) {
7644 if (_thisType == null) { 8315 if (_thisType == null) {
7645 recordStaticType(node, _dynamicType); 8316 recordStaticType(node, _dynamicType);
7646 } else { 8317 } else {
7647 recordStaticType(node, _thisType); 8318 recordStaticType(node, _thisType);
7648 } 8319 }
7649 return null; 8320 return null;
7650 } 8321 }
7651 8322
7652 /** 8323 /**
7653 * The Dart Language Specification, 12.8: <blockquote>The static type of a thr ow expression is 8324 * The Dart Language Specification, 12.8: <blockquote>The static type of a thr ow expression is
7654 * bottom.</blockquote> 8325 * bottom.</blockquote>
7655 */ 8326 */
7656 Object visitThrowExpression(ThrowExpression node) { 8327 Object visitThrowExpression(ThrowExpression node) {
7657 recordStaticType(node, _typeProvider.bottomType); 8328 recordStaticType(node, _typeProvider.bottomType);
7658 return null; 8329 return null;
7659 } 8330 }
7660 Object visitVariableDeclaration(VariableDeclaration node) { 8331 Object visitVariableDeclaration(VariableDeclaration node) {
7661 Expression initializer = node.initializer; 8332 Expression initializer = node.initializer;
7662 if (initializer != null) { 8333 if (initializer != null) {
7663 Type2 rightType = getBestType(initializer); 8334 Type2 rightType = initializer.bestType;
7664 SimpleIdentifier name = node.name; 8335 SimpleIdentifier name = node.name;
7665 recordPropagatedType2(name, rightType); 8336 recordPropagatedType2(name, rightType);
7666 VariableElement element = name.element as VariableElement; 8337 VariableElement element = name.element as VariableElement;
7667 if (element != null) { 8338 if (element != null) {
7668 _resolver.override(element, rightType); 8339 _resolver.override(element, rightType);
7669 } 8340 }
7670 } 8341 }
7671 return null; 8342 return null;
7672 } 8343 }
7673 8344
(...skipping 30 matching lines...) Expand all
7704 * Given a function body, compute the propagated return type of the function. The propagated 8375 * Given a function body, compute the propagated return type of the function. The propagated
7705 * return type of functions with a block body is the least upper bound of all 8376 * return type of functions with a block body is the least upper bound of all
7706 * [ReturnStatement] expressions, with an expression body it is the type of th e expression. 8377 * [ReturnStatement] expressions, with an expression body it is the type of th e expression.
7707 * 8378 *
7708 * @param body the boy of the function whose propagated return type is to be c omputed 8379 * @param body the boy of the function whose propagated return type is to be c omputed
7709 * @return the propagated return type that was computed 8380 * @return the propagated return type that was computed
7710 */ 8381 */
7711 Type2 computePropagatedReturnType2(FunctionBody body) { 8382 Type2 computePropagatedReturnType2(FunctionBody body) {
7712 if (body is ExpressionFunctionBody) { 8383 if (body is ExpressionFunctionBody) {
7713 ExpressionFunctionBody expressionBody = body as ExpressionFunctionBody; 8384 ExpressionFunctionBody expressionBody = body as ExpressionFunctionBody;
7714 return getBestType(expressionBody.expression); 8385 return expressionBody.expression.bestType;
7715 } 8386 }
7716 if (body is BlockFunctionBody) { 8387 if (body is BlockFunctionBody) {
7717 List<Type2> result = [null]; 8388 List<Type2> result = [null];
7718 body.accept(new GeneralizingASTVisitor_8(this, result)); 8389 body.accept(new GeneralizingASTVisitor_8(result));
7719 return result[0]; 8390 return result[0];
7720 } 8391 }
7721 return null; 8392 return null;
7722 } 8393 }
7723 8394
7724 /** 8395 /**
7725 * Compute the static return type of the method or function represented by the given element. 8396 * Compute the static return type of the method or function represented by the given element.
7726 * 8397 *
7727 * @param element the element representing the method or function invoked by t he given node 8398 * @param element the element representing the method or function invoked by t he given node
7728 * @return the static return type that was computed 8399 * @return the static return type that was computed
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
7792 */ 8463 */
7793 Type2 computeStaticReturnType3(FunctionExpression node) { 8464 Type2 computeStaticReturnType3(FunctionExpression node) {
7794 FunctionBody body = node.body; 8465 FunctionBody body = node.body;
7795 if (body is ExpressionFunctionBody) { 8466 if (body is ExpressionFunctionBody) {
7796 return getStaticType(((body as ExpressionFunctionBody)).expression); 8467 return getStaticType(((body as ExpressionFunctionBody)).expression);
7797 } 8468 }
7798 return _dynamicType; 8469 return _dynamicType;
7799 } 8470 }
7800 8471
7801 /** 8472 /**
7802 * Return the propagated type of the given expression if it is available, or t he static type if
7803 * there is no propagated type.
7804 *
7805 * @param expression the expression whose type is to be returned
7806 * @return the propagated or static type of the given expression
7807 */
7808 Type2 getBestType(Expression expression) {
7809 Type2 type = expression.propagatedType;
7810 if (type == null) {
7811 type = expression.staticType;
7812 if (type == null) {
7813 return _dynamicType;
7814 }
7815 }
7816 return type;
7817 }
7818
7819 /**
7820 * If the given element name can be mapped to the name of a class defined with in the given 8473 * If the given element name can be mapped to the name of a class defined with in the given
7821 * library, return the type specified by the argument. 8474 * library, return the type specified by the argument.
7822 * 8475 *
7823 * @param library the library in which the specified type would be defined 8476 * @param library the library in which the specified type would be defined
7824 * @param elementName the name of the element for which a type is being sought 8477 * @param elementName the name of the element for which a type is being sought
7825 * @param nameMap an optional map used to map the element name to a type name 8478 * @param nameMap an optional map used to map the element name to a type name
7826 * @return the type specified by the first argument in the argument list 8479 * @return the type specified by the first argument in the argument list
7827 */ 8480 */
7828 Type2 getElementNameAsType(LibraryElement library, String elementName, Map<Str ing, String> nameMap) { 8481 Type2 getElementNameAsType(LibraryElement library, String elementName, Map<Str ing, String> nameMap) {
7829 if (elementName != null) { 8482 if (elementName != null) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
7902 * given library, return the type specified by the argument. 8555 * given library, return the type specified by the argument.
7903 * 8556 *
7904 * @param library the library in which the specified type would be defined 8557 * @param library the library in which the specified type would be defined
7905 * @param argumentList the list of arguments from which a type is to be extrac ted 8558 * @param argumentList the list of arguments from which a type is to be extrac ted
7906 * @param nameMap an optional map used to map the element name to a type name 8559 * @param nameMap an optional map used to map the element name to a type name
7907 * @return the type specified by the first argument in the argument list 8560 * @return the type specified by the first argument in the argument list
7908 */ 8561 */
7909 Type2 getFirstArgumentAsType2(LibraryElement library, ArgumentList argumentLis t, Map<String, String> nameMap) => getElementNameAsType(library, getFirstArgumen tAsString(argumentList), nameMap); 8562 Type2 getFirstArgumentAsType2(LibraryElement library, ArgumentList argumentLis t, Map<String, String> nameMap) => getElementNameAsType(library, getFirstArgumen tAsString(argumentList), nameMap);
7910 8563
7911 /** 8564 /**
7912 * Return the propagated type of the given expression.
7913 *
7914 * @param expression the expression whose type is to be returned
7915 * @return the propagated type of the given expression
7916 */
7917 Type2 getPropagatedType(Expression expression) {
7918 Type2 type = expression.propagatedType;
7919 return type;
7920 }
7921
7922 /**
7923 * Return the static type of the given expression. 8565 * Return the static type of the given expression.
7924 * 8566 *
7925 * @param expression the expression whose type is to be returned 8567 * @param expression the expression whose type is to be returned
7926 * @return the static type of the given expression 8568 * @return the static type of the given expression
7927 */ 8569 */
7928 Type2 getStaticType(Expression expression) { 8570 Type2 getStaticType(Expression expression) {
7929 Type2 type = expression.staticType; 8571 Type2 type = expression.staticType;
7930 if (type == null) { 8572 if (type == null) {
7931 return _dynamicType; 8573 return _dynamicType;
7932 } 8574 }
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
8098 if (identical(getStaticType(node.leftOperand), intType) && identical(getSt aticType(node.rightOperand), intType)) { 8740 if (identical(getStaticType(node.leftOperand), intType) && identical(getSt aticType(node.rightOperand), intType)) {
8099 staticType = intType; 8741 staticType = intType;
8100 } 8742 }
8101 } 8743 }
8102 return staticType; 8744 return staticType;
8103 } 8745 }
8104 get thisType_J2DAccessor => _thisType; 8746 get thisType_J2DAccessor => _thisType;
8105 set thisType_J2DAccessor(__v) => _thisType = __v; 8747 set thisType_J2DAccessor(__v) => _thisType = __v;
8106 } 8748 }
8107 class GeneralizingASTVisitor_8 extends GeneralizingASTVisitor<Object> { 8749 class GeneralizingASTVisitor_8 extends GeneralizingASTVisitor<Object> {
8108 final StaticTypeAnalyzer StaticTypeAnalyzer_this;
8109 List<Type2> result; 8750 List<Type2> result;
8110 GeneralizingASTVisitor_8(this.StaticTypeAnalyzer_this, this.result) : super(); 8751 GeneralizingASTVisitor_8(this.result) : super();
8111 Object visitExpression(Expression node) => null; 8752 Object visitExpression(Expression node) => null;
8112 Object visitReturnStatement(ReturnStatement node) { 8753 Object visitReturnStatement(ReturnStatement node) {
8113 Type2 type; 8754 Type2 type;
8114 Expression expression = node.expression; 8755 Expression expression = node.expression;
8115 if (expression != null) { 8756 if (expression != null) {
8116 type = StaticTypeAnalyzer_this.getBestType(expression); 8757 type = expression.bestType;
8117 } else { 8758 } else {
8118 type = BottomTypeImpl.instance; 8759 type = BottomTypeImpl.instance;
8119 } 8760 }
8120 if (result[0] == null) { 8761 if (result[0] == null) {
8121 result[0] = type; 8762 result[0] = type;
8122 } else { 8763 } else {
8123 result[0] = result[0].getLeastUpperBound(type); 8764 result[0] = result[0].getLeastUpperBound(type);
8124 } 8765 }
8125 return null; 8766 return null;
8126 } 8767 }
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
8631 } 9272 }
8632 return null; 9273 return null;
8633 } 9274 }
8634 Object visitClassDeclaration(ClassDeclaration node) { 9275 Object visitClassDeclaration(ClassDeclaration node) {
8635 _hasReferenceToSuper = false; 9276 _hasReferenceToSuper = false;
8636 super.visitClassDeclaration(node); 9277 super.visitClassDeclaration(node);
8637 ClassElementImpl classElement = getClassElement(node.name); 9278 ClassElementImpl classElement = getClassElement(node.name);
8638 InterfaceType superclassType = null; 9279 InterfaceType superclassType = null;
8639 ExtendsClause extendsClause = node.extendsClause; 9280 ExtendsClause extendsClause = node.extendsClause;
8640 if (extendsClause != null) { 9281 if (extendsClause != null) {
8641 ErrorCode errorCode = node.withClause == null ? CompileTimeErrorCode.EXTEN DS_NON_CLASS : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS; 9282 ErrorCode errorCode = (node.withClause == null ? CompileTimeErrorCode.EXTE NDS_NON_CLASS : CompileTimeErrorCode.MIXIN_WITH_NON_CLASS_SUPERCLASS) as ErrorCo de;
8642 superclassType = resolveType(extendsClause.superclass, errorCode, errorCod e); 9283 superclassType = resolveType(extendsClause.superclass, errorCode, errorCod e);
8643 if (superclassType != typeProvider.objectType) { 9284 if (superclassType != typeProvider.objectType) {
8644 classElement.validMixin = false; 9285 classElement.validMixin = false;
8645 } 9286 }
8646 } 9287 }
8647 if (classElement != null) { 9288 if (classElement != null) {
8648 if (superclassType == null) { 9289 if (superclassType == null) {
8649 InterfaceType objectType = typeProvider.objectType; 9290 InterfaceType objectType = typeProvider.objectType;
8650 if (classElement.type != objectType) { 9291 if (classElement.type != objectType) {
8651 superclassType = objectType; 9292 superclassType = objectType;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
8819 if (name.name == null) { 9460 if (name.name == null) {
8820 PrefixedIdentifier prefixedIdentifier = typeName as PrefixedIdentifier ; 9461 PrefixedIdentifier prefixedIdentifier = typeName as PrefixedIdentifier ;
8821 SimpleIdentifier prefix = prefixedIdentifier.prefix; 9462 SimpleIdentifier prefix = prefixedIdentifier.prefix;
8822 element = nameScope.lookup(prefix, definingLibrary); 9463 element = nameScope.lookup(prefix, definingLibrary);
8823 if (element is PrefixElement) { 9464 if (element is PrefixElement) {
8824 if (parent.parent is InstanceCreationExpression && ((parent.parent a s InstanceCreationExpression)).isConst) { 9465 if (parent.parent is InstanceCreationExpression && ((parent.parent a s InstanceCreationExpression)).isConst) {
8825 reportError(CompileTimeErrorCode.CONST_WITH_NON_TYPE, prefixedIden tifier.identifier, [prefixedIdentifier.identifier.name]); 9466 reportError(CompileTimeErrorCode.CONST_WITH_NON_TYPE, prefixedIden tifier.identifier, [prefixedIdentifier.identifier.name]);
8826 } else { 9467 } else {
8827 reportError(StaticWarningCode.NEW_WITH_NON_TYPE, prefixedIdentifie r.identifier, [prefixedIdentifier.identifier.name]); 9468 reportError(StaticWarningCode.NEW_WITH_NON_TYPE, prefixedIdentifie r.identifier, [prefixedIdentifier.identifier.name]);
8828 } 9469 }
9470 setElement(prefix, element);
8829 return null; 9471 return null;
8830 } else if (element != null) { 9472 } else if (element != null) {
8831 name.name = prefixedIdentifier.identifier; 9473 name.name = prefixedIdentifier.identifier;
8832 name.period = prefixedIdentifier.period; 9474 name.period = prefixedIdentifier.period;
8833 node.name = prefix; 9475 node.name = prefix;
8834 typeName = prefix; 9476 typeName = prefix;
8835 } 9477 }
8836 } 9478 }
8837 } 9479 }
8838 } 9480 }
(...skipping 28 matching lines...) Expand all
8867 } else if (isTypeNameTargetInRedirectedConstructor(node)) { 9509 } else if (isTypeNameTargetInRedirectedConstructor(node)) {
8868 reportError(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName .name]); 9510 reportError(StaticWarningCode.REDIRECT_TO_NON_CLASS, typeName, [typeName .name]);
8869 } else if (isTypeNameInTypeArgumentList(node)) { 9511 } else if (isTypeNameInTypeArgumentList(node)) {
8870 reportError(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [ typeName.name]); 9512 reportError(StaticTypeWarningCode.NON_TYPE_AS_TYPE_ARGUMENT, typeName, [ typeName.name]);
8871 } else { 9513 } else {
8872 reportError(StaticWarningCode.UNDEFINED_CLASS, typeName, [typeName.name] ); 9514 reportError(StaticWarningCode.UNDEFINED_CLASS, typeName, [typeName.name] );
8873 } 9515 }
8874 elementValid = false; 9516 elementValid = false;
8875 } 9517 }
8876 if (!elementValid) { 9518 if (!elementValid) {
8877 setElement(typeName, _dynamicType.element); 9519 if (element is MultiplyDefinedElement) {
9520 setElement(typeName, element);
9521 } else {
9522 setElement(typeName, _dynamicType.element);
9523 }
8878 typeName.staticType = _dynamicType; 9524 typeName.staticType = _dynamicType;
8879 node.type = _dynamicType; 9525 node.type = _dynamicType;
8880 return null; 9526 return null;
8881 } 9527 }
8882 Type2 type = null; 9528 Type2 type = null;
8883 if (element is ClassElement) { 9529 if (element is ClassElement) {
8884 setElement(typeName, element); 9530 setElement(typeName, element);
8885 type = ((element as ClassElement)).type; 9531 type = ((element as ClassElement)).type;
8886 } else if (element is FunctionTypeAliasElement) { 9532 } else if (element is FunctionTypeAliasElement) {
8887 setElement(typeName, element); 9533 setElement(typeName, element);
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after
9362 * list and associate the created type with the element. 10008 * list and associate the created type with the element.
9363 * 10009 *
9364 * @param element the parameter element whose type is to be set 10010 * @param element the parameter element whose type is to be set
9365 * @param returnType the (possibly `null`) return type of the function 10011 * @param returnType the (possibly `null`) return type of the function
9366 * @param parameterList the list of parameters to the function 10012 * @param parameterList the list of parameters to the function
9367 */ 10013 */
9368 void setFunctionTypedParameterType(ParameterElementImpl element, TypeName retu rnType2, FormalParameterList parameterList) { 10014 void setFunctionTypedParameterType(ParameterElementImpl element, TypeName retu rnType2, FormalParameterList parameterList) {
9369 List<ParameterElement> parameters = getElements(parameterList); 10015 List<ParameterElement> parameters = getElements(parameterList);
9370 FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl (null); 10016 FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl (null);
9371 aliasElement.synthetic = true; 10017 aliasElement.synthetic = true;
9372 aliasElement.parameters = parameters; 10018 aliasElement.shareParameters(parameters);
9373 aliasElement.returnType = computeReturnType(returnType2); 10019 aliasElement.returnType = computeReturnType(returnType2);
9374 FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement); 10020 FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement);
9375 ClassElement definingClass = element.getAncestor(ClassElement); 10021 ClassElement definingClass = element.getAncestor(ClassElement);
9376 if (definingClass != null) { 10022 if (definingClass != null) {
9377 aliasElement.typeVariables = definingClass.typeVariables; 10023 aliasElement.shareTypeVariables(definingClass.typeVariables);
9378 type.typeArguments = definingClass.type.typeArguments; 10024 type.typeArguments = definingClass.type.typeArguments;
9379 } else { 10025 } else {
9380 FunctionTypeAliasElement alias = element.getAncestor(FunctionTypeAliasElem ent); 10026 FunctionTypeAliasElement alias = element.getAncestor(FunctionTypeAliasElem ent);
9381 while (alias != null && alias.isSynthetic) { 10027 while (alias != null && alias.isSynthetic) {
9382 alias = alias.getAncestor(FunctionTypeAliasElement); 10028 alias = alias.getAncestor(FunctionTypeAliasElement);
9383 } 10029 }
9384 if (alias != null) { 10030 if (alias != null) {
9385 aliasElement.typeVariables = alias.typeVariables; 10031 aliasElement.typeVariables = alias.typeVariables;
9386 type.typeArguments = alias.type.typeArguments; 10032 type.typeArguments = alias.type.typeArguments;
9387 } else { 10033 } else {
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
9647 } 10293 }
9648 /** 10294 /**
9649 * Instances of the class `LibraryImportScope` represent the scope containing al l of the names 10295 * Instances of the class `LibraryImportScope` represent the scope containing al l of the names
9650 * available from imported libraries. 10296 * available from imported libraries.
9651 * 10297 *
9652 * @coverage dart.engine.resolver 10298 * @coverage dart.engine.resolver
9653 */ 10299 */
9654 class LibraryImportScope extends Scope { 10300 class LibraryImportScope extends Scope {
9655 10301
9656 /** 10302 /**
9657 * @return `true` if the given [Identifier] is the part of type annotation.
9658 */
9659 static bool isTypeAnnotation(Identifier identifier) {
9660 ASTNode parent = identifier.parent;
9661 if (parent is TypeName) {
9662 ASTNode parent2 = parent.parent;
9663 if (parent2 is FunctionDeclaration) {
9664 FunctionDeclaration decl = parent2 as FunctionDeclaration;
9665 return identical(decl.returnType, parent);
9666 }
9667 if (parent2 is FunctionTypeAlias) {
9668 FunctionTypeAlias decl = parent2 as FunctionTypeAlias;
9669 return identical(decl.returnType, parent);
9670 }
9671 if (parent2 is MethodDeclaration) {
9672 MethodDeclaration decl = parent2 as MethodDeclaration;
9673 return identical(decl.returnType, parent);
9674 }
9675 if (parent2 is VariableDeclarationList) {
9676 VariableDeclarationList decl = parent2 as VariableDeclarationList;
9677 return identical(decl.type, parent);
9678 }
9679 if (parent2 is SimpleFormalParameter) {
9680 SimpleFormalParameter decl = parent2 as SimpleFormalParameter;
9681 return identical(decl.type, parent);
9682 }
9683 if (parent2 is TypeParameter) {
9684 TypeParameter decl = parent2 as TypeParameter;
9685 return identical(decl.bound, parent);
9686 }
9687 if (parent2 is TypeArgumentList) {
9688 ASTNode parent3 = parent2.parent;
9689 if (parent3 is TypeName) {
9690 TypeName typeName = parent3 as TypeName;
9691 if (identical((typeName).typeArguments, parent2)) {
9692 return isTypeAnnotation(typeName.name);
9693 }
9694 }
9695 }
9696 return false;
9697 }
9698 return false;
9699 }
9700
9701 /**
9702 * The element representing the library in which this scope is enclosed. 10303 * The element representing the library in which this scope is enclosed.
9703 */ 10304 */
9704 LibraryElement _definingLibrary; 10305 LibraryElement _definingLibrary;
9705 10306
9706 /** 10307 /**
9707 * The listener that is to be informed when an error is encountered. 10308 * The listener that is to be informed when an error is encountered.
9708 */ 10309 */
9709 AnalysisErrorListener _errorListener; 10310 AnalysisErrorListener _errorListener;
9710 10311
9711 /** 10312 /**
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
9753 String libName1 = "", libName2 = ""; 10354 String libName1 = "", libName2 = "";
9754 List<Element> conflictingMembers = ((foundElement as MultiplyDefinedElemen tImpl)).conflictingElements; 10355 List<Element> conflictingMembers = ((foundElement as MultiplyDefinedElemen tImpl)).conflictingElements;
9755 LibraryElement enclosingLibrary = conflictingMembers[0].getAncestor(Librar yElement); 10356 LibraryElement enclosingLibrary = conflictingMembers[0].getAncestor(Librar yElement);
9756 if (enclosingLibrary != null) { 10357 if (enclosingLibrary != null) {
9757 libName1 = enclosingLibrary.definingCompilationUnit.displayName; 10358 libName1 = enclosingLibrary.definingCompilationUnit.displayName;
9758 } 10359 }
9759 enclosingLibrary = conflictingMembers[1].getAncestor(LibraryElement); 10360 enclosingLibrary = conflictingMembers[1].getAncestor(LibraryElement);
9760 if (enclosingLibrary != null) { 10361 if (enclosingLibrary != null) {
9761 libName2 = enclosingLibrary.definingCompilationUnit.displayName; 10362 libName2 = enclosingLibrary.definingCompilationUnit.displayName;
9762 } 10363 }
9763 ErrorCode errorCode = isTypeAnnotation(identifier) ? StaticWarningCode.AMB IGUOUS_IMPORT : CompileTimeErrorCode.AMBIGUOUS_IMPORT; 10364 _errorListener.onError(new AnalysisError.con2(source, identifier.offset, i dentifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, l ibName2]));
9764 _errorListener.onError(new AnalysisError.con2(source, identifier.offset, i dentifier.length, errorCode, [foundEltName, libName1, libName2]));
9765 return foundElement; 10365 return foundElement;
9766 } 10366 }
9767 if (foundElement != null) { 10367 if (foundElement != null) {
9768 defineWithoutChecking2(name, foundElement); 10368 defineWithoutChecking2(name, foundElement);
9769 } 10369 }
9770 return foundElement; 10370 return foundElement;
9771 } 10371 }
9772 10372
9773 /** 10373 /**
9774 * Create all of the namespaces associated with the libraries imported into th is library. The 10374 * Create all of the namespaces associated with the libraries imported into th is library. The
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
10295 * Instances of the class `ConstantVerifier` traverse an AST structure looking f or additional 10895 * Instances of the class `ConstantVerifier` traverse an AST structure looking f or additional
10296 * errors and warnings not covered by the parser and resolver. In particular, it looks for errors 10896 * errors and warnings not covered by the parser and resolver. In particular, it looks for errors
10297 * and warnings related to constant expressions. 10897 * and warnings related to constant expressions.
10298 * 10898 *
10299 * @coverage dart.engine.resolver 10899 * @coverage dart.engine.resolver
10300 */ 10900 */
10301 class ConstantVerifier extends RecursiveASTVisitor<Object> { 10901 class ConstantVerifier extends RecursiveASTVisitor<Object> {
10302 10902
10303 /** 10903 /**
10304 * The error reporter by which errors will be reported. 10904 * The error reporter by which errors will be reported.
10305 */
10306 ErrorReporter _errorReporter;
10307
10308 /**
10309 * The type representing the type 'bool'.
10310 */
10311 InterfaceType _boolType;
10312
10313 /**
10314 * The type representing the type 'int'.
10315 */
10316 InterfaceType _intType;
10317
10318 /**
10319 * The type representing the type 'num'.
10320 */
10321 InterfaceType _numType;
10322
10323 /**
10324 * The type representing the type 'string'.
10325 */
10326 InterfaceType _stringType;
10327
10328 /**
10329 * Initialize a newly created constant verifier.
10330 *
10331 * @param errorReporter the error reporter by which errors will be reported
10332 */
10333 ConstantVerifier(ErrorReporter errorReporter, TypeProvider typeProvider) {
10334 this._errorReporter = errorReporter;
10335 this._boolType = typeProvider.boolType;
10336 this._intType = typeProvider.intType;
10337 this._numType = typeProvider.numType;
10338 this._stringType = typeProvider.stringType;
10339 }
10340 Object visitAnnotation(Annotation node) {
10341 super.visitAnnotation(node);
10342 Element element = node.element;
10343 if (element is ConstructorElement) {
10344 ConstructorElement constructorElement = element as ConstructorElement;
10345 if (!constructorElement.isConst) {
10346 _errorReporter.reportError2(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION _CONSTRUCTOR, node, []);
10347 return null;
10348 }
10349 ArgumentList argumentList = node.arguments;
10350 if (argumentList == null) {
10351 _errorReporter.reportError2(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCT OR_ARGUMENTS, node, []);
10352 return null;
10353 }
10354 validateConstantArguments(argumentList);
10355 }
10356 return null;
10357 }
10358 Object visitConstructorDeclaration(ConstructorDeclaration node) {
10359 if (node.constKeyword != null) {
10360 validateInitializers(node);
10361 }
10362 validateDefaultValues(node.parameters);
10363 return super.visitConstructorDeclaration(node);
10364 }
10365 Object visitFunctionExpression(FunctionExpression node) {
10366 super.visitFunctionExpression(node);
10367 validateDefaultValues(node.parameters);
10368 return null;
10369 }
10370 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
10371 validateConstantArguments2(node);
10372 return super.visitInstanceCreationExpression(node);
10373 }
10374 Object visitListLiteral(ListLiteral node) {
10375 super.visitListLiteral(node);
10376 if (node.modifier != null) {
10377 for (Expression element in node.elements) {
10378 validate(element, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
10379 }
10380 }
10381 return null;
10382 }
10383 Object visitMapLiteral(MapLiteral node) {
10384 super.visitMapLiteral(node);
10385 bool isConst = node.modifier != null;
10386 bool reportEqualKeys = true;
10387 Set<Object> keys = new Set<Object>();
10388 List<Expression> invalidKeys = new List<Expression>();
10389 for (MapLiteralEntry entry in node.entries) {
10390 Expression key = entry.key;
10391 if (isConst) {
10392 EvaluationResultImpl result = validate(key, CompileTimeErrorCode.NON_CON STANT_MAP_KEY);
10393 validate(entry.value, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
10394 if (result is ValidResult) {
10395 Object value = ((result as ValidResult)).value;
10396 if (keys.contains(value)) {
10397 invalidKeys.add(key);
10398 } else {
10399 javaSetAdd(keys, value);
10400 }
10401 }
10402 } else {
10403 EvaluationResultImpl result = key.accept(new ConstantVisitor());
10404 if (result is ValidResult) {
10405 Object value = ((result as ValidResult)).value;
10406 if (keys.contains(value)) {
10407 invalidKeys.add(key);
10408 } else {
10409 javaSetAdd(keys, value);
10410 }
10411 } else {
10412 reportEqualKeys = false;
10413 }
10414 }
10415 }
10416 if (reportEqualKeys) {
10417 for (Expression key in invalidKeys) {
10418 _errorReporter.reportError2(StaticWarningCode.EQUAL_KEYS_IN_MAP, key, [] );
10419 }
10420 }
10421 return null;
10422 }
10423 Object visitMethodDeclaration(MethodDeclaration node) {
10424 super.visitMethodDeclaration(node);
10425 validateDefaultValues(node.parameters);
10426 return null;
10427 }
10428 Object visitSwitchCase(SwitchCase node) {
10429 super.visitSwitchCase(node);
10430 validate(node.expression, CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION) ;
10431 return null;
10432 }
10433 Object visitVariableDeclaration(VariableDeclaration node) {
10434 super.visitVariableDeclaration(node);
10435 Expression initializer = node.initializer;
10436 if (initializer != null && node.isConst) {
10437 VariableElementImpl element = node.element as VariableElementImpl;
10438 EvaluationResultImpl result = element.evaluationResult;
10439 if (result == null) {
10440 result = validate(initializer, CompileTimeErrorCode.CONST_INITIALIZED_WI TH_NON_CONSTANT_VALUE);
10441 element.evaluationResult = result;
10442 } else if (result is ErrorResult) {
10443 reportErrors(result, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CON STANT_VALUE);
10444 }
10445 }
10446 return null;
10447 }
10448
10449 /**
10450 * Return `true` if the given value is the result of evaluating an expression whose value is
10451 * a valid key in a const map literal. Keys in const map literals must be eith er a string, number,
10452 * boolean, list, map, or null.
10453 *
10454 * @param value
10455 * @return `true` if the given value is a valid key in a const map literal
10456 */
10457 bool isValidConstMapKey(Object value) => true;
10458
10459 /**
10460 * If the given result represents one or more errors, report those errors. Exc ept for special
10461 * cases, use the given error code rather than the one reported in the error.
10462 *
10463 * @param result the result containing any errors that need to be reported
10464 * @param errorCode the error code to be used if the result represents an erro r
10465 */
10466 void reportErrors(EvaluationResultImpl result, ErrorCode errorCode2) {
10467 if (result is ErrorResult) {
10468 for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) {
10469 ErrorCode dataErrorCode = data.errorCode;
10470 if (identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCE PTION) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRIN G) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || ide ntical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dat aErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM)) {
10471 _errorReporter.reportError2(dataErrorCode, data.node, []);
10472 } else {
10473 _errorReporter.reportError2(errorCode2, data.node, []);
10474 }
10475 }
10476 }
10477 }
10478
10479 /**
10480 * Validate that the given expression is a compile time constant. Return the v alue of the compile
10481 * time constant, or `null` if the expression is not a compile time constant.
10482 *
10483 * @param expression the expression to be validated
10484 * @param errorCode the error code to be used if the expression is not a compi le time constant
10485 * @return the value of the compile time constant
10486 */
10487 EvaluationResultImpl validate(Expression expression, ErrorCode errorCode) {
10488 EvaluationResultImpl result = expression.accept(new ConstantVisitor());
10489 reportErrors(result, errorCode);
10490 return result;
10491 }
10492
10493 /**
10494 * Validate that if the passed arguments are constant expressions.
10495 *
10496 * @param argumentList the argument list to evaluate
10497 */
10498 void validateConstantArguments(ArgumentList argumentList) {
10499 for (Expression argument in argumentList.arguments) {
10500 if (argument is NamedExpression) {
10501 argument = ((argument as NamedExpression)).expression;
10502 }
10503 validate(argument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
10504 }
10505 }
10506
10507 /**
10508 * Validate that if the passed instance creation is 'const' then all its argum ents are constant
10509 * expressions.
10510 *
10511 * @param node the instance creation evaluate
10512 */
10513 void validateConstantArguments2(InstanceCreationExpression node) {
10514 if (!node.isConst) {
10515 return;
10516 }
10517 ArgumentList argumentList = node.argumentList;
10518 if (argumentList == null) {
10519 return;
10520 }
10521 validateConstantArguments(argumentList);
10522 }
10523
10524 /**
10525 * Validate that the default value associated with each of the parameters in t he given list is a
10526 * compile time constant.
10527 *
10528 * @param parameters the list of parameters to be validated
10529 */
10530 void validateDefaultValues(FormalParameterList parameters2) {
10531 if (parameters2 == null) {
10532 return;
10533 }
10534 for (FormalParameter parameter in parameters2.parameters) {
10535 if (parameter is DefaultFormalParameter) {
10536 DefaultFormalParameter defaultParameter = parameter as DefaultFormalPara meter;
10537 Expression defaultValue = defaultParameter.defaultValue;
10538 if (defaultValue != null) {
10539 EvaluationResultImpl result = validate(defaultValue, CompileTimeErrorC ode.NON_CONSTANT_DEFAULT_VALUE);
10540 VariableElementImpl element = parameter.element as VariableElementImpl ;
10541 element.evaluationResult = result;
10542 }
10543 }
10544 }
10545 }
10546
10547 /**
10548 * Validates that the given expression is a compile time constant.
10549 *
10550 * @param parameterElements the elements of parameters of constant constructor , they are
10551 * considered as a valid potentially constant expressions
10552 * @param expression the expression to validate
10553 */
10554 void validateInitializerExpression(List<ParameterElement> parameterElements, E xpression expression) {
10555 EvaluationResultImpl result = expression.accept(new ConstantVisitor_10(this, parameterElements));
10556 reportErrors(result, CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER) ;
10557 }
10558
10559 /**
10560 * Validates that all of the arguments of a constructor initializer are compil e time constants.
10561 *
10562 * @param parameterElements the elements of parameters of constant constructor , they are
10563 * considered as a valid potentially constant expressions
10564 * @param argumentList the argument list to validate
10565 */
10566 void validateInitializerInvocationArguments(List<ParameterElement> parameterEl ements, ArgumentList argumentList) {
10567 if (argumentList == null) {
10568 return;
10569 }
10570 for (Expression argument in argumentList.arguments) {
10571 validateInitializerExpression(parameterElements, argument);
10572 }
10573 }
10574
10575 /**
10576 * Validates that the expressions of the given initializers (of a constant con structor) are all
10577 * compile time constants.
10578 *
10579 * @param constructor the constant constructor declaration to validate
10580 */
10581 void validateInitializers(ConstructorDeclaration constructor) {
10582 List<ParameterElement> parameterElements = constructor.parameters.elements;
10583 NodeList<ConstructorInitializer> initializers = constructor.initializers;
10584 for (ConstructorInitializer initializer in initializers) {
10585 if (initializer is ConstructorFieldInitializer) {
10586 ConstructorFieldInitializer fieldInitializer = initializer as Constructo rFieldInitializer;
10587 validateInitializerExpression(parameterElements, fieldInitializer.expres sion);
10588 }
10589 if (initializer is RedirectingConstructorInvocation) {
10590 RedirectingConstructorInvocation invocation = initializer as Redirecting ConstructorInvocation;
10591 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
10592 }
10593 if (initializer is SuperConstructorInvocation) {
10594 SuperConstructorInvocation invocation = initializer as SuperConstructorI nvocation;
10595 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
10596 }
10597 }
10598 }
10599 }
10600 class ConstantVisitor_10 extends ConstantVisitor {
10601 final ConstantVerifier ConstantVerifier_this;
10602 List<ParameterElement> parameterElements;
10603 ConstantVisitor_10(this.ConstantVerifier_this, this.parameterElements) : super ();
10604 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
10605 Element element = node.element;
10606 for (ParameterElement parameterElement in parameterElements) {
10607 if (identical(parameterElement, element) && parameterElement != null) {
10608 Type2 type = parameterElement.type;
10609 if (type != null) {
10610 if (type.isDynamic) {
10611 return ValidResult.RESULT_DYNAMIC;
10612 }
10613 if (type.isSubtypeOf(ConstantVerifier_this._boolType)) {
10614 return ValidResult.RESULT_BOOL;
10615 }
10616 if (type.isSubtypeOf(ConstantVerifier_this._intType)) {
10617 return ValidResult.RESULT_INT;
10618 }
10619 if (type.isSubtypeOf(ConstantVerifier_this._numType)) {
10620 return ValidResult.RESULT_NUM;
10621 }
10622 if (type.isSubtypeOf(ConstantVerifier_this._stringType)) {
10623 return ValidResult.RESULT_STRING;
10624 }
10625 }
10626 return ValidResult.RESULT_OBJECT;
10627 }
10628 }
10629 return super.visitSimpleIdentifier(node);
10630 }
10631 }
10632 /**
10633 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f or cases of
10634 * [HintCode#DEAD_CODE].
10635 *
10636 * @coverage dart.engine.resolver
10637 */
10638 class DeadCodeVerifier extends RecursiveASTVisitor<Object> {
10639
10640 /**
10641 * The error reporter by which errors will be reported.
10642 */ 10905 */
10643 ErrorReporter _errorReporter; 10906 ErrorReporter _errorReporter;
10644 10907
10645 /** 10908 /**
10646 * Create a new instance of the [DeadCodeVerifier]. 10909 * The type representing the type 'bool'.
10647 * 10910 */
10648 * @param errorReporter the error reporter 10911 InterfaceType _boolType;
10649 */ 10912
10650 DeadCodeVerifier(ErrorReporter errorReporter) { 10913 /**
10914 * The type representing the type 'int'.
10915 */
10916 InterfaceType _intType;
10917
10918 /**
10919 * The type representing the type 'num'.
10920 */
10921 InterfaceType _numType;
10922
10923 /**
10924 * The type representing the type 'string'.
10925 */
10926 InterfaceType _stringType;
10927
10928 /**
10929 * Initialize a newly created constant verifier.
10930 *
10931 * @param errorReporter the error reporter by which errors will be reported
10932 */
10933 ConstantVerifier(ErrorReporter errorReporter, TypeProvider typeProvider) {
10651 this._errorReporter = errorReporter; 10934 this._errorReporter = errorReporter;
10652 } 10935 this._boolType = typeProvider.boolType;
10653 Object visitBinaryExpression(BinaryExpression node) { 10936 this._intType = typeProvider.intType;
10654 sc.Token operator = node.operator; 10937 this._numType = typeProvider.numType;
10655 bool isAmpAmp = identical(operator.type, sc.TokenType.AMPERSAND_AMPERSAND); 10938 this._stringType = typeProvider.stringType;
10656 bool isBarBar = identical(operator.type, sc.TokenType.BAR_BAR); 10939 }
10657 if (isAmpAmp || isBarBar) { 10940 Object visitAnnotation(Annotation node) {
10658 Expression lhsCondition = node.leftOperand; 10941 super.visitAnnotation(node);
10659 ValidResult lhsResult = getConstantBooleanValue(lhsCondition); 10942 Element element = node.element;
10660 if (lhsResult != null) { 10943 if (element is ConstructorElement) {
10661 if (identical(lhsResult, ValidResult.RESULT_TRUE) && isBarBar) { 10944 ConstructorElement constructorElement = element as ConstructorElement;
10662 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, []) ; 10945 if (!constructorElement.isConst) {
10663 safelyVisit(lhsCondition); 10946 _errorReporter.reportError2(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION _CONSTRUCTOR, node, []);
10664 return null;
10665 } else if (identical(lhsResult, ValidResult.RESULT_FALSE) && isAmpAmp) {
10666 _errorReporter.reportError2(HintCode.DEAD_CODE, node.rightOperand, []) ;
10667 safelyVisit(lhsCondition);
10668 return null;
10669 }
10670 }
10671 }
10672 return super.visitBinaryExpression(node);
10673 }
10674
10675 /**
10676 * For each [Block], this method reports and error on all statements between t he end of the
10677 * block and the first return statement (assuming there it is not at the end o f the block.)
10678 *
10679 * @param node the block to evaluate
10680 */
10681 Object visitBlock(Block node) {
10682 NodeList<Statement> statements = node.statements;
10683 int size = statements.length;
10684 for (int i = 0; i < size; i++) {
10685 Statement currentStatement = statements[i];
10686 safelyVisit(currentStatement);
10687 if (currentStatement is ReturnStatement && i != size - 1) {
10688 Statement nextStatement = statements[i + 1];
10689 Statement lastStatement = statements[size - 1];
10690 int offset = nextStatement.offset;
10691 int length = lastStatement.end - offset;
10692 _errorReporter.reportError3(HintCode.DEAD_CODE, offset, length, []);
10693 return null; 10947 return null;
10694 } 10948 }
10695 } 10949 ArgumentList argumentList = node.arguments;
10696 return null; 10950 if (argumentList == null) {
10697 } 10951 _errorReporter.reportError2(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCT OR_ARGUMENTS, node, []);
10698 Object visitConditionalExpression(ConditionalExpression node) {
10699 Expression conditionExpression = node.condition;
10700 ValidResult result = getConstantBooleanValue(conditionExpression);
10701 if (result != null) {
10702 if (identical(result, ValidResult.RESULT_TRUE)) {
10703 _errorReporter.reportError2(HintCode.DEAD_CODE, node.elseExpression, []) ;
10704 safelyVisit(node.thenExpression);
10705 return null; 10952 return null;
10953 }
10954 validateConstantArguments(argumentList);
10955 }
10956 return null;
10957 }
10958 Object visitConstructorDeclaration(ConstructorDeclaration node) {
10959 if (node.constKeyword != null) {
10960 validateInitializers(node);
10961 }
10962 validateDefaultValues(node.parameters);
10963 return super.visitConstructorDeclaration(node);
10964 }
10965 Object visitFunctionExpression(FunctionExpression node) {
10966 super.visitFunctionExpression(node);
10967 validateDefaultValues(node.parameters);
10968 return null;
10969 }
10970 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
10971 validateConstantArguments2(node);
10972 return super.visitInstanceCreationExpression(node);
10973 }
10974 Object visitListLiteral(ListLiteral node) {
10975 super.visitListLiteral(node);
10976 if (node.modifier != null) {
10977 for (Expression element in node.elements) {
10978 validate(element, CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT);
10979 }
10980 }
10981 return null;
10982 }
10983 Object visitMapLiteral(MapLiteral node) {
10984 super.visitMapLiteral(node);
10985 bool isConst = node.modifier != null;
10986 bool reportEqualKeys = true;
10987 Set<Object> keys = new Set<Object>();
10988 List<Expression> invalidKeys = new List<Expression>();
10989 for (MapLiteralEntry entry in node.entries) {
10990 Expression key = entry.key;
10991 if (isConst) {
10992 EvaluationResultImpl result = validate(key, CompileTimeErrorCode.NON_CON STANT_MAP_KEY);
10993 validate(entry.value, CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE);
10994 if (result is ValidResult) {
10995 Object value = ((result as ValidResult)).value;
10996 if (keys.contains(value)) {
10997 invalidKeys.add(key);
10998 } else {
10999 javaSetAdd(keys, value);
11000 }
11001 }
10706 } else { 11002 } else {
10707 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenExpression, []) ; 11003 EvaluationResultImpl result = key.accept(new ConstantVisitor());
10708 safelyVisit(node.elseExpression); 11004 if (result is ValidResult) {
10709 return null; 11005 Object value = ((result as ValidResult)).value;
10710 } 11006 if (keys.contains(value)) {
10711 } 11007 invalidKeys.add(key);
10712 return super.visitConditionalExpression(node); 11008 } else {
10713 } 11009 javaSetAdd(keys, value);
10714 Object visitIfStatement(IfStatement node) { 11010 }
10715 Expression conditionExpression = node.condition; 11011 } else {
10716 ValidResult result = getConstantBooleanValue(conditionExpression); 11012 reportEqualKeys = false;
10717 if (result != null) { 11013 }
10718 if (identical(result, ValidResult.RESULT_TRUE)) { 11014 }
10719 Statement elseStatement = node.elseStatement; 11015 }
10720 if (elseStatement != null) { 11016 if (reportEqualKeys) {
10721 _errorReporter.reportError2(HintCode.DEAD_CODE, elseStatement, []); 11017 for (Expression key in invalidKeys) {
10722 safelyVisit(node.thenStatement); 11018 _errorReporter.reportError2(StaticWarningCode.EQUAL_KEYS_IN_MAP, key, [] );
10723 return null; 11019 }
10724 } 11020 }
10725 } else { 11021 return null;
10726 _errorReporter.reportError2(HintCode.DEAD_CODE, node.thenStatement, []); 11022 }
10727 safelyVisit(node.elseStatement); 11023 Object visitMethodDeclaration(MethodDeclaration node) {
10728 return null; 11024 super.visitMethodDeclaration(node);
10729 } 11025 validateDefaultValues(node.parameters);
10730 } 11026 return null;
10731 return super.visitIfStatement(node); 11027 }
10732 } 11028 Object visitSwitchCase(SwitchCase node) {
10733 Object visitTryStatement(TryStatement node) { 11029 super.visitSwitchCase(node);
10734 safelyVisit(node.body); 11030 validate(node.expression, CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION) ;
10735 safelyVisit(node.finallyClause); 11031 return null;
10736 NodeList<CatchClause> catchClauses = node.catchClauses; 11032 }
10737 int numOfCatchClauses = catchClauses.length; 11033 Object visitVariableDeclaration(VariableDeclaration node) {
10738 List<Type2> visitedTypes = new List<Type2>(); 11034 super.visitVariableDeclaration(node);
10739 for (int i = 0; i < numOfCatchClauses; i++) { 11035 Expression initializer = node.initializer;
10740 CatchClause catchClause = catchClauses[i]; 11036 if (initializer != null && node.isConst) {
10741 if (catchClause.onKeyword != null) { 11037 VariableElementImpl element = node.element as VariableElementImpl;
10742 TypeName typeName = catchClause.exceptionType; 11038 EvaluationResultImpl result = element.evaluationResult;
10743 if (typeName != null && typeName.type != null) { 11039 if (result == null) {
10744 Type2 currentType = typeName.type; 11040 result = validate(initializer, CompileTimeErrorCode.CONST_INITIALIZED_WI TH_NON_CONSTANT_VALUE);
10745 if (currentType.isObject) { 11041 element.evaluationResult = result;
10746 safelyVisit(catchClause); 11042 } else if (result is ErrorResult) {
10747 if (i + 1 != numOfCatchClauses) { 11043 reportErrors(result, CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CON STANT_VALUE);
10748 CatchClause nextCatchClause = catchClauses[i + 1]; 11044 }
10749 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 11045 }
10750 int offset = nextCatchClause.offset; 11046 return null;
10751 int length = lastCatchClause.end - offset; 11047 }
10752 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CAT CH, offset, length, []); 11048
10753 return null; 11049 /**
10754 } 11050 * Return `true` if the given value is the result of evaluating an expression whose value is
10755 } 11051 * a valid key in a const map literal. Keys in const map literals must be eith er a string, number,
10756 for (Type2 type in visitedTypes) { 11052 * boolean, list, map, or null.
10757 if (currentType.isSubtypeOf(type)) { 11053 *
10758 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 11054 * @param value
10759 int offset = catchClause.offset; 11055 * @return `true` if the given value is a valid key in a const map literal
10760 int length = lastCatchClause.end - offset; 11056 */
10761 _errorReporter.reportError3(HintCode.DEAD_CODE_ON_CATCH_SUBTYPE, o ffset, length, [currentType.displayName, type.displayName]); 11057 bool isValidConstMapKey(Object value) => true;
10762 return null; 11058
10763 } 11059 /**
10764 } 11060 * If the given result represents one or more errors, report those errors. Exc ept for special
10765 visitedTypes.add(currentType); 11061 * cases, use the given error code rather than the one reported in the error.
10766 } 11062 *
10767 safelyVisit(catchClause); 11063 * @param result the result containing any errors that need to be reported
10768 } else { 11064 * @param errorCode the error code to be used if the result represents an erro r
10769 safelyVisit(catchClause); 11065 */
10770 if (i + 1 != numOfCatchClauses) { 11066 void reportErrors(EvaluationResultImpl result, ErrorCode errorCode2) {
10771 CatchClause nextCatchClause = catchClauses[i + 1]; 11067 if (result is ErrorResult) {
10772 CatchClause lastCatchClause = catchClauses[numOfCatchClauses - 1]; 11068 for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) {
10773 int offset = nextCatchClause.offset; 11069 ErrorCode dataErrorCode = data.errorCode;
10774 int length = lastCatchClause.end - offset; 11070 if (identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCE PTION) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRIN G) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || ide ntical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dat aErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM)) {
10775 _errorReporter.reportError3(HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH, offset, length, []); 11071 _errorReporter.reportError2(dataErrorCode, data.node, []);
10776 return null; 11072 } else {
10777 } 11073 _errorReporter.reportError2(errorCode2, data.node, []);
10778 } 11074 }
10779 } 11075 }
10780 return null; 11076 }
10781 } 11077 }
10782 Object visitWhileStatement(WhileStatement node) { 11078
10783 Expression conditionExpression = node.condition; 11079 /**
10784 safelyVisit(conditionExpression); 11080 * Validate that the given expression is a compile time constant. Return the v alue of the compile
10785 ValidResult result = getConstantBooleanValue(conditionExpression); 11081 * time constant, or `null` if the expression is not a compile time constant.
10786 if (result != null) { 11082 *
10787 if (identical(result, ValidResult.RESULT_FALSE)) { 11083 * @param expression the expression to be validated
10788 _errorReporter.reportError2(HintCode.DEAD_CODE, node.body, []); 11084 * @param errorCode the error code to be used if the expression is not a compi le time constant
10789 return null; 11085 * @return the value of the compile time constant
10790 } 11086 */
10791 } 11087 EvaluationResultImpl validate(Expression expression, ErrorCode errorCode) {
10792 safelyVisit(node.body); 11088 EvaluationResultImpl result = expression.accept(new ConstantVisitor());
10793 return null; 11089 reportErrors(result, errorCode);
10794 } 11090 return result;
10795 11091 }
10796 /** 11092
10797 * Given some [Expression], this method returns [ValidResult#RESULT_TRUE] if i t is 11093 /**
10798 * `true`, [ValidResult#RESULT_FALSE] if it is `false`, or `null` if the 11094 * Validate that if the passed arguments are constant expressions.
10799 * expression is not a constant boolean value. 11095 *
10800 * 11096 * @param argumentList the argument list to evaluate
10801 * @param expression the expression to evaluate 11097 */
10802 * @return [ValidResult#RESULT_TRUE] if it is `true`, [ValidResult#RESULT_FALS E] 11098 void validateConstantArguments(ArgumentList argumentList) {
10803 * if it is `false`, or `null` if the expression is not a constant boo lean 11099 for (Expression argument in argumentList.arguments) {
10804 * value 11100 if (argument is NamedExpression) {
10805 */ 11101 argument = ((argument as NamedExpression)).expression;
10806 ValidResult getConstantBooleanValue(Expression expression) { 11102 }
10807 if (expression is BooleanLiteral) { 11103 validate(argument, CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT);
10808 if (((expression as BooleanLiteral)).value) { 11104 }
10809 return ValidResult.RESULT_TRUE; 11105 }
10810 } else { 11106
10811 return ValidResult.RESULT_FALSE; 11107 /**
10812 } 11108 * Validate that if the passed instance creation is 'const' then all its argum ents are constant
10813 } else { 11109 * expressions.
10814 EvaluationResultImpl result = expression.accept(new ConstantVisitor()); 11110 *
10815 if (identical(result, ValidResult.RESULT_TRUE)) { 11111 * @param node the instance creation evaluate
10816 return ValidResult.RESULT_TRUE; 11112 */
10817 } else if (identical(result, ValidResult.RESULT_FALSE)) { 11113 void validateConstantArguments2(InstanceCreationExpression node) {
10818 return ValidResult.RESULT_FALSE; 11114 if (!node.isConst) {
10819 } 11115 return;
10820 return null; 11116 }
10821 } 11117 ArgumentList argumentList = node.argumentList;
10822 } 11118 if (argumentList == null) {
10823 11119 return;
10824 /** 11120 }
10825 * If the given node is not `null`, visit this instance of the dead code verif ier. 11121 validateConstantArguments(argumentList);
10826 * 11122 }
10827 * @param node the node to be visited 11123
10828 */ 11124 /**
10829 void safelyVisit(ASTNode node) { 11125 * Validate that the default value associated with each of the parameters in t he given list is a
10830 if (node != null) { 11126 * compile time constant.
10831 node.accept(this); 11127 *
10832 } 11128 * @param parameters the list of parameters to be validated
11129 */
11130 void validateDefaultValues(FormalParameterList parameters2) {
11131 if (parameters2 == null) {
11132 return;
11133 }
11134 for (FormalParameter parameter in parameters2.parameters) {
11135 if (parameter is DefaultFormalParameter) {
11136 DefaultFormalParameter defaultParameter = parameter as DefaultFormalPara meter;
11137 Expression defaultValue = defaultParameter.defaultValue;
11138 if (defaultValue != null) {
11139 EvaluationResultImpl result = validate(defaultValue, CompileTimeErrorC ode.NON_CONSTANT_DEFAULT_VALUE);
11140 VariableElementImpl element = parameter.element as VariableElementImpl ;
11141 element.evaluationResult = result;
11142 }
11143 }
11144 }
11145 }
11146
11147 /**
11148 * Validates that the given expression is a compile time constant.
11149 *
11150 * @param parameterElements the elements of parameters of constant constructor , they are
11151 * considered as a valid potentially constant expressions
11152 * @param expression the expression to validate
11153 */
11154 void validateInitializerExpression(List<ParameterElement> parameterElements, E xpression expression) {
11155 EvaluationResultImpl result = expression.accept(new ConstantVisitor_10(this, parameterElements));
11156 reportErrors(result, CompileTimeErrorCode.NON_CONSTANT_VALUE_IN_INITIALIZER) ;
11157 }
11158
11159 /**
11160 * Validates that all of the arguments of a constructor initializer are compil e time constants.
11161 *
11162 * @param parameterElements the elements of parameters of constant constructor , they are
11163 * considered as a valid potentially constant expressions
11164 * @param argumentList the argument list to validate
11165 */
11166 void validateInitializerInvocationArguments(List<ParameterElement> parameterEl ements, ArgumentList argumentList) {
11167 if (argumentList == null) {
11168 return;
11169 }
11170 for (Expression argument in argumentList.arguments) {
11171 validateInitializerExpression(parameterElements, argument);
11172 }
11173 }
11174
11175 /**
11176 * Validates that the expressions of the given initializers (of a constant con structor) are all
11177 * compile time constants.
11178 *
11179 * @param constructor the constant constructor declaration to validate
11180 */
11181 void validateInitializers(ConstructorDeclaration constructor) {
11182 List<ParameterElement> parameterElements = constructor.parameters.parameterE lements;
11183 NodeList<ConstructorInitializer> initializers = constructor.initializers;
11184 for (ConstructorInitializer initializer in initializers) {
11185 if (initializer is ConstructorFieldInitializer) {
11186 ConstructorFieldInitializer fieldInitializer = initializer as Constructo rFieldInitializer;
11187 validateInitializerExpression(parameterElements, fieldInitializer.expres sion);
11188 }
11189 if (initializer is RedirectingConstructorInvocation) {
11190 RedirectingConstructorInvocation invocation = initializer as Redirecting ConstructorInvocation;
11191 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
11192 }
11193 if (initializer is SuperConstructorInvocation) {
11194 SuperConstructorInvocation invocation = initializer as SuperConstructorI nvocation;
11195 validateInitializerInvocationArguments(parameterElements, invocation.arg umentList);
11196 }
11197 }
11198 }
11199 }
11200 class ConstantVisitor_10 extends ConstantVisitor {
11201 final ConstantVerifier ConstantVerifier_this;
11202 List<ParameterElement> parameterElements;
11203 ConstantVisitor_10(this.ConstantVerifier_this, this.parameterElements) : super ();
11204 EvaluationResultImpl visitSimpleIdentifier(SimpleIdentifier node) {
11205 Element element = node.element;
11206 for (ParameterElement parameterElement in parameterElements) {
11207 if (identical(parameterElement, element) && parameterElement != null) {
11208 Type2 type = parameterElement.type;
11209 if (type != null) {
11210 if (type.isDynamic) {
11211 return ValidResult.RESULT_DYNAMIC;
11212 }
11213 if (type.isSubtypeOf(ConstantVerifier_this._boolType)) {
11214 return ValidResult.RESULT_BOOL;
11215 }
11216 if (type.isSubtypeOf(ConstantVerifier_this._intType)) {
11217 return ValidResult.RESULT_INT;
11218 }
11219 if (type.isSubtypeOf(ConstantVerifier_this._numType)) {
11220 return ValidResult.RESULT_NUM;
11221 }
11222 if (type.isSubtypeOf(ConstantVerifier_this._stringType)) {
11223 return ValidResult.RESULT_STRING;
11224 }
11225 }
11226 return ValidResult.RESULT_OBJECT;
11227 }
11228 }
11229 return super.visitSimpleIdentifier(node);
10833 } 11230 }
10834 } 11231 }
10835 /** 11232 /**
10836 * Instances of the class `ErrorVerifier` traverse an AST structure looking for additional 11233 * Instances of the class `ErrorVerifier` traverse an AST structure looking for additional
10837 * errors and warnings not covered by the parser and resolver. 11234 * errors and warnings not covered by the parser and resolver.
10838 * 11235 *
10839 * @coverage dart.engine.resolver 11236 * @coverage dart.engine.resolver
10840 */ 11237 */
10841 class ErrorVerifier extends RecursiveASTVisitor<Object> { 11238 class ErrorVerifier extends RecursiveASTVisitor<Object> {
10842 11239
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
11038 } 11435 }
11039 Object visitAssignmentExpression(AssignmentExpression node) { 11436 Object visitAssignmentExpression(AssignmentExpression node) {
11040 sc.Token operator = node.operator; 11437 sc.Token operator = node.operator;
11041 sc.TokenType operatorType = operator.type; 11438 sc.TokenType operatorType = operator.type;
11042 if (identical(operatorType, sc.TokenType.EQ)) { 11439 if (identical(operatorType, sc.TokenType.EQ)) {
11043 checkForInvalidAssignment2(node.leftHandSide, node.rightHandSide); 11440 checkForInvalidAssignment2(node.leftHandSide, node.rightHandSide);
11044 } else { 11441 } else {
11045 checkForInvalidAssignment(node); 11442 checkForInvalidAssignment(node);
11046 } 11443 }
11047 checkForAssignmentToFinal(node); 11444 checkForAssignmentToFinal(node);
11445 checkForArgumentTypeNotAssignable2(node.rightHandSide);
11048 return super.visitAssignmentExpression(node); 11446 return super.visitAssignmentExpression(node);
11049 } 11447 }
11050 Object visitBinaryExpression(BinaryExpression node) { 11448 Object visitBinaryExpression(BinaryExpression node) {
11051 checkForArgumentTypeNotAssignable2(node.rightOperand); 11449 checkForArgumentTypeNotAssignable2(node.rightOperand);
11052 return super.visitBinaryExpression(node); 11450 return super.visitBinaryExpression(node);
11053 } 11451 }
11054 Object visitCatchClause(CatchClause node) { 11452 Object visitCatchClause(CatchClause node) {
11055 bool previousIsInCatchClause = _isInCatchClause; 11453 bool previousIsInCatchClause = _isInCatchClause;
11056 try { 11454 try {
11057 _isInCatchClause = true; 11455 _isInCatchClause = true;
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
11324 return super.visitMethodDeclaration(node); 11722 return super.visitMethodDeclaration(node);
11325 } finally { 11723 } finally {
11326 _enclosingFunction = previousFunction; 11724 _enclosingFunction = previousFunction;
11327 _isInStaticMethod = false; 11725 _isInStaticMethod = false;
11328 } 11726 }
11329 } 11727 }
11330 Object visitMethodInvocation(MethodInvocation node) { 11728 Object visitMethodInvocation(MethodInvocation node) {
11331 checkForStaticAccessToInstanceMember(node.target, node.methodName); 11729 checkForStaticAccessToInstanceMember(node.target, node.methodName);
11332 return super.visitMethodInvocation(node); 11730 return super.visitMethodInvocation(node);
11333 } 11731 }
11732 Object visitNativeClause(NativeClause node) {
11733 if (!_isInSystemLibrary) {
11734 _errorReporter.reportError2(ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node, []);
11735 }
11736 return super.visitNativeClause(node);
11737 }
11334 Object visitNativeFunctionBody(NativeFunctionBody node) { 11738 Object visitNativeFunctionBody(NativeFunctionBody node) {
11335 checkForNativeFunctionBodyInNonSDKCode(node); 11739 checkForNativeFunctionBodyInNonSDKCode(node);
11336 return super.visitNativeFunctionBody(node); 11740 return super.visitNativeFunctionBody(node);
11337 } 11741 }
11338 Object visitPostfixExpression(PostfixExpression node) { 11742 Object visitPostfixExpression(PostfixExpression node) {
11339 checkForAssignmentToFinal2(node.operand); 11743 checkForAssignmentToFinal2(node.operand);
11744 checkForIntNotAssignable(node.operand);
11340 return super.visitPostfixExpression(node); 11745 return super.visitPostfixExpression(node);
11341 } 11746 }
11342 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 11747 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
11343 if (node.parent is! Annotation) { 11748 if (node.parent is! Annotation) {
11344 checkForStaticAccessToInstanceMember(node.prefix, node.identifier); 11749 checkForStaticAccessToInstanceMember(node.prefix, node.identifier);
11345 } 11750 }
11346 return super.visitPrefixedIdentifier(node); 11751 return super.visitPrefixedIdentifier(node);
11347 } 11752 }
11348 Object visitPrefixExpression(PrefixExpression node) { 11753 Object visitPrefixExpression(PrefixExpression node) {
11349 if (node.operator.type.isIncrementOperator) { 11754 if (node.operator.type.isIncrementOperator) {
11350 checkForAssignmentToFinal2(node.operand); 11755 checkForAssignmentToFinal2(node.operand);
11351 } 11756 }
11757 checkForIntNotAssignable(node.operand);
11352 return super.visitPrefixExpression(node); 11758 return super.visitPrefixExpression(node);
11353 } 11759 }
11354 Object visitPropertyAccess(PropertyAccess node) { 11760 Object visitPropertyAccess(PropertyAccess node) {
11355 Expression target = node.realTarget; 11761 Expression target = node.realTarget;
11356 checkForStaticAccessToInstanceMember(target, node.propertyName); 11762 checkForStaticAccessToInstanceMember(target, node.propertyName);
11357 return super.visitPropertyAccess(node); 11763 return super.visitPropertyAccess(node);
11358 } 11764 }
11359 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) { 11765 Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
11360 _isInConstructorInitializer = true; 11766 _isInConstructorInitializer = true;
11361 try { 11767 try {
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
11850 */ 12256 */
11851 bool checkForAllRedirectConstructorErrorCodes(ConstructorDeclaration node) { 12257 bool checkForAllRedirectConstructorErrorCodes(ConstructorDeclaration node) {
11852 ConstructorName redirectedNode = node.redirectedConstructor; 12258 ConstructorName redirectedNode = node.redirectedConstructor;
11853 if (redirectedNode == null) { 12259 if (redirectedNode == null) {
11854 return false; 12260 return false;
11855 } 12261 }
11856 ConstructorElement redirectedElement = redirectedNode.element; 12262 ConstructorElement redirectedElement = redirectedNode.element;
11857 if (redirectedElement == null) { 12263 if (redirectedElement == null) {
11858 TypeName constructorTypeName = redirectedNode.type; 12264 TypeName constructorTypeName = redirectedNode.type;
11859 Type2 redirectedType = constructorTypeName.type; 12265 Type2 redirectedType = constructorTypeName.type;
11860 if (redirectedType != null && redirectedType.element != null && redirected Type.element != DynamicElementImpl.instance) { 12266 if (redirectedType != null && redirectedType.element != null && !redirecte dType.isDynamic) {
11861 String constructorStrName = constructorTypeName.name.name; 12267 String constructorStrName = constructorTypeName.name.name;
11862 if (redirectedNode.name != null) { 12268 if (redirectedNode.name != null) {
11863 constructorStrName += ".${redirectedNode.name.name}"; 12269 constructorStrName += ".${redirectedNode.name.name}";
11864 } 12270 }
11865 _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_MISSING_CONSTR UCTOR, redirectedNode, [constructorStrName, redirectedType.displayName]); 12271 _errorReporter.reportError2(StaticWarningCode.REDIRECT_TO_MISSING_CONSTR UCTOR, redirectedNode, [constructorStrName, redirectedType.displayName]);
11866 return true; 12272 return true;
11867 } 12273 }
11868 return false; 12274 return false;
11869 } 12275 }
11870 FunctionType redirectedType = redirectedElement.type; 12276 FunctionType redirectedType = redirectedElement.type;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
12003 return false; 12409 return false;
12004 } 12410 }
12005 ErrorCode errorCode; 12411 ErrorCode errorCode;
12006 if (_isInConstInstanceCreation || _isEnclosingConstructorConst) { 12412 if (_isInConstInstanceCreation || _isEnclosingConstructorConst) {
12007 errorCode = CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE; 12413 errorCode = CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE;
12008 } else { 12414 } else {
12009 errorCode = StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE; 12415 errorCode = StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE;
12010 } 12416 }
12011 ParameterElement staticParameterElement = argument.staticParameterElement; 12417 ParameterElement staticParameterElement = argument.staticParameterElement;
12012 Type2 staticParameterType = staticParameterElement == null ? null : staticPa rameterElement.type; 12418 Type2 staticParameterType = staticParameterElement == null ? null : staticPa rameterElement.type;
12013 ParameterElement propagatedParameterElement = argument.parameterElement; 12419 ParameterElement propagatedParameterElement = argument.propagatedParameterEl ement;
12014 Type2 propagatedParameterType = propagatedParameterElement == null ? null : propagatedParameterElement.type; 12420 Type2 propagatedParameterType = propagatedParameterElement == null ? null : propagatedParameterElement.type;
12015 return checkForArgumentTypeNotAssignable3(argument, staticParameterType, pro pagatedParameterType, errorCode); 12421 return checkForArgumentTypeNotAssignable3(argument, staticParameterType, pro pagatedParameterType, errorCode);
12016 } 12422 }
12017 12423
12018 /** 12424 /**
12019 * This verifies that the passed expression can be assigned to its correspondi ng parameters. 12425 * This verifies that the passed expression can be assigned to its correspondi ng parameters.
12020 * 12426 *
12021 * @param expression the expression to evaluate 12427 * @param expression the expression to evaluate
12022 * @param expectedStaticType the expected static type 12428 * @param expectedStaticType the expected static type
12023 * @param expectedPropagatedType the expected propagated type, may be `null` 12429 * @param expectedPropagatedType the expected propagated type, may be `null`
12024 * @return `true` if and only if an error code is generated on the passed node 12430 * @return `true` if and only if an error code is generated on the passed node
12025 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE 12431 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
12026 * @see CompileTimeErrorCode#ARGUMENT_TYPE_NOT_ASSIGNABLE 12432 * @see CompileTimeErrorCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
12027 */ 12433 */
12028 bool checkForArgumentTypeNotAssignable3(Expression expression, Type2 expectedS taticType, Type2 expectedPropagatedType, ErrorCode errorCode) { 12434 bool checkForArgumentTypeNotAssignable3(Expression expression, Type2 expectedS taticType, Type2 expectedPropagatedType, ErrorCode errorCode) => checkForArgumen tTypeNotAssignable4(expression, expectedStaticType, getStaticType(expression), e xpectedPropagatedType, expression.propagatedType, errorCode);
12029 Type2 staticArgumentType = getStaticType(expression); 12435
12030 if (staticArgumentType == null || expectedStaticType == null) { 12436 /**
12437 * This verifies that the passed expression can be assigned to its correspondi ng parameters.
12438 *
12439 * @param expression the expression to evaluate
12440 * @param expectedStaticType the expected static type of the parameter
12441 * @param actualStaticType the actual static type of the argument
12442 * @param expectedPropagatedType the expected propagated type of the parameter , may be
12443 * `null`
12444 * @param actualPropagatedType the expected propagated type of the parameter, may be `null`
12445 * @return `true` if and only if an error code is generated on the passed node
12446 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
12447 * @see CompileTimeErrorCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
12448 */
12449 bool checkForArgumentTypeNotAssignable4(Expression expression, Type2 expectedS taticType, Type2 actualStaticType, Type2 expectedPropagatedType, Type2 actualPro pagatedType, ErrorCode errorCode) {
12450 if (actualStaticType == null || expectedStaticType == null) {
12031 return false; 12451 return false;
12032 } 12452 }
12033 if (_strictMode) { 12453 if (_strictMode) {
12034 if (staticArgumentType.isAssignableTo(expectedStaticType)) { 12454 if (actualStaticType.isAssignableTo(expectedStaticType)) {
12035 return false; 12455 return false;
12036 } 12456 }
12037 _errorReporter.reportError2(errorCode, expression, [ 12457 _errorReporter.reportError2(errorCode, expression, [
12038 staticArgumentType.displayName, 12458 actualStaticType.displayName,
12039 expectedStaticType.displayName]); 12459 expectedStaticType.displayName]);
12040 return true; 12460 return true;
12041 } 12461 }
12042 Type2 propagatedArgumentType = getPropagatedType(expression); 12462 if (actualPropagatedType == null || expectedPropagatedType == null) {
12043 if (propagatedArgumentType == null || expectedPropagatedType == null) { 12463 if (actualStaticType.isAssignableTo(expectedStaticType)) {
12044 if (staticArgumentType.isAssignableTo(expectedStaticType)) {
12045 return false; 12464 return false;
12046 } 12465 }
12047 _errorReporter.reportError2(errorCode, expression, [ 12466 _errorReporter.reportError2(errorCode, expression, [
12048 staticArgumentType.displayName, 12467 actualStaticType.displayName,
12049 expectedStaticType.displayName]); 12468 expectedStaticType.displayName]);
12050 return true; 12469 return true;
12051 } 12470 }
12052 if (staticArgumentType.isAssignableTo(expectedStaticType) || staticArgumentT ype.isAssignableTo(expectedPropagatedType) || propagatedArgumentType.isAssignabl eTo(expectedStaticType) || propagatedArgumentType.isAssignableTo(expectedPropaga tedType)) { 12471 if (actualStaticType.isAssignableTo(expectedStaticType) || actualStaticType. isAssignableTo(expectedPropagatedType) || actualPropagatedType.isAssignableTo(ex pectedStaticType) || actualPropagatedType.isAssignableTo(expectedPropagatedType) ) {
12053 return false; 12472 return false;
12054 } 12473 }
12055 _errorReporter.reportError2(errorCode, expression, [ 12474 _errorReporter.reportError2(errorCode, expression, [
12056 (propagatedArgumentType == null ? staticArgumentType : propagatedArgumen tType).displayName, 12475 (actualPropagatedType == null ? actualStaticType : actualPropagatedType) .displayName,
12057 (expectedPropagatedType == null ? expectedStaticType : expectedPropagate dType).displayName]); 12476 (expectedPropagatedType == null ? expectedStaticType : expectedPropagate dType).displayName]);
12058 return true; 12477 return true;
12059 } 12478 }
12060 12479
12061 /** 12480 /**
12062 * This verifies that left hand side of the passed assignment expression is no t final. 12481 * This verifies that left hand side of the passed assignment expression is no t final.
12063 * 12482 *
12064 * @param node the assignment expression to evaluate 12483 * @param node the assignment expression to evaluate
12065 * @return `true` if and only if an error code is generated on the passed node 12484 * @return `true` if and only if an error code is generated on the passed node
12066 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL 12485 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL
12067 */ 12486 */
12068 bool checkForAssignmentToFinal(AssignmentExpression node) { 12487 bool checkForAssignmentToFinal(AssignmentExpression node) {
12069 Expression leftExpression = node.leftHandSide; 12488 Expression leftExpression = node.leftHandSide;
12070 return checkForAssignmentToFinal2(leftExpression); 12489 return checkForAssignmentToFinal2(leftExpression);
12071 } 12490 }
12072 12491
12073 /** 12492 /**
12074 * This verifies that the passed expression is not final. 12493 * This verifies that the passed expression is not final.
12075 * 12494 *
12076 * @param node the expression to evaluate 12495 * @param node the expression to evaluate
12077 * @return `true` if and only if an error code is generated on the passed node 12496 * @return `true` if and only if an error code is generated on the passed node
12497 * @see StaticWarningCode#ASSIGNMENT_TO_CONST
12078 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL 12498 * @see StaticWarningCode#ASSIGNMENT_TO_FINAL
12079 * @see StaticWarningCode#ASSIGNMENT_TO_METHOD 12499 * @see StaticWarningCode#ASSIGNMENT_TO_METHOD
12080 */ 12500 */
12081 bool checkForAssignmentToFinal2(Expression expression) { 12501 bool checkForAssignmentToFinal2(Expression expression) {
12082 Element element = null; 12502 Element element = null;
12083 if (expression is Identifier) { 12503 if (expression is Identifier) {
12084 element = ((expression as Identifier)).element; 12504 element = ((expression as Identifier)).element;
12085 } 12505 }
12086 if (expression is PropertyAccess) { 12506 if (expression is PropertyAccess) {
12087 element = ((expression as PropertyAccess)).propertyName.element; 12507 element = ((expression as PropertyAccess)).propertyName.element;
12088 } 12508 }
12509 if (element is PropertyAccessorElement) {
12510 PropertyAccessorElement accessor = element as PropertyAccessorElement;
12511 element = accessor.variable;
12512 }
12089 if (element is VariableElement) { 12513 if (element is VariableElement) {
12090 VariableElement leftVar = element as VariableElement; 12514 VariableElement variable = element as VariableElement;
12091 if (leftVar.isFinal) { 12515 if (variable.isConst) {
12516 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_CONST, expre ssion, []);
12517 return true;
12518 }
12519 if (variable.isFinal) {
12092 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expre ssion, []); 12520 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expre ssion, []);
12093 return true; 12521 return true;
12094 } 12522 }
12095 return false;
12096 }
12097 if (element is PropertyAccessorElement) {
12098 PropertyAccessorElement leftAccessor = element as PropertyAccessorElement;
12099 if (!leftAccessor.isSetter) {
12100 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_FINAL, expre ssion, []);
12101 return true;
12102 }
12103 return false; 12523 return false;
12104 } 12524 }
12105 if (element is MethodElement) { 12525 if (element is MethodElement) {
12106 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_METHOD, expres sion, []); 12526 _errorReporter.reportError2(StaticWarningCode.ASSIGNMENT_TO_METHOD, expres sion, []);
12107 return true; 12527 return true;
12108 } 12528 }
12109 return false; 12529 return false;
12110 } 12530 }
12111 12531
12112 /** 12532 /**
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after
12857 if (staticType.isAssignableTo(fieldType)) { 13277 if (staticType.isAssignableTo(fieldType)) {
12858 return false; 13278 return false;
12859 } else if (_strictMode) { 13279 } else if (_strictMode) {
12860 if (_isEnclosingConstructorConst) { 13280 if (_isEnclosingConstructorConst) {
12861 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER _NOT_ASSIGNABLE, expression, [staticType.displayName, fieldType.displayName]); 13281 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER _NOT_ASSIGNABLE, expression, [staticType.displayName, fieldType.displayName]);
12862 } else { 13282 } else {
12863 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSI GNABLE, expression, [staticType.displayName, fieldType.displayName]); 13283 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSI GNABLE, expression, [staticType.displayName, fieldType.displayName]);
12864 } 13284 }
12865 return true; 13285 return true;
12866 } 13286 }
12867 Type2 propagatedType = getPropagatedType(expression); 13287 Type2 propagatedType = expression.propagatedType;
12868 if (propagatedType != null && propagatedType.isAssignableTo(fieldType)) { 13288 if (propagatedType != null && propagatedType.isAssignableTo(fieldType)) {
12869 return false; 13289 return false;
12870 } 13290 }
12871 if (_isEnclosingConstructorConst) { 13291 if (_isEnclosingConstructorConst) {
12872 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_N OT_ASSIGNABLE, expression, [ 13292 _errorReporter.reportError2(CompileTimeErrorCode.CONST_FIELD_INITIALIZER_N OT_ASSIGNABLE, expression, [
12873 (propagatedType == null ? staticType : propagatedType).displayName, 13293 (propagatedType == null ? staticType : propagatedType).displayName,
12874 fieldType.displayName]); 13294 fieldType.displayName]);
12875 } else { 13295 } else {
12876 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGN ABLE, expression, [ 13296 _errorReporter.reportError2(StaticWarningCode.FIELD_INITIALIZER_NOT_ASSIGN ABLE, expression, [
12877 (propagatedType == null ? staticType : propagatedType).displayName, 13297 (propagatedType == null ? staticType : propagatedType).displayName,
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
13106 */ 13526 */
13107 bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) { 13527 bool checkForInconsistentCaseExpressionTypes(SwitchStatement node) {
13108 NodeList<SwitchMember> switchMembers = node.members; 13528 NodeList<SwitchMember> switchMembers = node.members;
13109 bool foundError = false; 13529 bool foundError = false;
13110 Type2 firstType = null; 13530 Type2 firstType = null;
13111 for (SwitchMember switchMember in switchMembers) { 13531 for (SwitchMember switchMember in switchMembers) {
13112 if (switchMember is SwitchCase) { 13532 if (switchMember is SwitchCase) {
13113 SwitchCase switchCase = switchMember as SwitchCase; 13533 SwitchCase switchCase = switchMember as SwitchCase;
13114 Expression expression = switchCase.expression; 13534 Expression expression = switchCase.expression;
13115 if (firstType == null) { 13535 if (firstType == null) {
13116 firstType = getBestType(expression); 13536 firstType = expression.bestType;
13117 } else { 13537 } else {
13118 Type2 nType = getBestType(expression); 13538 Type2 nType = expression.bestType;
13119 if (firstType != nType) { 13539 if (firstType != nType) {
13120 _errorReporter.reportError2(CompileTimeErrorCode.INCONSISTENT_CASE_E XPRESSION_TYPES, expression, [expression.toSource(), firstType.displayName]); 13540 _errorReporter.reportError2(CompileTimeErrorCode.INCONSISTENT_CASE_E XPRESSION_TYPES, expression, [expression.toSource(), firstType.displayName]);
13121 foundError = true; 13541 foundError = true;
13122 } 13542 }
13123 } 13543 }
13124 } 13544 }
13125 } 13545 }
13126 if (!foundError) { 13546 if (!foundError) {
13127 checkForCaseExpressionTypeImplementsEquals(node, firstType); 13547 checkForCaseExpressionTypeImplementsEquals(node, firstType);
13128 } 13548 }
(...skipping 13 matching lines...) Expand all
13142 if (errors == null || errors.isEmpty) { 13562 if (errors == null || errors.isEmpty) {
13143 return false; 13563 return false;
13144 } 13564 }
13145 for (AnalysisError error in errors) { 13565 for (AnalysisError error in errors) {
13146 _errorReporter.reportError(error); 13566 _errorReporter.reportError(error);
13147 } 13567 }
13148 return true; 13568 return true;
13149 } 13569 }
13150 13570
13151 /** 13571 /**
13572 * This verifies that an 'int' can be assigned to the parameter corresponding to the given
13573 * expression. This is used for prefix and postfix expressions where the argum ent value is
13574 * implicit.
13575 *
13576 * @param argument the expression to which the operator is being applied
13577 * @return `true` if and only if an error code is generated on the passed node
13578 * @see StaticWarningCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
13579 * @see CompileTimeErrorCode#ARGUMENT_TYPE_NOT_ASSIGNABLE
13580 */
13581 bool checkForIntNotAssignable(Expression argument) {
13582 if (argument == null) {
13583 return false;
13584 }
13585 ErrorCode errorCode;
13586 if (_isInConstInstanceCreation || _isEnclosingConstructorConst) {
13587 errorCode = CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE;
13588 } else {
13589 errorCode = StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE;
13590 }
13591 ParameterElement staticParameterElement = argument.staticParameterElement;
13592 Type2 staticParameterType = staticParameterElement == null ? null : staticPa rameterElement.type;
13593 ParameterElement propagatedParameterElement = argument.propagatedParameterEl ement;
13594 Type2 propagatedParameterType = propagatedParameterElement == null ? null : propagatedParameterElement.type;
13595 return checkForArgumentTypeNotAssignable4(argument, staticParameterType, _ty peProvider.intType, propagatedParameterType, _typeProvider.intType, errorCode);
13596 }
13597
13598 /**
13152 * Given an assignment using a compound assignment operator, this verifies tha t the given 13599 * Given an assignment using a compound assignment operator, this verifies tha t the given
13153 * assignment is valid. 13600 * assignment is valid.
13154 * 13601 *
13155 * @param node the assignment expression being tested 13602 * @param node the assignment expression being tested
13156 * @return `true` if and only if an error code is generated on the passed node 13603 * @return `true` if and only if an error code is generated on the passed node
13157 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT 13604 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT
13158 */ 13605 */
13159 bool checkForInvalidAssignment(AssignmentExpression node) { 13606 bool checkForInvalidAssignment(AssignmentExpression node) {
13160 Expression lhs = node.leftHandSide; 13607 Expression lhs = node.leftHandSide;
13161 if (lhs == null) { 13608 if (lhs == null) {
13162 return false; 13609 return false;
13163 } 13610 }
13164 VariableElement leftElement = getVariableElement(lhs); 13611 VariableElement leftElement = getVariableElement(lhs);
13165 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe; 13612 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe;
13166 MethodElement invokedMethod = node.element; 13613 MethodElement invokedMethod = node.staticElement;
13167 if (invokedMethod == null) { 13614 if (invokedMethod == null) {
13168 return false; 13615 return false;
13169 } 13616 }
13170 Type2 rightType = invokedMethod.type.returnType; 13617 Type2 rightType = invokedMethod.type.returnType;
13171 if (leftType == null || rightType == null) { 13618 if (leftType == null || rightType == null) {
13172 return false; 13619 return false;
13173 } 13620 }
13174 if (!rightType.isAssignableTo(leftType)) { 13621 if (!rightType.isAssignableTo(leftType)) {
13175 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, node .rightHandSide, [rightType.displayName, leftType.displayName]); 13622 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, node .rightHandSide, [rightType.displayName, leftType.displayName]);
13176 return true; 13623 return true;
(...skipping 10 matching lines...) Expand all
13187 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT 13634 * @see StaticTypeWarningCode#INVALID_ASSIGNMENT
13188 */ 13635 */
13189 bool checkForInvalidAssignment2(Expression lhs, Expression rhs) { 13636 bool checkForInvalidAssignment2(Expression lhs, Expression rhs) {
13190 if (lhs == null || rhs == null) { 13637 if (lhs == null || rhs == null) {
13191 return false; 13638 return false;
13192 } 13639 }
13193 VariableElement leftElement = getVariableElement(lhs); 13640 VariableElement leftElement = getVariableElement(lhs);
13194 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe; 13641 Type2 leftType = (leftElement == null) ? getStaticType(lhs) : leftElement.ty pe;
13195 Type2 staticRightType = getStaticType(rhs); 13642 Type2 staticRightType = getStaticType(rhs);
13196 bool isStaticAssignable = staticRightType.isAssignableTo(leftType); 13643 bool isStaticAssignable = staticRightType.isAssignableTo(leftType);
13197 Type2 propagatedRightType = getPropagatedType(rhs); 13644 Type2 propagatedRightType = rhs.propagatedType;
13198 if (_strictMode || propagatedRightType == null) { 13645 if (_strictMode || propagatedRightType == null) {
13199 if (!isStaticAssignable) { 13646 if (!isStaticAssignable) {
13200 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]); 13647 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]);
13201 return true; 13648 return true;
13202 } 13649 }
13203 } else { 13650 } else {
13204 bool isPropagatedAssignable = propagatedRightType.isAssignableTo(leftType) ; 13651 bool isPropagatedAssignable = propagatedRightType.isAssignableTo(leftType) ;
13205 if (!isStaticAssignable && !isPropagatedAssignable) { 13652 if (!isStaticAssignable && !isPropagatedAssignable) {
13206 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]); 13653 _errorReporter.reportError2(StaticTypeWarningCode.INVALID_ASSIGNMENT, rh s, [staticRightType.displayName, leftType.displayName]);
13207 return true; 13654 return true;
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
13567 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE 14014 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE
13568 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO 14015 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_TWO
13569 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE 14016 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_THREE
13570 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR 14017 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FOUR
13571 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU S 14018 * @see StaticWarningCode#NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLU S
13572 */ 14019 */
13573 bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) { 14020 bool checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration node) {
13574 if (_enclosingClass.isAbstract) { 14021 if (_enclosingClass.isAbstract) {
13575 return false; 14022 return false;
13576 } 14023 }
13577 Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>(); 14024 List<MethodElement> methods = _enclosingClass.methods;
14025 List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
13578 Set<String> methodsInEnclosingClass = new Set<String>(); 14026 Set<String> methodsInEnclosingClass = new Set<String>();
13579 Set<String> accessorsInEnclosingClass = new Set<String>(); 14027 Set<String> accessorsInEnclosingClass = new Set<String>();
13580 List<MethodElement> methods = _enclosingClass.methods;
13581 for (MethodElement method in methods) { 14028 for (MethodElement method in methods) {
13582 javaSetAdd(methodsInEnclosingClass, method.name); 14029 javaSetAdd(methodsInEnclosingClass, method.name);
13583 } 14030 }
13584 List<PropertyAccessorElement> accessors = _enclosingClass.accessors;
13585 for (PropertyAccessorElement accessor in accessors) { 14031 for (PropertyAccessorElement accessor in accessors) {
13586 javaSetAdd(accessorsInEnclosingClass, accessor.name); 14032 javaSetAdd(accessorsInEnclosingClass, accessor.name);
13587 } 14033 }
14034 if (methodsInEnclosingClass.contains(ElementResolver.NO_SUCH_METHOD_METHOD_N AME)) {
14035 return false;
14036 }
14037 Set<ExecutableElement> missingOverrides = new Set<ExecutableElement>();
14038 Map<String, ExecutableElement> membersInheritedFromInterfaces = _inheritance Manager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
13588 Map<String, ExecutableElement> membersInheritedFromSuperclasses = _inheritan ceManager.getMapOfMembersInheritedFromClasses(_enclosingClass); 14039 Map<String, ExecutableElement> membersInheritedFromSuperclasses = _inheritan ceManager.getMapOfMembersInheritedFromClasses(_enclosingClass);
13589 for (MapEntry<String, ExecutableElement> entry in getMapEntrySet(membersInhe ritedFromSuperclasses)) {
13590 ExecutableElement executableElt = entry.getValue();
13591 if (executableElt is MethodElement) {
13592 MethodElement methodElt = executableElt as MethodElement;
13593 if (methodElt.isAbstract) {
13594 String methodName = entry.getKey();
13595 if (!methodsInEnclosingClass.contains(methodName)) {
13596 javaSetAdd(missingOverrides, executableElt);
13597 }
13598 }
13599 } else if (executableElt is PropertyAccessorElement) {
13600 PropertyAccessorElement propertyAccessorElt = executableElt as PropertyA ccessorElement;
13601 if (propertyAccessorElt.isAbstract) {
13602 String accessorName = entry.getKey();
13603 if (!accessorsInEnclosingClass.contains(accessorName)) {
13604 javaSetAdd(missingOverrides, executableElt);
13605 }
13606 }
13607 }
13608 }
13609 Map<String, ExecutableElement> membersInheritedFromInterfaces = _inheritance Manager.getMapOfMembersInheritedFromInterfaces(_enclosingClass);
13610 for (MapEntry<String, ExecutableElement> entry in getMapEntrySet(membersInhe ritedFromInterfaces)) { 14040 for (MapEntry<String, ExecutableElement> entry in getMapEntrySet(membersInhe ritedFromInterfaces)) {
13611 ExecutableElement executableElt = entry.getValue(); 14041 ExecutableElement executableElt = entry.getValue();
13612 ExecutableElement elt = membersInheritedFromSuperclasses[executableElt.nam e]; 14042 ExecutableElement elt = membersInheritedFromSuperclasses[executableElt.nam e];
13613 if (elt != null) { 14043 if (elt != null) {
13614 if (elt is MethodElement && !((elt as MethodElement)).isAbstract) { 14044 if (elt is MethodElement && !((elt as MethodElement)).isAbstract) {
13615 continue; 14045 continue;
13616 } else if (elt is PropertyAccessorElement && !((elt as PropertyAccessorE lement)).isAbstract) { 14046 } else if (elt is PropertyAccessorElement && !((elt as PropertyAccessorE lement)).isAbstract) {
13617 continue; 14047 continue;
13618 } 14048 }
13619 } 14049 }
13620 if (executableElt is MethodElement) { 14050 if (executableElt is MethodElement) {
13621 String methodName = entry.getKey(); 14051 String methodName = entry.getKey();
13622 if (!methodsInEnclosingClass.contains(methodName)) { 14052 if (!methodsInEnclosingClass.contains(methodName) && !memberHasConcreteM ethodImplementationInSuperclassChain(_enclosingClass, methodName, new List<Class Element>())) {
13623 javaSetAdd(missingOverrides, executableElt); 14053 javaSetAdd(missingOverrides, executableElt);
13624 } 14054 }
13625 } else if (executableElt is PropertyAccessorElement) { 14055 } else if (executableElt is PropertyAccessorElement) {
13626 String accessorName = entry.getKey(); 14056 String accessorName = entry.getKey();
13627 if (!accessorsInEnclosingClass.contains(accessorName)) { 14057 if (!accessorsInEnclosingClass.contains(accessorName) && !memberHasConcr eteAccessorImplementationInSuperclassChain(_enclosingClass, accessorName, new Li st<ClassElement>())) {
13628 javaSetAdd(missingOverrides, executableElt); 14058 javaSetAdd(missingOverrides, executableElt);
13629 } 14059 }
13630 } 14060 }
13631 } 14061 }
13632 int missingOverridesSize = missingOverrides.length; 14062 int missingOverridesSize = missingOverrides.length;
13633 if (missingOverridesSize == 0) { 14063 if (missingOverridesSize == 0) {
13634 return false; 14064 return false;
13635 } 14065 }
13636 List<ExecutableElement> missingOverridesArray = new List.from(missingOverrid es); 14066 List<ExecutableElement> missingOverridesArray = new List.from(missingOverrid es);
13637 List<String> stringMembersArrayListSet = new List<String>(); 14067 List<String> stringMembersArrayListSet = new List<String>();
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
13898 JavaStringBuilder builder = new JavaStringBuilder(); 14328 JavaStringBuilder builder = new JavaStringBuilder();
13899 for (int i = 0; i < listLength; i++) { 14329 for (int i = 0; i < listLength; i++) {
13900 builder.append(list[i].displayName); 14330 builder.append(list[i].displayName);
13901 if (i != listLength - 1) { 14331 if (i != listLength - 1) {
13902 builder.append(separator); 14332 builder.append(separator);
13903 } 14333 }
13904 } 14334 }
13905 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_INTERFACE_INH ERITANCE, _enclosingClass.nameOffset, enclosingClassName.length, [enclosingClass Name, builder.toString()]); 14335 _errorReporter.reportError3(CompileTimeErrorCode.RECURSIVE_INTERFACE_INH ERITANCE, _enclosingClass.nameOffset, enclosingClassName.length, [enclosingClass Name, builder.toString()]);
13906 return true; 14336 return true;
13907 } else if (list.length == 2) { 14337 } else if (list.length == 2) {
13908 ErrorCode errorCode = supertype != null && _enclosingClass == supertype. element ? CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTENDS : CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS; 14338 ErrorCode errorCode = (supertype != null && _enclosingClass == supertype .element ? CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_EXTEND S : CompileTimeErrorCode.RECURSIVE_INTERFACE_INHERITANCE_BASE_CASE_IMPLEMENTS) a s ErrorCode;
13909 _errorReporter.reportError3(errorCode, _enclosingClass.nameOffset, enclo singClassName.length, [enclosingClassName]); 14339 _errorReporter.reportError3(errorCode, _enclosingClass.nameOffset, enclo singClassName.length, [enclosingClassName]);
13910 return true; 14340 return true;
13911 } 14341 }
13912 } 14342 }
13913 for (int i = 1; i < list.length - 1; i++) { 14343 for (int i = 1; i < list.length - 1; i++) {
13914 if (classElt == list[i]) { 14344 if (classElt == list[i]) {
13915 list.removeAt(list.length - 1); 14345 list.removeAt(list.length - 1);
13916 return false; 14346 return false;
13917 } 14347 }
13918 } 14348 }
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
14108 if (staticReturnType.isVoid || staticReturnType.isDynamic || identical(sta ticReturnType, BottomTypeImpl.instance)) { 14538 if (staticReturnType.isVoid || staticReturnType.isDynamic || identical(sta ticReturnType, BottomTypeImpl.instance)) {
14109 return false; 14539 return false;
14110 } 14540 }
14111 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [ 14541 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
14112 staticReturnType.displayName, 14542 staticReturnType.displayName,
14113 expectedReturnType.displayName, 14543 expectedReturnType.displayName,
14114 _enclosingFunction.displayName]); 14544 _enclosingFunction.displayName]);
14115 return true; 14545 return true;
14116 } 14546 }
14117 bool isStaticAssignable = staticReturnType.isAssignableTo(expectedReturnType ); 14547 bool isStaticAssignable = staticReturnType.isAssignableTo(expectedReturnType );
14118 Type2 propagatedReturnType = getPropagatedType(returnExpression); 14548 Type2 propagatedReturnType = returnExpression.propagatedType;
14119 if (_strictMode || propagatedReturnType == null) { 14549 if (_strictMode || propagatedReturnType == null) {
14120 if (isStaticAssignable) { 14550 if (isStaticAssignable) {
14121 return false; 14551 return false;
14122 } 14552 }
14123 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [ 14553 _errorReporter.reportError2(StaticTypeWarningCode.RETURN_OF_INVALID_TYPE, returnExpression, [
14124 staticReturnType.displayName, 14554 staticReturnType.displayName,
14125 expectedReturnType.displayName, 14555 expectedReturnType.displayName,
14126 _enclosingFunction.displayName]); 14556 _enclosingFunction.displayName]);
14127 return true; 14557 return true;
14128 } else { 14558 } else {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
14196 14626
14197 /** 14627 /**
14198 * This verifies that the passed function type alias does not reference itself directly. 14628 * This verifies that the passed function type alias does not reference itself directly.
14199 * 14629 *
14200 * @param node the function type alias to evaluate 14630 * @param node the function type alias to evaluate
14201 * @return `true` if and only if an error code is generated on the passed node 14631 * @return `true` if and only if an error code is generated on the passed node
14202 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF 14632 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
14203 */ 14633 */
14204 bool checkForTypeAliasCannotReferenceItself_function(FunctionTypeAlias node) { 14634 bool checkForTypeAliasCannotReferenceItself_function(FunctionTypeAlias node) {
14205 FunctionTypeAliasElement element = node.element; 14635 FunctionTypeAliasElement element = node.element;
14206 if (!hasFunctionTypeAliasSelfReference(element)) { 14636 if (!hasTypedefSelfReference(element)) {
14207 return false; 14637 return false;
14208 } 14638 }
14209 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []); 14639 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []);
14210 return true; 14640 return true;
14211 } 14641 }
14212 14642
14213 /** 14643 /**
14214 * This verifies that the given class type alias does not reference itself. 14644 * This verifies that the given class type alias does not reference itself.
14215 * 14645 *
14216 * @return `true` if and only if an error code is generated on the passed node 14646 * @return `true` if and only if an error code is generated on the passed node
14217 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF 14647 * @see CompileTimeErrorCode#TYPE_ALIAS_CANNOT_REFERENCE_ITSELF
14218 */ 14648 */
14219 bool checkForTypeAliasCannotReferenceItself_mixin(ClassTypeAlias node) { 14649 bool checkForTypeAliasCannotReferenceItself_mixin(ClassTypeAlias node) {
14220 ClassElement element = node.element; 14650 ClassElement element = node.element;
14221 if (!hasClassTypeAliasSelfReference(element, new Set<ClassElement>())) { 14651 if (!hasTypedefSelfReference(element)) {
14222 return false; 14652 return false;
14223 } 14653 }
14224 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []); 14654 _errorReporter.reportError2(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE _ITSELF, node, []);
14225 return true; 14655 return true;
14226 } 14656 }
14227 14657
14228 /** 14658 /**
14229 * This verifies that the type arguments in the passed type name are all withi n their bounds. 14659 * This verifies that the type arguments in the passed type name are all withi n their bounds.
14230 * 14660 *
14231 * @param node the [TypeName] to evaluate 14661 * @param node the [TypeName] to evaluate
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
14425 for (TypeName interfaceNode in implementsClause.interfaces) { 14855 for (TypeName interfaceNode in implementsClause.interfaces) {
14426 if (interfaceNode.type == superType) { 14856 if (interfaceNode.type == superType) {
14427 hasProblem = true; 14857 hasProblem = true;
14428 _errorReporter.reportError2(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode, [superType.displayName]); 14858 _errorReporter.reportError2(CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, interfaceNode, [superType.displayName]);
14429 } 14859 }
14430 } 14860 }
14431 return hasProblem; 14861 return hasProblem;
14432 } 14862 }
14433 14863
14434 /** 14864 /**
14435 * Return the propagated type of the given expression, or the static type if t here is no
14436 * propagated type information.
14437 *
14438 * @param expression the expression whose type is to be returned
14439 * @return the propagated or static type of the given expression, whichever is best
14440 */
14441 Type2 getBestType(Expression expression) {
14442 Type2 type = getPropagatedType(expression);
14443 if (type == null) {
14444 type = getStaticType(expression);
14445 }
14446 return type;
14447 }
14448
14449 /**
14450 * Returns the Type (return type) for a given getter. 14865 * Returns the Type (return type) for a given getter.
14451 * 14866 *
14452 * @param propertyAccessorElement 14867 * @param propertyAccessorElement
14453 * @return The type of the given getter. 14868 * @return The type of the given getter.
14454 */ 14869 */
14455 Type2 getGetterType(PropertyAccessorElement propertyAccessorElement) { 14870 Type2 getGetterType(PropertyAccessorElement propertyAccessorElement) {
14456 FunctionType functionType = propertyAccessorElement.type; 14871 FunctionType functionType = propertyAccessorElement.type;
14457 if (functionType != null) { 14872 if (functionType != null) {
14458 return functionType.returnType; 14873 return functionType.returnType;
14459 } else { 14874 } else {
14460 return null; 14875 return null;
14461 } 14876 }
14462 } 14877 }
14463 14878
14464 /** 14879 /**
14465 * Return the propagated type of the given expression that is to be used for t ype analysis.
14466 *
14467 * @param expression the expression whose type is to be returned
14468 * @return the propagated type of the given expression
14469 */
14470 Type2 getPropagatedType(Expression expression) => expression.propagatedType;
14471
14472 /**
14473 * Returns the Type (first and only parameter) for a given setter. 14880 * Returns the Type (first and only parameter) for a given setter.
14474 * 14881 *
14475 * @param propertyAccessorElement 14882 * @param propertyAccessorElement
14476 * @return The type of the given setter. 14883 * @return The type of the given setter.
14477 */ 14884 */
14478 Type2 getSetterType(PropertyAccessorElement propertyAccessorElement) { 14885 Type2 getSetterType(PropertyAccessorElement propertyAccessorElement) {
14479 List<ParameterElement> setterParameters = propertyAccessorElement.parameters ; 14886 List<ParameterElement> setterParameters = propertyAccessorElement.parameters ;
14480 if (setterParameters.length == 0) { 14887 if (setterParameters.length == 0) {
14481 return null; 14888 return null;
14482 } 14889 }
(...skipping 25 matching lines...) Expand all
14508 if (expression is Identifier) { 14915 if (expression is Identifier) {
14509 Element element = ((expression as Identifier)).element; 14916 Element element = ((expression as Identifier)).element;
14510 if (element is VariableElement) { 14917 if (element is VariableElement) {
14511 return element as VariableElement; 14918 return element as VariableElement;
14512 } 14919 }
14513 } 14920 }
14514 return null; 14921 return null;
14515 } 14922 }
14516 14923
14517 /** 14924 /**
14518 * @return <code>true</code> if given [ClassElement] has direct or indirect re ference to
14519 * itself using only other typedef [ClassElement]s.
14520 */
14521 bool hasClassTypeAliasSelfReference(ClassElement element2, Set<ClassElement> s eenMixins) {
14522 if (seenMixins.contains(element2)) {
14523 return true;
14524 }
14525 javaSetAdd(seenMixins, element2);
14526 for (InterfaceType mixin in element2.mixins) {
14527 ClassElement mixinElement = mixin.element;
14528 if (!mixinElement.isTypedef) {
14529 continue;
14530 }
14531 if (hasClassTypeAliasSelfReference(mixinElement, seenMixins)) {
14532 return true;
14533 }
14534 }
14535 return false;
14536 }
14537
14538 /**
14539 * Checks if "target" is referenced by "current".
14540 */
14541 bool hasFunctionTypeAliasReference(Set<FunctionTypeAliasElement> visited, Func tionTypeAliasElement target, Element currentElement) {
14542 if (currentElement is! FunctionTypeAliasElement) {
14543 return false;
14544 }
14545 FunctionTypeAliasElement current = currentElement as FunctionTypeAliasElemen t;
14546 if (target == current) {
14547 return true;
14548 }
14549 if (visited.contains(current)) {
14550 return false;
14551 }
14552 javaSetAdd(visited, current);
14553 return hasFunctionTypeAliasReference2(visited, target, current);
14554 }
14555
14556 /**
14557 * Checks if "target" is referenced by "current".
14558 */
14559 bool hasFunctionTypeAliasReference2(Set<FunctionTypeAliasElement> visited, Fun ctionTypeAliasElement target, FunctionTypeAliasElement current) {
14560 FunctionType type = current.type;
14561 Set<Type2> referencedTypes = new Set();
14562 if (type != null) {
14563 for (TypeVariableElement typeVariable in current.typeVariables) {
14564 Type2 bound = typeVariable.bound;
14565 javaSetAdd(referencedTypes, bound);
14566 }
14567 javaSetAdd(referencedTypes, type.returnType);
14568 for (ParameterElement parameter in type.parameters) {
14569 javaSetAdd(referencedTypes, parameter.type);
14570 }
14571 }
14572 for (Type2 referencedType in referencedTypes) {
14573 if (referencedType != null && hasFunctionTypeAliasReference(visited, targe t, referencedType.element)) {
14574 return true;
14575 }
14576 }
14577 return false;
14578 }
14579
14580 /**
14581 * @return <code>true</code> if given [FunctionTypeAliasElement] has direct or indirect
14582 * reference to itself using other [FunctionTypeAliasElement]s.
14583 */
14584 bool hasFunctionTypeAliasSelfReference(FunctionTypeAliasElement target) {
14585 Set<FunctionTypeAliasElement> visited = new Set();
14586 return hasFunctionTypeAliasReference2(visited, target, target);
14587 }
14588
14589 /**
14590 * @return `true` if the given constructor redirects to itself, directly or in directly 14925 * @return `true` if the given constructor redirects to itself, directly or in directly
14591 */ 14926 */
14592 bool hasRedirectingFactoryConstructorCycle(ConstructorElement element) { 14927 bool hasRedirectingFactoryConstructorCycle(ConstructorElement element) {
14593 Set<ConstructorElement> constructors = new Set<ConstructorElement>(); 14928 Set<ConstructorElement> constructors = new Set<ConstructorElement>();
14594 ConstructorElement current = element; 14929 ConstructorElement current = element;
14595 while (current != null) { 14930 while (current != null) {
14596 if (constructors.contains(current)) { 14931 if (constructors.contains(current)) {
14597 return identical(current, element); 14932 return identical(current, element);
14598 } 14933 }
14599 javaSetAdd(constructors, current); 14934 javaSetAdd(constructors, current);
14600 current = current.redirectedConstructor; 14935 current = current.redirectedConstructor;
14601 if (current is ConstructorMember) { 14936 if (current is ConstructorMember) {
14602 current = ((current as ConstructorMember)).baseElement; 14937 current = ((current as ConstructorMember)).baseElement;
14603 } 14938 }
14604 } 14939 }
14605 return false; 14940 return false;
14606 } 14941 }
14607 14942
14608 /** 14943 /**
14944 * @return <code>true</code> if given [Element] has direct or indirect referen ce to itself
14945 * form anywhere except [ClassElement] or type variable bounds.
14946 */
14947 bool hasTypedefSelfReference(Element target) {
14948 Set<Element> checked = new Set<Element>();
14949 List<Element> toCheck = new List<Element>();
14950 toCheck.add(target);
14951 bool firstIteration = true;
14952 while (true) {
14953 Element current;
14954 while (true) {
14955 if (toCheck.isEmpty) {
14956 return false;
14957 }
14958 current = toCheck.removeAt(toCheck.length - 1);
14959 if (target == current) {
14960 if (firstIteration) {
14961 firstIteration = false;
14962 break;
14963 } else {
14964 return true;
14965 }
14966 }
14967 if (current != null && !checked.contains(current)) {
14968 break;
14969 }
14970 }
14971 current.accept(new GeneralizingElementVisitor_11(target, toCheck));
14972 javaSetAdd(checked, current);
14973 }
14974 }
14975
14976 /**
14609 * @return `true` if the given [ASTNode] is the part of constant constructor 14977 * @return `true` if the given [ASTNode] is the part of constant constructor
14610 * invocation. 14978 * invocation.
14611 */ 14979 */
14612 bool isInConstConstructorInvocation(ASTNode node) { 14980 bool isInConstConstructorInvocation(ASTNode node) {
14613 InstanceCreationExpression creation = node.getAncestor(InstanceCreationExpre ssion); 14981 InstanceCreationExpression creation = node.getAncestor(InstanceCreationExpre ssion);
14614 if (creation == null) { 14982 if (creation == null) {
14615 return false; 14983 return false;
14616 } 14984 }
14617 return creation.isConst; 14985 return creation.isConst;
14618 } 14986 }
(...skipping 14 matching lines...) Expand all
14633 if (n is ConstructorFieldInitializer) { 15001 if (n is ConstructorFieldInitializer) {
14634 return false; 15002 return false;
14635 } 15003 }
14636 if (n is MethodDeclaration) { 15004 if (n is MethodDeclaration) {
14637 MethodDeclaration method = n as MethodDeclaration; 15005 MethodDeclaration method = n as MethodDeclaration;
14638 return !method.isStatic; 15006 return !method.isStatic;
14639 } 15007 }
14640 } 15008 }
14641 return false; 15009 return false;
14642 } 15010 }
15011
15012 /**
15013 * Return `true` iff the passed [ClassElement] has a concrete implementation o f the
15014 * passed accessor name in the superclass chain.
15015 */
15016 bool memberHasConcreteAccessorImplementationInSuperclassChain(ClassElement cla ssElement, String accessorName, List<ClassElement> superclassChain) {
15017 if (superclassChain.contains(classElement)) {
15018 return false;
15019 } else {
15020 superclassChain.add(classElement);
15021 }
15022 for (PropertyAccessorElement accessor in classElement.accessors) {
15023 if (accessor.name == accessorName) {
15024 if (!accessor.isAbstract) {
15025 return true;
15026 }
15027 }
15028 }
15029 for (InterfaceType mixinType in classElement.mixins) {
15030 if (mixinType != null) {
15031 ClassElement mixinElement = mixinType.element;
15032 if (mixinElement != null) {
15033 for (PropertyAccessorElement accessor in mixinElement.accessors) {
15034 if (accessor.name == accessorName) {
15035 if (!accessor.isAbstract) {
15036 return true;
15037 }
15038 }
15039 }
15040 }
15041 }
15042 }
15043 InterfaceType superType = classElement.supertype;
15044 if (superType != null) {
15045 ClassElement superClassElt = superType.element;
15046 if (superClassElt != null) {
15047 return memberHasConcreteAccessorImplementationInSuperclassChain(superCla ssElt, accessorName, superclassChain);
15048 }
15049 }
15050 return false;
15051 }
15052
15053 /**
15054 * Return `true` iff the passed [ClassElement] has a concrete implementation o f the
15055 * passed method name in the superclass chain.
15056 */
15057 bool memberHasConcreteMethodImplementationInSuperclassChain(ClassElement class Element, String methodName, List<ClassElement> superclassChain) {
15058 if (superclassChain.contains(classElement)) {
15059 return false;
15060 } else {
15061 superclassChain.add(classElement);
15062 }
15063 for (MethodElement method in classElement.methods) {
15064 if (method.name == methodName) {
15065 if (!method.isAbstract) {
15066 return true;
15067 }
15068 }
15069 }
15070 for (InterfaceType mixinType in classElement.mixins) {
15071 if (mixinType != null) {
15072 ClassElement mixinElement = mixinType.element;
15073 if (mixinElement != null) {
15074 for (MethodElement method in mixinElement.methods) {
15075 if (method.name == methodName) {
15076 if (!method.isAbstract) {
15077 return true;
15078 }
15079 }
15080 }
15081 }
15082 }
15083 }
15084 InterfaceType superType = classElement.supertype;
15085 if (superType != null) {
15086 ClassElement superClassElt = superType.element;
15087 if (superClassElt != null) {
15088 return memberHasConcreteMethodImplementationInSuperclassChain(superClass Elt, methodName, superclassChain);
15089 }
15090 }
15091 return false;
15092 }
14643 } 15093 }
14644 /** 15094 /**
14645 * This enum holds one of four states of a field initialization state through a constructor 15095 * This enum holds one of four states of a field initialization state through a constructor
14646 * signature, not initialized, initialized in the field declaration, initialized in the field 15096 * signature, not initialized, initialized in the field declaration, initialized in the field
14647 * formal, and finally, initialized in the initializers list. 15097 * formal, and finally, initialized in the initializers list.
14648 */ 15098 */
14649 class INIT_STATE implements Comparable<INIT_STATE> { 15099 class INIT_STATE implements Enum<INIT_STATE> {
14650 static final INIT_STATE NOT_INIT = new INIT_STATE('NOT_INIT', 0); 15100 static final INIT_STATE NOT_INIT = new INIT_STATE('NOT_INIT', 0);
14651 static final INIT_STATE INIT_IN_DECLARATION = new INIT_STATE('INIT_IN_DECLARAT ION', 1); 15101 static final INIT_STATE INIT_IN_DECLARATION = new INIT_STATE('INIT_IN_DECLARAT ION', 1);
14652 static final INIT_STATE INIT_IN_FIELD_FORMAL = new INIT_STATE('INIT_IN_FIELD_F ORMAL', 2); 15102 static final INIT_STATE INIT_IN_FIELD_FORMAL = new INIT_STATE('INIT_IN_FIELD_F ORMAL', 2);
14653 static final INIT_STATE INIT_IN_INITIALIZERS = new INIT_STATE('INIT_IN_INITIAL IZERS', 3); 15103 static final INIT_STATE INIT_IN_INITIALIZERS = new INIT_STATE('INIT_IN_INITIAL IZERS', 3);
14654 static final List<INIT_STATE> values = [ 15104 static final List<INIT_STATE> values = [
14655 NOT_INIT, 15105 NOT_INIT,
14656 INIT_IN_DECLARATION, 15106 INIT_IN_DECLARATION,
14657 INIT_IN_FIELD_FORMAL, 15107 INIT_IN_FIELD_FORMAL,
14658 INIT_IN_INITIALIZERS]; 15108 INIT_IN_INITIALIZERS];
14659 15109
14660 /// The name of this enum constant, as declared in the enum declaration. 15110 /// The name of this enum constant, as declared in the enum declaration.
14661 final String name; 15111 final String name;
14662 15112
14663 /// The position in the enum declaration. 15113 /// The position in the enum declaration.
14664 final int ordinal; 15114 final int ordinal;
14665 INIT_STATE(this.name, this.ordinal); 15115 INIT_STATE(this.name, this.ordinal);
14666 int compareTo(INIT_STATE other) => ordinal - other.ordinal; 15116 int compareTo(INIT_STATE other) => ordinal - other.ordinal;
14667 int get hashCode => ordinal; 15117 int get hashCode => ordinal;
14668 String toString() => name; 15118 String toString() => name;
14669 } 15119 }
14670 /** 15120 class GeneralizingElementVisitor_11 extends GeneralizingElementVisitor<Object> {
14671 * Instances of the class `HintVerifier` traverse an AST structure looking for a dditional 15121 Element target;
14672 * additional suggestions not mentioned in the Dart Language Specification. 15122 List<Element> toCheck;
14673 * 15123 GeneralizingElementVisitor_11(this.target, this.toCheck) : super();
14674 * @coverage dart.engine.resolver 15124 bool _inClass = false;
14675 */ 15125 Object visitClassElement(ClassElement element) {
14676 class HintVerifier { 15126 addTypeToCheck(element.supertype);
14677 DeadCodeVerifier _deadCodeVerifier; 15127 for (InterfaceType mixin in element.mixins) {
14678 HintVerifier(AnalysisContext context, ErrorReporter errorReporter) { 15128 addTypeToCheck(mixin);
14679 _deadCodeVerifier = new DeadCodeVerifier(errorReporter); 15129 }
15130 _inClass = !element.isTypedef;
15131 try {
15132 return super.visitClassElement(element);
15133 } finally {
15134 _inClass = false;
15135 }
14680 } 15136 }
14681 void visitCompilationUnit(CompilationUnit node) { 15137 Object visitExecutableElement(ExecutableElement element) {
14682 node.accept(_deadCodeVerifier); 15138 if (element.isSynthetic) {
15139 return null;
15140 }
15141 addTypeToCheck(element.returnType);
15142 return super.visitExecutableElement(element);
15143 }
15144 Object visitFunctionTypeAliasElement(FunctionTypeAliasElement element) {
15145 addTypeToCheck(element.returnType);
15146 return super.visitFunctionTypeAliasElement(element);
15147 }
15148 Object visitParameterElement(ParameterElement element) {
15149 addTypeToCheck(element.type);
15150 return super.visitParameterElement(element);
15151 }
15152 Object visitTypeVariableElement(TypeVariableElement element) => null;
15153 Object visitVariableElement(VariableElement element) {
15154 addTypeToCheck(element.type);
15155 return super.visitVariableElement(element);
15156 }
15157 void addTypeToCheck(Type2 type) {
15158 if (type == null) {
15159 return;
15160 }
15161 Element element = type.element;
15162 if (_inClass && target == element) {
15163 return;
15164 }
15165 toCheck.add(element);
15166 if (type is InterfaceType) {
15167 InterfaceType interfaceType = type as InterfaceType;
15168 for (Type2 typeArgument in interfaceType.typeArguments) {
15169 addTypeToCheck(typeArgument);
15170 }
15171 }
14683 } 15172 }
14684 } 15173 }
14685 /** 15174 /**
14686 * Instances of the class `PubVerifier` traverse an AST structure looking for de viations from
14687 * pub best practices.
14688 */
14689 class PubVerifier extends RecursiveASTVisitor<Object> {
14690 static String _PUBSPEC_YAML = "pubspec.yaml";
14691
14692 /**
14693 * The analysis context containing the sources to be analyzed
14694 */
14695 AnalysisContext _context;
14696
14697 /**
14698 * The error reporter by which errors will be reported.
14699 */
14700 ErrorReporter _errorReporter;
14701 PubVerifier(AnalysisContext context, ErrorReporter errorReporter) {
14702 this._context = context;
14703 this._errorReporter = errorReporter;
14704 }
14705 Object visitImportDirective(ImportDirective directive) {
14706 return null;
14707 }
14708
14709 /**
14710 * This verifies that the passed file import directive is not contained in a s ource inside a
14711 * package "lib" directory hierarchy referencing a source outside that package "lib" directory
14712 * hierarchy.
14713 *
14714 * @param uriLiteral the import URL (not `null`)
14715 * @param path the file path being verified (not `null`)
14716 * @return `true` if and only if an error code is generated on the passed node
14717 * @see PubSuggestionCode.FILE_IMPORT_INSIDE_LIB_REFERENCES_FILE_OUTSIDE
14718 */
14719 bool checkForFileImportInsideLibReferencesFileOutside(StringLiteral uriLiteral , String path) {
14720 Source source = getSource(uriLiteral);
14721 String fullName = getSourceFullName(source);
14722 if (fullName != null) {
14723 int pathIndex = 0;
14724 int fullNameIndex = fullName.length;
14725 while (pathIndex < path.length && JavaString.startsWithBefore(path, "../", pathIndex)) {
14726 fullNameIndex = JavaString.lastIndexOf(fullName, '/', fullNameIndex);
14727 if (fullNameIndex < 4) {
14728 return false;
14729 }
14730 if (JavaString.startsWithBefore(fullName, "/lib", fullNameIndex - 4)) {
14731 String relativePubspecPath = path.substring(0, pathIndex + 3) + _PUBSP EC_YAML;
14732 Source pubspecSource = _context.sourceFactory.resolveUri(source, relat ivePubspecPath);
14733 if (pubspecSource.exists()) {
14734 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_INSIDE_LIB _REFERENCES_FILE_OUTSIDE, uriLiteral, []);
14735 }
14736 return true;
14737 }
14738 pathIndex += 3;
14739 }
14740 }
14741 return false;
14742 }
14743
14744 /**
14745 * This verifies that the passed file import directive is not contained in a s ource outside a
14746 * package "lib" directory hierarchy referencing a source inside that package "lib" directory
14747 * hierarchy.
14748 *
14749 * @param uriLiteral the import URL (not `null`)
14750 * @param path the file path being verified (not `null`)
14751 * @return `true` if and only if an error code is generated on the passed node
14752 * @see PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_REFERENCES_FILE_INSIDE
14753 */
14754 bool checkForFileImportOutsideLibReferencesFileInside(StringLiteral uriLiteral , String path) {
14755 if (path.startsWith("lib/")) {
14756 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, 0) ) {
14757 return true;
14758 }
14759 }
14760 int pathIndex = path.indexOf("/lib/");
14761 while (pathIndex != -1) {
14762 if (checkForFileImportOutsideLibReferencesFileInside2(uriLiteral, path, pa thIndex + 1)) {
14763 return true;
14764 }
14765 pathIndex = JavaString.indexOf(path, "/lib/", pathIndex + 4);
14766 }
14767 return false;
14768 }
14769 bool checkForFileImportOutsideLibReferencesFileInside2(StringLiteral uriLitera l, String path, int pathIndex) {
14770 Source source = getSource(uriLiteral);
14771 String relativePubspecPath = path.substring(0, pathIndex) + _PUBSPEC_YAML;
14772 Source pubspecSource = _context.sourceFactory.resolveUri(source, relativePub specPath);
14773 if (!pubspecSource.exists()) {
14774 return false;
14775 }
14776 String fullName = getSourceFullName(source);
14777 if (fullName != null) {
14778 if (!fullName.contains("/lib/")) {
14779 _errorReporter.reportError2(PubSuggestionCode.FILE_IMPORT_OUTSIDE_LIB_RE FERENCES_FILE_INSIDE, uriLiteral, []);
14780 return true;
14781 }
14782 }
14783 return false;
14784 }
14785
14786 /**
14787 * This verifies that the passed package import directive does not contain ".. "
14788 *
14789 * @param uriLiteral the import URL (not `null`)
14790 * @param path the path to be validated (not `null`)
14791 * @return `true` if and only if an error code is generated on the passed node
14792 * @see PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_DOT
14793 */
14794 bool checkForPackageImportContainsDotDot(StringLiteral uriLiteral, String path ) {
14795 if (path.startsWith("../") || path.contains("/../")) {
14796 _errorReporter.reportError2(PubSuggestionCode.PACKAGE_IMPORT_CONTAINS_DOT_ DOT, uriLiteral, []);
14797 return true;
14798 }
14799 return false;
14800 }
14801
14802 /**
14803 * Answer the source associated with the compilation unit containing the given AST node.
14804 *
14805 * @param node the node (not `null`)
14806 * @return the source or `null` if it could not be determined
14807 */
14808 Source getSource(ASTNode node) {
14809 Source source = null;
14810 CompilationUnit unit = node.getAncestor(CompilationUnit);
14811 if (unit != null) {
14812 CompilationUnitElement element = unit.element;
14813 if (element != null) {
14814 source = element.source;
14815 }
14816 }
14817 return source;
14818 }
14819
14820 /**
14821 * Answer the full name of the given source. The returned value will have all
14822 * [File#separatorChar] replace by '/'.
14823 *
14824 * @param source the source
14825 * @return the full name or `null` if it could not be determined
14826 */
14827 String getSourceFullName(Source source) {
14828 if (source != null) {
14829 String fullName = source.fullName;
14830 if (fullName != null) {
14831 return fullName.replaceAll(r'\', '/');
14832 }
14833 }
14834 return null;
14835 }
14836 }
14837 /**
14838 * The enumeration `ResolverErrorCode` defines the error codes used for errors d etected by the 15175 * The enumeration `ResolverErrorCode` defines the error codes used for errors d etected by the
14839 * resolver. The convention for this class is for the name of the error code to indicate the problem 15176 * resolver. The convention for this class is for the name of the error code to indicate the problem
14840 * that caused the error to be generated and for the error message to explain wh at is wrong and, 15177 * that caused the error to be generated and for the error message to explain wh at is wrong and,
14841 * when appropriate, how the problem can be corrected. 15178 * when appropriate, how the problem can be corrected.
14842 * 15179 *
14843 * @coverage dart.engine.resolver 15180 * @coverage dart.engine.resolver
14844 */ 15181 */
14845 class ResolverErrorCode implements Comparable<ResolverErrorCode>, ErrorCode { 15182 class ResolverErrorCode implements Enum<ResolverErrorCode>, ErrorCode {
14846 static final ResolverErrorCode BREAK_LABEL_ON_SWITCH_MEMBER = new ResolverErro rCode('BREAK_LABEL_ON_SWITCH_MEMBER', 0, ErrorType.COMPILE_TIME_ERROR, "Break la bel resolves to case or default statement"); 15183 static final ResolverErrorCode BREAK_LABEL_ON_SWITCH_MEMBER = new ResolverErro rCode('BREAK_LABEL_ON_SWITCH_MEMBER', 0, ErrorType.COMPILE_TIME_ERROR, "Break la bel resolves to case or default statement");
14847 static final ResolverErrorCode CONTINUE_LABEL_ON_SWITCH = new ResolverErrorCod e('CONTINUE_LABEL_ON_SWITCH', 1, ErrorType.COMPILE_TIME_ERROR, "A continue label resolves to switch, must be loop or switch member"); 15184 static final ResolverErrorCode CONTINUE_LABEL_ON_SWITCH = new ResolverErrorCod e('CONTINUE_LABEL_ON_SWITCH', 1, ErrorType.COMPILE_TIME_ERROR, "A continue label resolves to switch, must be loop or switch member");
14848 static final ResolverErrorCode MISSING_LIBRARY_DIRECTIVE_WITH_PART = new Resol verErrorCode('MISSING_LIBRARY_DIRECTIVE_WITH_PART', 2, ErrorType.COMPILE_TIME_ER ROR, "Libraries that have parts must have a library directive"); 15185 static final ResolverErrorCode MISSING_LIBRARY_DIRECTIVE_WITH_PART = new Resol verErrorCode('MISSING_LIBRARY_DIRECTIVE_WITH_PART', 2, ErrorType.COMPILE_TIME_ER ROR, "Libraries that have parts must have a library directive");
14849 static final List<ResolverErrorCode> values = [ 15186 static final List<ResolverErrorCode> values = [
14850 BREAK_LABEL_ON_SWITCH_MEMBER, 15187 BREAK_LABEL_ON_SWITCH_MEMBER,
14851 CONTINUE_LABEL_ON_SWITCH, 15188 CONTINUE_LABEL_ON_SWITCH,
14852 MISSING_LIBRARY_DIRECTIVE_WITH_PART]; 15189 MISSING_LIBRARY_DIRECTIVE_WITH_PART];
14853 15190
14854 /// The name of this enum constant, as declared in the enum declaration. 15191 /// The name of this enum constant, as declared in the enum declaration.
14855 final String name; 15192 final String name;
(...skipping 21 matching lines...) Expand all
14877 this._type = type; 15214 this._type = type;
14878 this._message = message; 15215 this._message = message;
14879 } 15216 }
14880 ErrorSeverity get errorSeverity => _type.severity; 15217 ErrorSeverity get errorSeverity => _type.severity;
14881 String get message => _message; 15218 String get message => _message;
14882 ErrorType get type => _type; 15219 ErrorType get type => _type;
14883 int compareTo(ResolverErrorCode other) => ordinal - other.ordinal; 15220 int compareTo(ResolverErrorCode other) => ordinal - other.ordinal;
14884 int get hashCode => ordinal; 15221 int get hashCode => ordinal;
14885 String toString() => name; 15222 String toString() => name;
14886 } 15223 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698