com.google.devtools.j2objc.translate.TypeSorter.java Source code

Java tutorial

Introduction

Here is the source code for com.google.devtools.j2objc.translate.TypeSorter.java

Source

/*
 * 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.google.devtools.j2objc.translate;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.devtools.j2objc.ast.AbstractTypeDeclaration;
import com.google.devtools.j2objc.ast.CompilationUnit;

import org.eclipse.jdt.core.dom.ITypeBinding;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Does a topological sort on the types declared in this unit so that supertypes
 * and interfaces end up before the types that extend or implement them.
 *
 * Should be called after inner class extraction.
 *
 * @author Keith Stanger
 */
public class TypeSorter {

    private static Multimap<String, String> findSuperTypes(Map<String, ITypeBinding> bindingMap) {
        Multimap<String, String> superTypes = HashMultimap.create();
        for (Map.Entry<String, ITypeBinding> entry : bindingMap.entrySet()) {
            String key = entry.getKey();
            ITypeBinding type = entry.getValue();
            ITypeBinding superclass = type.getSuperclass();
            if (superclass != null) {
                String superclassKey = superclass.getTypeDeclaration().getKey();
                if (bindingMap.containsKey(superclassKey)) {
                    superTypes.put(key, superclassKey);
                }
            }
            for (ITypeBinding interfaze : type.getInterfaces()) {
                String interfaceKey = interfaze.getTypeDeclaration().getKey();
                if (bindingMap.containsKey(interfaceKey)) {
                    superTypes.put(key, interfaceKey);
                }
            }
        }
        return superTypes;
    }

    public static void sortTypes(CompilationUnit unit) {
        List<AbstractTypeDeclaration> typeNodes = unit.getTypes();
        Map<String, AbstractTypeDeclaration> nodeMap = Maps.newHashMap();
        LinkedHashMap<String, ITypeBinding> bindingMap = Maps.newLinkedHashMap();
        for (AbstractTypeDeclaration node : typeNodes) {
            ITypeBinding typeBinding = node.getTypeBinding();
            String key = typeBinding.getKey();
            nodeMap.put(key, node);
            bindingMap.put(key, typeBinding);
        }
        Multimap<String, String> superTypes = findSuperTypes(bindingMap);

        ArrayList<String> rootTypes = Lists.newArrayListWithCapacity(typeNodes.size());
        for (String type : bindingMap.keySet()) {
            if (!superTypes.containsValue(type)) {
                rootTypes.add(type);
            }
        }

        typeNodes.clear();
        while (!rootTypes.isEmpty()) {
            String nextType = rootTypes.remove(rootTypes.size() - 1);
            typeNodes.add(0, nodeMap.get(nextType));
            for (String superType : superTypes.removeAll(nextType)) {
                if (!superTypes.containsValue(superType)) {
                    rootTypes.add(superType);
                }
            }
        }
    }
}