/* * Copyright 2011 Google Inc. All Rights Reserved. * * 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.types; import com.google.common.collect.Sets; import com.google.devtools.j2objc.ast.AbstractTypeDeclaration; import com.google.devtools.j2objc.ast.AnnotationTypeDeclaration; import com.google.devtools.j2objc.ast.AnnotationTypeMemberDeclaration; import com.google.devtools.j2objc.ast.BodyDeclaration; import com.google.devtools.j2objc.ast.CompilationUnit; import com.google.devtools.j2objc.ast.EnumDeclaration; import com.google.devtools.j2objc.ast.FieldDeclaration; import com.google.devtools.j2objc.ast.FunctionDeclaration; import com.google.devtools.j2objc.ast.MethodDeclaration; import com.google.devtools.j2objc.ast.SingleVariableDeclaration; import com.google.devtools.j2objc.ast.Type; import com.google.devtools.j2objc.ast.TypeDeclaration; import com.google.devtools.j2objc.ast.UnitTreeVisitor; import com.google.devtools.j2objc.util.TranslationUtil; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; /** * Collects the set of imports needed to resolve type references in a header. * * @author Tom Ball */ public class HeaderImportCollector extends UnitTreeVisitor { /** * Describes which declarations should be visited by the collector. */ public enum Filter { INCLUDE_ALL(true, true), PUBLIC_ONLY(true, false), PRIVATE_ONLY(false, true); private final boolean includePublic; private final boolean includePrivate; private Filter(boolean includePublic, boolean includePrivate) { this.includePublic = includePublic; this.includePrivate = includePrivate; } private boolean include(BodyDeclaration node) { return node.hasPrivateDeclaration() ? includePrivate : includePublic; } } private final Filter filter; // Forward declarations. The order in which imports are collected affect // which imports become forward declarations. private Set<Import> forwardDecls = new LinkedHashSet<>(); // Supertypes of the below declared types that haven't been seen by this collector. private Set<Import> superTypes = new LinkedHashSet<>(); // Declared types seen by this collector. private Set<Import> declaredTypes = new HashSet<>(); public HeaderImportCollector(CompilationUnit unit, Filter filter) { super(unit); this.filter = filter; } public Set<Import> getForwardDeclarations() { return forwardDecls; } public Set<Import> getSuperTypes() { return superTypes; } private void addForwardDecl(Type type) { if (type != null) { addForwardDecl(type.getTypeMirror()); } } private void addForwardDecl(TypeMirror type) { forwardDecls.addAll(Sets.difference(Import.getImports(type, unit.getEnv()), declaredTypes)); } private void addSuperType(TypeElement type) { if (type != null) { Import.addImports(type.asType(), superTypes, unit.getEnv()); } } private void addDeclaredType(TypeElement type) { Import.addImports(type.asType(), declaredTypes, unit.getEnv()); } @Override public boolean visit(AnnotationTypeMemberDeclaration node) { if (filter.include(node)) { addForwardDecl(node.getTypeMirror()); } return false; } @Override public boolean visit(FieldDeclaration node) { if (filter.include(node)) { addForwardDecl(node.getTypeMirror()); } return false; } @Override public boolean visit(FunctionDeclaration node) { if (filter.include(node)) { addForwardDecl(node.getReturnType()); for (SingleVariableDeclaration param : node.getParameters()) { addForwardDecl(param.getVariableElement().asType()); } } return false; } @Override public boolean visit(MethodDeclaration node) { if (filter.include(node)) { addForwardDecl(node.getReturnTypeMirror()); for (VariableElement param : node.getExecutableElement().getParameters()) { addForwardDecl(param.asType()); } } return false; } private boolean visitTypeDeclaration(AbstractTypeDeclaration node) { if (filter.include(node)) { addDeclaredType(node.getTypeElement()); addSuperType(TranslationUtil.getSuperType(node)); for (TypeElement interfaze : TranslationUtil.getInterfaceTypes(node)) { addSuperType(interfaze); } } return true; } @Override public boolean visit(TypeDeclaration node) { return visitTypeDeclaration(node); } @Override public boolean visit(EnumDeclaration node) { return visitTypeDeclaration(node); } @Override public boolean visit(AnnotationTypeDeclaration node) { return visitTypeDeclaration(node); } }