/* * 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.devtools.j2objc.ast.Annotation; import com.google.devtools.j2objc.ast.Block; import com.google.devtools.j2objc.ast.CompilationUnit; import com.google.devtools.j2objc.ast.MethodDeclaration; import com.google.devtools.j2objc.ast.PackageDeclaration; import com.google.devtools.j2objc.ast.ReturnStatement; import com.google.devtools.j2objc.ast.StringLiteral; import com.google.devtools.j2objc.ast.TreeUtil; import com.google.devtools.j2objc.ast.TypeDeclaration; import com.google.devtools.j2objc.types.GeneratedExecutableElement; import com.google.devtools.j2objc.types.GeneratedTypeElement; import com.google.devtools.j2objc.util.ElementUtil; import com.google.devtools.j2objc.util.NameTable; import com.google.devtools.j2objc.util.TranslationUtil; import com.google.devtools.j2objc.util.TypeUtil; import com.google.j2objc.annotations.ObjectiveCName; import java.util.List; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; /** * Creates a TypeDeclaration for a package-info.java file. * Not a TreeVisitor because it only needs to visit the CompilationUnit. */ public class PackageInfoRewriter { private final CompilationUnit unit; private final TypeUtil typeUtil; private final TranslationUtil translationUtil; public static void run(CompilationUnit unit) { if (unit.getMainTypeName().endsWith(NameTable.PACKAGE_INFO_CLASS_NAME)) { new PackageInfoRewriter(unit).run(); } } private PackageInfoRewriter(CompilationUnit unit) { this.unit = unit; typeUtil = unit.getEnv().typeUtil(); translationUtil = unit.getEnv().translationUtil(); } private void run() { PackageDeclaration pkg = unit.getPackage(); List<Annotation> annotations = pkg.getAnnotations(); List<Annotation> runtimeAnnotations = TreeUtil.getRuntimeAnnotationsList(annotations); String prefix = getPackagePrefix(pkg); boolean needsReflection = translationUtil.needsReflection(pkg); // Remove compile time annotations. annotations.retainAll(runtimeAnnotations); if ((annotations.isEmpty() && prefix == null) || !needsReflection) { return; } TypeElement typeElement = GeneratedTypeElement.newPackageInfoClass(pkg.getPackageElement(), typeUtil); TypeDeclaration typeDecl = new TypeDeclaration(typeElement); TreeUtil.moveList(pkg.getAnnotations(), typeDecl.getAnnotations()); if (prefix != null) { typeDecl.addBodyDeclaration(createPrefixMethod(prefix, typeElement)); } unit.addType(0, typeDecl); } private static String getPackagePrefix(PackageDeclaration pkg) { Annotation objcName = TreeUtil.getAnnotation(ObjectiveCName.class, pkg.getAnnotations()); if (objcName != null) { return (String) ElementUtil.getAnnotationValue(objcName.getAnnotationMirror(), "value"); } return null; } private MethodDeclaration createPrefixMethod(String prefix, TypeElement type) { ExecutableElement element = GeneratedExecutableElement.newMethodWithSelector( "__prefix", typeUtil.getJavaString().asType(), type) .addModifiers(Modifier.STATIC); MethodDeclaration method = new MethodDeclaration(element); method.setHasDeclaration(false); Block body = new Block(); method.setBody(body); body.addStatement(new ReturnStatement(new StringLiteral(prefix, typeUtil))); return method; } }