/* * 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.pipeline; import com.google.common.io.Files; import com.google.devtools.j2objc.Options; import com.google.devtools.j2objc.ast.Annotation; import com.google.devtools.j2objc.ast.CompilationUnit; import com.google.devtools.j2objc.ast.SingleMemberAnnotation; import com.google.devtools.j2objc.file.InputFile; import com.google.devtools.j2objc.file.RegularInputFile; import com.google.devtools.j2objc.util.ErrorUtil; import com.google.devtools.j2objc.util.FileUtil; import com.google.devtools.j2objc.util.Parser; import com.google.devtools.j2objc.util.TypeUtil; import com.google.j2objc.annotations.ObjectiveCName; import java.io.File; import java.io.IOException; import java.util.List; import java.util.logging.Logger; /** * Preprocesses each input file in the batch. */ public class InputFilePreprocessor { private static final Logger logger = Logger.getLogger(InputFilePreprocessor.class.getName()); private final Parser parser; private File strippedSourcesDir; private final Options options; public InputFilePreprocessor(Parser parser) { this.parser = parser; this.options = parser.options(); } public void processInputs(Iterable<ProcessingContext> inputs) { for (ProcessingContext input : inputs) { processInput(input); } } private void processInput(ProcessingContext input) { try { if (input.getFile().getUnitName().endsWith("package-info.java")) { processPackageInfoSource(input); } else { processRegularSource(input); } } catch (IOException e) { ErrorUtil.error(e.getMessage()); } } public File getStrippedSourcesDir() { return strippedSourcesDir; } private File getCreatedStrippedSourcesDir() { if (strippedSourcesDir == null) { strippedSourcesDir = Files.createTempDir(); logger.finest("Created temp dir for stripped sources: " + strippedSourcesDir.getPath()); } return strippedSourcesDir; } private void processRegularSource(ProcessingContext input) throws IOException { InputFile file = input.getFile(); String source = options.fileUtil().readFile(file); boolean shouldMapHeaders = options.getHeaderMap().useSourceDirectories(); boolean doIncompatibleStripping = source.contains("J2ObjCIncompatible"); if (!(shouldMapHeaders || doIncompatibleStripping)) { // No need to parse. return; } Parser.ParseResult parseResult = parser.parseWithoutBindings(file, source); if (parseResult == null) { // The parser found and reported one or more errors. return; } String qualifiedName = parseResult.mainTypeName(); if (shouldMapHeaders) { options.getHeaderMap().put(qualifiedName, input.getGenerationUnit().getOutputPath() + ".h"); } if (doIncompatibleStripping) { parseResult.stripIncompatibleSource(); File strippedDir = getCreatedStrippedSourcesDir(); String relativePath = qualifiedName.replace('.', File.separatorChar) + ".java"; File strippedFile = new File(strippedDir, relativePath); Files.createParentDirs(strippedFile); Files.write(parseResult.getSource(), strippedFile, options.fileUtil().getCharset()); input.setFile(new RegularInputFile(strippedFile.getPath(), relativePath)); } } private void processPackageInfoSource(ProcessingContext input) throws IOException { InputFile file = input.getFile(); String source = options.fileUtil().readFile(file); CompilationUnit compilationUnit = parser.parse(FileUtil.getMainTypeName(file), file.getUnitName(), source); if (compilationUnit != null) { extractPackagePrefix(file, compilationUnit); } } private void extractPackagePrefix(InputFile file, CompilationUnit unit) { // We should only reach here if it's a package-info.java file. assert file.getUnitName().endsWith("package-info.java"); List<Annotation> annotations = (List<Annotation>) unit.getPackage().getAnnotations(); for (Annotation annotation : annotations) { // getFullyQualifiedName() might not actually return a fully qualified name. String name = annotation.getTypeName().getFullyQualifiedName(); if (name.endsWith("ObjectiveCName")) { // Per Eclipse docs, binding resolution can be a resource hog. if (TypeUtil.getQualifiedName(annotation.getAnnotationMirror().getAnnotationType()).equals( ObjectiveCName.class.getCanonicalName())) { String key = unit.getPackage().getName().getFullyQualifiedName(); String val = (String) ((SingleMemberAnnotation) annotation).getValue().getConstantValue(); options.getPackagePrefixes().addPrefix(key, val); } } } } }