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

Unified Diff: pkg/analyzer2dart/lib/src/tree_shaker.dart

Issue 587323004: Classify method and property accesses semantically. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Comment fix Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: pkg/analyzer2dart/lib/src/tree_shaker.dart
diff --git a/pkg/analyzer2dart/lib/src/tree_shaker.dart b/pkg/analyzer2dart/lib/src/tree_shaker.dart
index 9cd84231f27a5749f3d8532a60eca0ae7009ca97..7389853509bf52c101dcbdb473da849ffbe4fe29 100644
--- a/pkg/analyzer2dart/lib/src/tree_shaker.dart
+++ b/pkg/analyzer2dart/lib/src/tree_shaker.dart
@@ -11,6 +11,7 @@ import 'package:analyzer/src/generated/element.dart';
import 'package:compiler/implementation/universe/universe.dart';
import 'closed_world.dart';
+import 'package:analyzer2dart/src/identifier_semantics.dart';
Johnni Winther 2014/09/25 12:09:36 What is the motivation for using a package and not
Paul Berry 2014/09/25 18:22:48 Hmm, I hadn't actually given it much thought. Thi
/**
* The result of performing local reachability analysis on a method.
@@ -24,7 +25,7 @@ class MethodAnalysis {
/**
* The functions statically called by the method.
*/
- final List<LocalElement> calls = <LocalElement>[];
+ final List<ExecutableElement> calls = <ExecutableElement>[];
/**
* The selectors used by the method to perform dynamic invocation.
@@ -209,19 +210,6 @@ class TreeShakingVisitor extends RecursiveAstVisitor {
TreeShakingVisitor(this.analysis);
- /**
- * Handle a true method call (a MethodInvocation that represents a call to
- * a non-static method).
- */
- void handleMethodCall(MethodInvocation node) {
- analysis.invokes.add(createSelectorFromMethodInvocation(node));
- }
-
- @override
- void visitFunctionDeclaration(FunctionDeclaration node) {
- super.visitFunctionDeclaration(node);
- }
-
@override
void visitInstanceCreationExpression(InstanceCreationExpression node) {
ConstructorElement staticElement = node.staticElement;
@@ -240,110 +228,86 @@ class TreeShakingVisitor extends RecursiveAstVisitor {
@override
void visitMethodInvocation(MethodInvocation node) {
- super.visitMethodInvocation(node);
- Element staticElement = node.methodName.staticElement;
- if (staticElement == null) {
- if (node.realTarget != null) {
- // Calling a method that has no known element, e.g.:
- // dynamic x;
- // x.foo();
- handleMethodCall(node);
- } else {
- // Calling a toplevel function which has no known element, e.g.
- // main() {
- // foo();
- // }
- // TODO(paulberry): deal with this case. May need to notify the back
- // end in case this makes it want to drag in some helper code.
+ if (node.target != null) {
+ node.target.accept(this);
+ }
+ node.argumentList.accept(this);
+ AccessSemantics semantics = classifyMethodInvocation(node);
+ switch (semantics.kind) {
+ case AccessKind.DYNAMIC:
+ analysis.invokes.add(createSelectorFromMethodInvocation(node));
+ break;
+ case AccessKind.LOCAL_FUNCTION:
+ case AccessKind.LOCAL_VARIABLE:
+ case AccessKind.PARAMETER:
+ // Locals don't need to be tree shaken.
+ break;
+ case AccessKind.STATIC_FIELD:
+ // Invocation of a field. TODO(paulberry): handle this.
+ throw new UnimplementedError();
+ case AccessKind.STATIC_METHOD:
+ analysis.calls.add(semantics.element);
+ break;
+ case AccessKind.STATIC_PROPERTY:
+ // Invocation of a property. TODO(paulberry): handle this.
+ throw new UnimplementedError();
+ default:
+ // Unexpected access kind.
throw new UnimplementedError();
- }
- } else if (staticElement is MethodElement) {
- // Invoking a method, e.g.:
- // class A {
- // f() {}
- // }
- // main() {
- // new A().f();
- // }
- // or via implicit this, i.e.:
- // class A {
- // f() {}
- // foo() {
- // f();
- // }
- // }
- // TODO(paulberry): if user-provided types are wrong, this may actually
- // be the PropertyAccessorElement case.
- // TODO(paulberry): do we need to do something different for static
- // methods?
- handleMethodCall(node);
- } else if (staticElement is PropertyAccessorElement) {
- // Invoking a callable getter, e.g.:
- // typedef FunctionType();
- // class A {
- // FunctionType get f { ... }
- // }
- // main() {
- // new A().f();
- // }
- // or via implicit this, i.e.:
- // typedef FunctionType();
- // class A {
- // FunctionType get f { ... }
- // foo() {
- // f();
- // }
- // }
- // This also covers the case where the getter is synthetic, because we
- // are getting a field (TODO(paulberry): verify that this is the case).
- // TODO(paulberry): deal with this case.
- // TODO(paulberry): if user-provided types are wrong, this may actually
- // be the MethodElement case.
- throw new UnimplementedError();
- } else if (staticElement is MultiplyInheritedExecutableElement) {
- // TODO(paulberry): deal with this case.
- throw new UnimplementedError();
- } else if (staticElement is LocalElement) {
- // Invoking a callable local, e.g.:
- // typedef FunctionType();
- // main() {
- // FunctionType f = ...;
- // f();
- // }
- // or:
- // main() {
- // f() { ... }
- // f();
- // }
- // or:
- // f() {}
- // main() {
- // f();
- // }
- // TODO(paulberry): for the moment we are assuming it's a toplevel
- // function.
- analysis.calls.add(staticElement);
- } else if (staticElement is MultiplyDefinedElement) {
- // TODO(paulberry): do we have to deal with this case?
- throw new UnimplementedError();
}
- // TODO(paulberry): I believe all the other possibilities are errors, but
- // we should double check.
}
@override
void visitPropertyAccess(PropertyAccess node) {
- // Accessing a getter or setter, e.g.:
- // class A {
- // get g() => ...;
- // }
- // main() {
- // new A().g;
- // }
- // TODO(paulberry): do setters go through this path as well?
- // TODO(paulberry): handle cases where the property access is represented
- // as a PrefixedIdentifier.
- super.visitPropertyAccess(node);
- analysis.invokes.add(new Selector.getter(node.propertyName.name, null));
+ if (node.target != null) {
+ node.target.accept(this);
+ }
+ _handlePropertyAccess(classifyPropertyAccess(node));
+ }
+
+ @override
+ visitPrefixedIdentifier(PrefixedIdentifier node) {
+ node.prefix.accept(this);
+ _handlePropertyAccess(classifyPrefixedIdentifier(node));
+ }
+
+ @override
+ visitSimpleIdentifier(SimpleIdentifier node) {
+ AccessSemantics semantics = classifyBareIdentifier(node);
+ if (semantics != null) {
+ _handlePropertyAccess(semantics);
+ }
+ }
+
+ void _handlePropertyAccess(AccessSemantics semantics) {
+ switch (semantics.kind) {
+ case AccessKind.DYNAMIC:
+ if (semantics.isRead) {
+ analysis.invokes.add(
+ new Selector.getter(semantics.identifier.name, null));
+ }
+ if (semantics.isWrite) {
+ // TODO(paulberry): implement.
+ throw new UnimplementedError();
+ }
+ break;
+ case AccessKind.LOCAL_FUNCTION:
+ case AccessKind.LOCAL_VARIABLE:
+ case AccessKind.PARAMETER:
+ // Locals don't need to be tree shaken.
+ break;
+ case AccessKind.STATIC_FIELD:
+ // TODO(paulberry): implement.
+ throw new UnimplementedError();
+ case AccessKind.STATIC_METHOD:
+ // Method tear-off. TODO(paulberry): implement.
+ break;
+ case AccessKind.STATIC_PROPERTY:
+ // TODO(paulberry): implement.
+ throw new UnimplementedError();
+ default:
+ // Unexpected access kind.
+ throw new UnimplementedError();
+ }
}
}

Powered by Google App Engine
This is Rietveld 408576698