Merge "Remove dependency of /system icu data file from icu4j target"
diff --git a/tools/srcgen/currysrc/Android.bp b/tools/srcgen/currysrc/Android.bp
index 81fbb67..9f29be5 100644
--- a/tools/srcgen/currysrc/Android.bp
+++ b/tools/srcgen/currysrc/Android.bp
@@ -45,6 +45,7 @@
"currysrc_org.eclipse",
"guavalib",
"gson-prebuilt-jar",
+ "jopt-simple-4.9",
],
srcs: ["src/**/*.java"],
}
diff --git a/tools/srcgen/currysrc/src/main/java/com/google/currysrc/aosp/RepackagingTransform.java b/tools/srcgen/currysrc/src/main/java/com/google/currysrc/aosp/RepackagingTransform.java
new file mode 100644
index 0000000..304a43a
--- /dev/null
+++ b/tools/srcgen/currysrc/src/main/java/com/google/currysrc/aosp/RepackagingTransform.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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.currysrc.aosp;
+
+import static com.google.currysrc.api.process.Rules.createMandatoryRule;
+import static com.google.currysrc.api.process.Rules.createOptionalRule;
+
+import com.google.common.collect.ImmutableList;
+import com.google.currysrc.Main;
+import com.google.currysrc.api.RuleSet;
+import com.google.currysrc.api.input.DirectoryInputFileGenerator;
+import com.google.currysrc.api.input.InputFileGenerator;
+import com.google.currysrc.api.output.BasicOutputSourceFileGenerator;
+import com.google.currysrc.api.output.OutputSourceFileGenerator;
+import com.google.currysrc.api.process.Rule;
+import com.google.currysrc.api.process.ast.BodyDeclarationLocators;
+import com.google.currysrc.api.process.ast.TypeLocator;
+import com.google.currysrc.processors.AddMarkerAnnotation;
+import com.google.currysrc.processors.HidePublicClasses;
+import com.google.currysrc.processors.InsertHeader;
+import com.google.currysrc.processors.ModifyQualifiedNames;
+import com.google.currysrc.processors.ModifyStringLiterals;
+import com.google.currysrc.processors.RenamePackage;
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import joptsimple.BuiltinHelpFormatter;
+import joptsimple.OptionParser;
+import joptsimple.OptionSet;
+import joptsimple.OptionSpec;
+import joptsimple.ValueConversionException;
+import joptsimple.ValueConverter;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
+
+/**
+ * General transformation tool for use by various external repositories that require repackaging.
+ */
+public class RepackagingTransform {
+
+ private static final PathConverter PATH_CONVERTER = new PathConverter();
+ private static final PackageTransformationConverter PACKAGE_TRANSFORMATION_CONVERTER =
+ new PackageTransformationConverter();
+
+ /**
+ * Usage: java ConscryptTransform {source dir} {target dir}
+ */
+ public static void main(String[] args) throws Exception {
+
+ OptionParser optionParser = new OptionParser();
+
+ OptionSpec<Path> sourceDirOption = optionParser
+ .accepts("source-dir", "directory containing the source that will be transformed")
+ .withRequiredArg()
+ .describedAs("source directory")
+ .required()
+ .withValuesConvertedBy(PATH_CONVERTER);
+
+ OptionSpec<Path> targetDirOption = optionParser
+ .accepts("target-dir", "directory into which the transformed source will be written")
+ .withRequiredArg()
+ .describedAs("target directory")
+ .required()
+ .withValuesConvertedBy(PATH_CONVERTER);
+
+ OptionSpec<PackageTransformation> packageTransformationOption = optionParser
+ .accepts("package-transformation", "transformation to apply to the package")
+ .withRequiredArg().withValuesConvertedBy(PACKAGE_TRANSFORMATION_CONVERTER);
+
+ OptionSpec<Path> corePlatformApiFileOption =
+ optionParser.accepts("core-platform-api-file",
+ "flat file containing body declaration identifiers for those classes and members that"
+ + " form part of the core platform api and so require a CorePlatformApi annotation"
+ + " to be added during transformation.")
+ .withRequiredArg()
+ .withValuesConvertedBy(PATH_CONVERTER);
+
+ OptionSpec<Path> intraCoreApiFileOption =
+ optionParser.accepts("intra-core-api-file",
+ "flat file containing body declaration identifiers for those classes and members that"
+ + " form part of the intra core api and so require an IntraCoreApi annotation to be"
+ + " added during transformation.")
+ .withRequiredArg()
+ .withValuesConvertedBy(PATH_CONVERTER);
+
+ OptionSpec<Path> unsupportedAppUsageFileOption =
+ optionParser.accepts("unsupported-app-usage-file",
+ "json file containing body declaration identifiers and annotation properties for those"
+ + " members that form part of the hiddenapi and so require an UnsupportedAppUsage"
+ + " annotation to be added during transformation.")
+ .withRequiredArg()
+ .withValuesConvertedBy(PATH_CONVERTER);
+
+ OptionSpec<Integer> tabSizeOption = optionParser.accepts("tab-size",
+ "the number of spaces that represent a single tabulation; set to the default indent used in"
+ + " the transformed code otherwise the transformed code may be incorrectly formatted")
+ .withRequiredArg()
+ .ofType(Integer.class)
+ .defaultsTo(4);
+
+ optionParser.formatHelpWith(new BuiltinHelpFormatter(120, 2));
+
+ OptionSet optionSet;
+ try {
+ optionSet = optionParser.parse(args);
+ if (!optionSet.nonOptionArguments().isEmpty()) {
+ throw new IllegalStateException(String.format("unexpected trailing arguments %s",
+ optionSet.nonOptionArguments().stream()
+ .map(Object::toString)
+ .collect(Collectors.joining(", "))));
+ }
+ } catch (RuntimeException e) {
+ optionParser.printHelpOn(System.err);
+ throw e;
+ }
+
+ Path sourceDir = optionSet.valueOf(sourceDirOption);
+ Path targetDir = optionSet.valueOf(targetDirOption);
+
+ ImmutableList.Builder<Rule> ruleBuilder = ImmutableList.builder();
+
+ // Doc change: Insert a warning about the source code being generated.
+ ruleBuilder.add(
+ createMandatoryRule(
+ new InsertHeader("/* GENERATED SOURCE. DO NOT MODIFY. */\n")));
+
+ List<PackageTransformation> packageTransformations = optionSet
+ .valuesOf(packageTransformationOption);
+ for (PackageTransformation packageTransformation : packageTransformations) {
+ String originalPackage = packageTransformation.prefixToRemove;
+ String androidPackage = packageTransformation.prefixToAdd;
+ ruleBuilder.add(
+ // AST change: Change the package of each CompilationUnit
+ createOptionalRule(new RenamePackage(originalPackage, androidPackage)),
+ // AST change: Change all qualified names in code and javadoc.
+ createOptionalRule(new ModifyQualifiedNames(originalPackage, androidPackage)),
+ // AST change: Change all string literals containing package names in code.
+ createOptionalRule(new ModifyStringLiterals(originalPackage, androidPackage)),
+ // AST change: Change all string literals containing package paths in code.
+ createOptionalRule(new ModifyStringLiterals(
+ packageToPath(originalPackage), packageToPath(androidPackage)))
+ );
+ }
+
+ // Doc change: Insert @hide on all public classes.
+ ruleBuilder.add(createHidePublicClassesRule());
+
+ Path corePlatformApiFile = optionSet.valueOf(corePlatformApiFileOption);
+ if (corePlatformApiFile != null) {
+ // AST change: Add CorePlatformApi to specified classes and members
+ ruleBuilder.add(
+ createOptionalRule(new AddMarkerAnnotation("libcore.api.CorePlatformApi",
+ BodyDeclarationLocators.readBodyDeclarationLocators(corePlatformApiFile))));
+ }
+
+ Path intraCoreApiFile = optionSet.valueOf(intraCoreApiFileOption);
+ if (intraCoreApiFile != null) {
+ // AST change: Add IntraCoreApi to specified classes and members
+ ruleBuilder.add(
+ createOptionalRule(new AddMarkerAnnotation("libcore.api.IntraCoreApi",
+ BodyDeclarationLocators.readBodyDeclarationLocators(intraCoreApiFile))));
+ }
+
+ Path unsupportedAppUsageFile = optionSet.valueOf(unsupportedAppUsageFileOption);
+ if (unsupportedAppUsageFile != null) {
+ // AST Change: Add UnsupportedAppUsage to specified class members.
+ ruleBuilder.add(
+ createOptionalRule(
+ Annotations.addUnsupportedAppUsage(unsupportedAppUsageFile)));
+ }
+
+ Map<String, String> options = JavaCore.getOptions();
+ options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_8);
+ options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_8);
+ options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED);
+ options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
+ options.put(DefaultCodeFormatterConstants.FORMATTER_TAB_SIZE,
+ String.valueOf(optionSet.valueOf(tabSizeOption)));
+
+ new Main(false /* debug */)
+ .setJdtOptions(options)
+ .execute(new TransformRules(sourceDir, targetDir, ruleBuilder.build()));
+ }
+
+ private static String packageToPath(String originalPackage) {
+ return "/" + originalPackage.replace('.', '/');
+ }
+
+ private static Rule createHidePublicClassesRule() {
+ List<TypeLocator> publicApiClassesWhitelist = Collections.emptyList();
+ return createOptionalRule(new HidePublicClasses(publicApiClassesWhitelist,
+ "This class is not part of the Android public SDK API"));
+ }
+
+ static class TransformRules implements RuleSet {
+
+ private final Path sourceDir;
+ private final Path targetDir;
+ private final List<Rule> rules;
+
+ TransformRules(Path sourceDir, Path targetDir, List<Rule> rules) {
+ this.sourceDir = sourceDir;
+ this.targetDir = targetDir;
+ this.rules = rules;
+ }
+
+ @Override
+ public InputFileGenerator getInputFileGenerator() {
+ return new DirectoryInputFileGenerator(sourceDir.toFile());
+ }
+
+ @Override
+ public List<Rule> getRuleList(File ignored) {
+ return rules;
+ }
+
+ @Override
+ public OutputSourceFileGenerator getOutputSourceFileGenerator() {
+ File outputDir = targetDir.toFile();
+ return new BasicOutputSourceFileGenerator(outputDir);
+ }
+ }
+
+ private RepackagingTransform() {
+ }
+
+ private static class PackageTransformation {
+
+ final String prefixToRemove;
+ final String prefixToAdd;
+
+ PackageTransformation(String prefixToRemove, String prefixToAdd) {
+ this.prefixToRemove = prefixToRemove;
+ this.prefixToAdd = prefixToAdd;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s:%s", prefixToRemove, prefixToAdd);
+ }
+ }
+
+ private static class PackageTransformationConverter implements
+ ValueConverter<PackageTransformation> {
+
+ @Override
+ public PackageTransformation convert(String value) {
+ String[] strings = value.split(":");
+ if (strings.length != 2) {
+ throw new ValueConversionException(
+ String.format("Expected '<prefix-to-remove>:<prefix-to-replace>' but got'%s'", value));
+ }
+ return new PackageTransformation(strings[0], strings[1]);
+ }
+
+ @Override
+ public Class<? extends PackageTransformation> valueType() {
+ return PackageTransformation.class;
+ }
+
+ @Override
+ public String valuePattern() {
+ return "prefix-to-remove:prefix-to-replace";
+ }
+ }
+
+ private static class PathConverter implements ValueConverter<Path> {
+
+ @Override
+ public Path convert(String value) {
+ return Paths.get(value);
+ }
+
+ @Override
+ public Class<? extends Path> valueType() {
+ return Path.class;
+ }
+
+ @Override
+ public String valuePattern() {
+ return "";
+ }
+ }
+}
diff --git a/tools/srcgen/currysrc/src/main/java/com/google/currysrc/api/process/ast/FieldLocator.java b/tools/srcgen/currysrc/src/main/java/com/google/currysrc/api/process/ast/FieldLocator.java
index e35713c..b58db23 100644
--- a/tools/srcgen/currysrc/src/main/java/com/google/currysrc/api/process/ast/FieldLocator.java
+++ b/tools/srcgen/currysrc/src/main/java/com/google/currysrc/api/process/ast/FieldLocator.java
@@ -15,6 +15,7 @@
*/
package com.google.currysrc.api.process.ast;
+import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
@@ -57,8 +58,13 @@
: (List<VariableDeclarationFragment>) fieldDeclaration.fragments()) {
String nodeFieldName = variableDeclarationFragment.getName().getFullyQualifiedName();
if (nodeFieldName.equals(fieldName)) {
- BodyDeclaration parentNode = (BodyDeclaration) node.getParent();
- return typeLocator.matches(parentNode);
+ ASTNode parentNode = node.getParent();
+ // Parent could be an AnonymousClassDeclaration which is not a BodyDeclaration so check
+ // first.
+ if (parentNode instanceof BodyDeclaration) {
+ BodyDeclaration parentDeclarationNode = (BodyDeclaration) parentNode;
+ return typeLocator.matches(parentDeclarationNode);
+ }
}
}
}