From 0dbcb4cdfc356e0ecffe2aba5ac458bfc152b55b Mon Sep 17 00:00:00 2001 From: Michael Ow Date: Wed, 2 Jul 2014 23:05:28 +0000 Subject: [PATCH] ICU-10993 Fix line ending errors X-SVN-Rev: 35990 --- .gitattributes | 3 - .../dev/tool/docs/DeprecatedAPIChecker.java | 1000 ++++++++--------- 2 files changed, 500 insertions(+), 503 deletions(-) diff --git a/.gitattributes b/.gitattributes index 91edd7a55b9..55a1b1ce375 100644 --- a/.gitattributes +++ b/.gitattributes @@ -261,7 +261,6 @@ icu4j/main/classes/core/.settings/edu.umd.cs.findbugs.core.prefs -text icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text icu4j/main/classes/core/manifest.stub -text -icu4j/main/classes/core/src/com/ibm/icu/text/ScientificFormatHelper.java -text icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text icu4j/main/classes/currdata/.settings/org.eclipse.core.resources.prefs -text icu4j/main/classes/currdata/.settings/org.eclipse.jdt.core.prefs -text @@ -322,7 +321,6 @@ icu4j/main/tests/core/manifest.stub -text icu4j/main/tests/core/src/com/ibm/icu/dev/data/rbbi/english.dict -text icu4j/main/tests/core/src/com/ibm/icu/dev/data/resources/testmessages.properties -text icu4j/main/tests/core/src/com/ibm/icu/dev/data/thai6.ucs -text -icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/ScientificFormatHelperTest.java -text icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.OlsonTimeZone.dat -text icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.impl.TimeZoneAdapter.dat -text icu4j/main/tests/core/src/com/ibm/icu/dev/test/serializable/data/ICU_3.6/com.ibm.icu.math.BigDecimal.dat -text @@ -617,7 +615,6 @@ icu4j/tools/build/icu4j51.api3.gz -text icu4j/tools/build/icu4j52.api3.gz -text icu4j/tools/build/icu4j53.api3.gz -text icu4j/tools/build/manifest.stub -text -icu4j/tools/build/src/com/ibm/icu/dev/tool/docs/DeprecatedAPIChecker.java -text icu4j/tools/misc/.settings/org.eclipse.core.resources.prefs -text icu4j/tools/misc/manifest.stub -text tools/currency/.classpath -text diff --git a/icu4j/tools/build/src/com/ibm/icu/dev/tool/docs/DeprecatedAPIChecker.java b/icu4j/tools/build/src/com/ibm/icu/dev/tool/docs/DeprecatedAPIChecker.java index ea8d07d54d0..50ba0aca917 100644 --- a/icu4j/tools/build/src/com/ibm/icu/dev/tool/docs/DeprecatedAPIChecker.java +++ b/icu4j/tools/build/src/com/ibm/icu/dev/tool/docs/DeprecatedAPIChecker.java @@ -1,500 +1,500 @@ -/* - ******************************************************************************* - * Copyright (C) 2014, International Business Machines Corporation and * - * others. All Rights Reserved. * - ******************************************************************************* - */ -package com.ibm.icu.dev.tool.docs; - -import java.io.File; -import java.io.PrintWriter; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.GenericArrayType; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.lang.reflect.WildcardType; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.TreeMap; - -public class DeprecatedAPIChecker { - - public static void main(String[] args) { - if (args.length != 1) { - System.err.println("Illegal command argument. Specify the API signature file path."); - } - // Load the ICU4J API signature file - Set apiInfoSet = APIData.read(new File(args[0]), true).getAPIInfoSet(); - - DeprecatedAPIChecker checker = new DeprecatedAPIChecker(apiInfoSet, new PrintWriter(System.err, true)); - checker.checkDeprecated(); - System.exit(checker.errCount); - } - - private int errCount = 0; - private Set apiInfoSet; - private PrintWriter pw; - - public DeprecatedAPIChecker(Set apiInfoSet, PrintWriter pw) { - this.apiInfoSet = apiInfoSet; - this.pw = pw; - } - - public int errorCount() { - return errCount; - } - - public void checkDeprecated() { - // Gather API class/enum names and its names that can be - // used for Class.forName() - Map apiClassNameMap = new TreeMap(); - for (APIInfo api : apiInfoSet) { - if (!api.isPublic() && !api.isProtected()) { - continue; - } - if (!api.isClass() && !api.isEnum()) { - continue; - } - String packageName = api.getPackageName(); - String className = api.getName(); - - // Replacing separator for nested class/enum (replacing '.' with - // '$'), so we can use the name for Class.forName(String) - String classNamePath = className.contains(".") ? className.replace('.', '$') : className; - - apiClassNameMap.put(packageName + "." + classNamePath, packageName + "." + className); - } - - // Walk through API classes using reflection - for (Entry classEntry : apiClassNameMap.entrySet()) { - String classNamePath = classEntry.getKey(); - try { - Class cls = Class.forName(classNamePath); - if (cls.isEnum()) { - checkEnum(cls, apiClassNameMap); - } else { - checkClass(cls, apiClassNameMap); - } - } catch (ClassNotFoundException e) { - pw.println("## Error ## Class " + classNamePath + " is not found."); - errCount++; - } - } - } - - private void checkClass(Class cls, Map clsNameMap) { - assert !cls.isEnum(); - - String clsPath = cls.getName(); - String clsName = clsNameMap.get(clsPath); - APIInfo api = null; - - if (clsName != null) { - api = findClassInfo(apiInfoSet, clsName); - } - if (api == null) { - pw.println("## Error ## Class " + clsName + " is not found in the API signature data."); - errCount++; - } - - // check class - compareDeprecated(isAPIDeprecated(api), cls.isAnnotationPresent(Deprecated.class), clsName, null, "Class"); - - // check fields - for (Field f : cls.getDeclaredFields()) { - if (!isPublicOrProtected(f.getModifiers())) { - continue; - } - - String fName = f.getName(); - api = findFieldInfo(apiInfoSet, clsName, fName); - if (api == null) { - pw.println("## Error ## Field " + clsName + "." + fName + " is not found in the API signature data."); - errCount++; - continue; - } - - compareDeprecated(isAPIDeprecated(api), f.isAnnotationPresent(Deprecated.class), clsName, fName, "Field"); - } - - // check constructors - for (Constructor ctor : cls.getDeclaredConstructors()) { - if (!isPublicOrProtected(ctor.getModifiers())) { - continue; - } - - List paramNames = getParamNames(ctor); - api = findConstructorInfo(apiInfoSet, clsName, paramNames); - - if (api == null) { - pw.println("## Error ## Constructor " + clsName + formatParams(paramNames) - + " is not found in the API signature data."); - errCount++; - continue; - } - - compareDeprecated(isAPIDeprecated(api), ctor.isAnnotationPresent(Deprecated.class), clsName, - api.getClassName() + formatParams(paramNames), "Constructor"); - } - - // check methods - for (Method mtd : cls.getDeclaredMethods()) { - // Note: We exclude synthetic method. - if (!isPublicOrProtected(mtd.getModifiers()) || mtd.isSynthetic()) { - continue; - } - - String mtdName = mtd.getName(); - List paramNames = getParamNames(mtd); - api = findMethodInfo(apiInfoSet, clsName, mtdName, paramNames); - - if (api == null) { - pw.println("## Error ## Method " + clsName + "#" + mtdName + formatParams(paramNames) - + " is not found in the API signature data."); - errCount++; - continue; - } - - compareDeprecated(isAPIDeprecated(api), mtd.isAnnotationPresent(Deprecated.class), clsName, mtdName - + formatParams(paramNames), "Method"); - - } - } - - private void checkEnum(Class cls, Map clsNameMap) { - assert cls.isEnum(); - - String enumPath = cls.getName(); - String enumName = clsNameMap.get(enumPath); - APIInfo api = null; - - if (enumName != null) { - api = findEnumInfo(apiInfoSet, enumName); - } - if (api == null) { - pw.println("## Error ## Enum " + enumName + " is not found in the API signature data."); - errCount++; - } - - // check enum - compareDeprecated(isAPIDeprecated(api), cls.isAnnotationPresent(Deprecated.class), enumName, null, "Enum"); - - // check enum constants - for (Field ec : cls.getDeclaredFields()) { - if (!ec.isEnumConstant()) { - continue; - } - String ecName = ec.getName(); - api = findEnumConstantInfo(apiInfoSet, enumName, ecName); - if (api == null) { - pw.println("## Error ## Enum constant " + enumName + "." + ecName - + " is not found in the API signature data."); - errCount++; - continue; - } - - compareDeprecated(isAPIDeprecated(api), ec.isAnnotationPresent(Deprecated.class), enumName, ecName, - "Enum Constant"); - } - - // check methods - for (Method mtd : cls.getDeclaredMethods()) { - // Note: We exclude built-in methods in a Java Enum instance - if (!isPublicOrProtected(mtd.getModifiers()) || isBuiltinEnumMethod(mtd)) { - continue; - } - - String mtdName = mtd.getName(); - List paramNames = getParamNames(mtd); - api = findMethodInfo(apiInfoSet, enumName, mtdName, paramNames); - - if (api == null) { - pw.println("## Error ## Method " + enumName + "#" + mtdName + formatParams(paramNames) - + " is not found in the API signature data."); - errCount++; - continue; - } - - compareDeprecated(isAPIDeprecated(api), mtd.isAnnotationPresent(Deprecated.class), enumName, mtdName - + formatParams(paramNames), "Method"); - - } - } - - private void compareDeprecated(boolean depTag, boolean depAnt, String cls, String name, String type) { - if (depTag != depAnt) { - String apiName = cls; - if (name != null) { - apiName += "." + name; - } - if (depTag) { - pw.println("No @Deprecated annotation: [" + type + "] " + apiName); - } else { - pw.println("No @deprecated JavaDoc tag: [" + type + "] " + apiName); - } - errCount++; - } - } - - private static boolean isPublicOrProtected(int modifier) { - return ((modifier & Modifier.PUBLIC) != 0) || ((modifier & Modifier.PROTECTED) != 0); - } - - // Check if a method is automatically generated for a each Enum - private static boolean isBuiltinEnumMethod(Method mtd) { - // Just check method name for now - String name = mtd.getName(); - return name.equals("values") || name.equals("valueOf"); - } - - private static boolean isAPIDeprecated(APIInfo api) { - return api.isDeprecated() || api.isInternal() || api.isObsolete(); - } - - private static APIInfo findClassInfo(Set apis, String cls) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getName(); - if (api.isClass() && clsName.equals(cls)) { - return api; - } - } - return null; - } - - private static APIInfo findFieldInfo(Set apis, String cls, String field) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getClassName(); - if (api.isField() && clsName.equals(cls) && api.getName().equals(field)) { - return api; - } - } - return null; - } - - private static APIInfo findConstructorInfo(Set apis, String cls, List params) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getClassName(); - if (api.isConstructor() && clsName.equals(cls)) { - // check params - List paramsFromApi = getParamNames(api); - if (paramsFromApi.size() == params.size()) { - boolean match = true; - for (int i = 0; i < params.size(); i++) { - if (!params.get(i).equals(paramsFromApi.get(i))) { - match = false; - break; - } - } - if (match) { - return api; - } - } - } - } - return null; - } - - private static APIInfo findMethodInfo(Set apis, String cls, String method, List params) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getClassName(); - if (api.isMethod() && clsName.equals(cls) && api.getName().equals(method)) { - // check params - List paramsFromApi = getParamNames(api); - if (paramsFromApi.size() == params.size()) { - boolean match = true; - for (int i = 0; i < params.size(); i++) { - if (!params.get(i).equals(paramsFromApi.get(i))) { - match = false; - break; - } - } - if (match) { - return api; - } - } - } - } - return null; - } - - private static APIInfo findEnumInfo(Set apis, String ecls) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getName(); - if (api.isEnum() && clsName.equals(ecls)) { - return api; - } - } - return null; - } - - private static APIInfo findEnumConstantInfo(Set apis, String ecls, String econst) { - for (APIInfo api : apis) { - String clsName = api.getPackageName() + "." + api.getClassName(); - if (api.isEnumConstant() && clsName.equals(ecls) && api.getName().equals(econst)) { - return api; - } - } - return null; - } - - private static List getParamNames(APIInfo api) { - if (!api.isMethod() && !api.isConstructor()) { - throw new IllegalArgumentException(api.toString() + " is not a constructor or a method."); - } - - List nameList = new ArrayList(); - String signature = api.getSignature(); - int start = signature.indexOf('('); - int end = signature.indexOf(')'); - - if (start < 0 || end < 0 || start > end) { - throw new RuntimeException(api.toString() + " has bad API signature: " + signature); - } - - String paramsSegment = signature.substring(start + 1, end); - // erase generic args - if (paramsSegment.indexOf('<') >= 0) { - StringBuilder buf = new StringBuilder(); - boolean inGenericsParams = false; - for (int i = 0; i < paramsSegment.length(); i++) { - char c = paramsSegment.charAt(i); - if (inGenericsParams) { - if (c == '>') { - inGenericsParams = false; - } - } else { - if (c == '<') { - inGenericsParams = true; - } else { - buf.append(c); - } - } - } - paramsSegment = buf.toString(); - } - - if (paramsSegment.length() > 0) { - String[] params = paramsSegment.split("\\s*,\\s*"); - for (String p : params) { - if (p.endsWith("...")) { - // varargs to array - p = p.substring(0, p.length() - 3) + "[]"; - } - nameList.add(p); - } - } - - return nameList; - } - - private static List getParamNames(Constructor ctor) { - return toTypeNameList(ctor.getGenericParameterTypes()); - } - - private static List getParamNames(Method method) { - return toTypeNameList(method.getGenericParameterTypes()); - } - - private static final String[] PRIMITIVES = { "byte", "short", "int", "long", "float", "double", "boolean", "char" }; - private static char[] PRIMITIVE_SIGNATURES = { 'B', 'S', 'I', 'J', 'F', 'D', 'Z', 'C' }; - - private static List toTypeNameList(Type[] types) { - List nameList = new ArrayList(); - - for (Type t : types) { - StringBuilder s = new StringBuilder(); - if (t instanceof ParameterizedType) { - // throw away generics parameters - ParameterizedType prdType = (ParameterizedType) t; - Class rawType = (Class) prdType.getRawType(); - s.append(rawType.getCanonicalName()); - } else if (t instanceof WildcardType) { - // we don't need to worry about WildcardType, - // because this tool erases generics parameters - // for comparing method/constructor parameters - throw new RuntimeException("WildcardType not supported by this tool"); - } else if (t instanceof TypeVariable) { - // this tool does not try to resolve actual parameter - // type - for example, " void foo(T in)" - // this tool just use the type variable "T" for API signature - // comparison. This is actually not perfect, but should be - // sufficient for our purpose. - TypeVariable tVar = (TypeVariable) t; - s.append(tVar.getName()); - } else if (t instanceof GenericArrayType) { - // same as TypeVariable. "T[]" is sufficient enough. - GenericArrayType tGenArray = (GenericArrayType) t; - s.append(tGenArray.toString()); - } else if (t instanceof Class) { - Class tClass = (Class) t; - String tName = tClass.getCanonicalName(); - - if (tName.charAt(0) == '[') { - // Array type - int idx = 0; - for (; idx < tName.length(); idx++) { - if (tName.charAt(idx) != '[') { - break; - } - } - int dimension = idx; - char sigChar = tName.charAt(dimension); - - String elemType = null; - if (sigChar == 'L') { - // class - elemType = tName.substring(dimension + 1, tName.length() - 1); - } else { - // primitive - for (int i = 0; i < PRIMITIVE_SIGNATURES.length; i++) { - if (sigChar == PRIMITIVE_SIGNATURES[i]) { - elemType = PRIMITIVES[i]; - break; - } - } - } - - if (elemType == null) { - throw new RuntimeException("Unexpected array type: " + tName); - } - - s.append(elemType); - for (int i = 0; i < dimension; i++) { - s.append("[]"); - } - } else { - s.append(tName); - } - } else { - throw new IllegalArgumentException("Unknown type: " + t); - } - - nameList.add(s.toString()); - } - - return nameList; - } - - private static String formatParams(List paramNames) { - StringBuilder buf = new StringBuilder("("); - boolean isFirst = true; - for (String p : paramNames) { - if (isFirst) { - isFirst = false; - } else { - buf.append(", "); - } - buf.append(p); - } - buf.append(")"); - - return buf.toString(); - } -} +/* + ******************************************************************************* + * Copyright (C) 2014, International Business Machines Corporation and * + * others. All Rights Reserved. * + ******************************************************************************* + */ +package com.ibm.icu.dev.tool.docs; + +import java.io.File; +import java.io.PrintWriter; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; + +public class DeprecatedAPIChecker { + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("Illegal command argument. Specify the API signature file path."); + } + // Load the ICU4J API signature file + Set apiInfoSet = APIData.read(new File(args[0]), true).getAPIInfoSet(); + + DeprecatedAPIChecker checker = new DeprecatedAPIChecker(apiInfoSet, new PrintWriter(System.err, true)); + checker.checkDeprecated(); + System.exit(checker.errCount); + } + + private int errCount = 0; + private Set apiInfoSet; + private PrintWriter pw; + + public DeprecatedAPIChecker(Set apiInfoSet, PrintWriter pw) { + this.apiInfoSet = apiInfoSet; + this.pw = pw; + } + + public int errorCount() { + return errCount; + } + + public void checkDeprecated() { + // Gather API class/enum names and its names that can be + // used for Class.forName() + Map apiClassNameMap = new TreeMap(); + for (APIInfo api : apiInfoSet) { + if (!api.isPublic() && !api.isProtected()) { + continue; + } + if (!api.isClass() && !api.isEnum()) { + continue; + } + String packageName = api.getPackageName(); + String className = api.getName(); + + // Replacing separator for nested class/enum (replacing '.' with + // '$'), so we can use the name for Class.forName(String) + String classNamePath = className.contains(".") ? className.replace('.', '$') : className; + + apiClassNameMap.put(packageName + "." + classNamePath, packageName + "." + className); + } + + // Walk through API classes using reflection + for (Entry classEntry : apiClassNameMap.entrySet()) { + String classNamePath = classEntry.getKey(); + try { + Class cls = Class.forName(classNamePath); + if (cls.isEnum()) { + checkEnum(cls, apiClassNameMap); + } else { + checkClass(cls, apiClassNameMap); + } + } catch (ClassNotFoundException e) { + pw.println("## Error ## Class " + classNamePath + " is not found."); + errCount++; + } + } + } + + private void checkClass(Class cls, Map clsNameMap) { + assert !cls.isEnum(); + + String clsPath = cls.getName(); + String clsName = clsNameMap.get(clsPath); + APIInfo api = null; + + if (clsName != null) { + api = findClassInfo(apiInfoSet, clsName); + } + if (api == null) { + pw.println("## Error ## Class " + clsName + " is not found in the API signature data."); + errCount++; + } + + // check class + compareDeprecated(isAPIDeprecated(api), cls.isAnnotationPresent(Deprecated.class), clsName, null, "Class"); + + // check fields + for (Field f : cls.getDeclaredFields()) { + if (!isPublicOrProtected(f.getModifiers())) { + continue; + } + + String fName = f.getName(); + api = findFieldInfo(apiInfoSet, clsName, fName); + if (api == null) { + pw.println("## Error ## Field " + clsName + "." + fName + " is not found in the API signature data."); + errCount++; + continue; + } + + compareDeprecated(isAPIDeprecated(api), f.isAnnotationPresent(Deprecated.class), clsName, fName, "Field"); + } + + // check constructors + for (Constructor ctor : cls.getDeclaredConstructors()) { + if (!isPublicOrProtected(ctor.getModifiers())) { + continue; + } + + List paramNames = getParamNames(ctor); + api = findConstructorInfo(apiInfoSet, clsName, paramNames); + + if (api == null) { + pw.println("## Error ## Constructor " + clsName + formatParams(paramNames) + + " is not found in the API signature data."); + errCount++; + continue; + } + + compareDeprecated(isAPIDeprecated(api), ctor.isAnnotationPresent(Deprecated.class), clsName, + api.getClassName() + formatParams(paramNames), "Constructor"); + } + + // check methods + for (Method mtd : cls.getDeclaredMethods()) { + // Note: We exclude synthetic method. + if (!isPublicOrProtected(mtd.getModifiers()) || mtd.isSynthetic()) { + continue; + } + + String mtdName = mtd.getName(); + List paramNames = getParamNames(mtd); + api = findMethodInfo(apiInfoSet, clsName, mtdName, paramNames); + + if (api == null) { + pw.println("## Error ## Method " + clsName + "#" + mtdName + formatParams(paramNames) + + " is not found in the API signature data."); + errCount++; + continue; + } + + compareDeprecated(isAPIDeprecated(api), mtd.isAnnotationPresent(Deprecated.class), clsName, mtdName + + formatParams(paramNames), "Method"); + + } + } + + private void checkEnum(Class cls, Map clsNameMap) { + assert cls.isEnum(); + + String enumPath = cls.getName(); + String enumName = clsNameMap.get(enumPath); + APIInfo api = null; + + if (enumName != null) { + api = findEnumInfo(apiInfoSet, enumName); + } + if (api == null) { + pw.println("## Error ## Enum " + enumName + " is not found in the API signature data."); + errCount++; + } + + // check enum + compareDeprecated(isAPIDeprecated(api), cls.isAnnotationPresent(Deprecated.class), enumName, null, "Enum"); + + // check enum constants + for (Field ec : cls.getDeclaredFields()) { + if (!ec.isEnumConstant()) { + continue; + } + String ecName = ec.getName(); + api = findEnumConstantInfo(apiInfoSet, enumName, ecName); + if (api == null) { + pw.println("## Error ## Enum constant " + enumName + "." + ecName + + " is not found in the API signature data."); + errCount++; + continue; + } + + compareDeprecated(isAPIDeprecated(api), ec.isAnnotationPresent(Deprecated.class), enumName, ecName, + "Enum Constant"); + } + + // check methods + for (Method mtd : cls.getDeclaredMethods()) { + // Note: We exclude built-in methods in a Java Enum instance + if (!isPublicOrProtected(mtd.getModifiers()) || isBuiltinEnumMethod(mtd)) { + continue; + } + + String mtdName = mtd.getName(); + List paramNames = getParamNames(mtd); + api = findMethodInfo(apiInfoSet, enumName, mtdName, paramNames); + + if (api == null) { + pw.println("## Error ## Method " + enumName + "#" + mtdName + formatParams(paramNames) + + " is not found in the API signature data."); + errCount++; + continue; + } + + compareDeprecated(isAPIDeprecated(api), mtd.isAnnotationPresent(Deprecated.class), enumName, mtdName + + formatParams(paramNames), "Method"); + + } + } + + private void compareDeprecated(boolean depTag, boolean depAnt, String cls, String name, String type) { + if (depTag != depAnt) { + String apiName = cls; + if (name != null) { + apiName += "." + name; + } + if (depTag) { + pw.println("No @Deprecated annotation: [" + type + "] " + apiName); + } else { + pw.println("No @deprecated JavaDoc tag: [" + type + "] " + apiName); + } + errCount++; + } + } + + private static boolean isPublicOrProtected(int modifier) { + return ((modifier & Modifier.PUBLIC) != 0) || ((modifier & Modifier.PROTECTED) != 0); + } + + // Check if a method is automatically generated for a each Enum + private static boolean isBuiltinEnumMethod(Method mtd) { + // Just check method name for now + String name = mtd.getName(); + return name.equals("values") || name.equals("valueOf"); + } + + private static boolean isAPIDeprecated(APIInfo api) { + return api.isDeprecated() || api.isInternal() || api.isObsolete(); + } + + private static APIInfo findClassInfo(Set apis, String cls) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getName(); + if (api.isClass() && clsName.equals(cls)) { + return api; + } + } + return null; + } + + private static APIInfo findFieldInfo(Set apis, String cls, String field) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getClassName(); + if (api.isField() && clsName.equals(cls) && api.getName().equals(field)) { + return api; + } + } + return null; + } + + private static APIInfo findConstructorInfo(Set apis, String cls, List params) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getClassName(); + if (api.isConstructor() && clsName.equals(cls)) { + // check params + List paramsFromApi = getParamNames(api); + if (paramsFromApi.size() == params.size()) { + boolean match = true; + for (int i = 0; i < params.size(); i++) { + if (!params.get(i).equals(paramsFromApi.get(i))) { + match = false; + break; + } + } + if (match) { + return api; + } + } + } + } + return null; + } + + private static APIInfo findMethodInfo(Set apis, String cls, String method, List params) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getClassName(); + if (api.isMethod() && clsName.equals(cls) && api.getName().equals(method)) { + // check params + List paramsFromApi = getParamNames(api); + if (paramsFromApi.size() == params.size()) { + boolean match = true; + for (int i = 0; i < params.size(); i++) { + if (!params.get(i).equals(paramsFromApi.get(i))) { + match = false; + break; + } + } + if (match) { + return api; + } + } + } + } + return null; + } + + private static APIInfo findEnumInfo(Set apis, String ecls) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getName(); + if (api.isEnum() && clsName.equals(ecls)) { + return api; + } + } + return null; + } + + private static APIInfo findEnumConstantInfo(Set apis, String ecls, String econst) { + for (APIInfo api : apis) { + String clsName = api.getPackageName() + "." + api.getClassName(); + if (api.isEnumConstant() && clsName.equals(ecls) && api.getName().equals(econst)) { + return api; + } + } + return null; + } + + private static List getParamNames(APIInfo api) { + if (!api.isMethod() && !api.isConstructor()) { + throw new IllegalArgumentException(api.toString() + " is not a constructor or a method."); + } + + List nameList = new ArrayList(); + String signature = api.getSignature(); + int start = signature.indexOf('('); + int end = signature.indexOf(')'); + + if (start < 0 || end < 0 || start > end) { + throw new RuntimeException(api.toString() + " has bad API signature: " + signature); + } + + String paramsSegment = signature.substring(start + 1, end); + // erase generic args + if (paramsSegment.indexOf('<') >= 0) { + StringBuilder buf = new StringBuilder(); + boolean inGenericsParams = false; + for (int i = 0; i < paramsSegment.length(); i++) { + char c = paramsSegment.charAt(i); + if (inGenericsParams) { + if (c == '>') { + inGenericsParams = false; + } + } else { + if (c == '<') { + inGenericsParams = true; + } else { + buf.append(c); + } + } + } + paramsSegment = buf.toString(); + } + + if (paramsSegment.length() > 0) { + String[] params = paramsSegment.split("\\s*,\\s*"); + for (String p : params) { + if (p.endsWith("...")) { + // varargs to array + p = p.substring(0, p.length() - 3) + "[]"; + } + nameList.add(p); + } + } + + return nameList; + } + + private static List getParamNames(Constructor ctor) { + return toTypeNameList(ctor.getGenericParameterTypes()); + } + + private static List getParamNames(Method method) { + return toTypeNameList(method.getGenericParameterTypes()); + } + + private static final String[] PRIMITIVES = { "byte", "short", "int", "long", "float", "double", "boolean", "char" }; + private static char[] PRIMITIVE_SIGNATURES = { 'B', 'S', 'I', 'J', 'F', 'D', 'Z', 'C' }; + + private static List toTypeNameList(Type[] types) { + List nameList = new ArrayList(); + + for (Type t : types) { + StringBuilder s = new StringBuilder(); + if (t instanceof ParameterizedType) { + // throw away generics parameters + ParameterizedType prdType = (ParameterizedType) t; + Class rawType = (Class) prdType.getRawType(); + s.append(rawType.getCanonicalName()); + } else if (t instanceof WildcardType) { + // we don't need to worry about WildcardType, + // because this tool erases generics parameters + // for comparing method/constructor parameters + throw new RuntimeException("WildcardType not supported by this tool"); + } else if (t instanceof TypeVariable) { + // this tool does not try to resolve actual parameter + // type - for example, " void foo(T in)" + // this tool just use the type variable "T" for API signature + // comparison. This is actually not perfect, but should be + // sufficient for our purpose. + TypeVariable tVar = (TypeVariable) t; + s.append(tVar.getName()); + } else if (t instanceof GenericArrayType) { + // same as TypeVariable. "T[]" is sufficient enough. + GenericArrayType tGenArray = (GenericArrayType) t; + s.append(tGenArray.toString()); + } else if (t instanceof Class) { + Class tClass = (Class) t; + String tName = tClass.getCanonicalName(); + + if (tName.charAt(0) == '[') { + // Array type + int idx = 0; + for (; idx < tName.length(); idx++) { + if (tName.charAt(idx) != '[') { + break; + } + } + int dimension = idx; + char sigChar = tName.charAt(dimension); + + String elemType = null; + if (sigChar == 'L') { + // class + elemType = tName.substring(dimension + 1, tName.length() - 1); + } else { + // primitive + for (int i = 0; i < PRIMITIVE_SIGNATURES.length; i++) { + if (sigChar == PRIMITIVE_SIGNATURES[i]) { + elemType = PRIMITIVES[i]; + break; + } + } + } + + if (elemType == null) { + throw new RuntimeException("Unexpected array type: " + tName); + } + + s.append(elemType); + for (int i = 0; i < dimension; i++) { + s.append("[]"); + } + } else { + s.append(tName); + } + } else { + throw new IllegalArgumentException("Unknown type: " + t); + } + + nameList.add(s.toString()); + } + + return nameList; + } + + private static String formatParams(List paramNames) { + StringBuilder buf = new StringBuilder("("); + boolean isFirst = true; + for (String p : paramNames) { + if (isFirst) { + isFirst = false; + } else { + buf.append(", "); + } + buf.append(p); + } + buf.append(")"); + + return buf.toString(); + } +}