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

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

Issue 1051313002: Task: gather elements used in a unit. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 8 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
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/dart.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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:math" as math; 7 import "dart:math" as math;
8 import 'dart:collection'; 8 import 'dart:collection';
9 9
10 import 'package:analyzer/src/generated/utilities_collection.dart'; 10 import 'package:analyzer/src/generated/utilities_collection.dart';
(...skipping 4326 matching lines...) Expand 10 before | Expand all | Expand 10 after
4337 */ 4337 */
4338 void _defineTypeParameters() { 4338 void _defineTypeParameters() {
4339 Scope typeParameterScope = enclosingScope; 4339 Scope typeParameterScope = enclosingScope;
4340 for (TypeParameterElement typeParameter in _typeElement.typeParameters) { 4340 for (TypeParameterElement typeParameter in _typeElement.typeParameters) {
4341 typeParameterScope.define(typeParameter); 4341 typeParameterScope.define(typeParameter);
4342 } 4342 }
4343 } 4343 }
4344 } 4344 }
4345 4345
4346 /** 4346 /**
4347 * An [AstVisitor] that fills [UsedElements].
4348 */
4349 class GatherUsedElementsVisitor extends RecursiveAstVisitor {
4350 final UsedElements usedElements = new UsedElements();
4351
4352 final LibraryElement _enclosingLibrary;
4353 ClassElement _enclosingClass;
4354 ExecutableElement _enclosingExec;
4355
4356 GatherUsedElementsVisitor(this._enclosingLibrary);
4357
4358 @override
4359 visitCatchClause(CatchClause node) {
4360 SimpleIdentifier exceptionParameter = node.exceptionParameter;
4361 SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
4362 if (exceptionParameter != null) {
4363 Element element = exceptionParameter.staticElement;
4364 usedElements.addCatchException(element);
4365 if (stackTraceParameter != null || node.onKeyword == null) {
4366 usedElements.addElement(element);
4367 }
4368 }
4369 if (stackTraceParameter != null) {
4370 Element element = stackTraceParameter.staticElement;
4371 usedElements.addCatchStackTrace(element);
4372 }
4373 super.visitCatchClause(node);
4374 }
4375
4376 @override
4377 visitClassDeclaration(ClassDeclaration node) {
4378 ClassElement enclosingClassOld = _enclosingClass;
4379 try {
4380 _enclosingClass = node.element;
4381 super.visitClassDeclaration(node);
4382 } finally {
4383 _enclosingClass = enclosingClassOld;
4384 }
4385 }
4386
4387 @override
4388 visitFunctionDeclaration(FunctionDeclaration node) {
4389 ExecutableElement enclosingExecOld = _enclosingExec;
4390 try {
4391 _enclosingExec = node.element;
4392 super.visitFunctionDeclaration(node);
4393 } finally {
4394 _enclosingExec = enclosingExecOld;
4395 }
4396 }
4397
4398 @override
4399 visitFunctionExpression(FunctionExpression node) {
4400 if (node.parent is! FunctionDeclaration) {
4401 usedElements.addElement(node.element);
4402 }
4403 super.visitFunctionExpression(node);
4404 }
4405
4406 @override
4407 visitMethodDeclaration(MethodDeclaration node) {
4408 ExecutableElement enclosingExecOld = _enclosingExec;
4409 try {
4410 _enclosingExec = node.element;
4411 super.visitMethodDeclaration(node);
4412 } finally {
4413 _enclosingExec = enclosingExecOld;
4414 }
4415 }
4416
4417 @override
4418 visitSimpleIdentifier(SimpleIdentifier node) {
4419 if (node.inDeclarationContext()) {
4420 return;
4421 }
4422 Element element = node.staticElement;
4423 bool isIdentifierRead = _isReadIdentifier(node);
4424 if (element is LocalVariableElement) {
4425 if (isIdentifierRead) {
4426 usedElements.addElement(element);
4427 }
4428 } else {
4429 _useIdentifierElement(node);
4430 if (element == null ||
4431 element is! LocalElement && !identical(element, _enclosingExec)) {
4432 usedElements.members.add(node.name);
4433 if (isIdentifierRead) {
4434 usedElements.readMembers.add(node.name);
4435 }
4436 }
4437 }
4438 }
4439
4440 @override
4441 visitTypeName(TypeName node) {
4442 _useIdentifierElement(node.name);
4443 }
4444
4445 /**
4446 * Marks an [Element] of [node] as used in the library.
4447 */
4448 void _useIdentifierElement(Identifier node) {
4449 Element element = node.staticElement;
4450 if (element == null) {
4451 return;
4452 }
4453 // check if a local element
4454 if (!identical(element.library, _enclosingLibrary)) {
4455 return;
4456 }
4457 // ignore references to an element from itself
4458 if (identical(element, _enclosingClass)) {
4459 return;
4460 }
4461 if (identical(element, _enclosingExec)) {
4462 return;
4463 }
4464 // ignore places where the element is not actually used
4465 if (node.parent is TypeName) {
4466 AstNode parent2 = node.parent.parent;
4467 if (parent2 is IsExpression) {
4468 return;
4469 }
4470 if (parent2 is VariableDeclarationList) {
4471 return;
4472 }
4473 }
4474 // OK
4475 usedElements.addElement(element);
4476 }
4477
4478 static bool _isReadIdentifier(SimpleIdentifier node) {
4479 // not reading at all
4480 if (!node.inGetterContext()) {
4481 return false;
4482 }
4483 // check if useless reading
4484 AstNode parent = node.parent;
4485 if (parent.parent is ExpressionStatement &&
4486 (parent is PrefixExpression ||
4487 parent is PostfixExpression ||
4488 parent is AssignmentExpression && parent.leftHandSide == node)) {
4489 // v++;
4490 // ++v;
4491 // v += 2;
4492 return false;
4493 }
4494 // OK
4495 return true;
4496 }
4497 }
4498
4499 /**
4347 * Instances of the class `HintGenerator` traverse a library's worth of dart cod e at a time to 4500 * Instances of the class `HintGenerator` traverse a library's worth of dart cod e at a time to
4348 * generate hints over the set of sources. 4501 * generate hints over the set of sources.
4349 * 4502 *
4350 * See [HintCode]. 4503 * See [HintCode].
4351 */ 4504 */
4352 class HintGenerator { 4505 class HintGenerator {
4353 final List<CompilationUnit> _compilationUnits; 4506 final List<CompilationUnit> _compilationUnits;
4354 4507
4355 final InternalAnalysisContext _context; 4508 final InternalAnalysisContext _context;
4356 4509
4357 final AnalysisErrorListener _errorListener; 4510 final AnalysisErrorListener _errorListener;
4358 4511
4359 LibraryElement _library; 4512 LibraryElement _library;
4360 4513
4361 ImportsVerifier _importsVerifier; 4514 ImportsVerifier _importsVerifier;
4362 4515
4363 bool _enableDart2JSHints = false; 4516 bool _enableDart2JSHints = false;
4364 4517
4365 /** 4518 /**
4366 * The inheritance manager used to find overridden methods. 4519 * The inheritance manager used to find overridden methods.
4367 */ 4520 */
4368 InheritanceManager _manager; 4521 InheritanceManager _manager;
4369 4522
4370 _GatherUsedElementsVisitor _usedElementsVisitor; 4523 GatherUsedElementsVisitor _usedElementsVisitor;
4371 4524
4372 HintGenerator(this._compilationUnits, this._context, this._errorListener) { 4525 HintGenerator(this._compilationUnits, this._context, this._errorListener) {
4373 _library = _compilationUnits[0].element.library; 4526 _library = _compilationUnits[0].element.library;
4374 _importsVerifier = new ImportsVerifier(_library); 4527 _importsVerifier = new ImportsVerifier(_library);
4375 _enableDart2JSHints = _context.analysisOptions.dart2jsHint; 4528 _enableDart2JSHints = _context.analysisOptions.dart2jsHint;
4376 _manager = new InheritanceManager(_compilationUnits[0].element.library); 4529 _manager = new InheritanceManager(_compilationUnits[0].element.library);
4377 _usedElementsVisitor = new _GatherUsedElementsVisitor(_library); 4530 _usedElementsVisitor = new GatherUsedElementsVisitor(_library);
4378 } 4531 }
4379 4532
4380 void generateForLibrary() { 4533 void generateForLibrary() {
4381 PerformanceStatistics.hints.makeCurrentWhile(() { 4534 PerformanceStatistics.hints.makeCurrentWhile(() {
4382 for (int i = 0; i < _compilationUnits.length; i++) { 4535 for (int i = 0; i < _compilationUnits.length; i++) {
4383 CompilationUnitElement element = _compilationUnits[i].element; 4536 CompilationUnitElement element = _compilationUnits[i].element;
4384 if (element != null) { 4537 if (element != null) {
4385 if (i == 0) { 4538 if (i == 0) {
4386 _importsVerifier.inDefiningCompilationUnit = true; 4539 _importsVerifier.inDefiningCompilationUnit = true;
4387 _generateForCompilationUnit(_compilationUnits[i], element.source); 4540 _generateForCompilationUnit(_compilationUnits[i], element.source);
(...skipping 10383 matching lines...) Expand 10 before | Expand all | Expand 10 after
14771 return identical(parent.type, node); 14924 return identical(parent.type, node);
14772 } 14925 }
14773 if (parent is SimpleFormalParameter) { 14926 if (parent is SimpleFormalParameter) {
14774 return identical(parent.type, node); 14927 return identical(parent.type, node);
14775 } 14928 }
14776 return false; 14929 return false;
14777 } 14930 }
14778 } 14931 }
14779 14932
14780 /** 14933 /**
14934 * A container with sets of used [Element]s.
14935 */
14936 class UsedElements {
14937 /**
14938 * Resolved, locally defined elements that are used or potentially can be
14939 * used.
14940 */
14941 final HashSet<Element> elements = new HashSet<Element>();
14942
14943 /**
14944 * [LocalVariableElement]s that represent exceptions in [CatchClause]s.
14945 */
14946 final HashSet<LocalVariableElement> catchExceptionElements =
14947 new HashSet<LocalVariableElement>();
14948
14949 /**
14950 * [LocalVariableElement]s that represent stack traces in [CatchClause]s.
14951 */
14952 final HashSet<LocalVariableElement> catchStackTraceElements =
14953 new HashSet<LocalVariableElement>();
14954
14955 /**
14956 * Names of resolved or unresolved class members that are referenced in the
14957 * library.
14958 */
14959 final HashSet<String> members = new HashSet<String>();
14960
14961 /**
14962 * Names of resolved or unresolved class members that are read in the
14963 * library.
14964 */
14965 final HashSet<String> readMembers = new HashSet<String>();
14966
14967 void addCatchException(LocalVariableElement element) {
14968 if (element != null) {
14969 catchExceptionElements.add(element);
14970 }
14971 }
14972
14973 void addCatchStackTrace(LocalVariableElement element) {
14974 if (element != null) {
14975 catchStackTraceElements.add(element);
14976 }
14977 }
14978
14979 void addElement(Element element) {
14980 if (element != null) {
14981 elements.add(element);
14982 }
14983 }
14984
14985 bool isCatchException(LocalVariableElement element) {
14986 return catchExceptionElements.contains(element);
14987 }
14988
14989 bool isCatchStackTrace(LocalVariableElement element) {
14990 return catchStackTraceElements.contains(element);
14991 }
14992 }
14993
14994 /**
14781 * Instances of the class `VariableResolverVisitor` are used to resolve 14995 * Instances of the class `VariableResolverVisitor` are used to resolve
14782 * [SimpleIdentifier]s to local variables and formal parameters. 14996 * [SimpleIdentifier]s to local variables and formal parameters.
14783 */ 14997 */
14784 class VariableResolverVisitor extends ScopedVisitor { 14998 class VariableResolverVisitor extends ScopedVisitor {
14785 /** 14999 /**
14786 * The method or function that we are currently visiting, or `null` if we are not inside a 15000 * The method or function that we are currently visiting, or `null` if we are not inside a
14787 * method or function. 15001 * method or function.
14788 */ 15002 */
14789 ExecutableElement _enclosingFunction; 15003 ExecutableElement _enclosingFunction;
14790 15004
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
14996 @override 15210 @override
14997 Object visitMethodDeclaration(MethodDeclaration node) { 15211 Object visitMethodDeclaration(MethodDeclaration node) {
14998 nonFields.add(node); 15212 nonFields.add(node);
14999 return null; 15213 return null;
15000 } 15214 }
15001 15215
15002 @override 15216 @override
15003 Object visitNode(AstNode node) => node.accept(builder); 15217 Object visitNode(AstNode node) => node.accept(builder);
15004 } 15218 }
15005 15219
15006 class _GatherUsedElementsVisitor extends RecursiveAstVisitor {
15007 final _UsedElements usedElements = new _UsedElements();
15008
15009 final LibraryElement _enclosingLibrary;
15010 ClassElement _enclosingClass;
15011 ExecutableElement _enclosingExec;
15012
15013 _GatherUsedElementsVisitor(this._enclosingLibrary);
15014
15015 @override
15016 visitCatchClause(CatchClause node) {
15017 SimpleIdentifier exceptionParameter = node.exceptionParameter;
15018 SimpleIdentifier stackTraceParameter = node.stackTraceParameter;
15019 if (exceptionParameter != null) {
15020 Element element = exceptionParameter.staticElement;
15021 usedElements.addCatchException(element);
15022 if (stackTraceParameter != null || node.onKeyword == null) {
15023 _useElement(element);
15024 }
15025 }
15026 if (stackTraceParameter != null) {
15027 Element element = stackTraceParameter.staticElement;
15028 usedElements.addCatchStackTrace(element);
15029 }
15030 super.visitCatchClause(node);
15031 }
15032
15033 @override
15034 visitClassDeclaration(ClassDeclaration node) {
15035 ClassElement enclosingClassOld = _enclosingClass;
15036 try {
15037 _enclosingClass = node.element;
15038 super.visitClassDeclaration(node);
15039 } finally {
15040 _enclosingClass = enclosingClassOld;
15041 }
15042 }
15043
15044 @override
15045 visitFunctionDeclaration(FunctionDeclaration node) {
15046 ExecutableElement enclosingExecOld = _enclosingExec;
15047 try {
15048 _enclosingExec = node.element;
15049 super.visitFunctionDeclaration(node);
15050 } finally {
15051 _enclosingExec = enclosingExecOld;
15052 }
15053 }
15054
15055 @override
15056 visitFunctionExpression(FunctionExpression node) {
15057 if (node.parent is! FunctionDeclaration) {
15058 _useElement(node.element);
15059 }
15060 super.visitFunctionExpression(node);
15061 }
15062
15063 @override
15064 visitMethodDeclaration(MethodDeclaration node) {
15065 ExecutableElement enclosingExecOld = _enclosingExec;
15066 try {
15067 _enclosingExec = node.element;
15068 super.visitMethodDeclaration(node);
15069 } finally {
15070 _enclosingExec = enclosingExecOld;
15071 }
15072 }
15073
15074 @override
15075 visitSimpleIdentifier(SimpleIdentifier node) {
15076 if (node.inDeclarationContext()) {
15077 return;
15078 }
15079 Element element = node.staticElement;
15080 bool isIdentifierRead = _isReadIdentifier(node);
15081 if (element is LocalVariableElement) {
15082 if (isIdentifierRead) {
15083 _useElement(element);
15084 }
15085 // } else if (element is PropertyAccessorElement &&
15086 // element.isSynthetic &&
15087 // element.isPrivate) {
15088 // PropertyInducingElement variable = element.variable;
15089 // if (node.inGetterContext()) {
15090 // AstNode parent = node.parent;
15091 // if (parent.parent is ExpressionStatement &&
15092 // (parent is PrefixExpression ||
15093 // parent is PostfixExpression ||
15094 // parent is AssignmentExpression && parent.leftHandSide == node)) {
15095 // // f++;
15096 // // ++f;
15097 // // f += 2;
15098 // } else {
15099 // _useElement(variable);
15100 // }
15101 // }
15102 } else {
15103 _useIdentifierElement(node);
15104 if (element == null ||
15105 element is! LocalElement && !identical(element, _enclosingExec)) {
15106 usedElements.members.add(node.name);
15107 if (isIdentifierRead) {
15108 usedElements.readMembers.add(node.name);
15109 }
15110 }
15111 }
15112 }
15113
15114 @override
15115 visitTypeName(TypeName node) {
15116 _useIdentifierElement(node.name);
15117 }
15118
15119 _useElement(Element element) {
15120 if (element != null) {
15121 usedElements.elements.add(element);
15122 }
15123 }
15124
15125 /**
15126 * Marks an [Element] of [node] as used in the library.
15127 */
15128 void _useIdentifierElement(Identifier node) {
15129 Element element = node.staticElement;
15130 if (element == null) {
15131 return;
15132 }
15133 // check if a local element
15134 if (!identical(element.library, _enclosingLibrary)) {
15135 return;
15136 }
15137 // ignore references to an element from itself
15138 if (identical(element, _enclosingClass)) {
15139 return;
15140 }
15141 if (identical(element, _enclosingExec)) {
15142 return;
15143 }
15144 // ignore places where the element is not actually used
15145 if (node.parent is TypeName) {
15146 AstNode parent2 = node.parent.parent;
15147 if (parent2 is IsExpression) {
15148 return;
15149 }
15150 if (parent2 is VariableDeclarationList) {
15151 return;
15152 }
15153 }
15154 // OK
15155 _useElement(element);
15156 }
15157
15158 static bool _isReadIdentifier(SimpleIdentifier node) {
15159 // not reading at all
15160 if (!node.inGetterContext()) {
15161 return false;
15162 }
15163 // check if useless reading
15164 AstNode parent = node.parent;
15165 if (parent.parent is ExpressionStatement &&
15166 (parent is PrefixExpression ||
15167 parent is PostfixExpression ||
15168 parent is AssignmentExpression && parent.leftHandSide == node)) {
15169 // v++;
15170 // ++v;
15171 // v += 2;
15172 return false;
15173 }
15174 // OK
15175 return true;
15176 }
15177 }
15178
15179 class _ResolverVisitor_isVariableAccessedInClosure 15220 class _ResolverVisitor_isVariableAccessedInClosure
15180 extends RecursiveAstVisitor<Object> { 15221 extends RecursiveAstVisitor<Object> {
15181 final Element variable; 15222 final Element variable;
15182 15223
15183 bool result = false; 15224 bool result = false;
15184 15225
15185 bool _inClosure = false; 15226 bool _inClosure = false;
15186 15227
15187 _ResolverVisitor_isVariableAccessedInClosure(this.variable); 15228 _ResolverVisitor_isVariableAccessedInClosure(this.variable);
15188 15229
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
15273 */ 15314 */
15274 class _UnusedElementsVerifier extends RecursiveElementVisitor { 15315 class _UnusedElementsVerifier extends RecursiveElementVisitor {
15275 /** 15316 /**
15276 * The error listener to which errors will be reported. 15317 * The error listener to which errors will be reported.
15277 */ 15318 */
15278 final AnalysisErrorListener _errorListener; 15319 final AnalysisErrorListener _errorListener;
15279 15320
15280 /** 15321 /**
15281 * The elements know to be used. 15322 * The elements know to be used.
15282 */ 15323 */
15283 final _UsedElements _usedElements; 15324 final UsedElements _usedElements;
15284 15325
15285 /** 15326 /**
15286 * Create a new instance of the [_UnusedElementsVerifier]. 15327 * Create a new instance of the [_UnusedElementsVerifier].
15287 */ 15328 */
15288 _UnusedElementsVerifier(this._errorListener, this._usedElements); 15329 _UnusedElementsVerifier(this._errorListener, this._usedElements);
15289 15330
15290 @override 15331 @override
15291 visitClassElement(ClassElement element) { 15332 visitClassElement(ClassElement element) {
15292 if (!_isUsedElement(element)) { 15333 if (!_isUsedElement(element)) {
15293 _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [ 15334 _reportErrorForElement(HintCode.UNUSED_ELEMENT, element, [
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
15408 15449
15409 void _reportErrorForElement( 15450 void _reportErrorForElement(
15410 ErrorCode errorCode, Element element, List<Object> arguments) { 15451 ErrorCode errorCode, Element element, List<Object> arguments) {
15411 if (element != null) { 15452 if (element != null) {
15412 _errorListener.onError(new AnalysisError.con2(element.source, 15453 _errorListener.onError(new AnalysisError.con2(element.source,
15413 element.nameOffset, element.displayName.length, errorCode, 15454 element.nameOffset, element.displayName.length, errorCode,
15414 arguments)); 15455 arguments));
15415 } 15456 }
15416 } 15457 }
15417 } 15458 }
15418
15419 class _UsedElements {
15420 /**
15421 * Resolved, locally defined elements that are used or potentially can be
15422 * used.
15423 */
15424 final HashSet<Element> elements = new HashSet<Element>();
15425
15426 /**
15427 * [LocalVariableElement]s that represent exceptions in [CatchClause]s.
15428 */
15429 final HashSet<LocalVariableElement> catchExceptionElements =
15430 new HashSet<LocalVariableElement>();
15431
15432 /**
15433 * [LocalVariableElement]s that represent stack traces in [CatchClause]s.
15434 */
15435 final HashSet<LocalVariableElement> catchStackTraceElements =
15436 new HashSet<LocalVariableElement>();
15437
15438 /**
15439 * Names of resolved or unresolved class members that are referenced in the
15440 * library.
15441 */
15442 final HashSet<String> members = new HashSet<String>();
15443
15444 /**
15445 * Names of resolved or unresolved class members that are read in the
15446 * library.
15447 */
15448 final HashSet<String> readMembers = new HashSet<String>();
15449
15450 void addCatchException(LocalVariableElement element) {
15451 if (element != null) {
15452 catchExceptionElements.add(element);
15453 }
15454 }
15455
15456 void addCatchStackTrace(LocalVariableElement element) {
15457 if (element != null) {
15458 catchStackTraceElements.add(element);
15459 }
15460 }
15461
15462 bool isCatchException(LocalVariableElement element) {
15463 return catchExceptionElements.contains(element);
15464 }
15465
15466 bool isCatchStackTrace(LocalVariableElement element) {
15467 return catchStackTraceElements.contains(element);
15468 }
15469 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/dart.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698