/*
* 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.gen;
import com.google.common.collect.Sets;
import com.google.devtools.j2objc.J2ObjC;
import com.google.devtools.j2objc.types.Import;
import java.util.Set;
/**
* Generates Objective-C implementation (.m) files from compilation units.
*
* @author Tom Ball
*/
public class ObjectiveCImplementationGenerator extends ObjectiveCSourceFileGenerator {
private final String suffix;
/**
* Generate an Objective-C implementation file for each type declared in a
* specified compilation unit.
*/
public static void generate(GenerationUnit unit) {
new ObjectiveCImplementationGenerator(unit).generate();
}
private ObjectiveCImplementationGenerator(GenerationUnit unit) {
super(unit, unit.options().emitLineDirectives());
suffix = unit.options().getLanguage().suffix();
}
@Override
protected String getSuffix() {
return suffix;
}
public void generate() {
print(J2ObjC.getFileHeader(getGenerationUnit().getSourceName()));
printImports();
printIgnoreIncompletePragmas();
pushIgnoreDeprecatedDeclarationsPragma();
for (GeneratedType generatedType : getOrderedTypes()) {
print(generatedType.getPrivateDeclarationCode());
}
for (GeneratedType generatedType : getOrderedTypes()) {
print(generatedType.getImplementationCode());
}
popIgnoreDeprecatedDeclarationsPragma();
// TODO(kstanger): We should write directly to file instead of using a builder.
save(getOutputPath());
}
private void printIgnoreIncompletePragmas() {
GenerationUnit unit = getGenerationUnit();
if (unit.hasIncompleteProtocol() || unit.hasIncompleteImplementation()) {
newline();
}
if (unit.hasIncompleteProtocol()) {
println("#pragma clang diagnostic ignored \"-Wprotocol\"");
}
if (unit.hasIncompleteImplementation()) {
println("#pragma clang diagnostic ignored \"-Wincomplete-implementation\"");
}
}
private void printImports() {
Set<String> includeFiles = Sets.newTreeSet();
includeFiles.add("J2ObjC_source.h");
includeFiles.add(getGenerationUnit().getOutputPath() + ".h");
for (GeneratedType generatedType : getOrderedTypes()) {
for (Import imp : generatedType.getImplementationIncludes()) {
if (!isLocalType(imp.getTypeName())) {
includeFiles.add(imp.getImportFileName());
}
}
}
newline();
for (String header : includeFiles) {
printf("#include \"%s\"\n", header);
}
for (String code : getGenerationUnit().getNativeImplementationBlocks()) {
print(code);
}
Set<String> seenTypes = Sets.newHashSet();
Set<Import> forwardDecls = Sets.newHashSet();
for (GeneratedType generatedType : getOrderedTypes()) {
String name = generatedType.getTypeName();
seenTypes.add(name);
for (Import imp : generatedType.getImplementationForwardDeclarations()) {
String typeName = imp.getTypeName();
GeneratedType localType = getLocalType(typeName);
// For local types, only forward declare private types that haven't been seen yet.
// For non-local types, only forward declare types that haven't been imported.
if (localType != null ? (localType.isPrivate() && !seenTypes.contains(typeName))
: !includeFiles.contains(imp.getImportFileName())) {
forwardDecls.add(imp);
}
}
}
printForwardDeclarations(forwardDecls);
}
}