Skip to content

Commit

Permalink
Change ObjectiveCName retention to runtime, and look for ObjectiveCNa…
Browse files Browse the repository at this point in the history
…med packages on the classpath.

	Change on 2015/02/05 by mthvedt <mthvedt@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=85638104
  • Loading branch information
mthvedt authored and tomball committed Feb 11, 2015
1 parent 69d5913 commit e4572b4
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 44 deletions.
Expand Up @@ -23,10 +23,14 @@
* Annotation that specifies what the Objective-C class, protocol, method, * Annotation that specifies what the Objective-C class, protocol, method,
* constructor or package declaration should be when translated. * constructor or package declaration should be when translated.
* *
* Though this interface is marked with {@link RetentionPolicy#RUNTIME},
* it will not be emitted in transpiled output from the J2ObjC transpiler.
* This is the only annotation ignored in this way.
*
* @author Tom Ball * @author Tom Ball
*/ */
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE }) @Target({ ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.PACKAGE })
@Retention(RetentionPolicy.CLASS) @Retention(RetentionPolicy.RUNTIME)
public @interface ObjectiveCName { public @interface ObjectiveCName {


/** /**
Expand Down
16 changes: 3 additions & 13 deletions translator/src/main/java/com/google/devtools/j2objc/J2ObjC.java
Expand Up @@ -20,6 +20,7 @@
import com.google.devtools.j2objc.util.DeadCodeMap; import com.google.devtools.j2objc.util.DeadCodeMap;
import com.google.devtools.j2objc.util.ErrorUtil; import com.google.devtools.j2objc.util.ErrorUtil;
import com.google.devtools.j2objc.util.JdtParser; import com.google.devtools.j2objc.util.JdtParser;
import com.google.devtools.j2objc.util.PathClassLoader;
import com.google.devtools.j2objc.util.ProGuardUsageParser; import com.google.devtools.j2objc.util.ProGuardUsageParser;


import java.io.File; import java.io.File;
Expand Down Expand Up @@ -66,27 +67,16 @@ public static String getFileHeader(String sourceFileName) {
return String.format(Options.getFileHeader(), sourceFileName); return String.format(Options.getFileHeader(), sourceFileName);
} }


private static class JarFileLoader extends URLClassLoader {
public JarFileLoader() {
super(new URL[]{});
}

public void addJarFile(String path) throws MalformedURLException {
String urlPath = "jar:file://" + path + "!/";
addURL(new URL(urlPath));
}
}

private static void initPlugins(String[] pluginPaths, String pluginOptionString) private static void initPlugins(String[] pluginPaths, String pluginOptionString)
throws IOException { throws IOException {
@SuppressWarnings("resource") @SuppressWarnings("resource")
JarFileLoader classLoader = new JarFileLoader(); PathClassLoader classLoader = new PathClassLoader();
for (String path : pluginPaths) { for (String path : pluginPaths) {
if (path.endsWith(".jar")) { if (path.endsWith(".jar")) {
JarInputStream jarStream = null; JarInputStream jarStream = null;
try { try {
jarStream = new JarInputStream(new FileInputStream(path)); jarStream = new JarInputStream(new FileInputStream(path));
classLoader.addJarFile(new File(path).getAbsolutePath()); classLoader.addPath(path);


JarEntry entry; JarEntry entry;
while ((entry = jarStream.getNextJarEntry()) != null) { while ((entry = jarStream.getNextJarEntry()) != null) {
Expand Down
Expand Up @@ -57,8 +57,8 @@
import com.google.devtools.j2objc.types.Import; import com.google.devtools.j2objc.types.Import;
import com.google.devtools.j2objc.util.DeadCodeMap; import com.google.devtools.j2objc.util.DeadCodeMap;
import com.google.devtools.j2objc.util.ErrorUtil; import com.google.devtools.j2objc.util.ErrorUtil;
import com.google.devtools.j2objc.util.PathClassLoader;
import com.google.devtools.j2objc.util.JdtParser; import com.google.devtools.j2objc.util.JdtParser;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.util.TimeTracker; import com.google.devtools.j2objc.util.TimeTracker;


import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.ITypeBinding;
Expand All @@ -69,9 +69,6 @@
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration; import java.util.Enumeration;
Expand Down Expand Up @@ -647,17 +644,8 @@ private static void loadMappingFiles() {
* in case any might have annotations that should be processed. * in case any might have annotations that should be processed.
*/ */
private boolean hasAnnotationProcessors() { private boolean hasAnnotationProcessors() {
List<URL> urls = Lists.newArrayList(); ServiceLoader<Processor> serviceLoader = ServiceLoader.load(
for (String path: Options.getClassPathEntries()) { Processor.class, new PathClassLoader(Options.getClassPathEntries()));
try {
File f = new File(path);
urls.add(new URL("file://" + f.getAbsolutePath()));
} catch (MalformedURLException e) {
ErrorUtil.error(e.toString());
}
}
URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]));
ServiceLoader<Processor> serviceLoader = ServiceLoader.load(Processor.class, classLoader);
Iterator<Processor> iterator = serviceLoader.iterator(); Iterator<Processor> iterator = serviceLoader.iterator();
return iterator.hasNext(); return iterator.hasNext();
} }
Expand Down
Expand Up @@ -53,7 +53,6 @@
import com.google.devtools.j2objc.ast.VariableDeclarationExpression; import com.google.devtools.j2objc.ast.VariableDeclarationExpression;
import com.google.devtools.j2objc.ast.VariableDeclarationStatement; import com.google.devtools.j2objc.ast.VariableDeclarationStatement;
import com.google.devtools.j2objc.util.BindingUtil; import com.google.devtools.j2objc.util.BindingUtil;
import com.google.devtools.j2objc.util.NameTable;
import com.google.devtools.j2objc.util.TranslationUtil; import com.google.devtools.j2objc.util.TranslationUtil;


import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IAnnotationBinding;
Expand Down
Expand Up @@ -16,6 +16,7 @@


import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.j2objc.annotations.ObjectiveCName;


import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IAnnotationBinding;
import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IBinding;
Expand All @@ -25,6 +26,7 @@
import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.Modifier;


import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator; import java.util.Comparator;
Expand Down Expand Up @@ -316,18 +318,21 @@ public static boolean isRuntimeAnnotation(IAnnotationBinding binding) {
} }


/** /**
* Returns true if the specified binding is of an annotation that has * Returns true if the specified binding is of an annotation is runtime, and not
* a runtime retention policy. * ignorable by J2ObjC. Currently the only annotation we ignore is @ObjectiveCName.
*/ */
public static boolean isRuntimeAnnotation(ITypeBinding binding) { public static boolean isRuntimeAnnotation(ITypeBinding binding) {
if (binding != null) { if (binding == null) {
for (IAnnotationBinding ann : binding.getAnnotations()) { return false;
if (ann.getName().equals("Retention")) { }
IVariableBinding retentionBinding = if (binding.getQualifiedName().equals(ObjectiveCName.class.getCanonicalName())) {
(IVariableBinding) ann.getDeclaredMemberValuePairs()[0].getValue(); return false;
return retentionBinding.getName().equals(RetentionPolicy.RUNTIME.name()); }
} IAnnotationBinding retentionBinding = getAnnotation(binding, Retention.class);
} if (retentionBinding != null) {
IVariableBinding runtimeBinding =
(IVariableBinding) getAnnotationValue(retentionBinding, "value");
return runtimeBinding.getName().equals(RetentionPolicy.RUNTIME.toString());
} }
return false; return false;
} }
Expand Down
Expand Up @@ -40,6 +40,8 @@


import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
Expand All @@ -54,6 +56,7 @@ public class NameTable {


private static NameTable instance; private static NameTable instance;
private final Map<IBinding, String> renamings = Maps.newHashMap(); private final Map<IBinding, String> renamings = Maps.newHashMap();
private final ClassLoader classLoader;


public static final String INIT_NAME = "init"; public static final String INIT_NAME = "init";
public static final String DEALLOC_METHOD = "dealloc"; public static final String DEALLOC_METHOD = "dealloc";
Expand Down Expand Up @@ -248,15 +251,17 @@ public class NameTable {
*/ */
private final Map<String, String> prefixMap; private final Map<String, String> prefixMap;


private NameTable(Map<String, String> prefixMap) { private NameTable(Map<String, String> prefixMap, ClassLoader classLoader) {
this.prefixMap = prefixMap; this.prefixMap = prefixMap;
this.classLoader = classLoader;
} }


/** /**
* Initialize this service using the AST returned by the parser. * Initialize this service using the AST returned by the parser.
*/ */
public static void initialize() { public static void initialize() {
instance = new NameTable(Options.getPackagePrefixes()); instance = new NameTable(
Options.getPackagePrefixes(), new PathClassLoader(Options.getClassPathEntries()));
} }


public static void cleanup() { public static void cleanup() {
Expand Down Expand Up @@ -676,6 +681,18 @@ public static String getPrefix(IPackageBinding packageBinding) {
// Continue, as there's no package-info to check. // Continue, as there's no package-info to check.
} }


try {
Class<?> clazz = instance.classLoader.loadClass(packageName + ".package-info");
ObjectiveCName objectiveCName = clazz.getAnnotation(ObjectiveCName.class);
if (objectiveCName != null) {
String prefix = objectiveCName.value();
instance.prefixMap.put(packageName, prefix);
return prefix;
}
} catch (ClassNotFoundException e) {
// Class does not exist -- ignore exception
}

StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
for (String part : packageName.split("\\.")) { for (String part : packageName.split("\\.")) {
sb.append(capitalize(part)); sb.append(capitalize(part));
Expand Down
@@ -0,0 +1,59 @@
/*
* 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.util;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

/**
* A ClassLoader that understands file system paths.
*
* @author Mike Thvedt
*/
public class PathClassLoader extends URLClassLoader {
private static final Logger logger = Logger.getLogger(PathClassLoader.class.getName());

public PathClassLoader() {
super(new URL[0]);
}

public PathClassLoader(List<String> paths) {
this();
addPaths(paths);
}

public void addPaths(List<String> paths) {
for (String path: paths) {
addPath(path);
}
}

public void addPath(String path) {
URL url;
try {
url = new File(path).toURI().toURL();
addURL(url);
} catch (MalformedURLException e) {
logger.warning("Don't understand path: " + path);
}
}
}
Expand Up @@ -20,8 +20,14 @@
import com.google.devtools.j2objc.GenerationTest; import com.google.devtools.j2objc.GenerationTest;
import com.google.devtools.j2objc.Options; import com.google.devtools.j2objc.Options;
import com.google.devtools.j2objc.Options.MemoryManagementOption; import com.google.devtools.j2objc.Options.MemoryManagementOption;
import com.google.devtools.j2objc.util.NameTable;


import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;


/** /**
* Tests for {@link ObjectiveCImplementationGenerator}. * Tests for {@link ObjectiveCImplementationGenerator}.
Expand Down Expand Up @@ -771,8 +777,8 @@ public void testPackageInfoPrefixAnnotation() throws IOException {
public void testPackageInfoPreprocessing() throws IOException { public void testPackageInfoPreprocessing() throws IOException {
addSourceFile( addSourceFile(
"@ObjectiveCName(\"FBM\")\n" "@ObjectiveCName(\"FBM\")\n"
+ "package foo.bar.mumble;\n" + "package foo.bar.mumble;\n"
+ "import com.google.j2objc.annotations.ObjectiveCName;", + "import com.google.j2objc.annotations.ObjectiveCName;",
"foo/bar/mumble/package-info.java"); "foo/bar/mumble/package-info.java");
loadPackageInfo("foo/bar/mumble/package-info.java"); loadPackageInfo("foo/bar/mumble/package-info.java");
String translation = translateSourceFile("package foo.bar.mumble;\n" String translation = translateSourceFile("package foo.bar.mumble;\n"
Expand All @@ -785,6 +791,33 @@ public void testPackageInfoPreprocessing() throws IOException {
assertNotInTranslation(translation, "FooBarMumbleTest"); assertNotInTranslation(translation, "FooBarMumbleTest");
} }


public void testPackageInfoOnClasspath() throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
addSourceFile(
"@ObjectiveCName(\"FBM\")\n"
+ "package foo.bar.mumble;\n"
+ "import com.google.j2objc.annotations.ObjectiveCName;",
"src/foo/bar/mumble/package-info.java");
compiler.run(null, null, System.err,
tempDir.getAbsolutePath() + "/src/foo/bar/mumble/package-info.java");
List<String> oldClassPathEntries = new ArrayList<String>(Options.getClassPathEntries());
Options.getClassPathEntries().add(tempDir.getAbsolutePath() + "/src/");
NameTable.initialize();
try {
String translation = translateSourceFile("package foo.bar.mumble;\n"
+ "public class Test {}",
"foo.bar.mumble.Test", "foo/bar/mumble/Test.h");
assertTranslation(translation, "@interface FBMTest");
assertTranslation(translation, "typedef FBMTest FooBarMumbleTest;");
translation = getTranslatedFile("foo/bar/mumble/Test.m");
assertTranslation(translation, "@implementation FBMTest");
assertNotInTranslation(translation, "FooBarMumbleTest");
} finally {
Options.getClassPathEntries().clear();
Options.getClassPathEntries().addAll(oldClassPathEntries);
}
}

public void testInitializeNotInClassExtension() throws IOException { public void testInitializeNotInClassExtension() throws IOException {
String translation = translateSourceFile( String translation = translateSourceFile(
"class Test { static Integer i = new Integer(5); }", "Test", "Test.m"); "class Test { static Integer i = new Integer(5); }", "Test", "Test.m");
Expand Down

0 comments on commit e4572b4

Please sign in to comment.