Merge "Support for dex signature -> source position map."
diff --git a/src/com/google/doclava/Doclava.java b/src/com/google/doclava/Doclava.java
index 9aaf577..57a4b5a 100644
--- a/src/com/google/doclava/Doclava.java
+++ b/src/com/google/doclava/Doclava.java
@@ -189,6 +189,7 @@
String privateApiFile = null;
String privateDexApiFile = null;
String debugStubsFile = "";
+ String apiMappingFile = null;
HashSet<String> stubPackages = null;
HashSet<String> stubImportPackages = null;
boolean stubSourceOnly = false;
@@ -316,6 +317,8 @@
privateApiFile = a[1];
} else if (a[0].equals("-privateDexApi")) {
privateDexApiFile = a[1];
+ } else if (a[0].equals("-apiMapping")) {
+ apiMappingFile = a[1];
} else if (a[0].equals("-nodocs")) {
generateDocs = false;
} else if (a[0].equals("-noassets")) {
@@ -554,10 +557,10 @@
// Stubs
if (stubsDir != null || apiFile != null || dexApiFile != null || proguardFile != null
|| removedApiFile != null || removedDexApiFile != null || exactApiFile != null
- || privateApiFile != null || privateDexApiFile != null) {
+ || privateApiFile != null || privateDexApiFile != null || apiMappingFile != null) {
Stubs.writeStubsAndApi(stubsDir, apiFile, dexApiFile, proguardFile, removedApiFile,
- removedDexApiFile, exactApiFile, privateApiFile, privateDexApiFile, stubPackages,
- stubImportPackages, stubSourceOnly);
+ removedDexApiFile, exactApiFile, privateApiFile, privateDexApiFile, apiMappingFile,
+ stubPackages, stubImportPackages, stubSourceOnly);
}
Errors.printErrors();
@@ -864,6 +867,9 @@
if (option.equals("-privateDexApi")) {
return 2;
}
+ if (option.equals("-apiMapping")) {
+ return 2;
+ }
if (option.equals("-nodocs")) {
return 1;
}
diff --git a/src/com/google/doclava/Stubs.java b/src/com/google/doclava/Stubs.java
index 343a020..3c9138a 100644
--- a/src/com/google/doclava/Stubs.java
+++ b/src/com/google/doclava/Stubs.java
@@ -48,8 +48,8 @@
public class Stubs {
public static void writeStubsAndApi(String stubsDir, String apiFile, String dexApiFile,
String keepListFile, String removedApiFile, String removedDexApiFile, String exactApiFile,
- String privateApiFile, String privateDexApiFile, HashSet<String> stubPackages,
- HashSet<String> stubImportPackages, boolean stubSourceOnly) {
+ String privateApiFile, String privateDexApiFile, String apiMappingFile,
+ HashSet<String> stubPackages, HashSet<String> stubImportPackages, boolean stubSourceOnly) {
// figure out which classes we need
final HashSet<ClassInfo> notStrippable = new HashSet<ClassInfo>();
Collection<ClassInfo> all = Converter.allClasses();
@@ -62,6 +62,7 @@
PrintStream exactApiWriter = null;
PrintStream privateApiWriter = null;
PrintStream privateDexApiWriter = null;
+ PrintStream apiMappingWriter = null;
if (apiFile != null) {
try {
@@ -148,6 +149,17 @@
"Cannot open file for write");
}
}
+ if (apiMappingFile != null) {
+ try {
+ File apiMapping = new File(apiMappingFile);
+ apiMapping.getParentFile().mkdirs();
+ apiMappingWriter = new PrintStream(
+ new BufferedOutputStream(new FileOutputStream(apiMapping)));
+ } catch (FileNotFoundException e) {
+ Errors.error(Errors.IO_ERROR, new SourcePositionInfo(apiMappingFile, 0, 0),
+ "Cannot open file for write");
+ }
+ }
// If a class is public or protected, not hidden, not imported and marked as included,
// then we can't strip it
for (ClassInfo cl : all) {
@@ -264,7 +276,7 @@
}
if (privateApiWriter != null || privateDexApiWriter != null || removedApiWriter != null
- || removedDexApiWriter != null) {
+ || removedDexApiWriter != null || apiMappingWriter != null) {
allClassesByPackage = Converter.allClasses().stream()
// Make sure that the files only contains information from the required packages.
.filter(ci -> stubPackages == null
@@ -320,6 +332,12 @@
privateDexApiWriter.close();
}
+ // Write out the API mapping
+ if (apiMappingWriter != null) {
+ writeApiMapping(apiMappingWriter, allClassesByPackage);
+ apiMappingWriter.close();
+ }
+
// Write out the removed API
if (removedApiWriter != null) {
writeApi(removedApiWriter, allClassesByPackage, removedEmit, removedReference);
@@ -1459,6 +1477,34 @@
}
}
+ static void writeApiMapping(PrintStream mappingWriter,
+ Map<PackageInfo, List<ClassInfo>> classesByPackage) {
+
+ for (PackageInfo pkg : classesByPackage.keySet().stream().sorted(PackageInfo.comparator)
+ .collect(Collectors.toList())) {
+ if (pkg.name().equals(PackageInfo.DEFAULT_PACKAGE)) continue;
+ for (ClassInfo cl : classesByPackage.get(pkg).stream().sorted(ClassInfo.comparator)
+ .collect(Collectors.toList())) {
+ cl.getExhaustiveConstructors().stream().sorted(MethodInfo.comparator).forEach(method -> {
+ writeMethodDexApi(mappingWriter, cl, method);
+ writeSourcePositionInfo(mappingWriter, method);
+ });
+ cl.getExhaustiveMethods().stream().sorted(MethodInfo.comparator).forEach(method -> {
+ writeMethodDexApi(mappingWriter, cl, method);
+ writeSourcePositionInfo(mappingWriter, method);
+ });
+ cl.getExhaustiveEnumConstants().stream().sorted(FieldInfo.comparator).forEach(enumInfo -> {
+ writeFieldDexApi(mappingWriter, cl, enumInfo);
+ writeSourcePositionInfo(mappingWriter, enumInfo);
+ });
+ cl.getExhaustiveFields().stream().sorted(FieldInfo.comparator).forEach(field -> {
+ writeFieldDexApi(mappingWriter, cl, field);
+ writeSourcePositionInfo(mappingWriter, field);
+ });
+ }
+ }
+ }
+
/**
* Write the removed members of the class to removed.txt
*/
@@ -1765,6 +1811,11 @@
apiWriter.print(";\n");
}
+ static void writeSourcePositionInfo(PrintStream writer, DocInfo docInfo) {
+ SourcePositionInfo pos = docInfo.position();
+ writer.println(pos);
+ }
+
static void writeMethodDexApi(PrintStream apiWriter, ClassInfo cl, MethodInfo mi) {
apiWriter.print(toSlashFormat(cl.qualifiedName()));
apiWriter.print("->");