| 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 engine.resolver; | 5 library engine.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 import "dart:math" as math; | 8 import "dart:math" as math; |
| 9 | 9 |
| 10 import 'java_core.dart'; | 10 import 'java_core.dart'; |
| (...skipping 1891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1902 _errorReporter.reportErrorForNode(HintCode.IS_NOT_DOUBLE, node); | 1902 _errorReporter.reportErrorForNode(HintCode.IS_NOT_DOUBLE, node); |
| 1903 } | 1903 } |
| 1904 return true; | 1904 return true; |
| 1905 } | 1905 } |
| 1906 } | 1906 } |
| 1907 return false; | 1907 return false; |
| 1908 } | 1908 } |
| 1909 } | 1909 } |
| 1910 | 1910 |
| 1911 /** | 1911 /** |
| 1912 * Instances of the class [UnusedElementVerifier] traverse an element | |
| 1913 * structure looking for cases of [HintCode.UNUSED_ELEMENT] and | |
| 1914 * [HintCode.UNUSED_LOCAL_VARIABLE]. | |
| 1915 */ | |
| 1916 class UnusedElementVerifier extends RecursiveElementVisitor { | |
| 1917 /** | |
| 1918 * The error reporter by which errors will be reported. | |
| 1919 */ | |
| 1920 final ErrorReporter _errorReporter; | |
| 1921 | |
| 1922 /** | |
| 1923 * Create a new instance of the [UnusedElementVerifier]. | |
| 1924 */ | |
| 1925 UnusedElementVerifier(this._errorReporter); | |
| 1926 | |
| 1927 @override | |
| 1928 visitClassElement(ClassElement element) { | |
| 1929 if (element is ClassElementImpl && !element.isUsed) { | |
| 1930 _errorReporter.reportErrorForElement( | |
| 1931 HintCode.UNUSED_ELEMENT, | |
| 1932 element, | |
| 1933 [element.kind.displayName, element.displayName]); | |
| 1934 } | |
| 1935 element.visitChildren(this); | |
| 1936 } | |
| 1937 | |
| 1938 @override | |
| 1939 visitLocalVariableElement(LocalVariableElement element) { | |
| 1940 if (element is LocalVariableElementImpl && !element.isUsed) { | |
| 1941 _errorReporter.reportErrorForElement( | |
| 1942 HintCode.UNUSED_LOCAL_VARIABLE, | |
| 1943 element, | |
| 1944 [element.displayName]); | |
| 1945 } | |
| 1946 } | |
| 1947 } | |
| 1948 | |
| 1949 /** | |
| 1950 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f
or cases of | 1912 * Instances of the class `DeadCodeVerifier` traverse an AST structure looking f
or cases of |
| 1951 * [HintCode.DEAD_CODE]. | 1913 * [HintCode.DEAD_CODE]. |
| 1952 */ | 1914 */ |
| 1953 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { | 1915 class DeadCodeVerifier extends RecursiveAstVisitor<Object> { |
| 1954 /** | 1916 /** |
| 1955 * The error reporter by which errors will be reported. | 1917 * The error reporter by which errors will be reported. |
| 1956 */ | 1918 */ |
| 1957 final ErrorReporter _errorReporter; | 1919 final ErrorReporter _errorReporter; |
| 1958 | 1920 |
| 1959 /** | 1921 /** |
| (...skipping 1539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3499 } | 3461 } |
| 3500 | 3462 |
| 3501 @override | 3463 @override |
| 3502 Object visitCatchClause(CatchClause node) { | 3464 Object visitCatchClause(CatchClause node) { |
| 3503 SimpleIdentifier exceptionParameter = node.exceptionParameter; | 3465 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 3504 if (exceptionParameter != null) { | 3466 if (exceptionParameter != null) { |
| 3505 // exception | 3467 // exception |
| 3506 LocalVariableElementImpl exception = new LocalVariableElementImpl.forNode(
exceptionParameter); | 3468 LocalVariableElementImpl exception = new LocalVariableElementImpl.forNode(
exceptionParameter); |
| 3507 _currentHolder.addLocalVariable(exception); | 3469 _currentHolder.addLocalVariable(exception); |
| 3508 exceptionParameter.staticElement = exception; | 3470 exceptionParameter.staticElement = exception; |
| 3509 // we cannot catch an exception without declaring a variable, | |
| 3510 // so the exception variable is always used | |
| 3511 exception.markUsed(); | |
| 3512 // stack trace | 3471 // stack trace |
| 3513 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; | 3472 SimpleIdentifier stackTraceParameter = node.stackTraceParameter; |
| 3514 if (stackTraceParameter != null) { | 3473 if (stackTraceParameter != null) { |
| 3515 LocalVariableElementImpl stackTrace = new LocalVariableElementImpl.forNo
de(stackTraceParameter); | 3474 LocalVariableElementImpl stackTrace = new LocalVariableElementImpl.forNo
de(stackTraceParameter); |
| 3516 _currentHolder.addLocalVariable(stackTrace); | 3475 _currentHolder.addLocalVariable(stackTrace); |
| 3517 stackTraceParameter.staticElement = stackTrace; | 3476 stackTraceParameter.staticElement = stackTrace; |
| 3518 } | 3477 } |
| 3519 } | 3478 } |
| 3520 return super.visitCatchClause(node); | 3479 return super.visitCatchClause(node); |
| 3521 } | 3480 } |
| (...skipping 1848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5370 * | 5329 * |
| 5371 * See [HintCode]. | 5330 * See [HintCode]. |
| 5372 */ | 5331 */ |
| 5373 class HintGenerator { | 5332 class HintGenerator { |
| 5374 final List<CompilationUnit> _compilationUnits; | 5333 final List<CompilationUnit> _compilationUnits; |
| 5375 | 5334 |
| 5376 final AnalysisContext _context; | 5335 final AnalysisContext _context; |
| 5377 | 5336 |
| 5378 final AnalysisErrorListener _errorListener; | 5337 final AnalysisErrorListener _errorListener; |
| 5379 | 5338 |
| 5339 LibraryElement _library; |
| 5340 |
| 5380 ImportsVerifier _importsVerifier; | 5341 ImportsVerifier _importsVerifier; |
| 5381 | 5342 |
| 5382 bool _enableDart2JSHints = false; | 5343 bool _enableDart2JSHints = false; |
| 5383 | 5344 |
| 5384 /** | 5345 /** |
| 5385 * The inheritance manager used to find overridden methods. | 5346 * The inheritance manager used to find overridden methods. |
| 5386 */ | 5347 */ |
| 5387 InheritanceManager _manager; | 5348 InheritanceManager _manager; |
| 5388 | 5349 |
| 5350 _GatherUsedElementsVisitor _usedElementsVisitor; |
| 5351 |
| 5389 HintGenerator(this._compilationUnits, this._context, this._errorListener) { | 5352 HintGenerator(this._compilationUnits, this._context, this._errorListener) { |
| 5390 LibraryElement library = _compilationUnits[0].element.library; | 5353 _library = _compilationUnits[0].element.library; |
| 5391 _importsVerifier = new ImportsVerifier(library); | 5354 _importsVerifier = new ImportsVerifier(_library); |
| 5392 _enableDart2JSHints = _context.analysisOptions.dart2jsHint; | 5355 _enableDart2JSHints = _context.analysisOptions.dart2jsHint; |
| 5393 _manager = new InheritanceManager(_compilationUnits[0].element.library); | 5356 _manager = new InheritanceManager(_compilationUnits[0].element.library); |
| 5357 _usedElementsVisitor = new _GatherUsedElementsVisitor(_library); |
| 5394 } | 5358 } |
| 5395 | 5359 |
| 5396 void generateForLibrary() { | 5360 void generateForLibrary() { |
| 5397 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.hints.star
t(); | 5361 TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.hints.star
t(); |
| 5398 try { | 5362 try { |
| 5399 for (int i = 0; i < _compilationUnits.length; i++) { | 5363 for (int i = 0; i < _compilationUnits.length; i++) { |
| 5400 CompilationUnitElement element = _compilationUnits[i].element; | 5364 CompilationUnitElement element = _compilationUnits[i].element; |
| 5401 if (element != null) { | 5365 if (element != null) { |
| 5402 if (i == 0) { | 5366 if (i == 0) { |
| 5403 _importsVerifier.inDefiningCompilationUnit = true; | 5367 _importsVerifier.inDefiningCompilationUnit = true; |
| 5404 _generateForCompilationUnit(_compilationUnits[i], element.source); | 5368 _generateForCompilationUnit(_compilationUnits[i], element.source); |
| 5405 _importsVerifier.inDefiningCompilationUnit = false; | 5369 _importsVerifier.inDefiningCompilationUnit = false; |
| 5406 } else { | 5370 } else { |
| 5407 _generateForCompilationUnit(_compilationUnits[i], element.source); | 5371 _generateForCompilationUnit(_compilationUnits[i], element.source); |
| 5408 } | 5372 } |
| 5409 } | 5373 } |
| 5410 } | 5374 } |
| 5411 ErrorReporter definingCompilationUnitErrorReporter = new ErrorReporter(_er
rorListener, _compilationUnits[0].element.source); | 5375 ErrorReporter definingCompilationUnitErrorReporter = new ErrorReporter(_er
rorListener, _compilationUnits[0].element.source); |
| 5412 _importsVerifier.generateDuplicateImportHints(definingCompilationUnitError
Reporter); | 5376 _importsVerifier.generateDuplicateImportHints(definingCompilationUnitError
Reporter); |
| 5413 _importsVerifier.generateUnusedImportHints(definingCompilationUnitErrorRep
orter); | 5377 _importsVerifier.generateUnusedImportHints(definingCompilationUnitErrorRep
orter); |
| 5378 _library.accept(new _UnusedElementsVerifier(_errorListener, _usedElementsV
isitor.usedElements)); |
| 5414 } finally { | 5379 } finally { |
| 5415 timeCounter.stop(); | 5380 timeCounter.stop(); |
| 5416 } | 5381 } |
| 5417 } | 5382 } |
| 5418 | 5383 |
| 5419 void _generateForCompilationUnit(CompilationUnit unit, Source source) { | 5384 void _generateForCompilationUnit(CompilationUnit unit, Source source) { |
| 5420 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); | 5385 ErrorReporter errorReporter = new ErrorReporter(_errorListener, source); |
| 5421 unit.accept(_importsVerifier); | 5386 unit.accept(_importsVerifier); |
| 5422 // dead code analysis | 5387 // dead code analysis |
| 5423 unit.accept(new DeadCodeVerifier(errorReporter)); | 5388 unit.accept(new DeadCodeVerifier(errorReporter)); |
| 5424 unit.element.accept(new UnusedElementVerifier(errorReporter)); | 5389 unit.accept(_usedElementsVisitor); |
| 5425 // dart2js analysis | 5390 // dart2js analysis |
| 5426 if (_enableDart2JSHints) { | 5391 if (_enableDart2JSHints) { |
| 5427 unit.accept(new Dart2JSVerifier(errorReporter)); | 5392 unit.accept(new Dart2JSVerifier(errorReporter)); |
| 5428 } | 5393 } |
| 5429 // Dart best practices | 5394 // Dart best practices |
| 5430 unit.accept(new BestPracticesVerifier(errorReporter)); | 5395 unit.accept(new BestPracticesVerifier(errorReporter)); |
| 5431 unit.accept(new OverrideVerifier(_manager, errorReporter)); | 5396 unit.accept(new OverrideVerifier(_manager, errorReporter)); |
| 5432 // Find to-do comments | 5397 // Find to-do comments |
| 5433 new ToDoFinder(errorReporter).findIn(unit); | 5398 new ToDoFinder(errorReporter).findIn(unit); |
| 5434 // pub analysis | 5399 // pub analysis |
| (...skipping 9704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15139 types.add(type); | 15104 types.add(type); |
| 15140 } | 15105 } |
| 15141 } | 15106 } |
| 15142 return types; | 15107 return types; |
| 15143 } | 15108 } |
| 15144 | 15109 |
| 15145 void _setElement(Identifier typeName, Element element) { | 15110 void _setElement(Identifier typeName, Element element) { |
| 15146 if (element != null) { | 15111 if (element != null) { |
| 15147 if (typeName is SimpleIdentifier) { | 15112 if (typeName is SimpleIdentifier) { |
| 15148 typeName.staticElement = element; | 15113 typeName.staticElement = element; |
| 15149 _markTypeNameElementUsed(typeName, element); | |
| 15150 } else if (typeName is PrefixedIdentifier) { | 15114 } else if (typeName is PrefixedIdentifier) { |
| 15151 PrefixedIdentifier identifier = typeName; | 15115 PrefixedIdentifier identifier = typeName; |
| 15152 identifier.identifier.staticElement = element; | 15116 identifier.identifier.staticElement = element; |
| 15153 SimpleIdentifier prefix = identifier.prefix; | 15117 SimpleIdentifier prefix = identifier.prefix; |
| 15154 Element prefixElement = nameScope.lookup(prefix, definingLibrary); | 15118 Element prefixElement = nameScope.lookup(prefix, definingLibrary); |
| 15155 if (prefixElement != null) { | 15119 if (prefixElement != null) { |
| 15156 prefix.staticElement = prefixElement; | 15120 prefix.staticElement = prefixElement; |
| 15157 } | 15121 } |
| 15158 } | 15122 } |
| 15159 } | 15123 } |
| 15160 } | 15124 } |
| 15161 | 15125 |
| 15162 /** | 15126 /** |
| 15163 * Marks [element] as used in its defining library. | |
| 15164 */ | |
| 15165 void _markTypeNameElementUsed(Identifier typeName, Element element) { | |
| 15166 if (identical(element, _enclosingClass)) { | |
| 15167 return; | |
| 15168 } | |
| 15169 // ignore places where the element is not actually used | |
| 15170 if (typeName.parent is TypeName) { | |
| 15171 AstNode parent2 = typeName.parent.parent; | |
| 15172 if (parent2 is IsExpression) { | |
| 15173 return; | |
| 15174 } | |
| 15175 if (parent2 is VariableDeclarationList) { | |
| 15176 return; | |
| 15177 } | |
| 15178 } | |
| 15179 // check if the element is a local top-level element | |
| 15180 if (element is ElementImpl && | |
| 15181 element.enclosingElement is CompilationUnitElement && | |
| 15182 identical(element.library, definingLibrary)) { | |
| 15183 element.markUsed(); | |
| 15184 } | |
| 15185 } | |
| 15186 | |
| 15187 /** | |
| 15188 * Given a parameter element, create a function type based on the given return
type and parameter | 15127 * Given a parameter element, create a function type based on the given return
type and parameter |
| 15189 * list and associate the created type with the element. | 15128 * list and associate the created type with the element. |
| 15190 * | 15129 * |
| 15191 * @param element the parameter element whose type is to be set | 15130 * @param element the parameter element whose type is to be set |
| 15192 * @param returnType the (possibly `null`) return type of the function | 15131 * @param returnType the (possibly `null`) return type of the function |
| 15193 * @param parameterList the list of parameters to the function | 15132 * @param parameterList the list of parameters to the function |
| 15194 */ | 15133 */ |
| 15195 void _setFunctionTypedParameterType(ParameterElementImpl element, TypeName ret
urnType, FormalParameterList parameterList) { | 15134 void _setFunctionTypedParameterType(ParameterElementImpl element, TypeName ret
urnType, FormalParameterList parameterList) { |
| 15196 List<ParameterElement> parameters = _getElements(parameterList); | 15135 List<ParameterElement> parameters = _getElements(parameterList); |
| 15197 FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl
.forNode(null); | 15136 FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl
.forNode(null); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15385 ElementKind kind = element.kind; | 15324 ElementKind kind = element.kind; |
| 15386 if (kind == ElementKind.LOCAL_VARIABLE) { | 15325 if (kind == ElementKind.LOCAL_VARIABLE) { |
| 15387 node.staticElement = element; | 15326 node.staticElement = element; |
| 15388 LocalVariableElementImpl variableImpl = element as LocalVariableElementImp
l; | 15327 LocalVariableElementImpl variableImpl = element as LocalVariableElementImp
l; |
| 15389 if (node.inSetterContext()) { | 15328 if (node.inSetterContext()) { |
| 15390 variableImpl.markPotentiallyMutatedInScope(); | 15329 variableImpl.markPotentiallyMutatedInScope(); |
| 15391 if (element.enclosingElement != _enclosingFunction) { | 15330 if (element.enclosingElement != _enclosingFunction) { |
| 15392 variableImpl.markPotentiallyMutatedInClosure(); | 15331 variableImpl.markPotentiallyMutatedInClosure(); |
| 15393 } | 15332 } |
| 15394 } | 15333 } |
| 15395 if (node.inGetterContext()) { | |
| 15396 if (parent.parent is ExpressionStatement && | |
| 15397 (parent is PrefixExpression || | |
| 15398 parent is PostfixExpression || | |
| 15399 parent is AssignmentExpression && parent.leftHandSide == node)) { | |
| 15400 // v++; | |
| 15401 // ++v; | |
| 15402 // v += 2; | |
| 15403 } else { | |
| 15404 variableImpl.markUsed(); | |
| 15405 } | |
| 15406 } | |
| 15407 if (parent is MethodInvocation && parent.methodName == node) { | |
| 15408 variableImpl.markUsed(); | |
| 15409 } | |
| 15410 } else if (kind == ElementKind.PARAMETER) { | 15334 } else if (kind == ElementKind.PARAMETER) { |
| 15411 node.staticElement = element; | 15335 node.staticElement = element; |
| 15412 if (node.inSetterContext()) { | 15336 if (node.inSetterContext()) { |
| 15413 ParameterElementImpl parameterImpl = element as ParameterElementImpl; | 15337 ParameterElementImpl parameterImpl = element as ParameterElementImpl; |
| 15414 parameterImpl.markPotentiallyMutatedInScope(); | 15338 parameterImpl.markPotentiallyMutatedInScope(); |
| 15415 // If we are in some closure, check if it is not the same as where varia
ble is declared. | 15339 // If we are in some closure, check if it is not the same as where varia
ble is declared. |
| 15416 if (_enclosingFunction != null && (element.enclosingElement != _enclosin
gFunction)) { | 15340 if (_enclosingFunction != null && (element.enclosingElement != _enclosin
gFunction)) { |
| 15417 parameterImpl.markPotentiallyMutatedInClosure(); | 15341 parameterImpl.markPotentiallyMutatedInClosure(); |
| 15418 } | 15342 } |
| 15419 } | 15343 } |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15609 /** | 15533 /** |
| 15610 * Return the tag that has the given identifier, or {@code null} if there is n
o such tag (the | 15534 * Return the tag that has the given identifier, or {@code null} if there is n
o such tag (the |
| 15611 * identifier is not defined). | 15535 * identifier is not defined). |
| 15612 * | 15536 * |
| 15613 * @return the tag that has the given identifier | 15537 * @return the tag that has the given identifier |
| 15614 */ | 15538 */ |
| 15615 String getTagWithId(String identifier) { | 15539 String getTagWithId(String identifier) { |
| 15616 return idToTagMap[identifier]; | 15540 return idToTagMap[identifier]; |
| 15617 } | 15541 } |
| 15618 } | 15542 } |
| 15543 |
| 15544 |
| 15545 class _GatherUsedElementsVisitor extends RecursiveAstVisitor { |
| 15546 final Set<Element> usedElements = new HashSet<Element>(); |
| 15547 |
| 15548 final LibraryElement _enclosingLibrary; |
| 15549 ClassElement _enclosingClass; |
| 15550 |
| 15551 _GatherUsedElementsVisitor(this._enclosingLibrary); |
| 15552 |
| 15553 @override |
| 15554 visitCatchClause(CatchClause node) { |
| 15555 SimpleIdentifier exceptionParameter = node.exceptionParameter; |
| 15556 _useStaticElement(exceptionParameter); |
| 15557 super.visitCatchClause(node); |
| 15558 } |
| 15559 |
| 15560 @override |
| 15561 visitClassDeclaration(ClassDeclaration node) { |
| 15562 ClassElement enclosingClassOld = _enclosingClass; |
| 15563 try { |
| 15564 _enclosingClass = node.element; |
| 15565 super.visitClassDeclaration(node); |
| 15566 } finally { |
| 15567 _enclosingClass = enclosingClassOld; |
| 15568 } |
| 15569 } |
| 15570 |
| 15571 @override |
| 15572 visitSimpleIdentifier(SimpleIdentifier node) { |
| 15573 if (node.inDeclarationContext()) { |
| 15574 return; |
| 15575 } |
| 15576 Element staticElement = node.staticElement; |
| 15577 if (staticElement is LocalVariableElement) { |
| 15578 AstNode parent = node.parent; |
| 15579 if (node.inGetterContext()) { |
| 15580 if (parent.parent is ExpressionStatement && |
| 15581 (parent is PrefixExpression || |
| 15582 parent is PostfixExpression || |
| 15583 parent is AssignmentExpression && parent.leftHandSide == node)) { |
| 15584 // v++; |
| 15585 // ++v; |
| 15586 // v += 2; |
| 15587 } else { |
| 15588 _useElement(staticElement); |
| 15589 } |
| 15590 } |
| 15591 if (parent is MethodInvocation && parent.methodName == node) { |
| 15592 _useElement(staticElement); |
| 15593 } |
| 15594 } else { |
| 15595 _useIdentifierElement(node); |
| 15596 } |
| 15597 } |
| 15598 |
| 15599 @override |
| 15600 visitTypeName(TypeName node) { |
| 15601 _useIdentifierElement(node.name); |
| 15602 } |
| 15603 |
| 15604 /** |
| 15605 * Marks an [Element] of [node] as used in the library. |
| 15606 */ |
| 15607 void _useIdentifierElement(Identifier node) { |
| 15608 Element element = node.staticElement; |
| 15609 if (element == null) { |
| 15610 return; |
| 15611 } |
| 15612 // check if a local element |
| 15613 if (!identical(element.library, _enclosingLibrary)) { |
| 15614 return; |
| 15615 } |
| 15616 // ignore references to an element from itself |
| 15617 if (identical(element, _enclosingClass)) { |
| 15618 return; |
| 15619 } |
| 15620 // ignore places where the element is not actually used |
| 15621 if (node.parent is TypeName) { |
| 15622 AstNode parent2 = node.parent.parent; |
| 15623 if (parent2 is IsExpression) { |
| 15624 return; |
| 15625 } |
| 15626 if (parent2 is VariableDeclarationList) { |
| 15627 return; |
| 15628 } |
| 15629 } |
| 15630 // OK |
| 15631 _useElement(element); |
| 15632 } |
| 15633 |
| 15634 _useElement(Element element) { |
| 15635 if (element != null) { |
| 15636 usedElements.add(element); |
| 15637 } |
| 15638 } |
| 15639 |
| 15640 void _useStaticElement(SimpleIdentifier identifier) { |
| 15641 if (identifier != null) { |
| 15642 _useElement(identifier.staticElement); |
| 15643 } |
| 15644 } |
| 15645 } |
| 15646 |
| 15647 |
| 15648 /** |
| 15649 * Instances of the class [_UnusedElementsVerifier] traverse an element |
| 15650 * structure looking for cases of [HintCode.UNUSED_ELEMENT] and |
| 15651 * [HintCode.UNUSED_LOCAL_VARIABLE]. |
| 15652 */ |
| 15653 class _UnusedElementsVerifier extends RecursiveElementVisitor { |
| 15654 /** |
| 15655 * The error listener to which errors will be reported. |
| 15656 */ |
| 15657 final AnalysisErrorListener _errorListener; |
| 15658 |
| 15659 /** |
| 15660 * The elements know to be used. |
| 15661 */ |
| 15662 final Set<Element> _usedElements; |
| 15663 |
| 15664 /** |
| 15665 * Create a new instance of the [_UnusedElementsVerifier]. |
| 15666 */ |
| 15667 _UnusedElementsVerifier(this._errorListener, this._usedElements); |
| 15668 |
| 15669 @override |
| 15670 visitClassElement(ClassElement element) { |
| 15671 if (!_isUsed(element)) { |
| 15672 _reportErrorForElement( |
| 15673 HintCode.UNUSED_ELEMENT, |
| 15674 element, |
| 15675 [element.kind.displayName, element.displayName]); |
| 15676 } |
| 15677 element.visitChildren(this); |
| 15678 } |
| 15679 |
| 15680 @override |
| 15681 visitLocalVariableElement(LocalVariableElement element) { |
| 15682 if (!_isUsed(element)) { |
| 15683 _reportErrorForElement( |
| 15684 HintCode.UNUSED_LOCAL_VARIABLE, |
| 15685 element, |
| 15686 [element.displayName]); |
| 15687 } |
| 15688 } |
| 15689 |
| 15690 bool _isUsed(Element element) { |
| 15691 if (element is! LocalVariableElement) { |
| 15692 if (element.isPublic) { |
| 15693 return true; |
| 15694 } |
| 15695 } |
| 15696 return _usedElements.contains(element); |
| 15697 } |
| 15698 |
| 15699 void _reportErrorForElement(ErrorCode errorCode, Element element, List<Object>
arguments) { |
| 15700 if (element != null) { |
| 15701 _errorListener.onError( |
| 15702 new AnalysisError.con2( |
| 15703 element.source, |
| 15704 element.nameOffset, |
| 15705 element.displayName.length, |
| 15706 errorCode, |
| 15707 arguments)); |
| 15708 } |
| 15709 } |
| 15710 } |
| OLD | NEW |