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

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

Issue 719223002: Move unused local variables and classes analysis into HintGenerator. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
« no previous file with comments | « pkg/analyzer/lib/src/generated/element_resolver.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/element_resolver.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698