com.facebook.buck.android.dalvik.firstorder.FirstOrderHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.android.dalvik.firstorder.FirstOrderHelper.java

Source

/*
 * 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.android.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 void 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);
        }
    }

    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());
    }
}