1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.icu4j.srcgen;
17 
18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.Lists;
20 import com.google.currysrc.Main;
21 import com.google.currysrc.api.Rules;
22 import com.google.currysrc.api.input.InputFileGenerator;
23 import com.google.currysrc.api.output.BasicOutputSourceFileGenerator;
24 import com.google.currysrc.api.output.OutputSourceFileGenerator;
25 import com.google.currysrc.api.process.DefaultRule;
26 import com.google.currysrc.api.process.Rule;
27 import com.google.currysrc.api.process.ast.BodyDeclarationLocator;
28 import com.google.currysrc.api.process.ast.BodyDeclarationLocators;
29 import com.google.currysrc.api.process.ast.TypeLocator;
30 import com.google.currysrc.processors.HidePublicClasses;
31 import com.google.currysrc.processors.InsertHeader;
32 import com.google.currysrc.processors.ModifyQualifiedNames;
33 import com.google.currysrc.processors.ModifyStringLiterals;
34 import com.google.currysrc.processors.RemoveJavaDocTags;
35 import com.google.currysrc.processors.RenamePackage;
36 import com.google.currysrc.processors.ReplaceSelectedJavadoc;
37 import com.google.currysrc.processors.ReplaceTextCommentScanner;
38 
39 import java.io.File;
40 import java.io.IOException;
41 import java.util.Arrays;
42 import java.util.List;
43 
44 import static com.android.icu4j.srcgen.Icu4jTransformRules.createMandatoryRule;
45 import static com.android.icu4j.srcgen.Icu4jTransformRules.createOptionalRule;
46 
47 /**
48  * Applies Android's ICU4J source code transformation rules. If you make any changes to this class
49  * then you should re-run the generate_android_icu4j.sh script.
50  */
51 public class Icu4jTransform {
52 
53   // The list of public ICU API classes exposed on Android. If you change this, you should change
54   // the INITIAL_DEPRECATED_SET below to include entries from the new classes.
55   static final String[] PUBLIC_API_CLASSES = new String[] {
56       /* ASCII order please. */
57       "android.icu.lang.UCharacter",
58       "android.icu.lang.UCharacterCategory",
59       "android.icu.lang.UCharacterDirection",
60       "android.icu.lang.UCharacterEnums",
61       "android.icu.lang.UProperty",
62       "android.icu.lang.UScript",
63       "android.icu.math.BigDecimal",
64       "android.icu.math.MathContext",
65       "android.icu.text.AlphabeticIndex",
66       "android.icu.text.BreakIterator",
67       "android.icu.text.CollationKey",
68       "android.icu.text.Collator",
69       "android.icu.text.CollationElementIterator",
70       "android.icu.text.CompactDecimalFormat",
71       "android.icu.text.CurrencyPluralInfo",
72       "android.icu.text.DateFormat",
73       "android.icu.text.DateFormatSymbols",
74       "android.icu.text.DateIntervalInfo",
75       "android.icu.text.DateIntervalFormat",
76       "android.icu.text.DateTimePatternGenerator",
77       "android.icu.text.DecimalFormat",
78       "android.icu.text.DecimalFormatSymbols",
79       "android.icu.text.DisplayContext",
80       "android.icu.text.IDNA",
81       "android.icu.text.LocaleDisplayNames",
82       "android.icu.text.MeasureFormat",
83       "android.icu.text.MessageFormat",
84       "android.icu.text.MessagePattern",
85       "android.icu.text.Normalizer",
86       "android.icu.text.Normalizer2",
87       "android.icu.text.NumberFormat",
88       "android.icu.text.NumberingSystem",
89       "android.icu.text.PluralFormat",
90       "android.icu.text.PluralRules",
91       "android.icu.text.RelativeDateTimeFormatter",
92       "android.icu.text.Replaceable",
93       "android.icu.text.RuleBasedCollator",
94       "android.icu.text.SearchIterator",
95       "android.icu.text.SelectFormat",
96       "android.icu.text.SimpleDateFormat",
97       "android.icu.text.StringPrepParseException",
98       "android.icu.text.StringSearch",
99       "android.icu.text.SymbolTable",
100       "android.icu.text.TimeZoneFormat",
101       "android.icu.text.TimeZoneNames",
102       "android.icu.text.UCharacterIterator",
103       "android.icu.text.UFormat",
104       "android.icu.text.UnicodeFilter",
105       "android.icu.text.UnicodeMatcher",
106       "android.icu.text.UnicodeSet",
107       "android.icu.text.UnicodeSetIterator",
108       "android.icu.text.UnicodeSetSpanner",
109       "android.icu.util.BuddhistCalendar",
110       "android.icu.util.Calendar",
111       "android.icu.util.CECalendar",
112       "android.icu.util.ChineseCalendar",
113       "android.icu.util.CopticCalendar",
114       "android.icu.util.Currency",
115       "android.icu.util.CurrencyAmount",
116       "android.icu.util.DateInterval",
117       "android.icu.util.EthiopticCalendar",
118       "android.icu.util.Freezable",
119       "android.icu.util.GregorianCalendar",
120       "android.icu.util.HebrewCalendar",
121       "android.icu.util.ICUUncheckedIOException",
122       "android.icu.util.IndianCalendar",
123       "android.icu.util.IslamicCalendar",
124       "android.icu.util.JapaneseCalendar",
125       "android.icu.util.Measure",
126       "android.icu.util.MeasureUnit",
127       "android.icu.util.Output",
128       "android.icu.util.RangeValueIterator",
129       "android.icu.util.TaiwanCalendar",
130       "android.icu.util.TimeUnit",
131       "android.icu.util.TimeZone",
132       "android.icu.util.ULocale",
133       "android.icu.util.ValueIterator",
134       "android.icu.util.VersionInfo",
135   };
136 
137   /**
138    * The set of deprecated ICU types/methods/fields that must not be part of the public API as they
139    * were deprecated when Android first exposed ICU as a public API. Methods deprecated by ICU
140    * after this will be visible and deprecated in Android.
141    */
142   // This list was originally generated by the CaptureDeprecatedElements tool when run against
143   // ICU56 with the original PUBLIC_API_CLASSES.
144   private static final String[] INITIAL_DEPRECATED_SET = new String[] {
145       /* ASCII order please. */
146       "field:android.icu.lang.UProperty#ISO_COMMENT",
147       "field:android.icu.lang.UProperty#UNDEFINED",
148       "field:android.icu.lang.UProperty#UNICODE_1_NAME",
149       "field:android.icu.lang.UScript#DUPLOYAN_SHORTAND",
150       "field:android.icu.text.DateFormat#ABBR_STANDALONE_MONTH",
151       "field:android.icu.text.DateFormat#DATE_SKELETONS",
152       "field:android.icu.text.DateFormat#HOUR_GENERIC_TZ",
153       "field:android.icu.text.DateFormat#HOUR_MINUTE_GENERIC_TZ",
154       "field:android.icu.text.DateFormat#HOUR_MINUTE_TZ",
155       "field:android.icu.text.DateFormat#HOUR_TZ",
156       "field:android.icu.text.DateFormat#STANDALONE_MONTH",
157       "field:android.icu.text.DateFormat#TIME_SKELETONS",
158       "field:android.icu.text.DateFormat#ZONE_SKELETONS",
159       "field:android.icu.text.DateFormatSymbols#DT_CONTEXT_COUNT",
160       "field:android.icu.text.DateFormatSymbols#DT_WIDTH_COUNT",
161       "field:android.icu.text.DateFormatSymbols#NUMERIC",
162       "field:android.icu.text.DateTimePatternGenerator#MATCH_MINUTE_FIELD_LENGTH",
163       "field:android.icu.text.DateTimePatternGenerator#MATCH_SECOND_FIELD_LENGTH",
164       "field:android.icu.text.IDNA#ALLOW_UNASSIGNED",
165       "field:android.icu.text.Normalizer#COMPARE_NORM_OPTIONS_SHIFT",
166       "field:android.icu.text.Normalizer#COMPOSE",
167       "field:android.icu.text.Normalizer#COMPOSE_COMPAT",
168       "field:android.icu.text.Normalizer#DECOMP",
169       "field:android.icu.text.Normalizer#DECOMP_COMPAT",
170       "field:android.icu.text.Normalizer#DEFAULT",
171       "field:android.icu.text.Normalizer#DONE",
172       "field:android.icu.text.Normalizer#FCD",
173       "field:android.icu.text.Normalizer#IGNORE_HANGUL",
174       "field:android.icu.text.Normalizer#NFC",
175       "field:android.icu.text.Normalizer#NFD",
176       "field:android.icu.text.Normalizer#NFKC",
177       "field:android.icu.text.Normalizer#NFKD",
178       "field:android.icu.text.Normalizer#NONE",
179       "field:android.icu.text.Normalizer#NO_OP",
180       "field:android.icu.text.Normalizer#UNICODE_3_2",
181       "field:android.icu.text.PluralRules#CATEGORY_SEPARATOR",
182       "field:android.icu.text.PluralRules#KEYWORD_RULE_SEPARATOR",
183       "field:android.icu.text.PluralRules$FixedDecimal#decimalDigits",
184       "field:android.icu.text.PluralRules$FixedDecimal#decimalDigitsWithoutTrailingZeros",
185       "field:android.icu.text.PluralRules$FixedDecimal#hasIntegerValue",
186       "field:android.icu.text.PluralRules$FixedDecimal#integerValue",
187       "field:android.icu.text.PluralRules$FixedDecimal#isNegative",
188       "field:android.icu.text.PluralRules$FixedDecimal#source",
189       "field:android.icu.text.PluralRules$FixedDecimal#visibleDecimalDigitCount",
190       "field:android.icu.text.PluralRules$FixedDecimal#visibleDecimalDigitCountWithoutTrailingZeros",
191       "field:android.icu.text.PluralRules$FixedDecimalRange#end",
192       "field:android.icu.text.PluralRules$FixedDecimalRange#start",
193       "field:android.icu.text.PluralRules$FixedDecimalSamples#bounded",
194       "field:android.icu.text.PluralRules$FixedDecimalSamples#sampleType",
195       "field:android.icu.text.PluralRules$FixedDecimalSamples#samples",
196       "field:android.icu.text.PluralRules$StandardPluralCategories#COUNT",
197       "field:android.icu.text.PluralRules$StandardPluralCategories#VALUES",
198       "field:android.icu.text.UnicodeSetIterator#endElement",
199       "field:android.icu.text.UnicodeSetIterator#nextElement",
200       "field:android.icu.util.Calendar#WEEKDAY",
201       "field:android.icu.util.Calendar#WEEKEND",
202       "field:android.icu.util.Calendar#WEEKEND_CEASE",
203       "field:android.icu.util.Calendar#WEEKEND_ONSET",
204       "field:android.icu.util.MeasureUnit#subType",
205       "field:android.icu.util.MeasureUnit#type",
206       "field:android.icu.util.VersionInfo#ICU_DATA_VERSION",
207       "field:android.icu.util.VersionInfo#ICU_DATA_VERSION_PATH",
208       "field:android.icu.util.VersionInfo#UCOL_TAILORINGS_VERSION",
209       "method:android.icu.lang.UCharacter#getCharFromName1_0(String)",
210       "method:android.icu.lang.UCharacter#getISOComment(int)",
211       "method:android.icu.lang.UCharacter#getName1_0(int)",
212       "method:android.icu.lang.UCharacter#getName1_0Iterator()",
213       "method:android.icu.lang.UCharacter#getPropertyValueEnumNoThrow(int,CharSequence)",
214       "method:android.icu.lang.UCharacter#getStringPropertyValue(int,int,int)",
215       "method:android.icu.lang.UCharacter#isJavaLetter(int)",
216       "method:android.icu.lang.UCharacter#isJavaLetterOrDigit(int)",
217       "method:android.icu.lang.UCharacter#isSpace(int)",
218       "method:android.icu.lang.UCharacter#toTitleFirst(ULocale,String)",
219       "method:android.icu.text.AlphabeticIndex#getFirstCharactersInScripts()",
220       "method:android.icu.text.BreakIterator#getBreakInstance(ULocale,int)",
221       "method:android.icu.text.CollationElementIterator#getRuleBasedCollator()",
222       "method:android.icu.text.CollationElementIterator#hashCode()",
223       "method:android.icu.text.Collator#doCompare(CharSequence,CharSequence)",
224       "method:android.icu.text.Collator#setStrength2(int)",
225       "method:android.icu.text.Collator#setVariableTop(String)",
226       "method:android.icu.text.Collator#setVariableTop(int)",
227       "method:android.icu.text.CompactDecimalFormat#CompactDecimalFormat(String,DecimalFormatSymbols,CompactStyle,PluralRules,long[],Map<String,String[][]>,Map<String,String[]>,Collection<String>)",
228       "method:android.icu.text.CurrencyPluralInfo#hashCode()",
229       "method:android.icu.text.DateFormatSymbols#getDateFormatBundle(Calendar,Locale)",
230       "method:android.icu.text.DateFormatSymbols#getDateFormatBundle(Calendar,ULocale)",
231       "method:android.icu.text.DateFormatSymbols#getDateFormatBundle(Class<? extends Calendar>,Locale)",
232       "method:android.icu.text.DateFormatSymbols#getDateFormatBundle(Class<? extends Calendar>,ULocale)",
233       "method:android.icu.text.DateFormatSymbols#getLeapMonthPattern(int,int)",
234       "method:android.icu.text.DateFormatSymbols#initializeData(ULocale,CalendarData)",
235       "method:android.icu.text.DateFormatSymbols#setLeapMonthPattern(String,int,int)",
236       "method:android.icu.text.DateIntervalFormat#DateIntervalFormat(String,DateIntervalInfo,SimpleDateFormat)",
237       "method:android.icu.text.DateIntervalFormat#getPatterns(Calendar,Calendar,Output<String>)",
238       "method:android.icu.text.DateIntervalFormat#getRawPatterns()",
239       "method:android.icu.text.DateIntervalFormat#parseObject(String,ParsePosition)",
240       "method:android.icu.text.DateIntervalInfo#DateIntervalInfo()",
241       "method:android.icu.text.DateIntervalInfo#genPatternInfo(String,boolean)",
242       "method:android.icu.text.DateIntervalInfo#getPatterns()",
243       "method:android.icu.text.DateIntervalInfo#getRawPatterns()",
244       "method:android.icu.text.DateTimePatternGenerator#addPatternWithSkeleton(String,String,boolean,PatternInfo)",
245       "method:android.icu.text.DateTimePatternGenerator#getAppendFormatNumber(String)",
246       "method:android.icu.text.DateTimePatternGenerator#getCanonicalSkeletonAllowingDuplicates(String)",
247       "method:android.icu.text.DateTimePatternGenerator#getDefaultHourFormatChar()",
248       "method:android.icu.text.DateTimePatternGenerator#getFields(String)",
249       "method:android.icu.text.DateTimePatternGenerator#getFrozenInstance(ULocale)",
250       "method:android.icu.text.DateTimePatternGenerator#getRedundants(Collection<String>)",
251       "method:android.icu.text.DateTimePatternGenerator#getSkeletonAllowingDuplicates(String)",
252       "method:android.icu.text.DateTimePatternGenerator#isSingleField(String)",
253       "method:android.icu.text.DateTimePatternGenerator#setDefaultHourFormatChar(char)",
254       "method:android.icu.text.DateTimePatternGenerator#skeletonsAreSimilar(String,String)",
255       "method:android.icu.text.DateTimePatternGenerator$FormatParser#FormatParser()",
256       "method:android.icu.text.DateTimePatternGenerator$FormatParser#getItems()",
257       "method:android.icu.text.DateTimePatternGenerator$FormatParser#hasDateAndTimeFields()",
258       "method:android.icu.text.DateTimePatternGenerator$FormatParser#quoteLiteral(String)",
259       "method:android.icu.text.DateTimePatternGenerator$FormatParser#set(String)",
260       "method:android.icu.text.DateTimePatternGenerator$FormatParser#set(String,boolean)",
261       "method:android.icu.text.DateTimePatternGenerator$FormatParser#toString()",
262       "method:android.icu.text.DateTimePatternGenerator$FormatParser#toString(int,int)",
263       "method:android.icu.text.DateTimePatternGenerator$VariableField#VariableField(String)",
264       "method:android.icu.text.DateTimePatternGenerator$VariableField#VariableField(String,boolean)",
265       "method:android.icu.text.DateTimePatternGenerator$VariableField#getCanonicalCode(int)",
266       "method:android.icu.text.DateTimePatternGenerator$VariableField#getType()",
267       "method:android.icu.text.DateTimePatternGenerator$VariableField#isNumeric()",
268       "method:android.icu.text.DateTimePatternGenerator$VariableField#toString()",
269       "method:android.icu.text.DecimalFormat#getEffectiveCurrency()",
270       "method:android.icu.text.DecimalFormatSymbols#getMinusString()",
271       "method:android.icu.text.DecimalFormatSymbols#getPlusString()",
272       "method:android.icu.text.IDNA#IDNA()",
273       "method:android.icu.text.IDNA#addError(Info,Error)",
274       "method:android.icu.text.IDNA#addLabelError(Info,Error)",
275       "method:android.icu.text.IDNA#compare(String,String,int)",
276       "method:android.icu.text.IDNA#compare(StringBuffer,StringBuffer,int)",
277       "method:android.icu.text.IDNA#compare(UCharacterIterator,UCharacterIterator,int)",
278       "method:android.icu.text.IDNA#convertIDNToASCII(String,int)",
279       "method:android.icu.text.IDNA#convertIDNToASCII(StringBuffer,int)",
280       "method:android.icu.text.IDNA#convertIDNToASCII(UCharacterIterator,int)",
281       "method:android.icu.text.IDNA#convertIDNToUnicode(String,int)",
282       "method:android.icu.text.IDNA#convertIDNToUnicode(StringBuffer,int)",
283       "method:android.icu.text.IDNA#convertIDNToUnicode(UCharacterIterator,int)",
284       "method:android.icu.text.IDNA#convertToASCII(String,int)",
285       "method:android.icu.text.IDNA#convertToASCII(StringBuffer,int)",
286       "method:android.icu.text.IDNA#convertToASCII(UCharacterIterator,int)",
287       "method:android.icu.text.IDNA#convertToUnicode(String,int)",
288       "method:android.icu.text.IDNA#convertToUnicode(StringBuffer,int)",
289       "method:android.icu.text.IDNA#convertToUnicode(UCharacterIterator,int)",
290       "method:android.icu.text.IDNA#hasCertainErrors(Info,EnumSet<Error>)",
291       "method:android.icu.text.IDNA#hasCertainLabelErrors(Info,EnumSet<Error>)",
292       "method:android.icu.text.IDNA#isBiDi(Info)",
293       "method:android.icu.text.IDNA#isOkBiDi(Info)",
294       "method:android.icu.text.IDNA#promoteAndResetLabelErrors(Info)",
295       "method:android.icu.text.IDNA#resetInfo(Info)",
296       "method:android.icu.text.IDNA#setBiDi(Info)",
297       "method:android.icu.text.IDNA#setNotOkBiDi(Info)",
298       "method:android.icu.text.IDNA#setTransitionalDifferent(Info)",
299       "method:android.icu.text.LocaleDisplayNames#LocaleDisplayNames()",
300       "method:android.icu.text.LocaleDisplayNames#scriptDisplayNameInContext(String)",
301       "method:android.icu.text.MeasureFormat#formatMeasureRange(Measure,Measure)",
302       "method:android.icu.text.MeasureFormat#getRangeFormat(ULocale,FormatWidth)",
303       "method:android.icu.text.MeasureFormat#getRangePattern(ULocale,FormatWidth)",
304       "method:android.icu.text.Normalizer#Normalizer(CharacterIterator,Mode,int)",
305       "method:android.icu.text.Normalizer#Normalizer(String,Mode,int)",
306       "method:android.icu.text.Normalizer#Normalizer(UCharacterIterator,Mode,int)",
307       "method:android.icu.text.Normalizer#clone()",
308       "method:android.icu.text.Normalizer#compose(String,boolean)",
309       "method:android.icu.text.Normalizer#compose(String,boolean,int)",
310       "method:android.icu.text.Normalizer#compose(char[],char[],boolean,int)",
311       "method:android.icu.text.Normalizer#compose(char[],int,int,char[],int,int,boolean,int)",
312       "method:android.icu.text.Normalizer#concatenate(String,String,Mode,int)",
313       "method:android.icu.text.Normalizer#concatenate(char[],char[],Mode,int)",
314       "method:android.icu.text.Normalizer#concatenate(char[],int,int,char[],int,int,char[],int,int,Normalizer.Mode,int)",
315       "method:android.icu.text.Normalizer#current()",
316       "method:android.icu.text.Normalizer#decompose(String,boolean)",
317       "method:android.icu.text.Normalizer#decompose(String,boolean,int)",
318       "method:android.icu.text.Normalizer#decompose(char[],char[],boolean,int)",
319       "method:android.icu.text.Normalizer#decompose(char[],int,int,char[],int,int,boolean,int)",
320       "method:android.icu.text.Normalizer#endIndex()",
321       "method:android.icu.text.Normalizer#first()",
322       "method:android.icu.text.Normalizer#getBeginIndex()",
323       "method:android.icu.text.Normalizer#getEndIndex()",
324       "method:android.icu.text.Normalizer#getFC_NFKC_Closure(int)",
325       "method:android.icu.text.Normalizer#getFC_NFKC_Closure(int,char[])",
326       "method:android.icu.text.Normalizer#getIndex()",
327       "method:android.icu.text.Normalizer#getLength()",
328       "method:android.icu.text.Normalizer#getMode()",
329       "method:android.icu.text.Normalizer#getOption(int)",
330       "method:android.icu.text.Normalizer#getText()",
331       "method:android.icu.text.Normalizer#getText(char[])",
332       "method:android.icu.text.Normalizer#isNormalized(String,Mode,int)",
333       "method:android.icu.text.Normalizer#isNormalized(char[],int,int,Mode,int)",
334       "method:android.icu.text.Normalizer#isNormalized(int,Mode,int)",
335       "method:android.icu.text.Normalizer#last()",
336       "method:android.icu.text.Normalizer#next()",
337       "method:android.icu.text.Normalizer#normalize(String,Mode)",
338       "method:android.icu.text.Normalizer#normalize(String,Mode,int)",
339       "method:android.icu.text.Normalizer#normalize(char[],char[],Mode,int)",
340       "method:android.icu.text.Normalizer#normalize(char[],int,int,char[],int,int,Mode,int)",
341       "method:android.icu.text.Normalizer#normalize(int,Mode)",
342       "method:android.icu.text.Normalizer#normalize(int,Mode,int)",
343       "method:android.icu.text.Normalizer#previous()",
344       "method:android.icu.text.Normalizer#quickCheck(String,Mode)",
345       "method:android.icu.text.Normalizer#quickCheck(String,Mode,int)",
346       "method:android.icu.text.Normalizer#quickCheck(char[],Mode,int)",
347       "method:android.icu.text.Normalizer#quickCheck(char[],int,int,Mode,int)",
348       "method:android.icu.text.Normalizer#reset()",
349       "method:android.icu.text.Normalizer#setIndex(int)",
350       "method:android.icu.text.Normalizer#setIndexOnly(int)",
351       "method:android.icu.text.Normalizer#setMode(Mode)",
352       "method:android.icu.text.Normalizer#setOption(int,boolean)",
353       "method:android.icu.text.Normalizer#setText(CharacterIterator)",
354       "method:android.icu.text.Normalizer#setText(String)",
355       "method:android.icu.text.Normalizer#setText(StringBuffer)",
356       "method:android.icu.text.Normalizer#setText(UCharacterIterator)",
357       "method:android.icu.text.Normalizer#setText(char[])",
358       "method:android.icu.text.Normalizer#startIndex()",
359       "method:android.icu.text.Normalizer$Mode#Mode()",
360       "method:android.icu.text.Normalizer$Mode#getNormalizer2(int)",
361       "method:android.icu.text.Normalizer2#Normalizer2()",
362       "method:android.icu.text.NumberFormat#getEffectiveCurrency()",
363       "method:android.icu.text.NumberFormat#getPattern(Locale,int)",
364       "method:android.icu.text.PluralFormat#setLocale(ULocale)",
365       "method:android.icu.text.PluralRules#addSample(String,Number,int,Set<Double>)",
366       "method:android.icu.text.PluralRules#compareTo(PluralRules)",
367       "method:android.icu.text.PluralRules#computeLimited(String,SampleType)",
368       "method:android.icu.text.PluralRules#getAllKeywordValues(String,SampleType)",
369       "method:android.icu.text.PluralRules#getDecimalSamples(String,SampleType)",
370       "method:android.icu.text.PluralRules#getKeywordStatus(String,int,Set<Double>,Output<Double>,SampleType)",
371       "method:android.icu.text.PluralRules#getRules(String)",
372       "method:android.icu.text.PluralRules#getSamples(String,SampleType)",
373       "method:android.icu.text.PluralRules#hashCode()",
374       "method:android.icu.text.PluralRules#isLimited(String)",
375       "method:android.icu.text.PluralRules#isLimited(String,SampleType)",
376       "method:android.icu.text.PluralRules#matches(FixedDecimal,String)",
377       "method:android.icu.text.PluralRules#select(FixedDecimal)",
378       "method:android.icu.text.PluralRules#select(double,int,long)",
379       "method:android.icu.text.PluralRules$Factory#Factory()",
380       "method:android.icu.text.PluralRules$Factory#forLocale(ULocale)",
381       "method:android.icu.text.PluralRules$Factory#forLocale(ULocale,PluralType)",
382       "method:android.icu.text.PluralRules$Factory#getAvailableULocales()",
383       "method:android.icu.text.PluralRules$Factory#getDefaultFactory()",
384       "method:android.icu.text.PluralRules$Factory#getFunctionalEquivalent(ULocale,boolean[])",
385       "method:android.icu.text.PluralRules$Factory#hasOverride(ULocale)",
386       "method:android.icu.text.PluralRules$FixedDecimal#FixedDecimal(String)",
387       "method:android.icu.text.PluralRules$FixedDecimal#FixedDecimal(double)",
388       "method:android.icu.text.PluralRules$FixedDecimal#FixedDecimal(double,int)",
389       "method:android.icu.text.PluralRules$FixedDecimal#FixedDecimal(double,int,long)",
390       "method:android.icu.text.PluralRules$FixedDecimal#FixedDecimal(long)",
391       "method:android.icu.text.PluralRules$FixedDecimal#compareTo(FixedDecimal)",
392       "method:android.icu.text.PluralRules$FixedDecimal#decimals(double)",
393       "method:android.icu.text.PluralRules$FixedDecimal#doubleValue()",
394       "method:android.icu.text.PluralRules$FixedDecimal#equals(Object)",
395       "method:android.icu.text.PluralRules$FixedDecimal#floatValue()",
396       "method:android.icu.text.PluralRules$FixedDecimal#get(Operand)",
397       "method:android.icu.text.PluralRules$FixedDecimal#getBaseFactor()",
398       "method:android.icu.text.PluralRules$FixedDecimal#getDecimalDigits()",
399       "method:android.icu.text.PluralRules$FixedDecimal#getDecimalDigitsWithoutTrailingZeros()",
400       "method:android.icu.text.PluralRules$FixedDecimal#getIntegerValue()",
401       "method:android.icu.text.PluralRules$FixedDecimal#getOperand(String)",
402       "method:android.icu.text.PluralRules$FixedDecimal#getShiftedValue()",
403       "method:android.icu.text.PluralRules$FixedDecimal#getSource()",
404       "method:android.icu.text.PluralRules$FixedDecimal#getVisibleDecimalDigitCount()",
405       "method:android.icu.text.PluralRules$FixedDecimal#getVisibleDecimalDigitCountWithoutTrailingZeros()",
406       "method:android.icu.text.PluralRules$FixedDecimal#hasIntegerValue()",
407       "method:android.icu.text.PluralRules$FixedDecimal#hashCode()",
408       "method:android.icu.text.PluralRules$FixedDecimal#intValue()",
409       "method:android.icu.text.PluralRules$FixedDecimal#isHasIntegerValue()",
410       "method:android.icu.text.PluralRules$FixedDecimal#isNegative()",
411       "method:android.icu.text.PluralRules$FixedDecimal#longValue()",
412       "method:android.icu.text.PluralRules$FixedDecimal#toString()",
413       "method:android.icu.text.PluralRules$FixedDecimalRange#FixedDecimalRange(FixedDecimal,FixedDecimal)",
414       "method:android.icu.text.PluralRules$FixedDecimalRange#toString()",
415       "method:android.icu.text.PluralRules$FixedDecimalSamples#addSamples(Set<Double>)",
416       "method:android.icu.text.PluralRules$FixedDecimalSamples#getSamples()",
417       "method:android.icu.text.PluralRules$FixedDecimalSamples#getStartEndSamples(Set<FixedDecimal>)",
418       "method:android.icu.text.PluralRules$FixedDecimalSamples#toString()",
419       "method:android.icu.text.RuleBasedCollator#doCompare(CharSequence,CharSequence)",
420       "method:android.icu.text.RuleBasedCollator#internalGetCEs(CharSequence)",
421       "method:android.icu.text.RuleBasedCollator#isHiraganaQuaternary()",
422       "method:android.icu.text.RuleBasedCollator#setHiraganaQuaternary(boolean)",
423       "method:android.icu.text.RuleBasedCollator#setHiraganaQuaternaryDefault()",
424       "method:android.icu.text.RuleBasedCollator#setVariableTop(String)",
425       "method:android.icu.text.RuleBasedCollator#setVariableTop(int)",
426       "method:android.icu.text.SearchIterator#setMatchNotFound()",
427       "method:android.icu.text.SimpleDateFormat#SimpleDateFormat(String,DateFormatSymbols,ULocale)",
428       "method:android.icu.text.SimpleDateFormat#getInstance(Calendar.FormatConfiguration)",
429       "method:android.icu.text.SimpleDateFormat#intervalFormatByAlgorithm(Calendar,Calendar,StringBuffer,FieldPosition)",
430       "method:android.icu.text.SimpleDateFormat#subFormat(StringBuffer,char,int,int,int,DisplayContext,FieldPosition,Calendar)",
431       "method:android.icu.text.SimpleDateFormat#subFormat(char,int,int,int,DisplayContext,FieldPosition,Calendar)",
432       "method:android.icu.text.SimpleDateFormat#zeroPaddingNumber(NumberFormat,StringBuffer,int,int,int)",
433       "method:android.icu.text.StringPrepParseException#hashCode()",
434       "method:android.icu.text.StringSearch#setMatchNotFound()",
435       "method:android.icu.text.TimeZoneNames#getDisplayNames(String,NameType[],long,String[],int)",
436       "method:android.icu.text.TimeZoneNames#loadAllDisplayNames()",
437       "method:android.icu.text.TimeZoneNames$Factory#Factory()",
438       "method:android.icu.text.TimeZoneNames$Factory#getTimeZoneNames(ULocale)",
439       "method:android.icu.text.UnicodeFilter#UnicodeFilter()",
440       "method:android.icu.text.UnicodeSet#addBridges(UnicodeSet)",
441       "method:android.icu.text.UnicodeSet#applyPattern(String,ParsePosition,SymbolTable,int)",
442       "method:android.icu.text.UnicodeSet#compare(Iterator<T>,Iterator<T>)",
443       "method:android.icu.text.UnicodeSet#findIn(CharSequence,int,boolean)",
444       "method:android.icu.text.UnicodeSet#findLastIn(CharSequence,int,boolean)",
445       "method:android.icu.text.UnicodeSet#getDefaultXSymbolTable()",
446       "method:android.icu.text.UnicodeSet#getRegexEquivalent()",
447       "method:android.icu.text.UnicodeSet#getSingleCodePoint(CharSequence)",
448       "method:android.icu.text.UnicodeSet#matchesAt(CharSequence,int)",
449       "method:android.icu.text.UnicodeSet#setDefaultXSymbolTable(XSymbolTable)",
450       "method:android.icu.text.UnicodeSet#spanAndCount(CharSequence,int,SpanCondition,OutputInt)",
451       "method:android.icu.text.UnicodeSet#stripFrom(CharSequence,boolean)",
452       "method:android.icu.text.UnicodeSetIterator#getSet()",
453       "method:android.icu.text.UnicodeSetIterator#loadRange(int)",
454       "method:android.icu.util.Calendar#getDateTimePattern(Calendar,ULocale,int)",
455       "method:android.icu.util.Calendar#getDayOfWeekType(int)",
456       "method:android.icu.util.Calendar#getRelatedYear()",
457       "method:android.icu.util.Calendar#getWeekendTransition(int)",
458       "method:android.icu.util.Calendar#haveDefaultCentury()",
459       "method:android.icu.util.Calendar#setRelatedYear(int)",
460       "method:android.icu.util.Calendar$FormatConfiguration#getCalendar()",
461       "method:android.icu.util.Calendar$FormatConfiguration#getDateFormatSymbols()",
462       "method:android.icu.util.Calendar$FormatConfiguration#getLocale()",
463       "method:android.icu.util.Calendar$FormatConfiguration#getOverrideString()",
464       "method:android.icu.util.Calendar$FormatConfiguration#getPatternString()",
465       "method:android.icu.util.ChineseCalendar#ChineseCalendar(TimeZone,ULocale,int,TimeZone)",
466       "method:android.icu.util.ChineseCalendar#haveDefaultCentury()",
467       "method:android.icu.util.CopticCalendar#getJDEpochOffset()",
468       "method:android.icu.util.CopticCalendar#handleComputeFields(int)",
469       "method:android.icu.util.CopticCalendar#handleGetExtendedYear()",
470       "method:android.icu.util.Currency#parse(ULocale,String,int,ParsePosition)",
471       "method:android.icu.util.HebrewCalendar#isLeapYear(int)",
472       "method:android.icu.util.HebrewCalendar#validateField(int)",
473       "method:android.icu.util.JapaneseCalendar#haveDefaultCentury()",
474       "method:android.icu.util.MeasureUnit#MeasureUnit(String,String)",
475       "method:android.icu.util.MeasureUnit#addUnit(String,String,Factory)",
476       "method:android.icu.util.MeasureUnit#internalGetInstance(String,String)",
477       "method:android.icu.util.MeasureUnit#resolveUnitPerUnit(MeasureUnit,MeasureUnit)",
478       "method:android.icu.util.MeasureUnit$Factory#create(String,String)",
479       "method:android.icu.util.TimeZone#TimeZone(String)",
480       "method:android.icu.util.ULocale#getDisplayScriptInContext()",
481       "method:android.icu.util.ULocale#getDisplayScriptInContext(String,String)",
482       "method:android.icu.util.ULocale#getDisplayScriptInContext(String,ULocale)",
483       "method:android.icu.util.ULocale#getDisplayScriptInContext(ULocale)",
484       "method:android.icu.util.ULocale#minimizeSubtags(ULocale,Minimize)",
485       "method:android.icu.util.VersionInfo#getVersionString(int,int)",
486       "method:android.icu.util.VersionInfo#javaVersion()",
487       "type:android.icu.text.DateTimePatternGenerator$FormatParser",
488       "type:android.icu.text.DateTimePatternGenerator$VariableField",
489       "type:android.icu.text.Normalizer$Mode",
490       "type:android.icu.text.PluralRules$Factory",
491       "type:android.icu.text.PluralRules$FixedDecimal",
492       "type:android.icu.text.PluralRules$FixedDecimalRange",
493       "type:android.icu.text.PluralRules$FixedDecimalSamples",
494       "type:android.icu.text.PluralRules$SampleType",
495       "type:android.icu.text.PluralRules$StandardPluralCategories",
496       "type:android.icu.text.TimeZoneNames$Factory",
497       "type:android.icu.util.Calendar$FormatConfiguration",
498       "type:android.icu.util.MeasureUnit$Factory",
499       "type:android.icu.util.ULocale$Minimize",
500   };
501 
502   /** A set of declarations we don't want to expose in Android. */
503   private static final String[] DECLARATIONS_TO_HIDE = {
504       /* ASCII order please. */
505       "field:android.icu.lang.UCharacter$BidiPairedBracketType#COUNT",
506       "field:android.icu.lang.UCharacter$DecompositionType#COUNT",
507       "field:android.icu.lang.UCharacter$EastAsianWidth#COUNT",
508       "field:android.icu.lang.UCharacter$GraphemeClusterBreak#COUNT",
509       "field:android.icu.lang.UCharacter$HangulSyllableType#COUNT",
510       "field:android.icu.lang.UCharacter$JoiningGroup#COUNT",
511       "field:android.icu.lang.UCharacter$JoiningType#COUNT",
512       "field:android.icu.lang.UCharacter$LineBreak#COUNT",
513       "field:android.icu.lang.UCharacter$NumericType#COUNT",
514       "field:android.icu.lang.UCharacter$SentenceBreak#COUNT",
515       "field:android.icu.lang.UCharacter$UnicodeBlock#COUNT",
516       "field:android.icu.lang.UCharacter$WordBreak#COUNT",
517       "field:android.icu.lang.UCharacterEnums$ECharacterCategory#CHAR_CATEGORY_COUNT",
518       "field:android.icu.lang.UCharacterEnums$ECharacterDirection#CHAR_DIRECTION_COUNT",
519       "field:android.icu.lang.UProperty#BINARY_LIMIT",
520       "field:android.icu.lang.UProperty#DOUBLE_LIMIT",
521       "field:android.icu.lang.UProperty#INT_LIMIT",
522       "field:android.icu.lang.UProperty#MASK_LIMIT",
523       "field:android.icu.lang.UProperty#OTHER_PROPERTY_LIMIT",
524       "field:android.icu.lang.UProperty#STRING_LIMIT",
525       "field:android.icu.lang.UProperty$NameChoice#COUNT",
526       "field:android.icu.lang.UScript#CODE_LIMIT",
527       "field:android.icu.text.CollationKey$BoundMode#COUNT",
528       "field:android.icu.text.Collator$ReorderCodes#LIMIT",
529       "field:android.icu.text.DateFormat#FIELD_COUNT",
530       "field:android.icu.text.DateTimePatternGenerator#TYPE_LIMIT",
531       "field:android.icu.util.TimeZone#TIMEZONE_ICU",
532       "field:android.icu.util.TimeZone#TIMEZONE_JDK",
533       "method:android.icu.text.BreakIterator#registerInstance(BreakIterator,Locale,int)",
534       "method:android.icu.text.BreakIterator#registerInstance(BreakIterator,ULocale,int)",
535       "method:android.icu.text.BreakIterator#unregister(Object)",
536       "method:android.icu.text.CollationKey#CollationKey(String,RawCollationKey)",
537       "method:android.icu.text.Collator#getRawCollationKey(String,RawCollationKey)",
538       "method:android.icu.text.Collator#registerFactory(CollatorFactory)",
539       "method:android.icu.text.Collator#registerInstance(Collator,ULocale)",
540       "method:android.icu.text.Collator#unregister(Object)",
541       "method:android.icu.text.NumberFormat#registerFactory(NumberFormatFactory)",
542       "method:android.icu.text.NumberFormat#unregister(Object)",
543       "method:android.icu.text.RuleBasedCollator#getRawCollationKey(String,RawCollationKey)",
544       "method:android.icu.text.UnicodeSet#addAllTo(Iterable<T>,T[])",
545       "method:android.icu.text.UnicodeSet#addAllTo(Iterable<T>,U)",
546       "method:android.icu.text.UnicodeSet#addAllTo(String[])",
547       "method:android.icu.text.UnicodeSet#compare(int,CharSequence)",
548       "method:android.icu.text.UnicodeSet#compare(CharSequence,int)",
549       "method:android.icu.text.UnicodeSet#compare(Collection<T>,Collection<T>,ComparisonStyle)",
550       "method:android.icu.text.UnicodeSet#compare(Iterable<T>,Iterable<T>)",
551       "method:android.icu.text.UnicodeSet#resemblesPattern(String,int)",
552       "method:android.icu.text.UnicodeSet#toArray(UnicodeSet)",
553       "method:android.icu.util.CECalendar#ceToJD(long,int,int,int)",
554       "method:android.icu.util.CECalendar#getJDEpochOffset()",
555       "method:android.icu.util.CECalendar#jdToCE(int,int,int[])",
556       "method:android.icu.util.Currency#registerInstance(Currency,ULocale)",
557       "method:android.icu.util.Currency#unregister(Object)",
558       "method:android.icu.util.IslamicCalendar#isCivil()",
559       "method:android.icu.util.IslamicCalendar#setCivil(boolean)",
560       "method:android.icu.util.TimeZone#clearCachedDefault()",
561       "method:android.icu.util.TimeZone#getDefaultTimeZoneType()",
562       "method:android.icu.util.TimeZone#setDefault(TimeZone)",
563       "method:android.icu.util.TimeZone#setDefaultTimeZoneType(int)",
564       "method:android.icu.util.ULocale#setDefault(Category,ULocale)",
565       "method:android.icu.util.ULocale#setDefault(ULocale)",
566       "method:android.icu.util.VersionInfo#main(String[])",
567       "type:android.icu.text.Collator$CollatorFactory",
568       "type:android.icu.text.NumberFormat$NumberFormatFactory",
569       "type:android.icu.text.NumberFormat$SimpleNumberFormatFactory",
570   };
571 
572   // The declarations with JavaDocs that have @.jcite tags that should be transformed to doclava
573   // @sample tags. Ones not on this list will just be escaped and could show up in the generated
574   // docs. It is assumed that the complete set of ones that should appear in the public API are
575   // listed below and it's ok to escape those that are not.
576   private static final String[] JCITE_TRANSFORM_SET = {
577       "method:android.icu.text.DateIntervalFormat#getInstance(String,Locale)",
578       "method:android.icu.text.DateIntervalFormat#getInstance(String,Locale,DateIntervalInfo)",
579       "method:android.icu.text.DateTimePatternGenerator#addPattern(String,boolean,PatternInfo)",
580       "method:android.icu.text.DateTimePatternGenerator#getBestPattern(String)",
581       "method:android.icu.text.DateTimePatternGenerator#replaceFieldTypes(String,String)",
582       "method:android.icu.text.PluralFormat#PluralFormat(ULocale,String)",
583   };
584 
585   public static final String ANDROID_ICU4J_SAMPLE_DIR =
586       "external/icu/android_icu4j/src/samples/java";
587 
588   private static final boolean DEBUG = false;
589 
590   static final String ORIGINAL_ICU_PACKAGE = "com.ibm.icu";
591   static final String ANDROID_ICU_PACKAGE = "android.icu";
592 
Icu4jTransform()593   private Icu4jTransform() {
594   }
595 
596   /**
597    * Usage:
598    * java com.android.icu4j.srcgen.Icu4JTransform {source files/directories} {target dir}
599    */
main(String[] args)600   public static void main(String[] args) throws Exception {
601     new Main(DEBUG).execute(new Icu4jRules(args));
602   }
603 
604   static class Icu4jRules implements Rules {
605 
606     private static final String SOURCE_CODE_HEADER = "/* GENERATED SOURCE. DO NOT MODIFY. */\n";
607 
608     private static final String REPLACEMENT_JAVADOC_RESOURCE = "replacements.txt";
609 
610     private final InputFileGenerator inputFileGenerator;
611     private final List<Rule> rules;
612     private final BasicOutputSourceFileGenerator outputSourceFileGenerator;
613 
Icu4jRules(String[] args)614     public Icu4jRules(String[] args) throws IOException {
615       if (args.length < 2) {
616         throw new IllegalArgumentException("At least 2 arguments required.");
617       }
618 
619       String[] inputDirNames = new String[args.length - 1];
620       System.arraycopy(args, 0, inputDirNames, 0, args.length - 1);
621       inputFileGenerator = Icu4jTransformRules.createInputFileGenerator(inputDirNames);
622       rules = createTransformRules();
623       outputSourceFileGenerator =
624           Icu4jTransformRules.createOutputFileGenerator(args[args.length - 1]);
625     }
626 
627     @Override
getRuleList(File ignored)628     public List<Rule> getRuleList(File ignored) {
629       return rules;
630     }
631 
632     @Override
getInputFileGenerator()633     public InputFileGenerator getInputFileGenerator() {
634       return inputFileGenerator;
635     }
636 
637     @Override
getOutputSourceFileGenerator()638     public OutputSourceFileGenerator getOutputSourceFileGenerator() {
639       return outputSourceFileGenerator;
640     }
641 
642     // Rules for migrating com.ibm.icu source over to android.icu. Pulled out separately so they
643     // can be used for modifying ICU4J sample code as well.
getRepackagingRules()644     static Rule[] getRepackagingRules() {
645       return new Rule[] {
646           // Doc change: Insert a warning about the source code being generated.
647           createMandatoryRule(new InsertHeader(SOURCE_CODE_HEADER)),
648           // AST change: Change the package of each CompilationUnit from com.ibm.icu to android.icu.
649           createMandatoryRule(new RenamePackage(ORIGINAL_ICU_PACKAGE, ANDROID_ICU_PACKAGE)),
650           // AST change: Change all qualified names in code and javadoc.
651           createOptionalRule(new ModifyQualifiedNames(ORIGINAL_ICU_PACKAGE, ANDROID_ICU_PACKAGE)),
652           // AST change: Change all string literals containing package names in code.
653           createOptionalRule(new ModifyStringLiterals(ORIGINAL_ICU_PACKAGE, ANDROID_ICU_PACKAGE)),
654           // AST change: Change all string literals containing paths in code.
655           createOptionalRule(new ModifyStringLiterals("com/ibm/icu", "android/icu")),
656       };
657     }
658 
createTransformRules()659     private static List<Rule> createTransformRules() throws IOException {
660       // The rules needed to repackage source code that declares or references com.ibm.icu code
661       // so it references android.icu instead.
662       Rule[] repackageRules = getRepackagingRules();
663 
664       // The rules needed to fix up Android's documentation rules.
665       Rule[] apiDocsRules = new Rule[] {
666           // Below are the fixes that ensure the Android API documentation generation can be run
667           // over the source.
668 
669           // Doc change: Replace selected javadoc comments with Android-specific replacements.
670           createReplaceSelectedJavadocRule(),
671 
672           // Doc change: Switch all documentation references from com.ibm.icu to android.icu.
673           // e.g. importantly in <code> blocks and unimportantly in non-Javadoc comments.
674           // This must come after createReplaceSelectedJavadocRule().
675           createOptionalRule(
676               new ReplaceTextCommentScanner(ORIGINAL_ICU_PACKAGE, ANDROID_ICU_PACKAGE)),
677 
678           // AST change: Hide all ICU public classes except those in the whitelist.
679           createHidePublicClassesRule(),
680           // AST change: Hide ICU methods that are deprecated and Android does not want to make
681           // public.
682           createHideOriginalDeprecatedClassesRule(),
683           // AST change: Explicitly hide blacklisted methods such as those that get/set static
684           // default values that might lead to confusion or strange interactions between Android's
685           // ICU4J and java.text / java.util classes.
686           createHideBlacklistedDeclarationsRule(),
687           // AST change: Explicitly hide any elements that are marked as
688           // @draft / @provisional / @internal
689           createOptionalRule(new HideDraftProvisionalInternal()),
690 
691           // Doc change: Hack around javadoc @stable / @author placement error upstream: this should
692           // be fixed upstream.
693           createFixupBidiClassDocRule(),
694           // AST change: Remove JavaDoc tags that Android has no need of:
695           // @hide has been added in place of @draft, @provisional and @internal
696           // @stable <ICU version> will not mean much on Android.
697           createOptionalRule(new RemoveJavaDocTags(
698               "@stable", "@draft", "@provisional", "@internal", "@since")),
699           // AST change: Replace @icu and @icuenhanced with standard text.
700           createOptionalRule(new ReplaceIcuTags()),
701 
702           // AST change: Translate some of the @.jcite tags used by ICU into @sample tags used by
703           // doclava. Those that are not translated are escaped.
704           createTranslateJciteInclusionRule(),
705       };
706 
707       List<Rule> rulesList = Lists.newArrayList(repackageRules);
708       rulesList.addAll(Arrays.asList(apiDocsRules));
709       return rulesList;
710     }
711 
createReplaceSelectedJavadocRule()712     private static Rule createReplaceSelectedJavadocRule() throws IOException {
713       return createOptionalRule(
714           ReplaceSelectedJavadoc.createFromResource(REPLACEMENT_JAVADOC_RESOURCE));
715     }
716 
createTranslateJciteInclusionRule()717     private static Rule createTranslateJciteInclusionRule() {
718       List<BodyDeclarationLocator> whitelist =
719           BodyDeclarationLocators.createLocatorsFromStrings(JCITE_TRANSFORM_SET);
720       TranslateJcite.InclusionHandler transformer =
721           new TranslateJcite.InclusionHandler(ANDROID_ICU4J_SAMPLE_DIR, whitelist);
722       return createOptionalRule(transformer);
723     }
724 
createHideOriginalDeprecatedClassesRule()725     private static Rule createHideOriginalDeprecatedClassesRule() {
726       List<BodyDeclarationLocator> blacklist =
727           BodyDeclarationLocators.createLocatorsFromStrings(INITIAL_DEPRECATED_SET);
728       return createOptionalRule(
729           new TagMatchingDeclarations(blacklist, "@hide original deprecated declaration"));
730     }
731 
createHideBlacklistedDeclarationsRule()732     private static Rule createHideBlacklistedDeclarationsRule() {
733       List<BodyDeclarationLocator> blacklist =
734           BodyDeclarationLocators.createLocatorsFromStrings(DECLARATIONS_TO_HIDE);
735       return createOptionalRule(
736           new TagMatchingDeclarations(blacklist, "@hide unsupported on Android"));
737     }
738 
createHidePublicClassesRule()739     private static Rule createHidePublicClassesRule() {
740       ImmutableList.Builder<TypeLocator> apiClassesWhitelistBuilder = ImmutableList.builder();
741       for (String publicClassName : PUBLIC_API_CLASSES) {
742         apiClassesWhitelistBuilder.add(new TypeLocator(publicClassName));
743       }
744       return createOptionalRule(
745           new HidePublicClasses(
746               apiClassesWhitelistBuilder.build(),
747               "Only a subset of ICU is exposed in Android"));
748     }
749 
createFixupBidiClassDocRule()750     private static Rule createFixupBidiClassDocRule() {
751       FixupBidiClassDoc transformer = new FixupBidiClassDoc();
752       return new DefaultRule(transformer, transformer.matcher(), true /* mustModify */);
753     }
754   }
755 }
756