/*
* 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.gen;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.j2objc.Options;
import com.google.devtools.j2objc.ast.AbstractTypeDeclaration;
import com.google.devtools.j2objc.ast.CompilationUnit;
import com.google.devtools.j2objc.ast.TreeUtil;
import com.google.devtools.j2objc.types.HeaderImportCollector;
import com.google.devtools.j2objc.types.ImplementationImportCollector;
import com.google.devtools.j2objc.types.Import;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.NameTable;
import java.util.List;
import java.util.Set;
import javax.lang.model.element.TypeElement;
/**
* Contains the generated source code and additional context for a single Java
* type. Must not hold references to any AST nodes or bindings because we need
* those to be cleaned up by the garbage collector.
*/
public class GeneratedType {
private final String typeName;
private final boolean isPrivate;
private final List<String> superTypes;
private final Set<Import> headerForwardDeclarations;
private final Set<Import> headerIncludes;
private final Set<Import> implementationForwardDeclarations;
private final Set<Import> implementationIncludes;
private final String publicDeclarationCode;
private final String privateDeclarationCode;
private final String implementationCode;
private GeneratedType(
String typeName,
boolean isPrivate,
List<String> superTypes,
Set<Import> headerForwardDeclarations,
Set<Import> headerIncludes,
Set<Import> implementationForwardDeclarations,
Set<Import> implementationIncludes,
String publicDeclarationCode,
String privateDeclarationCode,
String implementationCode) {
this.typeName = Preconditions.checkNotNull(typeName);
this.isPrivate = isPrivate;
this.superTypes = Preconditions.checkNotNull(superTypes);
this.headerForwardDeclarations = Preconditions.checkNotNull(headerForwardDeclarations);
this.headerIncludes = Preconditions.checkNotNull(headerIncludes);
this.implementationForwardDeclarations =
Preconditions.checkNotNull(implementationForwardDeclarations);
this.implementationIncludes = Preconditions.checkNotNull(implementationIncludes);
this.publicDeclarationCode = Preconditions.checkNotNull(publicDeclarationCode);
this.privateDeclarationCode = Preconditions.checkNotNull(privateDeclarationCode);
this.implementationCode = Preconditions.checkNotNull(implementationCode);
}
public static GeneratedType fromTypeDeclaration(AbstractTypeDeclaration typeNode) {
TypeElement typeElement = typeNode.getTypeElement();
CompilationUnit unit = TreeUtil.getCompilationUnit(typeNode);
NameTable nameTable = unit.getEnv().nameTable();
boolean emitLineDirectives = unit.getEnv().options().emitLineDirectives();
ImmutableList.Builder<String> superTypes = ImmutableList.builder();
TypeElement superclass = ElementUtil.getSuperclass(typeElement);
if (superclass != null) {
superTypes.add(nameTable.getFullName(superclass));
}
for (TypeElement superInterface : ElementUtil.getInterfaces(typeElement)) {
superTypes.add(nameTable.getFullName(superInterface));
}
HeaderImportCollector headerCollector =
new HeaderImportCollector(unit, HeaderImportCollector.Filter.PUBLIC_ONLY);
typeNode.accept(headerCollector);
HeaderImportCollector privateDeclarationCollector =
new HeaderImportCollector(unit, HeaderImportCollector.Filter.PRIVATE_ONLY);
typeNode.accept(privateDeclarationCollector);
ImplementationImportCollector importCollector = new ImplementationImportCollector(unit);
typeNode.accept(importCollector);
SourceBuilder builder = new SourceBuilder(emitLineDirectives);
TypeDeclarationGenerator.generate(builder, typeNode);
String publicDeclarationCode = builder.toString();
builder = new SourceBuilder(emitLineDirectives);
TypePrivateDeclarationGenerator.generate(builder, typeNode);
String privateDeclarationCode;
String implementationCode;
Options options = unit.getEnv().options();
if (unit.getEnv().translationUtil().generateImplementation(typeElement)) {
builder = new SourceBuilder(options.emitLineDirectives());
TypePrivateDeclarationGenerator.generate(builder, typeNode);
privateDeclarationCode = builder.toString();
builder = new SourceBuilder(options.emitLineDirectives());
TypeImplementationGenerator.generate(builder, typeNode);
implementationCode = builder.toString();
} else {
privateDeclarationCode = "";
implementationCode = String.format(
"// Implementation not generated because %s is on the bootclasspath.\n",
ElementUtil.getQualifiedName(typeElement));
}
ImmutableSet.Builder<Import> implementationIncludes = ImmutableSet.builder();
implementationIncludes.addAll(privateDeclarationCollector.getSuperTypes());
implementationIncludes.addAll(importCollector.getImports());
return new GeneratedType(
nameTable.getFullName(typeElement),
typeNode.hasPrivateDeclaration(),
superTypes.build(),
ImmutableSet.copyOf(headerCollector.getForwardDeclarations()),
ImmutableSet.copyOf(headerCollector.getSuperTypes()),
ImmutableSet.copyOf(privateDeclarationCollector.getForwardDeclarations()),
implementationIncludes.build(),
publicDeclarationCode,
privateDeclarationCode,
implementationCode);
}
/**
* The name of the ObjC type declared by this GeneratedType.
*/
public String getTypeName() {
return typeName;
}
public boolean isPrivate() {
return isPrivate;
}
/**
* The list of type names that must be declared prior to this type because it
* inherits from them.
*/
public List<String> getSuperTypes() {
return superTypes;
}
public Set<Import> getHeaderForwardDeclarations() {
return headerForwardDeclarations;
}
public Set<Import> getHeaderIncludes() {
return headerIncludes;
}
public Set<Import> getImplementationForwardDeclarations() {
return implementationForwardDeclarations;
}
public Set<Import> getImplementationIncludes() {
return implementationIncludes;
}
public String getPublicDeclarationCode() {
return publicDeclarationCode;
}
public String getPrivateDeclarationCode() {
return privateDeclarationCode;
}
public String getImplementationCode() {
return implementationCode;
}
@Override
public String toString() {
return typeName != null ? typeName : "<no-type>";
}
}