| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 kernel.tree_shaker; | 5 library kernel.tree_shaker; |
| 6 | 6 |
| 7 import '../ast.dart'; | 7 import '../ast.dart'; |
| 8 import '../class_hierarchy.dart'; | 8 import '../class_hierarchy.dart'; |
| 9 import '../core_types.dart'; | 9 import '../core_types.dart'; |
| 10 import '../type_environment.dart'; | 10 import '../type_environment.dart'; |
| (...skipping 878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 889 class _TreeShakingTransformer extends Transformer { | 889 class _TreeShakingTransformer extends Transformer { |
| 890 final TreeShaker shaker; | 890 final TreeShaker shaker; |
| 891 | 891 |
| 892 _TreeShakingTransformer(this.shaker); | 892 _TreeShakingTransformer(this.shaker); |
| 893 | 893 |
| 894 Member _translateInterfaceTarget(Member target) { | 894 Member _translateInterfaceTarget(Member target) { |
| 895 return target != null && shaker.isMemberUsed(target) ? target : null; | 895 return target != null && shaker.isMemberUsed(target) ? target : null; |
| 896 } | 896 } |
| 897 | 897 |
| 898 void transform(Program program) { | 898 void transform(Program program) { |
| 899 for (var library in program.libraries) { | |
| 900 if (!shaker.forceShaking && library.importUri.scheme == 'dart') { | |
| 901 // The backend expects certain things to be present in the core | |
| 902 // libraries, so we currently don't shake off anything there. | |
| 903 continue; | |
| 904 } | |
| 905 library.transformChildren(this); | |
| 906 // Note: we can't shake off empty libraries yet since we don't check if | |
| 907 // there are private names that use the library. | |
| 908 } | |
| 909 for (Expression node in shaker._typedCalls) { | 899 for (Expression node in shaker._typedCalls) { |
| 910 // We should not leave dangling references, so if the target of a typed | 900 // We should not leave dangling references, so if the target of a typed |
| 911 // call has been removed, we must remove the reference. The receiver of | 901 // call has been removed, we must remove the reference. The receiver of |
| 912 // such a call can only be null. | 902 // such a call can only be null. |
| 913 // TODO(asgerf): Rewrite to a NSM call instead of adding dynamic calls. | 903 // TODO(asgerf): Rewrite to a NSM call instead of adding dynamic calls. |
| 914 if (node is MethodInvocation) { | 904 if (node is MethodInvocation) { |
| 915 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); | 905 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); |
| 916 } else if (node is PropertyGet) { | 906 } else if (node is PropertyGet) { |
| 917 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); | 907 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); |
| 918 } else if (node is PropertySet) { | 908 } else if (node is PropertySet) { |
| 919 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); | 909 node.interfaceTarget = _translateInterfaceTarget(node.interfaceTarget); |
| 920 } | 910 } |
| 921 } | 911 } |
| 912 for (var library in program.libraries) { |
| 913 if (!shaker.forceShaking && library.importUri.scheme == 'dart') { |
| 914 // The backend expects certain things to be present in the core |
| 915 // libraries, so we currently don't shake off anything there. |
| 916 continue; |
| 917 } |
| 918 library.transformChildren(this); |
| 919 // Note: we can't shake off empty libraries yet since we don't check if |
| 920 // there are private names that use the library. |
| 921 } |
| 922 } | 922 } |
| 923 | 923 |
| 924 Class visitClass(Class node) { | 924 Class visitClass(Class node) { |
| 925 switch (shaker.getClassRetention(node)) { | 925 switch (shaker.getClassRetention(node)) { |
| 926 case ClassRetention.None: | 926 case ClassRetention.None: |
| 927 node.canonicalName?.unbind(); |
| 927 return null; // Remove the class. | 928 return null; // Remove the class. |
| 928 | 929 |
| 929 case ClassRetention.Namespace: | 930 case ClassRetention.Namespace: |
| 930 // The class is only a namespace for static members. Remove its | 931 // The class is only a namespace for static members. Remove its |
| 931 // hierarchy information. This is mandatory, since these references | 932 // hierarchy information. This is mandatory, since these references |
| 932 // might otherwise become dangling. | 933 // might otherwise become dangling. |
| 933 node.supertype = shaker.coreTypes.objectClass.asRawSupertype; | 934 node.supertype = shaker.coreTypes.objectClass.asRawSupertype; |
| 934 node.implementedTypes.clear(); | 935 node.implementedTypes.clear(); |
| 935 node.typeParameters.clear(); | 936 node.typeParameters.clear(); |
| 936 node.isAbstract = true; | 937 node.isAbstract = true; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 947 case ClassRetention.ExternalInstance: | 948 case ClassRetention.ExternalInstance: |
| 948 break; | 949 break; |
| 949 } | 950 } |
| 950 node.transformChildren(this); | 951 node.transformChildren(this); |
| 951 return node; | 952 return node; |
| 952 } | 953 } |
| 953 | 954 |
| 954 Member defaultMember(Member node) { | 955 Member defaultMember(Member node) { |
| 955 if (!shaker.isMemberBodyUsed(node)) { | 956 if (!shaker.isMemberBodyUsed(node)) { |
| 956 if (!shaker.isMemberOverridden(node)) { | 957 if (!shaker.isMemberOverridden(node)) { |
| 958 node.canonicalName?.unbind(); |
| 957 return null; | 959 return null; |
| 958 } | 960 } |
| 959 if (node is Procedure) { | 961 if (node is Procedure) { |
| 960 // Remove body of unused member. | 962 // Remove body of unused member. |
| 961 if (node.enclosingClass.isAbstract) { | 963 if (node.enclosingClass.isAbstract) { |
| 962 node.isAbstract = true; | 964 node.isAbstract = true; |
| 963 node.function.body = null; | 965 node.function.body = null; |
| 964 } else { | 966 } else { |
| 965 // If the enclosing class is not abstract, the method should still | 967 // If the enclosing class is not abstract, the method should still |
| 966 // have a body even if it can never be called. | 968 // have a body even if it can never be called. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 } | 1113 } |
| 1112 break; | 1114 break; |
| 1113 case ProgramRootKind.Other: | 1115 case ProgramRootKind.Other: |
| 1114 return member; | 1116 return member; |
| 1115 default: | 1117 default: |
| 1116 } | 1118 } |
| 1117 } | 1119 } |
| 1118 } | 1120 } |
| 1119 throw "$root not found!"; | 1121 throw "$root not found!"; |
| 1120 } | 1122 } |
| OLD | NEW |