Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 4093 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4104 } | 4104 } |
| 4105 | 4105 |
| 4106 @override | 4106 @override |
| 4107 void visitPrefixedIdentifier(PrefixedIdentifier node) { | 4107 void visitPrefixedIdentifier(PrefixedIdentifier node) { |
| 4108 // If the prefixed identifier references some A.B, where A is a library | 4108 // If the prefixed identifier references some A.B, where A is a library |
| 4109 // prefix, then we can lookup the associated ImportDirective in | 4109 // prefix, then we can lookup the associated ImportDirective in |
| 4110 // prefixElementMap and remove it from the unusedImports list. | 4110 // prefixElementMap and remove it from the unusedImports list. |
| 4111 SimpleIdentifier prefixIdentifier = node.prefix; | 4111 SimpleIdentifier prefixIdentifier = node.prefix; |
| 4112 Element element = prefixIdentifier.staticElement; | 4112 Element element = prefixIdentifier.staticElement; |
| 4113 if (element is PrefixElement) { | 4113 if (element is PrefixElement) { |
| 4114 usedElements.prefixes.add(element); | 4114 List<SimpleIdentifier> list = usedElements.prefixes[element]; |
|
Brian Wilkerson
2016/04/06 15:17:40
usedElements.prefixes.putIfAbsent(element, () => <
srawlins
2016/04/07 15:27:23
Done.
| |
| 4115 if (list == null) { | |
| 4116 list = <SimpleIdentifier>[]; | |
| 4117 usedElements.prefixes[element] = list; | |
| 4118 } | |
| 4119 list.add(node.identifier); | |
| 4115 return; | 4120 return; |
| 4116 } | 4121 } |
| 4117 // Otherwise, pass the prefixed identifier element and name onto | 4122 // Otherwise, pass the prefixed identifier element and name onto |
| 4118 // visitIdentifier. | 4123 // visitIdentifier. |
| 4119 _visitIdentifier(element, prefixIdentifier.name); | 4124 _visitIdentifier(element, prefixIdentifier.name); |
| 4120 } | 4125 } |
| 4121 | 4126 |
| 4122 @override | 4127 @override |
| 4123 void visitSimpleIdentifier(SimpleIdentifier node) { | 4128 void visitSimpleIdentifier(SimpleIdentifier node) { |
| 4124 _visitIdentifier(node.staticElement, node.name); | 4129 _visitIdentifier(node.staticElement, node.name); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 4138 } | 4143 } |
| 4139 // If the element is multiply defined then call this method recursively for | 4144 // If the element is multiply defined then call this method recursively for |
| 4140 // each of the conflicting elements. | 4145 // each of the conflicting elements. |
| 4141 if (element is MultiplyDefinedElement) { | 4146 if (element is MultiplyDefinedElement) { |
| 4142 MultiplyDefinedElement multiplyDefinedElement = element; | 4147 MultiplyDefinedElement multiplyDefinedElement = element; |
| 4143 for (Element elt in multiplyDefinedElement.conflictingElements) { | 4148 for (Element elt in multiplyDefinedElement.conflictingElements) { |
| 4144 _visitIdentifier(elt, name); | 4149 _visitIdentifier(elt, name); |
| 4145 } | 4150 } |
| 4146 return; | 4151 return; |
| 4147 } else if (element is PrefixElement) { | 4152 } else if (element is PrefixElement) { |
| 4148 usedElements.prefixes.add(element); | 4153 List<SimpleIdentifier> list = usedElements.prefixes[element]; |
| 4154 if (list == null) { | |
| 4155 list = <SimpleIdentifier>[]; | |
| 4156 usedElements.prefixes[element] = list; | |
| 4157 } | |
| 4149 return; | 4158 return; |
| 4150 } else if (element.enclosingElement is! CompilationUnitElement) { | 4159 } else if (element.enclosingElement is! CompilationUnitElement) { |
| 4151 // Identifiers that aren't a prefix element and whose enclosing element | 4160 // Identifiers that aren't a prefix element and whose enclosing element |
| 4152 // isn't a CompilationUnit are ignored- this covers the case the | 4161 // isn't a CompilationUnit are ignored- this covers the case the |
| 4153 // identifier is a relative-reference, a reference to an identifier not | 4162 // identifier is a relative-reference, a reference to an identifier not |
| 4154 // imported by this library. | 4163 // imported by this library. |
| 4155 return; | 4164 return; |
| 4156 } | 4165 } |
| 4157 // Ignore if an unknown library. | 4166 // Ignore if an unknown library. |
| 4158 LibraryElement containingLibrary = element.library; | 4167 LibraryElement containingLibrary = element.library; |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4368 CompilationUnit definingUnit = _compilationUnits[0]; | 4377 CompilationUnit definingUnit = _compilationUnits[0]; |
| 4369 ErrorReporter definingUnitErrorReporter = | 4378 ErrorReporter definingUnitErrorReporter = |
| 4370 new ErrorReporter(_errorListener, definingUnit.element.source); | 4379 new ErrorReporter(_errorListener, definingUnit.element.source); |
| 4371 { | 4380 { |
| 4372 ImportsVerifier importsVerifier = new ImportsVerifier(); | 4381 ImportsVerifier importsVerifier = new ImportsVerifier(); |
| 4373 importsVerifier.addImports(definingUnit); | 4382 importsVerifier.addImports(definingUnit); |
| 4374 importsVerifier | 4383 importsVerifier |
| 4375 .removeUsedElements(_usedImportedElementsVisitor.usedElements); | 4384 .removeUsedElements(_usedImportedElementsVisitor.usedElements); |
| 4376 importsVerifier.generateDuplicateImportHints(definingUnitErrorReporter); | 4385 importsVerifier.generateDuplicateImportHints(definingUnitErrorReporter); |
| 4377 importsVerifier.generateUnusedImportHints(definingUnitErrorReporter); | 4386 importsVerifier.generateUnusedImportHints(definingUnitErrorReporter); |
| 4387 importsVerifier.generateUnusedShownNameHints(definingUnitErrorReporter); | |
| 4378 } | 4388 } |
| 4379 _library.accept(new UnusedLocalElementsVerifier( | 4389 _library.accept(new UnusedLocalElementsVerifier( |
| 4380 _errorListener, _usedLocalElementsVisitor.usedElements)); | 4390 _errorListener, _usedLocalElementsVisitor.usedElements)); |
| 4381 }); | 4391 }); |
| 4382 } | 4392 } |
| 4383 | 4393 |
| 4384 void _generateForCompilationUnit(CompilationUnit unit, Source source) { | 4394 void _generateForCompilationUnit(CompilationUnit unit, Source source) { |
| 4385 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); | 4395 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); |
| 4386 unit.accept(_usedImportedElementsVisitor); | 4396 unit.accept(_usedImportedElementsVisitor); |
| 4387 // dead code analysis | 4397 // dead code analysis |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4450 /** | 4460 /** |
| 4451 * Initialize a newly created scope to represent a switch statement or loop | 4461 * Initialize a newly created scope to represent a switch statement or loop |
| 4452 * nested within the current scope. [statement] is the statement associated | 4462 * nested within the current scope. [statement] is the statement associated |
| 4453 * with the newly created scope. | 4463 * with the newly created scope. |
| 4454 */ | 4464 */ |
| 4455 ImplicitLabelScope nest(Statement statement) => | 4465 ImplicitLabelScope nest(Statement statement) => |
| 4456 new ImplicitLabelScope._(this, statement); | 4466 new ImplicitLabelScope._(this, statement); |
| 4457 } | 4467 } |
| 4458 | 4468 |
| 4459 /** | 4469 /** |
| 4460 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the | 4470 * Instances of the class `ImportsVerifier` visit all of the referenced librarie s in the source code |
| 4461 * source code verifying that all of the imports are used, otherwise a | 4471 * verifying that all of the imports are used, otherwise a [HintCode.UNUSED_IMPO RT] hint is |
| 4462 * [HintCode.UNUSED_IMPORT] is generated with | 4472 * generated with [generateUnusedImportHints]. |
| 4463 * [generateUnusedImportHints]. | 4473 * |
| 4474 * Additionally, [generateDuplicateImportHints] generates [HintCode.DUPLICATE_IM PORT] hints and | |
| 4475 * [HintCode.UNUSED_SHOWN_NAME] hints. | |
| 4464 * | 4476 * |
| 4465 * While this class does not yet have support for an "Organize Imports" action, this logic built up | 4477 * While this class does not yet have support for an "Organize Imports" action, this logic built up |
| 4466 * in this class could be used for such an action in the future. | 4478 * in this class could be used for such an action in the future. |
| 4467 */ | 4479 */ |
| 4468 class ImportsVerifier { | 4480 class ImportsVerifier { |
| 4469 /** | 4481 /** |
| 4470 * A list of [ImportDirective]s that the current library imports, as identifie rs are visited | 4482 * A list of [ImportDirective]s that the current library imports, but does not use. |
| 4471 * by this visitor and an import has been identified as being used by the libr ary, the | 4483 * |
| 4472 * [ImportDirective] is removed from this list. After all the sources in the l ibrary have | 4484 * As identifiers are visited by this visitor and an import has been identifie d as being used |
| 4473 * been evaluated, this list represents the set of unused imports. | 4485 * by the library, the [ImportDirective] is removed from this list. After all the sources in the |
| 4486 * library have been evaluated, this list represents the set of unused imports . | |
| 4474 * | 4487 * |
| 4475 * See [ImportsVerifier.generateUnusedImportErrors]. | 4488 * See [ImportsVerifier.generateUnusedImportErrors]. |
| 4476 */ | 4489 */ |
| 4477 final List<ImportDirective> _unusedImports = <ImportDirective>[]; | 4490 final List<ImportDirective> _unusedImports = <ImportDirective>[]; |
| 4478 | 4491 |
| 4479 /** | 4492 /** |
| 4480 * After the list of [unusedImports] has been computed, this list is a proper subset of the | 4493 * After the list of [unusedImports] has been computed, this list is a proper subset of the |
| 4481 * unused imports that are listed more than once. | 4494 * unused imports that are listed more than once. |
| 4482 */ | 4495 */ |
| 4483 final List<ImportDirective> _duplicateImports = <ImportDirective>[]; | 4496 final List<ImportDirective> _duplicateImports = <ImportDirective>[]; |
| 4484 | 4497 |
| 4485 /** | 4498 /** |
| 4486 * This is a map between the set of [LibraryElement]s that the current library imports, and | 4499 * This is a map between the set of [LibraryElement]s that the current library imports, and the |
| 4487 * a list of [ImportDirective]s that imports the library. In cases where the c urrent library | 4500 * list of [ImportDirective]s that import each [LibraryElement]. In cases wher e the current |
| 4488 * imports a library with a single directive (such as `import lib1.dart;`), th e library | 4501 * library imports a library with a single directive (such as `import lib1.dar t;`), the library |
| 4489 * element will map to a list of one [ImportDirective], which will then be rem oved from the | 4502 * element will map to a list of one [ImportDirective], which will then be rem oved from the |
| 4490 * [unusedImports] list. In cases where the current library imports a library with multiple | 4503 * [unusedImports] list. In cases where the current library imports a library with multiple |
| 4491 * directives (such as `import lib1.dart; import lib1.dart show C;`), the | 4504 * directives (such as `import lib1.dart; import lib1.dart show C;`), the [Lib raryElement] will |
| 4492 * [LibraryElement] will be mapped to a list of the import directives, and the namespace | 4505 * be mapped to a list of the import directives, and the namespace will need t o be used to |
| 4493 * will need to be used to compute the correct [ImportDirective] being used, s ee | 4506 * compute the correct [ImportDirective] being used; see [_namespaceMap]. |
| 4494 * [namespaceMap]. | |
| 4495 */ | 4507 */ |
| 4496 final HashMap<LibraryElement, List<ImportDirective>> _libraryMap = | 4508 final HashMap<LibraryElement, List<ImportDirective>> _libraryMap = |
| 4497 new HashMap<LibraryElement, List<ImportDirective>>(); | 4509 new HashMap<LibraryElement, List<ImportDirective>>(); |
| 4498 | 4510 |
| 4499 /** | 4511 /** |
| 4500 * In cases where there is more than one import directive per library element, this mapping is | 4512 * In cases where there is more than one import directive per library element, this mapping is |
| 4501 * used to determine which of the multiple import directives are used by gener ating a | 4513 * used to determine which of the multiple import directives are used by gener ating a |
| 4502 * [Namespace] for each of the imports to do lookups in the same way that they are done from | 4514 * [Namespace] for each of the imports to do lookups in the same way that they are done from |
| 4503 * the [ElementResolver]. | 4515 * the [ElementResolver]. |
| 4504 */ | 4516 */ |
| 4505 final HashMap<ImportDirective, Namespace> _namespaceMap = | 4517 final HashMap<ImportDirective, Namespace> _namespaceMap = |
| 4506 new HashMap<ImportDirective, Namespace>(); | 4518 new HashMap<ImportDirective, Namespace>(); |
| 4507 | 4519 |
| 4508 /** | 4520 /** |
| 4509 * This is a map between prefix elements and the import directives from which they are derived. In | 4521 * This is a map between prefix elements and the import directives from which they are derived. In |
| 4510 * cases where a type is referenced via a prefix element, the import directive can be marked as | 4522 * cases where a type is referenced via a prefix element, the import directive can be marked as |
| 4511 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`, | 4523 * used (removed from the unusedImports) by looking at the resolved `lib` in ` lib.X`, |
| 4512 * instead of looking at which library the `lib.X` resolves. | 4524 * instead of looking at which library the `lib.X` resolves. |
| 4513 * | 4525 * |
| 4514 * TODO (jwren) Since multiple [ImportDirective]s can share the same [PrefixEl ement], | 4526 * TODO (jwren) Since multiple [ImportDirective]s can share the same [PrefixEl ement], |
| 4515 * it is possible to have an unreported unused import in situations where two imports use the same | 4527 * it is possible to have an unreported unused import in situations where two imports use the same |
| 4516 * prefix and at least one import directive is used. | 4528 * prefix and at least one import directive is used. |
| 4517 */ | 4529 */ |
| 4518 final HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap = | 4530 final HashMap<PrefixElement, List<ImportDirective>> _prefixElementMap = |
| 4519 new HashMap<PrefixElement, List<ImportDirective>>(); | 4531 new HashMap<PrefixElement, List<ImportDirective>>(); |
| 4520 | 4532 |
| 4533 /** | |
| 4534 * A map of identifiers that the current library's imports show, but that the library does not | |
| 4535 * use. | |
| 4536 * | |
| 4537 * Each import directive maps to a list of the identifiers that are imported v ia the "show" | |
| 4538 * keyword. | |
| 4539 * | |
| 4540 * As each identifier is visited by this visitor, it is identified as being us ed by the library, | |
| 4541 * and the identifier is removed from this map (under the import that imported it). After all the | |
| 4542 * sources in the library have been evaluated, each list in this map's values present the set of | |
| 4543 * unused shown elements. | |
| 4544 * | |
| 4545 * See [ImportsVerifier.generateUnusedShownNameHints]. | |
| 4546 */ | |
| 4547 final HashMap<ImportDirective, List<SimpleIdentifier>> _unusedShownNamesMap = | |
| 4548 new HashMap<ImportDirective, List<SimpleIdentifier>>(); | |
| 4549 | |
| 4521 void addImports(CompilationUnit node) { | 4550 void addImports(CompilationUnit node) { |
| 4522 for (Directive directive in node.directives) { | 4551 for (Directive directive in node.directives) { |
| 4523 if (directive is ImportDirective) { | 4552 if (directive is ImportDirective) { |
| 4524 ImportDirective importDirective = directive; | 4553 ImportDirective importDirective = directive; |
| 4525 LibraryElement libraryElement = importDirective.uriElement; | 4554 LibraryElement libraryElement = importDirective.uriElement; |
| 4526 if (libraryElement != null) { | 4555 if (libraryElement == null) { |
| 4527 _unusedImports.add(importDirective); | 4556 continue; |
|
Brian Wilkerson
2016/04/06 15:17:40
FWIW, I actually preferred the code the way it was
srawlins
2016/04/07 15:27:23
Acknowledged.
| |
| 4528 // | 4557 } |
| 4529 // Initialize prefixElementMap | 4558 _unusedImports.add(importDirective); |
| 4530 // | 4559 // |
| 4531 if (importDirective.asKeyword != null) { | 4560 // Initialize prefixElementMap |
| 4532 SimpleIdentifier prefixIdentifier = importDirective.prefix; | 4561 // |
| 4533 if (prefixIdentifier != null) { | 4562 if (importDirective.asKeyword != null) { |
| 4534 Element element = prefixIdentifier.staticElement; | 4563 SimpleIdentifier prefixIdentifier = importDirective.prefix; |
| 4535 if (element is PrefixElement) { | 4564 if (prefixIdentifier != null) { |
| 4536 PrefixElement prefixElementKey = element; | 4565 Element element = prefixIdentifier.staticElement; |
| 4537 List<ImportDirective> list = | 4566 if (element is PrefixElement) { |
| 4538 _prefixElementMap[prefixElementKey]; | 4567 PrefixElement prefixElementKey = element; |
| 4539 if (list == null) { | 4568 List<ImportDirective> list = _prefixElementMap[prefixElementKey]; |
| 4540 list = new List<ImportDirective>(); | 4569 if (list == null) { |
| 4541 _prefixElementMap[prefixElementKey] = list; | 4570 list = new List<ImportDirective>(); |
| 4542 } | 4571 _prefixElementMap[prefixElementKey] = list; |
| 4543 list.add(importDirective); | |
| 4544 } | 4572 } |
| 4545 // TODO (jwren) Can the element ever not be a PrefixElement? | 4573 list.add(importDirective); |
| 4546 } | 4574 } |
| 4575 // TODO (jwren) Can the element ever not be a PrefixElement? | |
| 4547 } | 4576 } |
| 4548 // | |
| 4549 // Initialize libraryMap: libraryElement -> importDirective | |
| 4550 // | |
| 4551 _putIntoLibraryMap(libraryElement, importDirective); | |
| 4552 // | |
| 4553 // For this new addition to the libraryMap, also recursively add any | |
| 4554 // exports from the libraryElement. | |
| 4555 // | |
| 4556 _addAdditionalLibrariesForExports( | |
| 4557 libraryElement, importDirective, new List<LibraryElement>()); | |
| 4558 } | 4577 } |
| 4578 // | |
| 4579 // Initialize libraryMap: libraryElement -> importDirective | |
| 4580 // | |
| 4581 _putIntoLibraryMap(libraryElement, importDirective); | |
| 4582 // | |
| 4583 // For this new addition to the libraryMap, also recursively add any | |
| 4584 // exports from the libraryElement. | |
| 4585 // | |
| 4586 _addAdditionalLibrariesForExports( | |
| 4587 libraryElement, importDirective, new List<LibraryElement>()); | |
| 4588 _addShownNames(importDirective); | |
| 4559 } | 4589 } |
| 4560 } | 4590 } |
| 4561 if (_unusedImports.length > 1) { | 4591 if (_unusedImports.length > 1) { |
| 4562 // order the list of unusedImports to find duplicates in faster than | 4592 // order the list of unusedImports to find duplicates in faster than |
| 4563 // O(n^2) time | 4593 // O(n^2) time |
| 4564 List<ImportDirective> importDirectiveArray = | 4594 List<ImportDirective> importDirectiveArray = |
| 4565 new List<ImportDirective>.from(_unusedImports); | 4595 new List<ImportDirective>.from(_unusedImports); |
| 4566 importDirectiveArray.sort(ImportDirective.COMPARATOR); | 4596 importDirectiveArray.sort(ImportDirective.COMPARATOR); |
| 4567 ImportDirective currentDirective = importDirectiveArray[0]; | 4597 ImportDirective currentDirective = importDirectiveArray[0]; |
| 4568 for (int i = 1; i < importDirectiveArray.length; i++) { | 4598 for (int i = 1; i < importDirectiveArray.length; i++) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 4591 * hints to | 4621 * hints to |
| 4592 */ | 4622 */ |
| 4593 void generateDuplicateImportHints(ErrorReporter errorReporter) { | 4623 void generateDuplicateImportHints(ErrorReporter errorReporter) { |
| 4594 for (ImportDirective duplicateImport in _duplicateImports) { | 4624 for (ImportDirective duplicateImport in _duplicateImports) { |
| 4595 errorReporter.reportErrorForNode( | 4625 errorReporter.reportErrorForNode( |
| 4596 HintCode.DUPLICATE_IMPORT, duplicateImport.uri); | 4626 HintCode.DUPLICATE_IMPORT, duplicateImport.uri); |
| 4597 } | 4627 } |
| 4598 } | 4628 } |
| 4599 | 4629 |
| 4600 /** | 4630 /** |
| 4601 * After all of the compilation units have been visited by this visitor, this method can be called | 4631 * Report an [HintCode.UNUSED_IMPORT] hint for each unused import. |
| 4602 * to report an [HintCode.UNUSED_IMPORT] hint for each of the import directive s in the | |
| 4603 * [unusedImports] list. | |
| 4604 * | 4632 * |
| 4605 * @param errorReporter the error reporter to report the set of [HintCode.UNUS ED_IMPORT] | 4633 * Only call this method after all of the compilation units have been visited by this visitor. |
| 4606 * hints to | 4634 * |
| 4635 * @param errorReporter the error reporter used to report the set of [HintCode .UNUSED_IMPORT] | |
| 4636 * hints | |
| 4607 */ | 4637 */ |
| 4608 void generateUnusedImportHints(ErrorReporter errorReporter) { | 4638 void generateUnusedImportHints(ErrorReporter errorReporter) { |
| 4609 for (ImportDirective unusedImport in _unusedImports) { | 4639 for (ImportDirective unusedImport in _unusedImports) { |
| 4610 // Check that the import isn't dart:core | 4640 // Check that the import isn't dart:core |
| 4611 ImportElement importElement = unusedImport.element; | 4641 ImportElement importElement = unusedImport.element; |
| 4612 if (importElement != null) { | 4642 if (importElement != null) { |
| 4613 LibraryElement libraryElement = importElement.importedLibrary; | 4643 LibraryElement libraryElement = importElement.importedLibrary; |
| 4614 if (libraryElement != null && libraryElement.isDartCore) { | 4644 if (libraryElement != null && libraryElement.isDartCore) { |
| 4615 continue; | 4645 continue; |
| 4616 } | 4646 } |
| 4617 } | 4647 } |
| 4618 errorReporter.reportErrorForNode( | 4648 errorReporter.reportErrorForNode( |
| 4619 HintCode.UNUSED_IMPORT, unusedImport.uri); | 4649 HintCode.UNUSED_IMPORT, unusedImport.uri); |
| 4620 } | 4650 } |
| 4621 } | 4651 } |
| 4622 | 4652 |
| 4623 /** | 4653 /** |
| 4654 * Report an [HintCode.UNUSED_SHOWN_NAME] hint for each unused shown name. | |
| 4655 * | |
| 4656 * Only call this method after all of the compilation units have been visited by this visitor. | |
| 4657 * | |
| 4658 * @param errorReporter the error reporter used to report the set of [HintCode .UNUSED_SHOWN_NAME] | |
| 4659 * hints | |
| 4660 */ | |
| 4661 void generateUnusedShownNameHints(ErrorReporter reporter) { | |
| 4662 _unusedShownNamesMap.forEach((ImportDirective importDirective, | |
| 4663 List<SimpleIdentifier> identifiers) { | |
| 4664 if (_unusedImports.contains(importDirective)) { | |
| 4665 // This import is actually wholly unused, not just one or more shown nam es from it. | |
| 4666 // This is then an "unused import", rather than unused shown names. | |
| 4667 return; | |
| 4668 } | |
| 4669 for (var identifier in identifiers) { | |
|
Brian Wilkerson
2016/04/06 15:17:40
nit: we fully type annotate everything in the anal
srawlins
2016/04/07 15:27:23
Done.
| |
| 4670 reporter.reportErrorForNode(HintCode.UNUSED_SHOWN_NAME, identifier); | |
| 4671 } | |
| 4672 }); | |
| 4673 } | |
| 4674 | |
| 4675 /** | |
| 4624 * Remove elements from [_unusedImports] using the given [usedElements]. | 4676 * Remove elements from [_unusedImports] using the given [usedElements]. |
| 4625 */ | 4677 */ |
| 4626 void removeUsedElements(UsedImportedElements usedElements) { | 4678 void removeUsedElements(UsedImportedElements usedElements) { |
| 4627 // Stop if all the imports are known to be used. | 4679 // Stop if all the imports and shown names are known to be used. |
| 4628 if (_unusedImports.isEmpty) { | 4680 if (_unusedImports.isEmpty && _unusedShownNamesMap.isEmpty) { |
| 4629 return; | 4681 return; |
| 4630 } | 4682 } |
| 4631 // Process import prefixes. | 4683 // Process import prefixes. |
| 4632 for (PrefixElement prefix in usedElements.prefixes) { | 4684 usedElements.prefixes.forEach((PrefixElement prefix, List<SimpleIdentifier> elements) { |
| 4633 List<ImportDirective> importDirectives = _prefixElementMap[prefix]; | 4685 List<ImportDirective> importDirectives = _prefixElementMap[prefix]; |
| 4634 if (importDirectives != null) { | 4686 if (importDirectives != null) { |
| 4635 for (ImportDirective importDirective in importDirectives) { | 4687 for (ImportDirective importDirective in importDirectives) { |
| 4636 _unusedImports.remove(importDirective); | 4688 _unusedImports.remove(importDirective); |
| 4689 for (SimpleIdentifier element in elements) { | |
| 4690 _removeFromUnusedShownNamesMap(element.staticElement, importDirectiv e); | |
| 4691 } | |
| 4637 } | 4692 } |
| 4638 } | 4693 } |
| 4639 } | 4694 }); |
| 4640 // Process top-level elements. | 4695 // Process top-level elements. |
| 4641 for (Element element in usedElements.elements) { | 4696 for (Element element in usedElements.elements) { |
| 4642 // Stop if all the imports are known to be used. | 4697 // Stop if all the imports and shown names are known to be used. |
| 4643 if (_unusedImports.isEmpty) { | 4698 if (_unusedImports.isEmpty && _unusedShownNamesMap.isEmpty) { |
| 4644 return; | 4699 return; |
| 4645 } | 4700 } |
| 4646 // Prepare import directives for this library. | 4701 // Prepare import directives for this element's library. |
| 4647 LibraryElement library = element.library; | 4702 LibraryElement library = element.library; |
| 4648 List<ImportDirective> importsLibrary = _libraryMap[library]; | 4703 List<ImportDirective> importsLibrary = _libraryMap[library]; |
| 4649 if (importsLibrary == null) { | 4704 if (importsLibrary == null) { |
| 4705 // element's library is not imported. Must be the current library. | |
| 4650 continue; | 4706 continue; |
| 4651 } | 4707 } |
| 4652 // If there is only one import directive for this library, then it must be | 4708 // If there is only one import directive for this library, then it must be |
| 4653 // the directive that this element is imported with, remove it from the | 4709 // the directive that this element is imported with, remove it from the |
| 4654 // unusedImports list. | 4710 // unusedImports list. |
| 4655 if (importsLibrary.length == 1) { | 4711 if (importsLibrary.length == 1) { |
| 4656 ImportDirective usedImportDirective = importsLibrary[0]; | 4712 ImportDirective usedImportDirective = importsLibrary[0]; |
| 4657 _unusedImports.remove(usedImportDirective); | 4713 _unusedImports.remove(usedImportDirective); |
| 4714 _removeFromUnusedShownNamesMap(element, usedImportDirective); | |
| 4658 continue; | 4715 continue; |
| 4659 } | 4716 } |
| 4660 // Otherwise, find import directives using namespaces. | 4717 // Otherwise, find import directives using namespaces. |
| 4661 String name = element.displayName; | 4718 String name = element.displayName; |
| 4662 for (ImportDirective importDirective in importsLibrary) { | 4719 for (ImportDirective importDirective in importsLibrary) { |
| 4663 Namespace namespace = _computeNamespace(importDirective); | 4720 Namespace namespace = _computeNamespace(importDirective); |
| 4664 if (namespace != null && namespace.get(name) != null) { | 4721 if (namespace != null && namespace.get(name) != null) { |
| 4665 _unusedImports.remove(importDirective); | 4722 _unusedImports.remove(importDirective); |
| 4723 _removeFromUnusedShownNamesMap(element, importDirective); | |
| 4666 } | 4724 } |
| 4667 } | 4725 } |
| 4668 } | 4726 } |
| 4669 } | 4727 } |
| 4670 | 4728 |
| 4671 /** | 4729 /** |
| 4730 * Remove [element] from the list of names shown by [importDirective]. | |
| 4731 */ | |
| 4732 void _removeFromUnusedShownNamesMap(Element element, | |
| 4733 ImportDirective importDirective) { | |
| 4734 List<SimpleIdentifier> list = _unusedShownNamesMap[importDirective]; | |
|
scheglov
2016/04/06 15:34:39
Could you use a more specific name than "list"?
srawlins
2016/04/07 15:27:23
Done.
| |
| 4735 if (list == null) { | |
| 4736 return; | |
| 4737 } | |
| 4738 for (var identifier in list) { | |
| 4739 if (identifier.staticElement == element) { | |
| 4740 list.remove(identifier); | |
| 4741 break; | |
| 4742 } | |
| 4743 } | |
| 4744 if (list.isEmpty) { | |
| 4745 _unusedShownNamesMap.remove(importDirective); | |
| 4746 } | |
| 4747 } | |
| 4748 | |
| 4749 /** | |
| 4672 * Recursively add any exported library elements into the [libraryMap]. | 4750 * Recursively add any exported library elements into the [libraryMap]. |
| 4673 */ | 4751 */ |
| 4674 void _addAdditionalLibrariesForExports(LibraryElement library, | 4752 void _addAdditionalLibrariesForExports(LibraryElement library, |
| 4675 ImportDirective importDirective, List<LibraryElement> exportPath) { | 4753 ImportDirective importDirective, List<LibraryElement> exportPath) { |
| 4676 if (exportPath.contains(library)) { | 4754 if (exportPath.contains(library)) { |
| 4677 return; | 4755 return; |
| 4678 } | 4756 } |
| 4679 exportPath.add(library); | 4757 exportPath.add(library); |
| 4680 for (LibraryElement exportedLibraryElt in library.exportedLibraries) { | 4758 for (LibraryElement exportedLibraryElt in library.exportedLibraries) { |
| 4681 _putIntoLibraryMap(exportedLibraryElt, importDirective); | 4759 _putIntoLibraryMap(exportedLibraryElt, importDirective); |
| 4682 _addAdditionalLibrariesForExports( | 4760 _addAdditionalLibrariesForExports( |
| 4683 exportedLibraryElt, importDirective, exportPath); | 4761 exportedLibraryElt, importDirective, exportPath); |
| 4684 } | 4762 } |
| 4685 } | 4763 } |
| 4686 | 4764 |
| 4687 /** | 4765 /** |
| 4688 * Lookup and return the [Namespace] from the [namespaceMap], if the map does not | 4766 * Lookup and return the [Namespace] from the [_namespaceMap]. |
| 4689 * have the computed namespace, compute it and cache it in the map. If the imp ort directive is not | 4767 * |
| 4690 * resolved or is not resolvable, `null` is returned. | 4768 * If the map does not have the computed namespace, compute it and cache it in the map. If |
| 4769 * [importDirective] is not resolved or is not resolvable, `null` is returned. | |
| 4691 * | 4770 * |
| 4692 * @param importDirective the import directive used to compute the returned na mespace | 4771 * @param importDirective the import directive used to compute the returned na mespace |
| 4693 * @return the computed or looked up [Namespace] | 4772 * @return the computed or looked up [Namespace] |
| 4694 */ | 4773 */ |
| 4695 Namespace _computeNamespace(ImportDirective importDirective) { | 4774 Namespace _computeNamespace(ImportDirective importDirective) { |
| 4696 Namespace namespace = _namespaceMap[importDirective]; | 4775 Namespace namespace = _namespaceMap[importDirective]; |
| 4697 if (namespace == null) { | 4776 if (namespace == null) { |
| 4698 // If the namespace isn't in the namespaceMap, then compute and put it in | 4777 // If the namespace isn't in the namespaceMap, then compute and put it in |
| 4699 // the map. | 4778 // the map. |
| 4700 ImportElement importElement = importDirective.element; | 4779 ImportElement importElement = importDirective.element; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 4715 */ | 4794 */ |
| 4716 void _putIntoLibraryMap( | 4795 void _putIntoLibraryMap( |
| 4717 LibraryElement libraryElement, ImportDirective importDirective) { | 4796 LibraryElement libraryElement, ImportDirective importDirective) { |
| 4718 List<ImportDirective> importList = _libraryMap[libraryElement]; | 4797 List<ImportDirective> importList = _libraryMap[libraryElement]; |
| 4719 if (importList == null) { | 4798 if (importList == null) { |
| 4720 importList = new List<ImportDirective>(); | 4799 importList = new List<ImportDirective>(); |
| 4721 _libraryMap[libraryElement] = importList; | 4800 _libraryMap[libraryElement] = importList; |
| 4722 } | 4801 } |
| 4723 importList.add(importDirective); | 4802 importList.add(importDirective); |
| 4724 } | 4803 } |
| 4804 | |
| 4805 /** | |
| 4806 * Add every shown name from [importDirective] into [_unusedShownNamesMap]. | |
| 4807 */ | |
| 4808 void _addShownNames(ImportDirective importDirective) { | |
| 4809 if (importDirective.combinators == null) { | |
| 4810 return; | |
| 4811 } | |
| 4812 List list = new List<SimpleIdentifier>(); | |
|
scheglov
2016/04/06 15:34:39
1. Add type arguments.
2. Use a better name.
srawlins
2016/04/07 15:27:23
Done.
| |
| 4813 _unusedShownNamesMap[importDirective] = list; | |
| 4814 for (Combinator combinator in importDirective.combinators) { | |
| 4815 if (combinator is ShowCombinator) { | |
| 4816 for (SimpleIdentifier name in combinator.shownNames) { | |
| 4817 list.add(name); | |
| 4818 } | |
| 4819 } | |
| 4820 } | |
| 4821 } | |
| 4725 } | 4822 } |
| 4726 | 4823 |
| 4727 /** | 4824 /** |
| 4728 * Maintains and manages contextual type information used for | 4825 * Maintains and manages contextual type information used for |
| 4729 * inferring types. | 4826 * inferring types. |
| 4730 */ | 4827 */ |
| 4731 class InferenceContext { | 4828 class InferenceContext { |
| 4732 // TODO(leafp): Consider replacing these node properties with a | 4829 // TODO(leafp): Consider replacing these node properties with a |
| 4733 // hash table help in an instance of this class. | 4830 // hash table help in an instance of this class. |
| 4734 static const String _typeProperty = | 4831 static const String _typeProperty = |
| (...skipping 7826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12561 } | 12658 } |
| 12562 | 12659 |
| 12563 /** | 12660 /** |
| 12564 * A container with information about used imports prefixes and used imported | 12661 * A container with information about used imports prefixes and used imported |
| 12565 * elements. | 12662 * elements. |
| 12566 */ | 12663 */ |
| 12567 class UsedImportedElements { | 12664 class UsedImportedElements { |
| 12568 /** | 12665 /** |
| 12569 * The set of referenced [PrefixElement]s. | 12666 * The set of referenced [PrefixElement]s. |
| 12570 */ | 12667 */ |
| 12571 final Set<PrefixElement> prefixes = new HashSet<PrefixElement>(); | 12668 final Map<PrefixElement, List<SimpleIdentifier>> prefixes = |
|
scheglov
2016/04/06 15:34:39
1. Instances of the class UsedImportedElements are
srawlins
2016/04/07 15:27:23
Done.
| |
| 12669 new HashMap<PrefixElement, List<SimpleIdentifier>>(); | |
| 12572 | 12670 |
| 12573 /** | 12671 /** |
| 12574 * The set of referenced top-level [Element]s. | 12672 * The set of referenced top-level [Element]s. |
| 12575 */ | 12673 */ |
| 12576 final Set<Element> elements = new HashSet<Element>(); | 12674 final Set<Element> elements = new HashSet<Element>(); |
| 12577 } | 12675 } |
| 12578 | 12676 |
| 12579 /** | 12677 /** |
| 12580 * A container with sets of used [Element]s. | 12678 * A container with sets of used [Element]s. |
| 12581 * All these elements are defined in a single compilation unit or a library. | 12679 * All these elements are defined in a single compilation unit or a library. |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12977 nonFields.add(node); | 13075 nonFields.add(node); |
| 12978 return null; | 13076 return null; |
| 12979 } | 13077 } |
| 12980 | 13078 |
| 12981 @override | 13079 @override |
| 12982 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 13080 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12983 | 13081 |
| 12984 @override | 13082 @override |
| 12985 Object visitWithClause(WithClause node) => null; | 13083 Object visitWithClause(WithClause node) => null; |
| 12986 } | 13084 } |
| OLD | NEW |