/* * Copyright 2012-present Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.buck.dalvik.firstorder; import com.google.common.collect.ImmutableSet; import java.util.HashMap; import java.util.Map; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; public class FirstOrderHelper { private final Iterable<Type> scenarioTypes; private final ImmutableSet.Builder<String> resultBuilder; private final Map<Type, FirstOrderTypeInfo> knownTypes; private FirstOrderHelper( Iterable<Type> scenarioTypes, ImmutableSet.Builder<String> resultBuilder) { this.scenarioTypes = scenarioTypes; this.resultBuilder = resultBuilder; this.knownTypes = new HashMap<>(); } public static void addTypesAndDependencies( Iterable<Type> scenarioTypes, Iterable<ClassNode> allClasses, ImmutableSet.Builder<String> classNamesBuilder) { FirstOrderHelper helper = new FirstOrderHelper(scenarioTypes, classNamesBuilder); helper.addDependencies(allClasses); } private ImmutableSet<String> addDependencies(Iterable<ClassNode> allClasses) { for (ClassNode classNode : allClasses) { FirstOrderVisitorContext context = new FirstOrderVisitorContext(); classNode.accept(context.classVisitor); FirstOrderTypeInfo info = context.builder.build(); knownTypes.put(info.type, info); } // TODO(mmarucheck): consider adding events here that allow developers to track // how many non android.* and java.* classes went unrecognized over time. // // Not all types will be known. This includes types from Android, java // runtime libraries, and any types that have been removed from the application // since the scenario ran. for (Type type : scenarioTypes) { addFirstOrderTypes(type); } return resultBuilder.build(); } private void addFirstOrderTypes(Type type) { addTypeAndSupers(type); FirstOrderTypeInfo info = knownTypes.get(type); if (info != null) { for (Type dependency : info.observedDependencies) { addTypeAndSupers(dependency); } } } private void addTypeAndSupers(Type type) { addType(type); FirstOrderTypeInfo info = knownTypes.get(type); if (info != null) { addTypeAndSupers(info.superType); for (Type interfaceType : info.interfaceTypes) { addTypeAndSupers(interfaceType); } } } private void addType(Type type) { resultBuilder.add(type.getInternalName()); } }