Merge "Removed unused source files. Apicheck and droiddoc are now in external/doclava."
This commit is contained in:
commit
2cce260bba
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2007-2008 The Android Open Source Project
|
||||
# Copyright (C) 2008 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.
|
||||
|
@ -14,31 +14,4 @@
|
|||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# We use copy-file-to-new-target so that the installed
|
||||
# script file's timestamp is at least as new as the
|
||||
# .jar file it wraps.
|
||||
|
||||
#TODO(dbort): add a template to do this stuff; share with jx
|
||||
|
||||
# the hat script
|
||||
# ============================================================
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_IS_HOST_MODULE := true
|
||||
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
LOCAL_MODULE := apicheck
|
||||
|
||||
include $(BUILD_SYSTEM)/base_rules.mk
|
||||
|
||||
$(LOCAL_BUILT_MODULE): $(HOST_OUT_JAVA_LIBRARIES)/doclava$(COMMON_JAVA_PACKAGE_SUFFIX)
|
||||
$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/etc/apicheck | $(ACP)
|
||||
@echo "Copy: $(PRIVATE_MODULE) ($@)"
|
||||
$(copy-file-to-new-target)
|
||||
$(hide) chmod 755 $@
|
||||
|
||||
# the other stuff
|
||||
# ============================================================
|
||||
subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
|
||||
src \
|
||||
))
|
||||
|
||||
include $(subdirs)
|
||||
# Apicheck is now part of Doclava -- See external/doclava.
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
# Copyright (C) 2008 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.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
|
||||
# apicheck java library
|
||||
# ============================================================
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-subdir-java-files)
|
||||
LOCAL_JAR_MANIFEST := MANIFEST.mf
|
||||
|
||||
LOCAL_MODULE:= apicheck
|
||||
|
||||
include $(BUILD_HOST_JAVA_LIBRARY)
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: com.android.apicheck.ApiCheck
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
public interface AbstractMethodInfo {
|
||||
|
||||
public void addException(String exec);
|
||||
public void addParameter(ParameterInfo p);
|
||||
|
||||
}
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.*;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Stack;
|
||||
|
||||
public class ApiCheck {
|
||||
// parse out and consume the -whatever command line flags
|
||||
private static ArrayList<String[]> parseFlags(ArrayList<String> allArgs) {
|
||||
ArrayList<String[]> ret = new ArrayList<String[]>();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < allArgs.size(); i++) {
|
||||
// flags with one value attached
|
||||
String flag = allArgs.get(i);
|
||||
if (flag.equals("-error")
|
||||
|| flag.equals("-warning")
|
||||
|| flag.equals("-hide")) {
|
||||
String[] arg = new String[2];
|
||||
arg[0] = flag;
|
||||
arg[1] = allArgs.get(++i);
|
||||
ret.add(arg);
|
||||
} else {
|
||||
// we've consumed all of the -whatever args, so we're done
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// i now points to the first non-flag arg; strip what came before
|
||||
for (; i > 0; i--) {
|
||||
allArgs.remove(0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void main(String[] originalArgs) {
|
||||
// translate to an ArrayList<String> for munging
|
||||
ArrayList<String> args = new ArrayList<String>(originalArgs.length);
|
||||
for (String a: originalArgs) {
|
||||
args.add(a);
|
||||
}
|
||||
|
||||
ArrayList<String[]> flags = ApiCheck.parseFlags(args);
|
||||
for (String[] a: flags) {
|
||||
if (a[0].equals("-error") || a[0].equals("-warning")
|
||||
|| a[0].equals("-hide")) {
|
||||
try {
|
||||
int level = -1;
|
||||
if (a[0].equals("-error")) {
|
||||
level = Errors.ERROR;
|
||||
}
|
||||
else if (a[0].equals("-warning")) {
|
||||
level = Errors.WARNING;
|
||||
}
|
||||
else if (a[0].equals("-hide")) {
|
||||
level = Errors.HIDDEN;
|
||||
}
|
||||
Errors.setErrorLevel(Integer.parseInt(a[1]), level);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
System.err.println("Bad argument: " + a[0] + " " + a[1]);
|
||||
System.exit(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ApiCheck acheck = new ApiCheck();
|
||||
|
||||
ApiInfo oldApi = acheck.parseApi(args.get(0));
|
||||
ApiInfo newApi = acheck.parseApi(args.get(1));
|
||||
|
||||
// only run the consistency check if we haven't had XML parse errors
|
||||
if (!Errors.hadError) {
|
||||
oldApi.isConsistent(newApi);
|
||||
}
|
||||
|
||||
Errors.printErrors();
|
||||
System.exit(Errors.hadError ? 1 : 0);
|
||||
}
|
||||
|
||||
public ApiInfo parseApi(String xmlFile) {
|
||||
FileReader fileReader = null;
|
||||
try {
|
||||
XMLReader xmlreader = XMLReaderFactory.createXMLReader();
|
||||
MakeHandler handler = new MakeHandler();
|
||||
xmlreader.setContentHandler(handler);
|
||||
xmlreader.setErrorHandler(handler);
|
||||
fileReader = new FileReader(xmlFile);
|
||||
xmlreader.parse(new InputSource(fileReader));
|
||||
ApiInfo apiInfo = handler.getApi();
|
||||
apiInfo.resolveSuperclasses();
|
||||
apiInfo.resolveInterfaces();
|
||||
return apiInfo;
|
||||
} catch (SAXParseException e) {
|
||||
Errors.error(Errors.PARSE_ERROR,
|
||||
new SourcePositionInfo(xmlFile, e.getLineNumber(), 0),
|
||||
e.getMessage());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Errors.error(Errors.PARSE_ERROR,
|
||||
new SourcePositionInfo(xmlFile, 0, 0), e.getMessage());
|
||||
} finally {
|
||||
if (fileReader != null) {
|
||||
try {
|
||||
fileReader.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class MakeHandler extends DefaultHandler {
|
||||
|
||||
private ApiInfo mApi;
|
||||
private PackageInfo mCurrentPackage;
|
||||
private ClassInfo mCurrentClass;
|
||||
private AbstractMethodInfo mCurrentMethod;
|
||||
private Stack<ClassInfo> mClassScope = new Stack<ClassInfo>();
|
||||
|
||||
|
||||
public MakeHandler() {
|
||||
super();
|
||||
mApi = new ApiInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName,
|
||||
Attributes attributes) {
|
||||
if (qName.equals("package")) {
|
||||
mCurrentPackage = new PackageInfo(attributes.getValue("name"),
|
||||
SourcePositionInfo.fromXml(attributes.getValue("source")));
|
||||
} else if (qName.equals("class")
|
||||
|| qName.equals("interface")) {
|
||||
// push the old outer scope for later recovery, then set
|
||||
// up the new current class object
|
||||
mClassScope.push(mCurrentClass);
|
||||
mCurrentClass = new ClassInfo(attributes.getValue("name"),
|
||||
mCurrentPackage,
|
||||
attributes.getValue("extends") ,
|
||||
qName.equals("interface"),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("abstract")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("static")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("final")),
|
||||
attributes.getValue("deprecated"),
|
||||
attributes.getValue("visibility"),
|
||||
SourcePositionInfo.fromXml(attributes.getValue("source")),
|
||||
mCurrentClass);
|
||||
} else if (qName.equals("method")) {
|
||||
mCurrentMethod = new MethodInfo(attributes.getValue("name"),
|
||||
attributes.getValue("return") ,
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("abstract")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("native")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("synchronized")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("static")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("final")),
|
||||
attributes.getValue("deprecated"),
|
||||
attributes.getValue("visibility"),
|
||||
SourcePositionInfo.fromXml(attributes.getValue("source")),
|
||||
mCurrentClass);
|
||||
} else if (qName.equals("constructor")) {
|
||||
mCurrentMethod = new ConstructorInfo(attributes.getValue("name"),
|
||||
attributes.getValue("type") ,
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("static")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("final")),
|
||||
attributes.getValue("deprecated"),
|
||||
attributes.getValue("visibility"),
|
||||
SourcePositionInfo.fromXml(attributes.getValue("source")),
|
||||
mCurrentClass);
|
||||
} else if (qName.equals("field")) {
|
||||
FieldInfo fInfo = new FieldInfo(attributes.getValue("name"),
|
||||
attributes.getValue("type") ,
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("transient")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("volatile")),
|
||||
attributes.getValue("value"),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("static")),
|
||||
Boolean.valueOf(
|
||||
attributes.getValue("final")),
|
||||
attributes.getValue("deprecated"),
|
||||
attributes.getValue("visibility"),
|
||||
SourcePositionInfo.fromXml(attributes.getValue("source")),
|
||||
mCurrentClass);
|
||||
mCurrentClass.addField(fInfo);
|
||||
} else if (qName.equals("parameter")) {
|
||||
mCurrentMethod.addParameter(new ParameterInfo(attributes.getValue("type"),
|
||||
attributes.getValue("name")));
|
||||
} else if (qName.equals("exception")) {
|
||||
mCurrentMethod.addException(attributes.getValue("type"));
|
||||
} else if (qName.equals("implements")) {
|
||||
mCurrentClass.addInterface(attributes.getValue("name"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) {
|
||||
if (qName.equals("method")) {
|
||||
mCurrentClass.addMethod((MethodInfo) mCurrentMethod);
|
||||
} else if (qName.equals("constructor")) {
|
||||
mCurrentClass.addConstructor((ConstructorInfo) mCurrentMethod);
|
||||
} else if (qName.equals("class")
|
||||
|| qName.equals("interface")) {
|
||||
mCurrentPackage.addClass(mCurrentClass);
|
||||
mCurrentClass = mClassScope.pop();
|
||||
} else if (qName.equals("package")){
|
||||
mApi.addPackage(mCurrentPackage);
|
||||
}
|
||||
}
|
||||
public ApiInfo getApi() {
|
||||
return mApi;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
import java.util.*;
|
||||
|
||||
public class ApiInfo {
|
||||
|
||||
private HashMap<String, PackageInfo> mPackages;
|
||||
private HashMap<String, ClassInfo> mAllClasses;
|
||||
|
||||
public ApiInfo() {
|
||||
mPackages = new HashMap<String, PackageInfo>();
|
||||
mAllClasses = new HashMap<String, ClassInfo>();
|
||||
}
|
||||
|
||||
public ClassInfo findClass(String name) {
|
||||
return mAllClasses.get(name);
|
||||
}
|
||||
|
||||
public void resolveInterfaces() {
|
||||
for (ClassInfo c : mAllClasses.values()) {
|
||||
c.resolveInterfaces(this);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConsistent(ApiInfo otherApi) {
|
||||
boolean consistent = true;
|
||||
for (PackageInfo pInfo : mPackages.values()) {
|
||||
if (otherApi.getPackages().containsKey(pInfo.name())) {
|
||||
if (!pInfo.isConsistent(otherApi.getPackages().get(pInfo.name()))) {
|
||||
consistent = false;
|
||||
}
|
||||
} else {
|
||||
Errors.error(Errors.REMOVED_PACKAGE, pInfo.position(),
|
||||
"Removed package " + pInfo.name());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
for (PackageInfo pInfo : otherApi.mPackages.values()) {
|
||||
if (!pInfo.isInBoth()) {
|
||||
Errors.error(Errors.ADDED_PACKAGE, pInfo.position(),
|
||||
"Added package " + pInfo.name());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
return consistent;
|
||||
}
|
||||
|
||||
public HashMap<String, PackageInfo> getPackages() {
|
||||
return mPackages;
|
||||
}
|
||||
|
||||
public void addPackage(PackageInfo pInfo) {
|
||||
// track the set of organized packages in the API
|
||||
mPackages.put(pInfo.name(), pInfo);
|
||||
|
||||
// accumulate a direct map of all the classes in the API
|
||||
for (ClassInfo cl: pInfo.allClasses().values()) {
|
||||
mAllClasses.put(cl.qualifiedName(), cl);
|
||||
}
|
||||
}
|
||||
|
||||
public void resolveSuperclasses() {
|
||||
for (ClassInfo cl: mAllClasses.values()) {
|
||||
// java.lang.Object has no superclass
|
||||
if (!cl.qualifiedName().equals("java.lang.Object")) {
|
||||
String scName = cl.superclassName();
|
||||
if (scName == null) {
|
||||
scName = "java.lang.Object";
|
||||
}
|
||||
|
||||
ClassInfo superclass = mAllClasses.get(scName);
|
||||
cl.setSuperClass(superclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,341 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
import java.util.*;
|
||||
|
||||
public class ClassInfo {
|
||||
private String mName;
|
||||
private String mSuperClassName;
|
||||
private boolean mIsInterface;
|
||||
private boolean mIsAbstract;
|
||||
private boolean mIsStatic;
|
||||
private boolean mIsFinal;
|
||||
private String mDeprecated;
|
||||
private String mScope;
|
||||
private List<String> mInterfaceNames;
|
||||
private List<ClassInfo> mInterfaces;
|
||||
private HashMap<String, MethodInfo> mMethods;
|
||||
private HashMap<String, FieldInfo> mFields;
|
||||
private HashMap<String, ConstructorInfo> mConstructors;
|
||||
private boolean mExistsInBoth;
|
||||
private PackageInfo mPackage;
|
||||
private SourcePositionInfo mSourcePosition;
|
||||
private ClassInfo mSuperClass;
|
||||
private ClassInfo mParentClass;
|
||||
|
||||
public ClassInfo(String name, PackageInfo pack, String superClass, boolean isInterface,
|
||||
boolean isAbstract, boolean isStatic, boolean isFinal, String deprecated,
|
||||
String visibility, SourcePositionInfo source, ClassInfo parent) {
|
||||
mName = name;
|
||||
mPackage = pack;
|
||||
mSuperClassName = superClass;
|
||||
mIsInterface = isInterface;
|
||||
mIsAbstract = isAbstract;
|
||||
mIsStatic = isStatic;
|
||||
mIsFinal = isFinal;
|
||||
mDeprecated = deprecated;
|
||||
mScope = visibility;
|
||||
mInterfaceNames = new ArrayList<String>();
|
||||
mInterfaces = new ArrayList<ClassInfo>();
|
||||
mMethods = new HashMap<String, MethodInfo>();
|
||||
mFields = new HashMap<String, FieldInfo>();
|
||||
mConstructors = new HashMap<String, ConstructorInfo>();
|
||||
mExistsInBoth = false;
|
||||
mSourcePosition = source;
|
||||
mParentClass = parent;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String qualifiedName() {
|
||||
String parentQName = (mParentClass != null)
|
||||
? (mParentClass.qualifiedName() + ".")
|
||||
: "";
|
||||
return mPackage.name() + "." + parentQName + name();
|
||||
}
|
||||
|
||||
public String superclassName() {
|
||||
return mSuperClassName;
|
||||
}
|
||||
|
||||
public SourcePositionInfo position() {
|
||||
return mSourcePosition;
|
||||
}
|
||||
|
||||
public boolean isInterface() {
|
||||
return mIsInterface;
|
||||
}
|
||||
|
||||
public boolean isFinal() {
|
||||
return mIsFinal;
|
||||
}
|
||||
|
||||
// Find a superclass implementation of the given method.
|
||||
public static MethodInfo overriddenMethod(MethodInfo candidate, ClassInfo newClassObj) {
|
||||
if (newClassObj == null) {
|
||||
return null;
|
||||
}
|
||||
for (MethodInfo mi : newClassObj.mMethods.values()) {
|
||||
if (mi.matches(candidate)) {
|
||||
// found it
|
||||
return mi;
|
||||
}
|
||||
}
|
||||
|
||||
// not found here. recursively search ancestors
|
||||
return ClassInfo.overriddenMethod(candidate, newClassObj.mSuperClass);
|
||||
}
|
||||
|
||||
// Find a superinterface declaration of the given method.
|
||||
public static MethodInfo interfaceMethod(MethodInfo candidate, ClassInfo newClassObj) {
|
||||
if (newClassObj == null) {
|
||||
return null;
|
||||
}
|
||||
for (ClassInfo interfaceInfo : newClassObj.mInterfaces) {
|
||||
for (MethodInfo mi : interfaceInfo.mMethods.values()) {
|
||||
if (mi.matches(candidate)) {
|
||||
return mi;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ClassInfo.interfaceMethod(candidate, newClassObj.mSuperClass);
|
||||
}
|
||||
|
||||
public boolean isConsistent(ClassInfo cl) {
|
||||
cl.mExistsInBoth = true;
|
||||
mExistsInBoth = true;
|
||||
boolean consistent = true;
|
||||
|
||||
if (isInterface() != cl.isInterface()) {
|
||||
Errors.error(Errors.CHANGED_CLASS, cl.position(),
|
||||
"Class " + cl.qualifiedName()
|
||||
+ " changed class/interface declaration");
|
||||
consistent = false;
|
||||
}
|
||||
for (String iface : mInterfaceNames) {
|
||||
if (!implementsInterface(cl, iface)) {
|
||||
Errors.error(Errors.REMOVED_INTERFACE, cl.position(),
|
||||
"Class " + qualifiedName() + " no longer implements " + iface);
|
||||
}
|
||||
}
|
||||
for (String iface : cl.mInterfaceNames) {
|
||||
if (!mInterfaceNames.contains(iface)) {
|
||||
Errors.error(Errors.ADDED_INTERFACE, cl.position(),
|
||||
"Added interface " + iface + " to class "
|
||||
+ qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (MethodInfo mInfo : mMethods.values()) {
|
||||
if (cl.mMethods.containsKey(mInfo.getHashableName())) {
|
||||
if (!mInfo.isConsistent(cl.mMethods.get(mInfo.getHashableName()))) {
|
||||
consistent = false;
|
||||
}
|
||||
} else {
|
||||
/* This class formerly provided this method directly, and now does not.
|
||||
* Check our ancestry to see if there's an inherited version that still
|
||||
* fulfills the API requirement.
|
||||
*/
|
||||
MethodInfo mi = ClassInfo.overriddenMethod(mInfo, cl);
|
||||
if (mi == null) {
|
||||
mi = ClassInfo.interfaceMethod(mInfo, cl);
|
||||
}
|
||||
if (mi == null) {
|
||||
Errors.error(Errors.REMOVED_METHOD, mInfo.position(),
|
||||
"Removed public method " + mInfo.qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (MethodInfo mInfo : cl.mMethods.values()) {
|
||||
if (!mInfo.isInBoth()) {
|
||||
/* Similarly to the above, do not fail if this "new" method is
|
||||
* really an override of an existing superclass method.
|
||||
*/
|
||||
MethodInfo mi = ClassInfo.overriddenMethod(mInfo, cl);
|
||||
if (mi == null) {
|
||||
Errors.error(Errors.ADDED_METHOD, mInfo.position(),
|
||||
"Added public method " + mInfo.qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (ConstructorInfo mInfo : mConstructors.values()) {
|
||||
if (cl.mConstructors.containsKey(mInfo.getHashableName())) {
|
||||
if (!mInfo.isConsistent(cl.mConstructors.get(mInfo.getHashableName()))) {
|
||||
consistent = false;
|
||||
}
|
||||
} else {
|
||||
Errors.error(Errors.REMOVED_METHOD, mInfo.position(),
|
||||
"Removed public constructor " + mInfo.prettySignature());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
for (ConstructorInfo mInfo : cl.mConstructors.values()) {
|
||||
if (!mInfo.isInBoth()) {
|
||||
Errors.error(Errors.ADDED_METHOD, mInfo.position(),
|
||||
"Added public constructor " + mInfo.prettySignature());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (FieldInfo mInfo : mFields.values()) {
|
||||
if (cl.mFields.containsKey(mInfo.name())) {
|
||||
if (!mInfo.isConsistent(cl.mFields.get(mInfo.name()))) {
|
||||
consistent = false;
|
||||
}
|
||||
} else {
|
||||
Errors.error(Errors.REMOVED_FIELD, mInfo.position(),
|
||||
"Removed field " + mInfo.qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
for (FieldInfo mInfo : cl.mFields.values()) {
|
||||
if (!mInfo.isInBoth()) {
|
||||
Errors.error(Errors.ADDED_FIELD, mInfo.position(),
|
||||
"Added public field " + mInfo.qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsAbstract != cl.mIsAbstract) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_ABSTRACT, cl.position(),
|
||||
"Class " + cl.qualifiedName() + " changed abstract qualifier");
|
||||
}
|
||||
|
||||
if (mIsFinal != cl.mIsFinal) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_FINAL, cl.position(),
|
||||
"Class " + cl.qualifiedName() + " changed final qualifier");
|
||||
}
|
||||
|
||||
if (mIsStatic != cl.mIsStatic) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_STATIC, cl.position(),
|
||||
"Class " + cl.qualifiedName() + " changed static qualifier");
|
||||
}
|
||||
|
||||
if (!mScope.equals(cl.mScope)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_SCOPE, cl.position(),
|
||||
"Class " + cl.qualifiedName() + " scope changed from "
|
||||
+ mScope + " to " + cl.mScope);
|
||||
}
|
||||
|
||||
if (!mDeprecated.equals(cl.mDeprecated)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_DEPRECATED, cl.position(),
|
||||
"Class " + cl.qualifiedName() + " has changed deprecation state");
|
||||
}
|
||||
|
||||
if (mSuperClassName != null) {
|
||||
if (cl.mSuperClassName == null || !mSuperClassName.equals(cl.mSuperClassName)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_SUPERCLASS, cl.position(),
|
||||
"Class " + qualifiedName() + " superclass changed from "
|
||||
+ mSuperClassName + " to " + cl.mSuperClassName);
|
||||
}
|
||||
} else if (cl.mSuperClassName != null) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_SUPERCLASS, cl.position(),
|
||||
"Class " + qualifiedName() + " superclass changed from "
|
||||
+ "null to " + cl.mSuperClassName);
|
||||
}
|
||||
|
||||
return consistent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code cl} implements the interface {@code iface} either
|
||||
* by either being that interface, implementing that interface or extending
|
||||
* a type that implements the interface.
|
||||
*/
|
||||
private boolean implementsInterface(ClassInfo cl, String iface) {
|
||||
if (cl.qualifiedName().equals(iface)) {
|
||||
return true;
|
||||
}
|
||||
for (ClassInfo clImplements : cl.mInterfaces) {
|
||||
if (implementsInterface(clImplements, iface)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (cl.mSuperClass != null && implementsInterface(cl.mSuperClass, iface)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void resolveInterfaces(ApiInfo apiInfo) {
|
||||
for (String interfaceName : mInterfaceNames) {
|
||||
mInterfaces.add(apiInfo.findClass(interfaceName));
|
||||
}
|
||||
}
|
||||
|
||||
public void addInterface(String name) {
|
||||
mInterfaceNames.add(name);
|
||||
}
|
||||
|
||||
public void addMethod(MethodInfo mInfo) {
|
||||
mMethods.put(mInfo.getHashableName(), mInfo);
|
||||
}
|
||||
|
||||
public void addConstructor(ConstructorInfo cInfo) {
|
||||
mConstructors.put(cInfo.getHashableName(), cInfo);
|
||||
|
||||
}
|
||||
|
||||
public void addField(FieldInfo fInfo) {
|
||||
mFields.put(fInfo.name(), fInfo);
|
||||
|
||||
}
|
||||
|
||||
public void setSuperClass(ClassInfo superclass) {
|
||||
mSuperClass = superclass;
|
||||
}
|
||||
|
||||
public boolean isInBoth() {
|
||||
return mExistsInBoth;
|
||||
}
|
||||
|
||||
public Map<String, ConstructorInfo> allConstructors() {
|
||||
return mConstructors;
|
||||
}
|
||||
|
||||
public Map<String, FieldInfo> allFields() {
|
||||
return mFields;
|
||||
}
|
||||
|
||||
public Map<String, MethodInfo> allMethods() {
|
||||
return mMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the class hierarchy for this class, starting with this class.
|
||||
*/
|
||||
public Iterable<ClassInfo> hierarchy() {
|
||||
List<ClassInfo> result = new ArrayList<ClassInfo>(4);
|
||||
for (ClassInfo c = this; c != null; c = c.mSuperClass) {
|
||||
result.add(c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
import java.util.*;
|
||||
|
||||
public class ConstructorInfo implements AbstractMethodInfo {
|
||||
|
||||
private String mName;
|
||||
private String mType;
|
||||
private boolean mIsStatic;
|
||||
private boolean mIsFinal;
|
||||
private String mDeprecated;
|
||||
private String mScope;
|
||||
private List<String> mExceptions;
|
||||
private List<ParameterInfo> mParameters;
|
||||
private boolean mExistsInBoth;
|
||||
private SourcePositionInfo mSourcePosition;
|
||||
private ClassInfo mClass;
|
||||
|
||||
public ConstructorInfo(String name, String type, boolean isStatic, boolean isFinal,
|
||||
String deprecated, String scope, SourcePositionInfo pos, ClassInfo clazz) {
|
||||
mName = name;
|
||||
mType = type;
|
||||
mIsStatic = isStatic;
|
||||
mIsFinal = isFinal;
|
||||
mDeprecated= deprecated;
|
||||
mScope = scope;
|
||||
mExistsInBoth = false;
|
||||
mExceptions = new ArrayList<String>();
|
||||
mParameters = new ArrayList<ParameterInfo>();
|
||||
mSourcePosition = pos;
|
||||
mClass = clazz;
|
||||
}
|
||||
|
||||
public void addParameter(ParameterInfo pInfo) {
|
||||
mParameters.add(pInfo);
|
||||
}
|
||||
|
||||
public void addException(String exec) {
|
||||
mExceptions.add(exec);
|
||||
}
|
||||
|
||||
public String getHashableName() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(name());
|
||||
for (ParameterInfo pInfo : mParameters) {
|
||||
result.append(":").append(pInfo.getType());
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public boolean isInBoth() {
|
||||
return mExistsInBoth;
|
||||
}
|
||||
|
||||
public SourcePositionInfo position() {
|
||||
return mSourcePosition;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String qualifiedName() {
|
||||
String baseName = (mClass != null)
|
||||
? (mClass.qualifiedName() + ".")
|
||||
: "";
|
||||
return baseName + name();
|
||||
}
|
||||
|
||||
public String prettySignature() {
|
||||
String params = "";
|
||||
for (ParameterInfo pInfo : mParameters) {
|
||||
if (params.length() > 0) {
|
||||
params += ", ";
|
||||
}
|
||||
params += pInfo.getType();
|
||||
}
|
||||
return qualifiedName() + '(' + params + ')';
|
||||
}
|
||||
|
||||
public boolean isConsistent(ConstructorInfo mInfo) {
|
||||
mInfo.mExistsInBoth = true;
|
||||
mExistsInBoth = true;
|
||||
boolean consistent = true;
|
||||
|
||||
if (mIsFinal != mInfo.mIsFinal) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_FINAL, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " has changed 'final' qualifier");
|
||||
}
|
||||
|
||||
if (mIsStatic != mInfo.mIsStatic) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_FINAL, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " has changed 'static' qualifier");
|
||||
}
|
||||
|
||||
if (!mScope.equals(mInfo.mScope)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_SCOPE, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " changed scope from "
|
||||
+ mScope + " to " + mInfo.mScope);
|
||||
}
|
||||
|
||||
if (!mDeprecated.equals(mInfo.mDeprecated)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_DEPRECATED, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " has changed deprecation state");
|
||||
}
|
||||
|
||||
for (String exec : mExceptions) {
|
||||
if (!mInfo.mExceptions.contains(exec)) {
|
||||
Errors.error(Errors.CHANGED_THROWS, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " no longer throws exception "
|
||||
+ exec);
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (String exec : mInfo.mExceptions) {
|
||||
if (!mExceptions.contains(exec)) {
|
||||
Errors.error(Errors.CHANGED_THROWS, mInfo.position(),
|
||||
"Constructor " + mInfo.qualifiedName() + " added thrown exception "
|
||||
+ exec);
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
|
||||
return consistent;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
import java.lang.Comparable;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class Errors
|
||||
{
|
||||
public static boolean hadError = false;
|
||||
private static boolean warningsAreErrors = false;
|
||||
private static TreeSet<Message> allErrors = new TreeSet<Message>();
|
||||
|
||||
private static class Message implements Comparable {
|
||||
SourcePositionInfo pos;
|
||||
String msg;
|
||||
|
||||
Message(SourcePositionInfo p, String m) {
|
||||
pos = p;
|
||||
msg = m;
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
Message that = (Message)o;
|
||||
int r = this.pos.compareTo(that.pos);
|
||||
if (r != 0) return r;
|
||||
return this.msg.compareTo(that.msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.pos.toString() + this.msg;
|
||||
}
|
||||
}
|
||||
|
||||
public static void error(Error error, SourcePositionInfo where, String text) {
|
||||
if (error.level == HIDDEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
String which = (!warningsAreErrors && error.level == WARNING) ? " warning " : " error ";
|
||||
String message = which + error.code + ": " + text;
|
||||
|
||||
if (where == null) {
|
||||
where = new SourcePositionInfo("unknown", 0, 0);
|
||||
}
|
||||
|
||||
allErrors.add(new Message(where, message));
|
||||
|
||||
if (error.level == ERROR || (warningsAreErrors && error.level == WARNING)) {
|
||||
hadError = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void printErrors() {
|
||||
for (Message m: allErrors) {
|
||||
System.err.println(m.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static int HIDDEN = 0;
|
||||
public static int WARNING = 1;
|
||||
public static int ERROR = 2;
|
||||
|
||||
public static void setWarningsAreErrors(boolean val) {
|
||||
warningsAreErrors = val;
|
||||
}
|
||||
|
||||
public static class Error {
|
||||
public int code;
|
||||
public int level;
|
||||
|
||||
public Error(int code, int level)
|
||||
{
|
||||
this.code = code;
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
|
||||
public static Error PARSE_ERROR = new Error(1, ERROR);
|
||||
public static Error ADDED_PACKAGE = new Error(2, WARNING);
|
||||
public static Error ADDED_CLASS = new Error(3, WARNING);
|
||||
public static Error ADDED_METHOD = new Error(4, WARNING);
|
||||
public static Error ADDED_FIELD = new Error(5, WARNING);
|
||||
public static Error ADDED_INTERFACE = new Error(6, WARNING);
|
||||
public static Error REMOVED_PACKAGE = new Error(7, WARNING);
|
||||
public static Error REMOVED_CLASS = new Error(8, WARNING);
|
||||
public static Error REMOVED_METHOD = new Error(9, WARNING);
|
||||
public static Error REMOVED_FIELD = new Error(10, WARNING);
|
||||
public static Error REMOVED_INTERFACE = new Error(11, WARNING);
|
||||
public static Error CHANGED_STATIC = new Error(12, WARNING);
|
||||
public static Error CHANGED_FINAL = new Error(13, WARNING);
|
||||
public static Error CHANGED_TRANSIENT = new Error(14, WARNING);
|
||||
public static Error CHANGED_VOLATILE = new Error(15, WARNING);
|
||||
public static Error CHANGED_TYPE = new Error(16, WARNING);
|
||||
public static Error CHANGED_VALUE = new Error(17, WARNING);
|
||||
public static Error CHANGED_SUPERCLASS = new Error(18, WARNING);
|
||||
public static Error CHANGED_SCOPE = new Error(19, WARNING);
|
||||
public static Error CHANGED_ABSTRACT = new Error(20, WARNING);
|
||||
public static Error CHANGED_THROWS = new Error(21, WARNING);
|
||||
public static Error CHANGED_NATIVE = new Error(22, HIDDEN);
|
||||
public static Error CHANGED_CLASS = new Error(23, WARNING);
|
||||
public static Error CHANGED_DEPRECATED = new Error(24, WARNING);
|
||||
public static Error CHANGED_SYNCHRONIZED = new Error(25, ERROR);
|
||||
|
||||
public static Error[] ERRORS = {
|
||||
PARSE_ERROR,
|
||||
ADDED_PACKAGE,
|
||||
ADDED_CLASS,
|
||||
ADDED_METHOD,
|
||||
ADDED_FIELD,
|
||||
ADDED_INTERFACE,
|
||||
REMOVED_PACKAGE,
|
||||
REMOVED_CLASS,
|
||||
REMOVED_METHOD,
|
||||
REMOVED_FIELD,
|
||||
REMOVED_INTERFACE,
|
||||
CHANGED_STATIC,
|
||||
CHANGED_FINAL,
|
||||
CHANGED_TRANSIENT,
|
||||
CHANGED_VOLATILE,
|
||||
CHANGED_TYPE,
|
||||
CHANGED_VALUE,
|
||||
CHANGED_SUPERCLASS,
|
||||
CHANGED_SCOPE,
|
||||
CHANGED_ABSTRACT,
|
||||
CHANGED_THROWS,
|
||||
CHANGED_NATIVE,
|
||||
CHANGED_CLASS,
|
||||
CHANGED_DEPRECATED,
|
||||
CHANGED_SYNCHRONIZED,
|
||||
};
|
||||
|
||||
public static boolean setErrorLevel(int code, int level) {
|
||||
for (Error e: ERRORS) {
|
||||
if (e.code == code) {
|
||||
e.level = level;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,160 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
public class FieldInfo {
|
||||
|
||||
private String mName;
|
||||
private String mType;
|
||||
private boolean mIsTransient;
|
||||
private boolean mIsVolatile;
|
||||
private String mValue;
|
||||
private boolean mIsStatic;
|
||||
private boolean mIsFinal;
|
||||
private String mDeprecated;
|
||||
private String mScope;
|
||||
private boolean mExistsInBoth;
|
||||
private SourcePositionInfo mSourcePosition;
|
||||
private ClassInfo mClass;
|
||||
|
||||
public FieldInfo (String name, String type, boolean isTransient, boolean isVolatile,
|
||||
String value, boolean isStatic, boolean isFinal, String deprecated,
|
||||
String scope, SourcePositionInfo source, ClassInfo parent) {
|
||||
mName = name;
|
||||
mType = type;
|
||||
mIsTransient = isTransient;
|
||||
mIsVolatile = isVolatile;
|
||||
mValue = value;
|
||||
mIsStatic = isStatic;
|
||||
mIsFinal = isFinal;
|
||||
mDeprecated = deprecated;
|
||||
mScope = scope;
|
||||
mExistsInBoth = false;
|
||||
mSourcePosition = source;
|
||||
mClass = parent;
|
||||
}
|
||||
|
||||
public boolean isInBoth() {
|
||||
return mExistsInBoth;
|
||||
}
|
||||
public SourcePositionInfo position() {
|
||||
return mSourcePosition;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String qualifiedName() {
|
||||
String parentQName = (mClass != null)
|
||||
? (mClass.qualifiedName() + ".")
|
||||
: "";
|
||||
return parentQName + name();
|
||||
}
|
||||
|
||||
// Check the declared value with a typed comparison, not a string comparison,
|
||||
// to accommodate toolchains with different fp -> string conversions.
|
||||
public boolean valueEquals(FieldInfo other) {
|
||||
// Type mismatch means nonequal, as does a null/non-null mismatch
|
||||
if (!mType.equals(other.mType)
|
||||
|| ((mValue == null) != (other.mValue == null))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Null values are considered equal
|
||||
if (mValue == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Floating point gets an implementation-type comparison; all others just use the string
|
||||
// If float/double parse fails, fall back to string comparison -- it means that it's a
|
||||
// canonical droiddoc-generated constant expression that represents a NaN.
|
||||
try {
|
||||
if (mType.equals("float")) {
|
||||
float val = Float.parseFloat(mValue);
|
||||
float otherVal = Float.parseFloat(other.mValue);
|
||||
return (val == otherVal);
|
||||
} else if (mType.equals("double")) {
|
||||
double val = Double.parseDouble(mValue);
|
||||
double otherVal = Double.parseDouble(other.mValue);
|
||||
return (val == otherVal);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// fall through
|
||||
}
|
||||
|
||||
return mValue.equals(other.mValue);
|
||||
}
|
||||
|
||||
public boolean isConsistent(FieldInfo fInfo) {
|
||||
fInfo.mExistsInBoth = true;
|
||||
mExistsInBoth = true;
|
||||
boolean consistent = true;
|
||||
if (!mType.equals(fInfo.mType)) {
|
||||
Errors.error(Errors.CHANGED_TYPE, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed type");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (!this.valueEquals(fInfo)) {
|
||||
Errors.error(Errors.CHANGED_VALUE, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed value from "
|
||||
+ mValue + " to " + fInfo.mValue);
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (!mScope.equals(fInfo.mScope)) {
|
||||
Errors.error(Errors.CHANGED_SCOPE, fInfo.position(),
|
||||
"Method " + fInfo.qualifiedName() + " changed scope from "
|
||||
+ mScope + " to " + fInfo.mScope);
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (mIsStatic != fInfo.mIsStatic) {
|
||||
Errors.error(Errors.CHANGED_STATIC, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed 'static' qualifier");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (mIsFinal != fInfo.mIsFinal) {
|
||||
Errors.error(Errors.CHANGED_FINAL, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed 'final' qualifier");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (mIsTransient != fInfo.mIsTransient) {
|
||||
Errors.error(Errors.CHANGED_TRANSIENT, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed 'transient' qualifier");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (mIsVolatile != fInfo.mIsVolatile) {
|
||||
Errors.error(Errors.CHANGED_VOLATILE, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed 'volatile' qualifier");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (!mDeprecated.equals(fInfo.mDeprecated)) {
|
||||
Errors.error(Errors.CHANGED_DEPRECATED, fInfo.position(),
|
||||
"Field " + fInfo.qualifiedName() + " has changed deprecation state");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
return consistent;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
import java.util.*;
|
||||
|
||||
public class MethodInfo implements AbstractMethodInfo {
|
||||
|
||||
private String mName;
|
||||
private String mReturn;
|
||||
private boolean mIsAbstract;
|
||||
private boolean mIsNative;
|
||||
private boolean mIsSynchronized;
|
||||
private boolean mIsStatic;
|
||||
private boolean mIsFinal;
|
||||
private String mDeprecated;
|
||||
private String mScope;
|
||||
private boolean mExistsInBoth;
|
||||
private List<ParameterInfo> mParameters;
|
||||
private List<String> mExceptions;
|
||||
private SourcePositionInfo mSourcePosition;
|
||||
private ClassInfo mClass;
|
||||
|
||||
public MethodInfo (String name, String returnType, boolean isAbstract, boolean isNative,
|
||||
boolean isSynchronized, boolean isStatic, boolean isFinal, String deprecated
|
||||
, String scope, SourcePositionInfo source, ClassInfo parent) {
|
||||
|
||||
mName = name;
|
||||
mReturn = returnType;
|
||||
mIsAbstract = isAbstract;
|
||||
mIsNative = isNative;
|
||||
mIsSynchronized = isSynchronized;
|
||||
mIsStatic = isStatic;
|
||||
mIsFinal = isFinal;
|
||||
mDeprecated = deprecated;
|
||||
mScope = scope;
|
||||
mParameters = new ArrayList<ParameterInfo>();
|
||||
mExceptions = new ArrayList<String>();
|
||||
mExistsInBoth = false;
|
||||
mSourcePosition = source;
|
||||
mClass = parent;
|
||||
}
|
||||
|
||||
|
||||
public String name() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String qualifiedName() {
|
||||
String parentQName = (mClass != null)
|
||||
? (mClass.qualifiedName() + ".")
|
||||
: "";
|
||||
return parentQName + name();
|
||||
}
|
||||
|
||||
public String prettySignature() {
|
||||
String params = "";
|
||||
for (ParameterInfo pInfo : mParameters) {
|
||||
if (params.length() > 0) {
|
||||
params += ", ";
|
||||
}
|
||||
params += pInfo.getType();
|
||||
}
|
||||
return qualifiedName() + '(' + params + ')';
|
||||
}
|
||||
|
||||
public SourcePositionInfo position() {
|
||||
return mSourcePosition;
|
||||
}
|
||||
|
||||
public ClassInfo containingClass() {
|
||||
return mClass;
|
||||
}
|
||||
|
||||
public boolean matches(MethodInfo other) {
|
||||
return getSignature().equals(other.getSignature());
|
||||
}
|
||||
|
||||
public boolean isConsistent(MethodInfo mInfo) {
|
||||
mInfo.mExistsInBoth = true;
|
||||
mExistsInBoth = true;
|
||||
boolean consistent = true;
|
||||
if (!mReturn.equals(mInfo.mReturn)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_TYPE, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed return type from "
|
||||
+ mReturn + " to " + mInfo.mReturn);
|
||||
}
|
||||
|
||||
if (mIsAbstract != mInfo.mIsAbstract) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_ABSTRACT, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed 'abstract' qualifier");
|
||||
}
|
||||
|
||||
if (mIsNative != mInfo.mIsNative) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_NATIVE, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed 'native' qualifier");
|
||||
}
|
||||
|
||||
if (mIsFinal != mInfo.mIsFinal) {
|
||||
// Compiler-generated methods vary in their 'final' qual between versions of
|
||||
// the compiler, so this check needs to be quite narrow. A change in 'final'
|
||||
// status of a method is only relevant if (a) the method is not declared 'static'
|
||||
// and (b) the method's class is not itself 'final'.
|
||||
if (!mIsStatic) {
|
||||
if ((mClass == null) || (!mClass.isFinal())) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_FINAL, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed 'final' qualifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mIsStatic != mInfo.mIsStatic) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_STATIC, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed 'static' qualifier");
|
||||
}
|
||||
|
||||
if (!mScope.equals(mInfo.mScope)) {
|
||||
consistent = false;
|
||||
Errors.error(Errors.CHANGED_SCOPE, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " changed scope from "
|
||||
+ mScope + " to " + mInfo.mScope);
|
||||
}
|
||||
|
||||
if (!mDeprecated.equals(mInfo.mDeprecated)) {
|
||||
Errors.error(Errors.CHANGED_DEPRECATED, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed deprecation state");
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
if (mIsSynchronized != mInfo.mIsSynchronized) {
|
||||
Errors.error(Errors.CHANGED_SYNCHRONIZED, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " has changed 'synchronized' qualifier from " + mIsSynchronized + " to " + mInfo.mIsSynchronized);
|
||||
consistent = false;
|
||||
}
|
||||
|
||||
for (String exec : mExceptions) {
|
||||
if (!mInfo.mExceptions.contains(exec)) {
|
||||
// exclude 'throws' changes to finalize() overrides with no arguments
|
||||
if (!name().equals("finalize") || (mParameters.size() > 0)) {
|
||||
Errors.error(Errors.CHANGED_THROWS, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " no longer throws exception "
|
||||
+ exec);
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (String exec : mInfo.mExceptions) {
|
||||
// exclude 'throws' changes to finalize() overrides with no arguments
|
||||
if (!mExceptions.contains(exec)) {
|
||||
if (!name().equals("finalize") || (mParameters.size() > 0)) {
|
||||
Errors.error(Errors.CHANGED_THROWS, mInfo.position(),
|
||||
"Method " + mInfo.qualifiedName() + " added thrown exception "
|
||||
+ exec);
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consistent;
|
||||
}
|
||||
|
||||
public void addParameter(ParameterInfo pInfo) {
|
||||
mParameters.add(pInfo);
|
||||
}
|
||||
|
||||
public void addException(String exc) {
|
||||
mExceptions.add(exc);
|
||||
}
|
||||
|
||||
public String getParameterHash() {
|
||||
String hash = "";
|
||||
for (ParameterInfo pInfo : mParameters) {
|
||||
hash += ":" + pInfo.getType();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String getHashableName() {
|
||||
return name() + getParameterHash();
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return name() + getParameterHash();
|
||||
}
|
||||
|
||||
public boolean isInBoth() {
|
||||
return mExistsInBoth;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
import java.util.*;
|
||||
|
||||
public class PackageInfo {
|
||||
private String mName;
|
||||
private HashMap<String, ClassInfo> mClasses;
|
||||
private boolean mExistsInBoth;
|
||||
private SourcePositionInfo mPosition;
|
||||
|
||||
public PackageInfo(String name, SourcePositionInfo position) {
|
||||
mName = name;
|
||||
mClasses = new HashMap<String, ClassInfo>();
|
||||
mExistsInBoth = false;
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
public void addClass(ClassInfo cl) {
|
||||
mClasses.put(cl.name() , cl);
|
||||
}
|
||||
|
||||
public HashMap<String, ClassInfo> allClasses() {
|
||||
return mClasses;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
public SourcePositionInfo position() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public boolean isConsistent(PackageInfo pInfo) {
|
||||
mExistsInBoth = true;
|
||||
pInfo.mExistsInBoth = true;
|
||||
boolean consistent = true;
|
||||
for (ClassInfo cInfo : mClasses.values()) {
|
||||
if (pInfo.mClasses.containsKey(cInfo.name())) {
|
||||
if (!cInfo.isConsistent(pInfo.mClasses.get(cInfo.name()))) {
|
||||
consistent = false;
|
||||
}
|
||||
} else {
|
||||
Errors.error(Errors.REMOVED_CLASS, cInfo.position(),
|
||||
"Removed public class " + cInfo.qualifiedName());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
for (ClassInfo cInfo : pInfo.mClasses.values()) {
|
||||
if (!cInfo.isInBoth()) {
|
||||
Errors.error(Errors.ADDED_CLASS, cInfo.position(),
|
||||
"Added class " + cInfo.name() + " to package "
|
||||
+ pInfo.name());
|
||||
consistent = false;
|
||||
}
|
||||
}
|
||||
return consistent;
|
||||
}
|
||||
|
||||
public boolean isInBoth() {
|
||||
return mExistsInBoth;
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
public class ParameterInfo {
|
||||
private String mType;
|
||||
private String mName;
|
||||
|
||||
public ParameterInfo(String type, String name) {
|
||||
mType = type;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mName;
|
||||
}
|
||||
}
|
|
@ -1,123 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.android.apicheck;
|
||||
|
||||
import java.lang.Comparable;
|
||||
|
||||
public class SourcePositionInfo implements Comparable
|
||||
{
|
||||
public SourcePositionInfo() {
|
||||
this.file = "<unknown>";
|
||||
this.line = 0;
|
||||
this.column = 0;
|
||||
}
|
||||
|
||||
public SourcePositionInfo(String file, int line, int column)
|
||||
{
|
||||
this.file = file;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
public SourcePositionInfo(SourcePositionInfo that)
|
||||
{
|
||||
this.file = that.file;
|
||||
this.line = that.line;
|
||||
this.column = that.column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given this position and str which occurs at that position, as well as str an index into str,
|
||||
* find the SourcePositionInfo.
|
||||
*
|
||||
* @throw StringIndexOutOfBoundsException if index > str.length()
|
||||
*/
|
||||
public static SourcePositionInfo add(SourcePositionInfo that, String str, int index)
|
||||
{
|
||||
if (that == null) {
|
||||
return null;
|
||||
}
|
||||
int line = that.line;
|
||||
char prev = 0;
|
||||
for (int i=0; i<index; i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c == '\r' || (c == '\n' && prev != '\r')) {
|
||||
line++;
|
||||
}
|
||||
prev = c;
|
||||
}
|
||||
return new SourcePositionInfo(that.file, line, 0);
|
||||
}
|
||||
|
||||
public static SourcePositionInfo findBeginning(SourcePositionInfo that, String str)
|
||||
{
|
||||
if (that == null) {
|
||||
return null;
|
||||
}
|
||||
int line = that.line-1; // -1 because, well, it seems to work
|
||||
int prev = 0;
|
||||
for (int i=str.length()-1; i>=0; i--) {
|
||||
char c = str.charAt(i);
|
||||
if ((c == '\r' && prev != '\n') || (c == '\n')) {
|
||||
line--;
|
||||
}
|
||||
prev = c;
|
||||
}
|
||||
return new SourcePositionInfo(that.file, line, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if (this.file == null) {
|
||||
return "(unknown)";
|
||||
} else {
|
||||
if (this.line == 0) {
|
||||
return this.file + ':';
|
||||
} else {
|
||||
return this.file + ':' + this.line + ':';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
SourcePositionInfo that = (SourcePositionInfo)o;
|
||||
int r = this.file.compareTo(that.file);
|
||||
if (r != 0) return r;
|
||||
return this.line - that.line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a SourcePositionInfo from the XML source= notation
|
||||
*/
|
||||
public static SourcePositionInfo fromXml(String source) {
|
||||
if (source != null) {
|
||||
for (int i = 0; i < source.length(); i++) {
|
||||
if (source.charAt(i) == ':') {
|
||||
return new SourcePositionInfo(source.substring(0, i),
|
||||
Integer.parseInt(source.substring(i+1)), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new SourcePositionInfo("(unknown)", 0, 0);
|
||||
}
|
||||
|
||||
public String file;
|
||||
public int line;
|
||||
public int column;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
|
||||
Copyright (C) 2008 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.
|
||||
|
||||
|
||||
======================================================================
|
||||
|
||||
jQuery 1.2.6 - New Wave Javascript
|
||||
|
||||
Copyright (c) 2008 John Resig (jquery.com)
|
||||
Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
and GPL (GPL-LICENSE.txt) licenses.
|
||||
|
||||
Copyright (c) 2009 John Resig, http://jquery.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
# Copyright (C) 2008 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.
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
AnnotationInstanceInfo.java \
|
||||
AnnotationValueInfo.java \
|
||||
AttributeInfo.java \
|
||||
AttrTagInfo.java \
|
||||
ClassInfo.java \
|
||||
DroidDoc.java \
|
||||
ClearPage.java \
|
||||
Comment.java \
|
||||
ContainerInfo.java \
|
||||
Converter.java \
|
||||
DocFile.java \
|
||||
DocInfo.java \
|
||||
Errors.java \
|
||||
FieldInfo.java \
|
||||
Hierarchy.java \
|
||||
InheritedTags.java \
|
||||
KeywordEntry.java \
|
||||
LinkReference.java \
|
||||
LiteralTagInfo.java \
|
||||
MemberInfo.java \
|
||||
MethodInfo.java \
|
||||
NavTree.java \
|
||||
PackageInfo.java \
|
||||
ParamTagInfo.java \
|
||||
ParameterInfo.java \
|
||||
ParsedTagInfo.java \
|
||||
Proofread.java \
|
||||
SampleCode.java \
|
||||
SampleTagInfo.java \
|
||||
Scoped.java \
|
||||
SeeTagInfo.java \
|
||||
SinceTagger.java \
|
||||
Sorter.java \
|
||||
SourcePositionInfo.java \
|
||||
Stubs.java \
|
||||
TagInfo.java \
|
||||
TextTagInfo.java \
|
||||
ThrowsTagInfo.java \
|
||||
TodoFile.java \
|
||||
TypeInfo.java
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := \
|
||||
apicheck \
|
||||
clearsilver
|
||||
|
||||
LOCAL_CLASSPATH := \
|
||||
$(HOST_JDK_TOOLS_JAR)
|
||||
|
||||
LOCAL_MODULE:= droiddoc
|
||||
|
||||
include $(BUILD_HOST_JAVA_LIBRARY)
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
class AnnotationInstanceInfo
|
||||
{
|
||||
private ClassInfo mType;
|
||||
private AnnotationValueInfo[] mElementValues;
|
||||
|
||||
public AnnotationInstanceInfo(ClassInfo type, AnnotationValueInfo[] elementValues)
|
||||
{
|
||||
mType = type;
|
||||
mElementValues = elementValues;
|
||||
}
|
||||
|
||||
ClassInfo type()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
AnnotationValueInfo[] elementValues()
|
||||
{
|
||||
return mElementValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder str = new StringBuilder();
|
||||
str.append("@");
|
||||
str.append(mType.qualifiedName());
|
||||
str.append("(");
|
||||
AnnotationValueInfo[] values = mElementValues;
|
||||
final int N = values.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
AnnotationValueInfo value = values[i];
|
||||
str.append(value.element().name());
|
||||
str.append("=");
|
||||
str.append(value.valueString());
|
||||
if (i != N-1) {
|
||||
str.append(",");
|
||||
}
|
||||
}
|
||||
str.append(")");
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public class AnnotationValueInfo
|
||||
{
|
||||
private Object mValue;
|
||||
private String mString;
|
||||
private MethodInfo mElement;
|
||||
|
||||
public AnnotationValueInfo(MethodInfo element)
|
||||
{
|
||||
mElement = element;
|
||||
}
|
||||
|
||||
public void init(Object value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public MethodInfo element()
|
||||
{
|
||||
return mElement;
|
||||
}
|
||||
|
||||
public Object value()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public String valueString()
|
||||
{
|
||||
Object v = mValue;
|
||||
if (v instanceof TypeInfo) {
|
||||
return ((TypeInfo)v).fullName();
|
||||
}
|
||||
else if (v instanceof FieldInfo) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
FieldInfo f = (FieldInfo)v;
|
||||
str.append(f.containingClass().qualifiedName());
|
||||
str.append('.');
|
||||
str.append(f.name());
|
||||
return str.toString();
|
||||
}
|
||||
else if (v instanceof AnnotationInstanceInfo) {
|
||||
return v.toString();
|
||||
}
|
||||
else if (v instanceof AnnotationValueInfo[]) {
|
||||
StringBuilder str = new StringBuilder();
|
||||
AnnotationValueInfo[] array = (AnnotationValueInfo[])v;
|
||||
final int N = array.length;
|
||||
str.append("{");
|
||||
for (int i=0; i<array.length; i++) {
|
||||
str.append(array[i].valueString());
|
||||
if (i != N-1) {
|
||||
str.append(",");
|
||||
}
|
||||
}
|
||||
str.append("}");
|
||||
return str.toString();
|
||||
}
|
||||
else {
|
||||
return FieldInfo.constantLiteralValue(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
|
||||
public class AttrTagInfo extends TagInfo
|
||||
{
|
||||
private static final String REF_COMMAND = "ref";
|
||||
private static final String NAME_COMMAND = "name";
|
||||
private static final String DESCRIPTION_COMMAND = "description";
|
||||
private static final Pattern TEXT = Pattern.compile("(\\S+)\\s*(.*)", Pattern.DOTALL);
|
||||
private static final Pattern NAME_TEXT = Pattern.compile("(\\S+)(.*)",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private ContainerInfo mBase;
|
||||
private String mCommand;
|
||||
|
||||
// if mCommand == "ref"
|
||||
private FieldInfo mRefField;
|
||||
private AttributeInfo mAttrInfo;
|
||||
|
||||
// if mCommand == "name"
|
||||
private String mAttrName;
|
||||
|
||||
// if mCommand == "description"
|
||||
private Comment mDescrComment;
|
||||
|
||||
AttrTagInfo(String name, String kind, String text, ContainerInfo base,
|
||||
SourcePositionInfo position)
|
||||
{
|
||||
super(name, kind, text, position);
|
||||
mBase = base;
|
||||
|
||||
parse(text, base, position);
|
||||
}
|
||||
|
||||
void parse(String text, ContainerInfo base, SourcePositionInfo position) {
|
||||
Matcher m;
|
||||
|
||||
m = TEXT.matcher(text);
|
||||
if (!m.matches()) {
|
||||
Errors.error(Errors.BAD_ATTR_TAG, position, "Bad @attr tag: " + text);
|
||||
return;
|
||||
}
|
||||
|
||||
String command = m.group(1);
|
||||
String more = m.group(2);
|
||||
|
||||
if (REF_COMMAND.equals(command)) {
|
||||
String ref = more.trim();
|
||||
LinkReference linkRef = LinkReference.parse(ref, mBase, position, false);
|
||||
if (!linkRef.good) {
|
||||
Errors.error(Errors.BAD_ATTR_TAG, position, "Unresolved @attr ref: " + ref);
|
||||
return;
|
||||
}
|
||||
if (!(linkRef.memberInfo instanceof FieldInfo)) {
|
||||
Errors.error(Errors.BAD_ATTR_TAG, position, "@attr must be a field: " + ref);
|
||||
return;
|
||||
}
|
||||
mCommand = command;
|
||||
mRefField = (FieldInfo)linkRef.memberInfo;
|
||||
}
|
||||
else if (NAME_COMMAND.equals(command)) {
|
||||
m = NAME_TEXT.matcher(more);
|
||||
if (!m.matches() || m.group(2).trim().length() != 0) {
|
||||
Errors.error(Errors.BAD_ATTR_TAG, position, "Bad @attr name tag: " + more);
|
||||
return;
|
||||
}
|
||||
mCommand = command;
|
||||
mAttrName = m.group(1);
|
||||
}
|
||||
else if (DESCRIPTION_COMMAND.equals(command)) {
|
||||
mCommand = command;
|
||||
mDescrComment = new Comment(more, base, position);
|
||||
}
|
||||
else {
|
||||
Errors.error(Errors.BAD_ATTR_TAG, position, "Bad @attr command: " + command);
|
||||
}
|
||||
}
|
||||
|
||||
public FieldInfo reference() {
|
||||
return REF_COMMAND.equals(mCommand) ? mRefField : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return NAME_COMMAND.equals(mCommand) ? mAttrName : null;
|
||||
}
|
||||
|
||||
public Comment description() {
|
||||
return DESCRIPTION_COMMAND.equals(mCommand) ? mDescrComment : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
super.makeHDF(data, base);
|
||||
}
|
||||
|
||||
public void setAttribute(AttributeInfo info) {
|
||||
mAttrInfo = info;
|
||||
}
|
||||
|
||||
public static void makeReferenceHDF(HDF data, String base, AttrTagInfo[] tags)
|
||||
{
|
||||
int i=0;
|
||||
for (AttrTagInfo t: tags) {
|
||||
if (REF_COMMAND.equals(t.mCommand)) {
|
||||
if (t.mAttrInfo == null) {
|
||||
String msg = "ERROR: unlinked attr: " + t.mRefField.name();
|
||||
if (false) {
|
||||
System.out.println(msg);
|
||||
} else {
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
} else {
|
||||
data.setValue(base + "." + i + ".name", t.mAttrInfo.name());
|
||||
data.setValue(base + "." + i + ".href", t.mAttrInfo.htmlPage());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
public class AttributeInfo {
|
||||
public static final Comparator<AttributeInfo> comparator = new Comparator<AttributeInfo>() {
|
||||
public int compare(AttributeInfo a, AttributeInfo b) {
|
||||
return a.name().compareTo(b.name());
|
||||
}
|
||||
};
|
||||
|
||||
public FieldInfo attrField;
|
||||
public ArrayList<MethodInfo> methods = new ArrayList<MethodInfo>();
|
||||
|
||||
private ClassInfo mClass;
|
||||
private String mName;
|
||||
private Comment mComment;
|
||||
|
||||
public AttributeInfo(ClassInfo cl, FieldInfo f) {
|
||||
mClass = cl;
|
||||
attrField = f;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
if (mName == null) {
|
||||
for (AttrTagInfo comment: attrField.comment().attrTags()) {
|
||||
String n = comment.name();
|
||||
if (n != null) {
|
||||
mName = n;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mName;
|
||||
}
|
||||
|
||||
public Comment comment() {
|
||||
if (mComment == null) {
|
||||
for (AttrTagInfo attr: attrField.comment().attrTags()) {
|
||||
Comment c = attr.description();
|
||||
if (c != null) {
|
||||
mComment = c;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mComment == null) {
|
||||
return new Comment("", mClass, new SourcePositionInfo());
|
||||
}
|
||||
return mComment;
|
||||
}
|
||||
|
||||
public String anchor() {
|
||||
return "attr_" + name();
|
||||
}
|
||||
public String htmlPage() {
|
||||
return mClass.htmlPage() + "#" + anchor();
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base) {
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".anchor", anchor());
|
||||
data.setValue(base + ".href", htmlPage());
|
||||
data.setValue(base + ".R.name", attrField.name());
|
||||
data.setValue(base + ".R.href", attrField.htmlPage());
|
||||
TagInfo.makeHDF(data, base + ".deprecated", attrField.comment().deprecatedTags());
|
||||
TagInfo.makeHDF(data, base + ".shortDescr", comment().briefTags());
|
||||
TagInfo.makeHDF(data, base + ".descr", comment().tags());
|
||||
|
||||
int i=0;
|
||||
for (MethodInfo m: methods) {
|
||||
String s = base + ".methods." + i;
|
||||
data.setValue(s + ".href", m.htmlPage());
|
||||
data.setValue(s + ".name", m.name() + m.prettySignature());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkLevel() {
|
||||
return attrField.checkLevel();
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,226 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ClearPage
|
||||
{
|
||||
/*
|
||||
public ClearPage()
|
||||
{
|
||||
String templ = "templates/index.cs";
|
||||
String filename = "docs/index.html";
|
||||
|
||||
data.setValue("A.B.C", "1");
|
||||
data.setValue("A.B.D", "2");
|
||||
}
|
||||
*/
|
||||
|
||||
public static ArrayList<String> hdfFiles = new ArrayList<String>();
|
||||
|
||||
private static ArrayList<String> mTemplateDirs = new ArrayList<String>();
|
||||
private static boolean mTemplateDirSet = false;
|
||||
|
||||
public static String outputDir = "docs";
|
||||
public static String htmlDir = null;
|
||||
public static String toroot = null;
|
||||
|
||||
public static void addTemplateDir(String dir)
|
||||
{
|
||||
mTemplateDirSet = true;
|
||||
mTemplateDirs.add(dir);
|
||||
|
||||
File hdfFile = new File(dir, "data.hdf");
|
||||
if (hdfFile.canRead()) {
|
||||
hdfFiles.add(hdfFile.getPath());
|
||||
}
|
||||
}
|
||||
|
||||
private static int countSlashes(String s)
|
||||
{
|
||||
final int N = s.length();
|
||||
int slashcount = 0;
|
||||
for (int i=0; i<N; i++) {
|
||||
if (s.charAt(i) == '/') {
|
||||
slashcount++;
|
||||
}
|
||||
}
|
||||
return slashcount;
|
||||
}
|
||||
|
||||
public static void write(HDF data, String templ, String filename)
|
||||
{
|
||||
write(data, templ, filename, false);
|
||||
}
|
||||
|
||||
public static void write(HDF data, String templ, String filename, boolean fullPath)
|
||||
{
|
||||
if (htmlDir != null) {
|
||||
data.setValue("hasindex", "true");
|
||||
}
|
||||
|
||||
String toroot;
|
||||
if (ClearPage.toroot != null) {
|
||||
toroot = ClearPage.toroot;
|
||||
} else {
|
||||
int slashcount = countSlashes(filename);
|
||||
if (slashcount > 0) {
|
||||
toroot = "";
|
||||
for (int i=0; i<slashcount; i++) {
|
||||
toroot += "../";
|
||||
}
|
||||
} else {
|
||||
toroot = "./";
|
||||
}
|
||||
}
|
||||
data.setValue("toroot", toroot);
|
||||
|
||||
data.setValue("filename", filename);
|
||||
|
||||
if (!fullPath) {
|
||||
filename = outputDir + "/" + filename;
|
||||
}
|
||||
|
||||
int i=0;
|
||||
if (htmlDir != null) {
|
||||
data.setValue("hdf.loadpaths." + i, htmlDir);
|
||||
i++;
|
||||
}
|
||||
if (mTemplateDirSet) {
|
||||
for (String dir: mTemplateDirs) {
|
||||
data.setValue("hdf.loadpaths." + i, dir);
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
data.setValue("hdf.loadpaths." + i, "templates");
|
||||
}
|
||||
|
||||
CS cs = new CS(data);
|
||||
cs.parseFile(templ);
|
||||
|
||||
File file = new File(outputFilename(filename));
|
||||
|
||||
ensureDirectory(file);
|
||||
|
||||
OutputStreamWriter stream = null;
|
||||
try {
|
||||
stream = new OutputStreamWriter(
|
||||
new FileOutputStream(file), "UTF-8");
|
||||
String rendered = cs.render();
|
||||
stream.write(rendered, 0, rendered.length());
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("error: " + e.getMessage() + "; when writing file: " + filename);
|
||||
}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// recursively create the directories to the output
|
||||
public static void ensureDirectory(File f)
|
||||
{
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null) {
|
||||
parent.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFile(File from, String toPath)
|
||||
{
|
||||
File to = new File(outputDir + "/" + toPath);
|
||||
FileInputStream in;
|
||||
FileOutputStream out;
|
||||
try {
|
||||
if (!from.exists()) {
|
||||
throw new IOException();
|
||||
}
|
||||
in = new FileInputStream(from);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(from.getAbsolutePath() + ": Error opening file");
|
||||
return ;
|
||||
}
|
||||
ensureDirectory(to);
|
||||
try {
|
||||
out = new FileOutputStream(to);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(from.getAbsolutePath() + ": Error opening file");
|
||||
return ;
|
||||
}
|
||||
|
||||
long sizel = from.length();
|
||||
final int maxsize = 64*1024;
|
||||
int size = sizel > maxsize ? maxsize : (int)sizel;
|
||||
byte[] buf = new byte[size];
|
||||
while (true) {
|
||||
try {
|
||||
size = in.read(buf);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(from.getAbsolutePath()
|
||||
+ ": error reading file");
|
||||
break;
|
||||
}
|
||||
if (size > 0) {
|
||||
try {
|
||||
out.write(buf, 0, size);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(from.getAbsolutePath()
|
||||
+ ": error writing file");
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
try {
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Takes a string that ends w/ .html and changes the .html to htmlExtension */
|
||||
public static String outputFilename(String htmlFile) {
|
||||
if (!DroidDoc.htmlExtension.equals(".html") && htmlFile.endsWith(".html")) {
|
||||
return htmlFile.substring(0, htmlFile.length()-5) + DroidDoc.htmlExtension;
|
||||
} else {
|
||||
return htmlFile;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,395 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class Comment
|
||||
{
|
||||
static final Pattern LEADING_WHITESPACE = Pattern.compile(
|
||||
"^[ \t\n\r]*(.*)$",
|
||||
Pattern.DOTALL);
|
||||
|
||||
static final Pattern TAG_BEGIN = Pattern.compile(
|
||||
"[\r\n][\r\n \t]*@",
|
||||
Pattern.DOTALL);
|
||||
|
||||
static final Pattern TAG = Pattern.compile(
|
||||
"(@[^ \t\r\n]+)[ \t\r\n]+(.*)",
|
||||
Pattern.DOTALL);
|
||||
|
||||
static final Pattern INLINE_TAG = Pattern.compile(
|
||||
"(.*?)\\{(@[^ \t\r\n\\}]+)[ \t\r\n]*(.*?)\\}",
|
||||
Pattern.DOTALL);
|
||||
|
||||
static final Pattern FIRST_SENTENCE = Pattern.compile(
|
||||
"((.*?)\\.)[ \t\r\n\\<](.*)",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private static final String[] KNOWN_TAGS = new String[] {
|
||||
"@author",
|
||||
"@since",
|
||||
"@version",
|
||||
"@deprecated",
|
||||
"@undeprecate",
|
||||
"@docRoot",
|
||||
"@sdkCurrent",
|
||||
"@inheritDoc",
|
||||
"@more",
|
||||
"@code",
|
||||
"@samplecode",
|
||||
"@sample",
|
||||
"@include",
|
||||
"@serial",
|
||||
"@com.intel.drl.spec_ref",
|
||||
"@ar.org.fitc.spec_ref",
|
||||
};
|
||||
|
||||
public Comment(String text, ContainerInfo base, SourcePositionInfo sp)
|
||||
{
|
||||
mText = text;
|
||||
mBase = base;
|
||||
// sp now points to the end of the text, not the beginning!
|
||||
mPosition = SourcePositionInfo.findBeginning(sp, text);
|
||||
}
|
||||
|
||||
private void parseRegex(String text)
|
||||
{
|
||||
Matcher m;
|
||||
|
||||
m = LEADING_WHITESPACE.matcher(text);
|
||||
m.matches();
|
||||
text = m.group(1);
|
||||
|
||||
m = TAG_BEGIN.matcher(text);
|
||||
|
||||
int start = 0;
|
||||
int end = 0;
|
||||
while (m.find()) {
|
||||
end = m.start();
|
||||
|
||||
tag(text, start, end);
|
||||
|
||||
start = m.end()-1; // -1 is the @
|
||||
}
|
||||
end = text.length();
|
||||
tag(text, start, end);
|
||||
}
|
||||
|
||||
private void tag(String text, int start, int end)
|
||||
{
|
||||
SourcePositionInfo pos = SourcePositionInfo.add(mPosition, mText, start);
|
||||
|
||||
if (start >= 0 && end > 0 && (end-start) > 0) {
|
||||
text = text.substring(start, end);
|
||||
|
||||
Matcher m = TAG.matcher(text);
|
||||
if (m.matches()) {
|
||||
// out of line tag
|
||||
tag(m.group(1), m.group(2), false, pos);
|
||||
} else {
|
||||
// look for inline tags
|
||||
m = INLINE_TAG.matcher(text);
|
||||
start = 0;
|
||||
while (m.find()) {
|
||||
String str = m.group(1);
|
||||
String tagname = m.group(2);
|
||||
String tagvalue = m.group(3);
|
||||
tag(null, m.group(1), true, pos);
|
||||
tag(tagname, tagvalue, true, pos);
|
||||
start = m.end();
|
||||
}
|
||||
int len = text.length();
|
||||
if (start != len) {
|
||||
tag(null, text.substring(start), true, pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void tag(String name, String text, boolean isInline, SourcePositionInfo pos)
|
||||
{
|
||||
/*
|
||||
String s = isInline ? "inline" : "outofline";
|
||||
System.out.println("---> " + s
|
||||
+ " name=[" + name + "] text=[" + text + "]");
|
||||
*/
|
||||
if (name == null) {
|
||||
mInlineTagsList.add(new TextTagInfo("Text", "Text", text, pos));
|
||||
}
|
||||
else if (name.equals("@param")) {
|
||||
mParamTagsList.add(new ParamTagInfo("@param", "@param", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@see")) {
|
||||
mSeeTagsList.add(new SeeTagInfo("@see", "@see", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@link") || name.equals("@linkplain")) {
|
||||
mInlineTagsList.add(new SeeTagInfo(name, "@see", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@throws") || name.equals("@exception")) {
|
||||
mThrowsTagsList.add(new ThrowsTagInfo("@throws", "@throws", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@return")) {
|
||||
mReturnTagsList.add(new ParsedTagInfo("@return", "@return", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@deprecated")) {
|
||||
if (text.length() == 0) {
|
||||
Errors.error(Errors.MISSING_COMMENT, pos,
|
||||
"@deprecated tag with no explanatory comment");
|
||||
text = "No replacement.";
|
||||
}
|
||||
mDeprecatedTagsList.add(new ParsedTagInfo("@deprecated", "@deprecated", text, mBase, pos));
|
||||
}
|
||||
else if (name.equals("@literal")) {
|
||||
mInlineTagsList.add(new LiteralTagInfo(name, name, text, pos));
|
||||
}
|
||||
else if (name.equals("@hide") || name.equals("@pending") || name.equals("@doconly")) {
|
||||
// nothing
|
||||
}
|
||||
else if (name.equals("@attr")) {
|
||||
AttrTagInfo tag = new AttrTagInfo("@attr", "@attr", text, mBase, pos);
|
||||
mAttrTagsList.add(tag);
|
||||
Comment c = tag.description();
|
||||
if (c != null) {
|
||||
for (TagInfo t: c.tags()) {
|
||||
mInlineTagsList.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name.equals("@undeprecate")) {
|
||||
mUndeprecateTagsList.add(new TextTagInfo("@undeprecate", "@undeprecate", text, pos));
|
||||
}
|
||||
else if (name.equals("@include") || name.equals("@sample")) {
|
||||
mInlineTagsList.add(new SampleTagInfo(name, "@include", text, mBase, pos));
|
||||
}
|
||||
else {
|
||||
boolean known = false;
|
||||
for (String s: KNOWN_TAGS) {
|
||||
if (s.equals(name)) {
|
||||
known = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!known) {
|
||||
Errors.error(Errors.UNKNOWN_TAG, pos == null ? null : new SourcePositionInfo(pos),
|
||||
"Unknown tag: " + name);
|
||||
}
|
||||
TagInfo t = new TextTagInfo(name, name, text, pos);
|
||||
if (isInline) {
|
||||
mInlineTagsList.add(t);
|
||||
} else {
|
||||
mTagsList.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseBriefTags()
|
||||
{
|
||||
int N = mInlineTagsList.size();
|
||||
|
||||
// look for "@more" tag, which means that we might go past the first sentence.
|
||||
int more = -1;
|
||||
for (int i=0; i<N; i++) {
|
||||
if (mInlineTagsList.get(i).name().equals("@more")) {
|
||||
more = i;
|
||||
}
|
||||
}
|
||||
if (more >= 0) {
|
||||
for (int i=0; i<more; i++) {
|
||||
mBriefTagsList.add(mInlineTagsList.get(i));
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<N; i++) {
|
||||
TagInfo t = mInlineTagsList.get(i);
|
||||
if (t.name().equals("Text")) {
|
||||
Matcher m = FIRST_SENTENCE.matcher(t.text());
|
||||
if (m.matches()) {
|
||||
String text = m.group(1);
|
||||
TagInfo firstSentenceTag = new TagInfo(t.name(), t.kind(), text, t.position());
|
||||
mBriefTagsList.add(firstSentenceTag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mBriefTagsList.add(t);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TagInfo[] tags()
|
||||
{
|
||||
init();
|
||||
return mInlineTags;
|
||||
}
|
||||
|
||||
public TagInfo[] tags(String name)
|
||||
{
|
||||
init();
|
||||
ArrayList<TagInfo> results = new ArrayList<TagInfo>();
|
||||
int N = mInlineTagsList.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
TagInfo t = mInlineTagsList.get(i);
|
||||
if (t.name().equals(name)) {
|
||||
results.add(t);
|
||||
}
|
||||
}
|
||||
return results.toArray(new TagInfo[results.size()]);
|
||||
}
|
||||
|
||||
public ParamTagInfo[] paramTags()
|
||||
{
|
||||
init();
|
||||
return mParamTags;
|
||||
}
|
||||
|
||||
public SeeTagInfo[] seeTags()
|
||||
{
|
||||
init();
|
||||
return mSeeTags;
|
||||
}
|
||||
|
||||
public ThrowsTagInfo[] throwsTags()
|
||||
{
|
||||
init();
|
||||
return mThrowsTags;
|
||||
}
|
||||
|
||||
public TagInfo[] returnTags()
|
||||
{
|
||||
init();
|
||||
return mReturnTags;
|
||||
}
|
||||
|
||||
public TagInfo[] deprecatedTags()
|
||||
{
|
||||
init();
|
||||
return mDeprecatedTags;
|
||||
}
|
||||
|
||||
public TagInfo[] undeprecateTags()
|
||||
{
|
||||
init();
|
||||
return mUndeprecateTags;
|
||||
}
|
||||
|
||||
public AttrTagInfo[] attrTags()
|
||||
{
|
||||
init();
|
||||
return mAttrTags;
|
||||
}
|
||||
|
||||
public TagInfo[] briefTags()
|
||||
{
|
||||
init();
|
||||
return mBriefTags;
|
||||
}
|
||||
|
||||
public boolean isHidden()
|
||||
{
|
||||
if (mHidden >= 0) {
|
||||
return mHidden != 0;
|
||||
} else {
|
||||
if (DroidDoc.checkLevel(DroidDoc.SHOW_HIDDEN)) {
|
||||
mHidden = 0;
|
||||
return false;
|
||||
}
|
||||
boolean b = mText.indexOf("@hide") >= 0 || mText.indexOf("@pending") >= 0;
|
||||
mHidden = b ? 1 : 0;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDocOnly() {
|
||||
if (mDocOnly >= 0) {
|
||||
return mDocOnly != 0;
|
||||
} else {
|
||||
boolean b = (mText != null) && (mText.indexOf("@doconly") >= 0);
|
||||
mDocOnly = b ? 1 : 0;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
if (!mInitialized) {
|
||||
initImpl();
|
||||
}
|
||||
}
|
||||
|
||||
private void initImpl()
|
||||
{
|
||||
isHidden();
|
||||
isDocOnly();
|
||||
parseRegex(mText);
|
||||
parseBriefTags();
|
||||
mText = null;
|
||||
mInitialized = true;
|
||||
|
||||
mInlineTags = mInlineTagsList.toArray(new TagInfo[mInlineTagsList.size()]);
|
||||
mParamTags = mParamTagsList.toArray(new ParamTagInfo[mParamTagsList.size()]);
|
||||
mSeeTags = mSeeTagsList.toArray(new SeeTagInfo[mSeeTagsList.size()]);
|
||||
mThrowsTags = mThrowsTagsList.toArray(new ThrowsTagInfo[mThrowsTagsList.size()]);
|
||||
mReturnTags = ParsedTagInfo.joinTags(mReturnTagsList.toArray(
|
||||
new ParsedTagInfo[mReturnTagsList.size()]));
|
||||
mDeprecatedTags = ParsedTagInfo.joinTags(mDeprecatedTagsList.toArray(
|
||||
new ParsedTagInfo[mDeprecatedTagsList.size()]));
|
||||
mUndeprecateTags = mUndeprecateTagsList.toArray(new TagInfo[mUndeprecateTagsList.size()]);
|
||||
mAttrTags = mAttrTagsList.toArray(new AttrTagInfo[mAttrTagsList.size()]);
|
||||
mBriefTags = mBriefTagsList.toArray(new TagInfo[mBriefTagsList.size()]);
|
||||
|
||||
mParamTagsList = null;
|
||||
mSeeTagsList = null;
|
||||
mThrowsTagsList = null;
|
||||
mReturnTagsList = null;
|
||||
mDeprecatedTagsList = null;
|
||||
mUndeprecateTagsList = null;
|
||||
mAttrTagsList = null;
|
||||
mBriefTagsList = null;
|
||||
}
|
||||
|
||||
boolean mInitialized;
|
||||
int mHidden = -1;
|
||||
int mDocOnly = -1;
|
||||
String mText;
|
||||
ContainerInfo mBase;
|
||||
SourcePositionInfo mPosition;
|
||||
int mLine = 1;
|
||||
|
||||
TagInfo[] mInlineTags;
|
||||
TagInfo[] mTags;
|
||||
ParamTagInfo[] mParamTags;
|
||||
SeeTagInfo[] mSeeTags;
|
||||
ThrowsTagInfo[] mThrowsTags;
|
||||
TagInfo[] mBriefTags;
|
||||
TagInfo[] mReturnTags;
|
||||
TagInfo[] mDeprecatedTags;
|
||||
TagInfo[] mUndeprecateTags;
|
||||
AttrTagInfo[] mAttrTags;
|
||||
|
||||
ArrayList<TagInfo> mInlineTagsList = new ArrayList<TagInfo>();
|
||||
ArrayList<TagInfo> mTagsList = new ArrayList<TagInfo>();
|
||||
ArrayList<ParamTagInfo> mParamTagsList = new ArrayList<ParamTagInfo>();
|
||||
ArrayList<SeeTagInfo> mSeeTagsList = new ArrayList<SeeTagInfo>();
|
||||
ArrayList<ThrowsTagInfo> mThrowsTagsList = new ArrayList<ThrowsTagInfo>();
|
||||
ArrayList<TagInfo> mBriefTagsList = new ArrayList<TagInfo>();
|
||||
ArrayList<ParsedTagInfo> mReturnTagsList = new ArrayList<ParsedTagInfo>();
|
||||
ArrayList<ParsedTagInfo> mDeprecatedTagsList = new ArrayList<ParsedTagInfo>();
|
||||
ArrayList<TagInfo> mUndeprecateTagsList = new ArrayList<TagInfo>();
|
||||
ArrayList<AttrTagInfo> mAttrTagsList = new ArrayList<AttrTagInfo>();
|
||||
|
||||
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public interface ContainerInfo
|
||||
{
|
||||
public String qualifiedName();
|
||||
public boolean checkLevel();
|
||||
}
|
|
@ -1,755 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.doclets.*;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class Converter
|
||||
{
|
||||
private static RootDoc root;
|
||||
|
||||
public static void makeInfo(RootDoc r)
|
||||
{
|
||||
root = r;
|
||||
|
||||
int N, i;
|
||||
|
||||
// create the objects
|
||||
ClassDoc[] classDocs = r.classes();
|
||||
N = classDocs.length;
|
||||
for (i=0; i<N; i++) {
|
||||
Converter.obtainClass(classDocs[i]);
|
||||
}
|
||||
ArrayList<ClassInfo> classesNeedingInit2 = new ArrayList<ClassInfo>();
|
||||
// fill in the fields that reference other classes
|
||||
while (mClassesNeedingInit.size() > 0) {
|
||||
i = mClassesNeedingInit.size()-1;
|
||||
ClassNeedingInit clni = mClassesNeedingInit.get(i);
|
||||
mClassesNeedingInit.remove(i);
|
||||
|
||||
initClass(clni.c, clni.cl);
|
||||
classesNeedingInit2.add(clni.cl);
|
||||
}
|
||||
mClassesNeedingInit = null;
|
||||
for (ClassInfo cl: classesNeedingInit2) {
|
||||
cl.init2();
|
||||
}
|
||||
|
||||
finishAnnotationValueInit();
|
||||
|
||||
// fill in the "root" stuff
|
||||
mRootClasses = Converter.convertClasses(r.classes());
|
||||
}
|
||||
|
||||
private static ClassInfo[] mRootClasses;
|
||||
public static ClassInfo[] rootClasses()
|
||||
{
|
||||
return mRootClasses;
|
||||
}
|
||||
|
||||
public static ClassInfo[] allClasses() {
|
||||
return (ClassInfo[])mClasses.all();
|
||||
}
|
||||
|
||||
private static void initClass(ClassDoc c, ClassInfo cl)
|
||||
{
|
||||
MethodDoc[] annotationElements;
|
||||
if (c instanceof AnnotationTypeDoc) {
|
||||
annotationElements = ((AnnotationTypeDoc)c).elements();
|
||||
} else {
|
||||
annotationElements = new MethodDoc[0];
|
||||
}
|
||||
cl.init(Converter.obtainType(c),
|
||||
Converter.convertClasses(c.interfaces()),
|
||||
Converter.convertTypes(c.interfaceTypes()),
|
||||
Converter.convertClasses(c.innerClasses()),
|
||||
Converter.convertMethods(c.constructors(false)),
|
||||
Converter.convertMethods(c.methods(false)),
|
||||
Converter.convertMethods(annotationElements),
|
||||
Converter.convertFields(c.fields(false)),
|
||||
Converter.convertFields(c.enumConstants()),
|
||||
Converter.obtainPackage(c.containingPackage()),
|
||||
Converter.obtainClass(c.containingClass()),
|
||||
Converter.obtainClass(c.superclass()),
|
||||
Converter.obtainType(c.superclassType()),
|
||||
Converter.convertAnnotationInstances(c.annotations())
|
||||
);
|
||||
cl.setHiddenMethods(Converter.getHiddenMethods(c.methods(false)));
|
||||
cl.setNonWrittenConstructors(Converter.convertNonWrittenConstructors(c.constructors(false)));
|
||||
cl.init3(Converter.convertTypes(c.typeParameters()), Converter.convertClasses(c.innerClasses(false)));
|
||||
}
|
||||
|
||||
public static ClassInfo obtainClass(String className)
|
||||
{
|
||||
return Converter.obtainClass(root.classNamed(className));
|
||||
}
|
||||
|
||||
public static PackageInfo obtainPackage(String packageName)
|
||||
{
|
||||
return Converter.obtainPackage(root.packageNamed(packageName));
|
||||
}
|
||||
|
||||
private static TagInfo convertTag(Tag tag)
|
||||
{
|
||||
return new TextTagInfo(tag.name(), tag.kind(), tag.text(),
|
||||
Converter.convertSourcePosition(tag.position()));
|
||||
}
|
||||
|
||||
private static ThrowsTagInfo convertThrowsTag(ThrowsTag tag,
|
||||
ContainerInfo base)
|
||||
{
|
||||
return new ThrowsTagInfo(tag.name(), tag.text(), tag.kind(),
|
||||
Converter.obtainClass(tag.exception()),
|
||||
tag.exceptionComment(), base,
|
||||
Converter.convertSourcePosition(tag.position()));
|
||||
}
|
||||
|
||||
private static ParamTagInfo convertParamTag(ParamTag tag,
|
||||
ContainerInfo base)
|
||||
{
|
||||
return new ParamTagInfo(tag.name(), tag.kind(), tag.text(),
|
||||
tag.isTypeParameter(), tag.parameterComment(),
|
||||
tag.parameterName(),
|
||||
base,
|
||||
Converter.convertSourcePosition(tag.position()));
|
||||
}
|
||||
|
||||
private static SeeTagInfo convertSeeTag(SeeTag tag, ContainerInfo base)
|
||||
{
|
||||
return new SeeTagInfo(tag.name(), tag.kind(), tag.text(), base,
|
||||
Converter.convertSourcePosition(tag.position()));
|
||||
}
|
||||
|
||||
private static SourcePositionInfo convertSourcePosition(SourcePosition sp)
|
||||
{
|
||||
if (sp == null) {
|
||||
return null;
|
||||
}
|
||||
return new SourcePositionInfo(sp.file().toString(), sp.line(),
|
||||
sp.column());
|
||||
}
|
||||
|
||||
public static TagInfo[] convertTags(Tag[] tags, ContainerInfo base)
|
||||
{
|
||||
int len = tags.length;
|
||||
TagInfo[] out = new TagInfo[len];
|
||||
for (int i=0; i<len; i++) {
|
||||
Tag t = tags[i];
|
||||
/*
|
||||
System.out.println("Tag name='" + t.name() + "' kind='"
|
||||
+ t.kind() + "'");
|
||||
*/
|
||||
if (t instanceof SeeTag) {
|
||||
out[i] = Converter.convertSeeTag((SeeTag)t, base);
|
||||
}
|
||||
else if (t instanceof ThrowsTag) {
|
||||
out[i] = Converter.convertThrowsTag((ThrowsTag)t, base);
|
||||
}
|
||||
else if (t instanceof ParamTag) {
|
||||
out[i] = Converter.convertParamTag((ParamTag)t, base);
|
||||
}
|
||||
else {
|
||||
out[i] = Converter.convertTag(t);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static ClassInfo[] convertClasses(ClassDoc[] classes)
|
||||
{
|
||||
if (classes == null) return null;
|
||||
int N = classes.length;
|
||||
ClassInfo[] result = new ClassInfo[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
result[i] = Converter.obtainClass(classes[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ParameterInfo convertParameter(Parameter p, SourcePosition pos)
|
||||
{
|
||||
if (p == null) return null;
|
||||
ParameterInfo pi = new ParameterInfo(p.name(), p.typeName(),
|
||||
Converter.obtainType(p.type()),
|
||||
Converter.convertSourcePosition(pos));
|
||||
return pi;
|
||||
}
|
||||
|
||||
private static ParameterInfo[] convertParameters(Parameter[] p, MemberDoc m)
|
||||
{
|
||||
SourcePosition pos = m.position();
|
||||
int len = p.length;
|
||||
ParameterInfo[] q = new ParameterInfo[len];
|
||||
for (int i=0; i<len; i++) {
|
||||
q[i] = Converter.convertParameter(p[i], pos);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
private static TypeInfo[] convertTypes(Type[] p)
|
||||
{
|
||||
if (p == null) return null;
|
||||
int len = p.length;
|
||||
TypeInfo[] q = new TypeInfo[len];
|
||||
for (int i=0; i<len; i++) {
|
||||
q[i] = Converter.obtainType(p[i]);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
private Converter()
|
||||
{
|
||||
}
|
||||
|
||||
private static class ClassNeedingInit
|
||||
{
|
||||
ClassNeedingInit(ClassDoc c, ClassInfo cl)
|
||||
{
|
||||
this.c = c;
|
||||
this.cl = cl;
|
||||
}
|
||||
ClassDoc c;
|
||||
ClassInfo cl;
|
||||
};
|
||||
private static ArrayList<ClassNeedingInit> mClassesNeedingInit
|
||||
= new ArrayList<ClassNeedingInit>();
|
||||
|
||||
static ClassInfo obtainClass(ClassDoc o)
|
||||
{
|
||||
return (ClassInfo)mClasses.obtain(o);
|
||||
}
|
||||
private static Cache mClasses = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
ClassDoc c = (ClassDoc)o;
|
||||
ClassInfo cl = new ClassInfo(
|
||||
c,
|
||||
c.getRawCommentText(),
|
||||
Converter.convertSourcePosition(c.position()),
|
||||
c.isPublic(),
|
||||
c.isProtected(),
|
||||
c.isPackagePrivate(),
|
||||
c.isPrivate(),
|
||||
c.isStatic(),
|
||||
c.isInterface(),
|
||||
c.isAbstract(),
|
||||
c.isOrdinaryClass(),
|
||||
c.isException(),
|
||||
c.isError(),
|
||||
c.isEnum(),
|
||||
(c instanceof AnnotationTypeDoc),
|
||||
c.isFinal(),
|
||||
c.isIncluded(),
|
||||
c.name(),
|
||||
c.qualifiedName(),
|
||||
c.qualifiedTypeName(),
|
||||
c.isPrimitive());
|
||||
if (mClassesNeedingInit != null) {
|
||||
mClassesNeedingInit.add(new ClassNeedingInit(c, cl));
|
||||
}
|
||||
return cl;
|
||||
}
|
||||
@Override
|
||||
protected void made(Object o, Object r)
|
||||
{
|
||||
if (mClassesNeedingInit == null) {
|
||||
initClass((ClassDoc)o, (ClassInfo)r);
|
||||
((ClassInfo)r).init2();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
ClassInfo[] all()
|
||||
{
|
||||
return (ClassInfo[])mCache.values().toArray(new ClassInfo[mCache.size()]);
|
||||
}
|
||||
};
|
||||
|
||||
private static MethodInfo[] getHiddenMethods(MethodDoc[] methods){
|
||||
if (methods == null) return null;
|
||||
ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
|
||||
int N = methods.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
MethodInfo m = Converter.obtainMethod(methods[i]);
|
||||
//System.out.println(m.toString() + ": ");
|
||||
//for (TypeInfo ti : m.getTypeParameters()){
|
||||
// if (ti.asClassInfo() != null){
|
||||
//System.out.println(" " +ti.asClassInfo().toString());
|
||||
//} else {
|
||||
//System.out.println(" null");
|
||||
//}
|
||||
//}
|
||||
if (m.isHidden()) {
|
||||
out.add(m);
|
||||
}
|
||||
}
|
||||
return out.toArray(new MethodInfo[out.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert MethodDoc[] into MethodInfo[]. Also filters according
|
||||
* to the -private, -public option, because the filtering doesn't seem
|
||||
* to be working in the ClassDoc.constructors(boolean) call.
|
||||
*/
|
||||
private static MethodInfo[] convertMethods(MethodDoc[] methods)
|
||||
{
|
||||
if (methods == null) return null;
|
||||
ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
|
||||
int N = methods.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
MethodInfo m = Converter.obtainMethod(methods[i]);
|
||||
//System.out.println(m.toString() + ": ");
|
||||
//for (TypeInfo ti : m.getTypeParameters()){
|
||||
// if (ti.asClassInfo() != null){
|
||||
//System.out.println(" " +ti.asClassInfo().toString());
|
||||
//} else {
|
||||
//System.out.println(" null");
|
||||
//}
|
||||
//}
|
||||
if (m.checkLevel()) {
|
||||
out.add(m);
|
||||
}
|
||||
}
|
||||
return out.toArray(new MethodInfo[out.size()]);
|
||||
}
|
||||
|
||||
private static MethodInfo[] convertMethods(ConstructorDoc[] methods)
|
||||
{
|
||||
if (methods == null) return null;
|
||||
ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
|
||||
int N = methods.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
MethodInfo m = Converter.obtainMethod(methods[i]);
|
||||
if (m.checkLevel()) {
|
||||
out.add(m);
|
||||
}
|
||||
}
|
||||
return out.toArray(new MethodInfo[out.size()]);
|
||||
}
|
||||
|
||||
private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods)
|
||||
{
|
||||
if (methods == null) return null;
|
||||
ArrayList<MethodInfo> out = new ArrayList<MethodInfo>();
|
||||
int N = methods.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
MethodInfo m = Converter.obtainMethod(methods[i]);
|
||||
if (!m.checkLevel()) {
|
||||
out.add(m);
|
||||
}
|
||||
}
|
||||
return out.toArray(new MethodInfo[out.size()]);
|
||||
}
|
||||
|
||||
private static MethodInfo obtainMethod(MethodDoc o)
|
||||
{
|
||||
return (MethodInfo)mMethods.obtain(o);
|
||||
}
|
||||
private static MethodInfo obtainMethod(ConstructorDoc o)
|
||||
{
|
||||
return (MethodInfo)mMethods.obtain(o);
|
||||
}
|
||||
private static Cache mMethods = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
if (o instanceof AnnotationTypeElementDoc) {
|
||||
AnnotationTypeElementDoc m = (AnnotationTypeElementDoc)o;
|
||||
MethodInfo result = new MethodInfo(
|
||||
m.getRawCommentText(),
|
||||
Converter.convertTypes(m.typeParameters()),
|
||||
m.name(), m.signature(),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
m.isPublic(), m.isProtected(),
|
||||
m.isPackagePrivate(), m.isPrivate(),
|
||||
m.isFinal(), m.isStatic(), m.isSynthetic(),
|
||||
m.isAbstract(), m.isSynchronized(), m.isNative(), true,
|
||||
"annotationElement",
|
||||
m.flatSignature(),
|
||||
Converter.obtainMethod(m.overriddenMethod()),
|
||||
Converter.obtainType(m.returnType()),
|
||||
Converter.convertParameters(m.parameters(), m),
|
||||
Converter.convertClasses(m.thrownExceptions()),
|
||||
Converter.convertSourcePosition(m.position()),
|
||||
Converter.convertAnnotationInstances(m.annotations())
|
||||
);
|
||||
result.setVarargs(m.isVarArgs());
|
||||
result.init(Converter.obtainAnnotationValue(m.defaultValue(), result));
|
||||
return result;
|
||||
}
|
||||
else if (o instanceof MethodDoc) {
|
||||
MethodDoc m = (MethodDoc)o;
|
||||
MethodInfo result = new MethodInfo(
|
||||
m.getRawCommentText(),
|
||||
Converter.convertTypes(m.typeParameters()),
|
||||
m.name(), m.signature(),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
m.isPublic(), m.isProtected(),
|
||||
m.isPackagePrivate(), m.isPrivate(),
|
||||
m.isFinal(), m.isStatic(), m.isSynthetic(),
|
||||
m.isAbstract(), m.isSynchronized(), m.isNative(), false,
|
||||
"method",
|
||||
m.flatSignature(),
|
||||
Converter.obtainMethod(m.overriddenMethod()),
|
||||
Converter.obtainType(m.returnType()),
|
||||
Converter.convertParameters(m.parameters(), m),
|
||||
Converter.convertClasses(m.thrownExceptions()),
|
||||
Converter.convertSourcePosition(m.position()),
|
||||
Converter.convertAnnotationInstances(m.annotations())
|
||||
);
|
||||
result.setVarargs(m.isVarArgs());
|
||||
result.init(null);
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
ConstructorDoc m = (ConstructorDoc)o;
|
||||
MethodInfo result = new MethodInfo(
|
||||
m.getRawCommentText(),
|
||||
Converter.convertTypes(m.typeParameters()),
|
||||
m.name(), m.signature(),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
Converter.obtainClass(m.containingClass()),
|
||||
m.isPublic(), m.isProtected(),
|
||||
m.isPackagePrivate(), m.isPrivate(),
|
||||
m.isFinal(), m.isStatic(), m.isSynthetic(),
|
||||
false, m.isSynchronized(), m.isNative(), false,
|
||||
"constructor",
|
||||
m.flatSignature(),
|
||||
null,
|
||||
null,
|
||||
Converter.convertParameters(m.parameters(), m),
|
||||
Converter.convertClasses(m.thrownExceptions()),
|
||||
Converter.convertSourcePosition(m.position()),
|
||||
Converter.convertAnnotationInstances(m.annotations())
|
||||
);
|
||||
result.setVarargs(m.isVarArgs());
|
||||
result.init(null);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private static FieldInfo[] convertFields(FieldDoc[] fields)
|
||||
{
|
||||
if (fields == null) return null;
|
||||
ArrayList<FieldInfo> out = new ArrayList<FieldInfo>();
|
||||
int N = fields.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
FieldInfo f = Converter.obtainField(fields[i]);
|
||||
if (f.checkLevel()) {
|
||||
out.add(f);
|
||||
}
|
||||
}
|
||||
return out.toArray(new FieldInfo[out.size()]);
|
||||
}
|
||||
|
||||
private static FieldInfo obtainField(FieldDoc o)
|
||||
{
|
||||
return (FieldInfo)mFields.obtain(o);
|
||||
}
|
||||
private static FieldInfo obtainField(ConstructorDoc o)
|
||||
{
|
||||
return (FieldInfo)mFields.obtain(o);
|
||||
}
|
||||
private static Cache mFields = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
FieldDoc f = (FieldDoc)o;
|
||||
return new FieldInfo(f.name(),
|
||||
Converter.obtainClass(f.containingClass()),
|
||||
Converter.obtainClass(f.containingClass()),
|
||||
f.isPublic(), f.isProtected(),
|
||||
f.isPackagePrivate(), f.isPrivate(),
|
||||
f.isFinal(), f.isStatic(), f.isTransient(), f.isVolatile(),
|
||||
f.isSynthetic(),
|
||||
Converter.obtainType(f.type()),
|
||||
f.getRawCommentText(), f.constantValue(),
|
||||
Converter.convertSourcePosition(f.position()),
|
||||
Converter.convertAnnotationInstances(f.annotations())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
private static PackageInfo obtainPackage(PackageDoc o)
|
||||
{
|
||||
return (PackageInfo)mPackagees.obtain(o);
|
||||
}
|
||||
private static Cache mPackagees = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
PackageDoc p = (PackageDoc)o;
|
||||
return new PackageInfo(p, p.name(),
|
||||
Converter.convertSourcePosition(p.position()));
|
||||
}
|
||||
};
|
||||
|
||||
private static TypeInfo obtainType(Type o)
|
||||
{
|
||||
return (TypeInfo)mTypes.obtain(o);
|
||||
}
|
||||
private static Cache mTypes = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
Type t = (Type)o;
|
||||
String simpleTypeName;
|
||||
if (t instanceof ClassDoc) {
|
||||
simpleTypeName = ((ClassDoc)t).name();
|
||||
} else {
|
||||
simpleTypeName = t.simpleTypeName();
|
||||
}
|
||||
TypeInfo ti = new TypeInfo(t.isPrimitive(), t.dimension(),
|
||||
simpleTypeName, t.qualifiedTypeName(),
|
||||
Converter.obtainClass(t.asClassDoc()));
|
||||
return ti;
|
||||
}
|
||||
@Override
|
||||
protected void made(Object o, Object r)
|
||||
{
|
||||
Type t = (Type)o;
|
||||
TypeInfo ti = (TypeInfo)r;
|
||||
if (t.asParameterizedType() != null) {
|
||||
ti.setTypeArguments(Converter.convertTypes(
|
||||
t.asParameterizedType().typeArguments()));
|
||||
}
|
||||
else if (t instanceof ClassDoc) {
|
||||
ti.setTypeArguments(Converter.convertTypes(((ClassDoc)t).typeParameters()));
|
||||
}
|
||||
else if (t.asTypeVariable() != null) {
|
||||
ti.setBounds(null, Converter.convertTypes((t.asTypeVariable().bounds())));
|
||||
ti.setIsTypeVariable(true);
|
||||
}
|
||||
else if (t.asWildcardType() != null) {
|
||||
ti.setIsWildcard(true);
|
||||
ti.setBounds(Converter.convertTypes(t.asWildcardType().superBounds()),
|
||||
Converter.convertTypes(t.asWildcardType().extendsBounds()));
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected Object keyFor(Object o)
|
||||
{
|
||||
Type t = (Type)o;
|
||||
String keyString = o.getClass().getName() + "/" + o.toString() + "/";
|
||||
if (t.asParameterizedType() != null){
|
||||
keyString += t.asParameterizedType().toString() +"/";
|
||||
if (t.asParameterizedType().typeArguments() != null){
|
||||
for(Type ty : t.asParameterizedType().typeArguments()){
|
||||
keyString += ty.toString() + "/";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
keyString += "NoParameterizedType//";
|
||||
}
|
||||
if (t.asTypeVariable() != null){
|
||||
keyString += t.asTypeVariable().toString() +"/";
|
||||
if (t.asTypeVariable().bounds() != null){
|
||||
for(Type ty : t.asTypeVariable().bounds()){
|
||||
keyString += ty.toString() + "/";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
keyString += "NoTypeVariable//";
|
||||
}
|
||||
if (t.asWildcardType() != null){
|
||||
keyString += t.asWildcardType().toString() +"/";
|
||||
if (t.asWildcardType().superBounds() != null){
|
||||
for(Type ty : t.asWildcardType().superBounds()){
|
||||
keyString += ty.toString() + "/";
|
||||
}
|
||||
}
|
||||
if (t.asWildcardType().extendsBounds() != null){
|
||||
for(Type ty : t.asWildcardType().extendsBounds()){
|
||||
keyString += ty.toString() + "/";
|
||||
}
|
||||
}
|
||||
}else{
|
||||
keyString += "NoWildCardType//";
|
||||
}
|
||||
|
||||
|
||||
|
||||
return keyString;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
private static MemberInfo obtainMember(MemberDoc o)
|
||||
{
|
||||
return (MemberInfo)mMembers.obtain(o);
|
||||
}
|
||||
private static Cache mMembers = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
if (o instanceof MethodDoc) {
|
||||
return Converter.obtainMethod((MethodDoc)o);
|
||||
}
|
||||
else if (o instanceof ConstructorDoc) {
|
||||
return Converter.obtainMethod((ConstructorDoc)o);
|
||||
}
|
||||
else if (o instanceof FieldDoc) {
|
||||
return Converter.obtainField((FieldDoc)o);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static AnnotationInstanceInfo[] convertAnnotationInstances(AnnotationDesc[] orig)
|
||||
{
|
||||
int len = orig.length;
|
||||
AnnotationInstanceInfo[] out = new AnnotationInstanceInfo[len];
|
||||
for (int i=0; i<len; i++) {
|
||||
out[i] = Converter.obtainAnnotationInstance(orig[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
private static AnnotationInstanceInfo obtainAnnotationInstance(AnnotationDesc o)
|
||||
{
|
||||
return (AnnotationInstanceInfo)mAnnotationInstances.obtain(o);
|
||||
}
|
||||
private static Cache mAnnotationInstances = new Cache()
|
||||
{
|
||||
@Override
|
||||
protected Object make(Object o)
|
||||
{
|
||||
AnnotationDesc a = (AnnotationDesc)o;
|
||||
ClassInfo annotationType = Converter.obtainClass(a.annotationType());
|
||||
AnnotationDesc.ElementValuePair[] ev = a.elementValues();
|
||||
AnnotationValueInfo[] elementValues = new AnnotationValueInfo[ev.length];
|
||||
for (int i=0; i<ev.length; i++) {
|
||||
elementValues[i] = obtainAnnotationValue(ev[i].value(),
|
||||
Converter.obtainMethod(ev[i].element()));
|
||||
}
|
||||
return new AnnotationInstanceInfo(annotationType, elementValues);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private abstract static class Cache
|
||||
{
|
||||
void put(Object key, Object value)
|
||||
{
|
||||
mCache.put(key, value);
|
||||
}
|
||||
Object obtain(Object o)
|
||||
{
|
||||
if (o == null ) {
|
||||
return null;
|
||||
}
|
||||
Object k = keyFor(o);
|
||||
Object r = mCache.get(k);
|
||||
if (r == null) {
|
||||
r = make(o);
|
||||
mCache.put(k, r);
|
||||
made(o, r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
protected HashMap<Object,Object> mCache = new HashMap<Object,Object>();
|
||||
protected abstract Object make(Object o);
|
||||
protected void made(Object o, Object r)
|
||||
{
|
||||
}
|
||||
protected Object keyFor(Object o) { return o; }
|
||||
Object[] all() { return null; }
|
||||
}
|
||||
|
||||
// annotation values
|
||||
private static HashMap<AnnotationValue,AnnotationValueInfo> mAnnotationValues = new HashMap();
|
||||
private static HashSet<AnnotationValue> mAnnotationValuesNeedingInit = new HashSet();
|
||||
|
||||
private static AnnotationValueInfo obtainAnnotationValue(AnnotationValue o, MethodInfo element)
|
||||
{
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
AnnotationValueInfo v = mAnnotationValues.get(o);
|
||||
if (v != null) return v;
|
||||
v = new AnnotationValueInfo(element);
|
||||
mAnnotationValues.put(o, v);
|
||||
if (mAnnotationValuesNeedingInit != null) {
|
||||
mAnnotationValuesNeedingInit.add(o);
|
||||
} else {
|
||||
initAnnotationValue(o, v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
private static void initAnnotationValue(AnnotationValue o, AnnotationValueInfo v) {
|
||||
Object orig = o.value();
|
||||
Object converted;
|
||||
if (orig instanceof Type) {
|
||||
// class literal
|
||||
converted = Converter.obtainType((Type)orig);
|
||||
}
|
||||
else if (orig instanceof FieldDoc) {
|
||||
// enum constant
|
||||
converted = Converter.obtainField((FieldDoc)orig);
|
||||
}
|
||||
else if (orig instanceof AnnotationDesc) {
|
||||
// annotation instance
|
||||
converted = Converter.obtainAnnotationInstance((AnnotationDesc)orig);
|
||||
}
|
||||
else if (orig instanceof AnnotationValue[]) {
|
||||
AnnotationValue[] old = (AnnotationValue[])orig;
|
||||
AnnotationValueInfo[] array = new AnnotationValueInfo[old.length];
|
||||
for (int i=0; i<array.length; i++) {
|
||||
array[i] = Converter.obtainAnnotationValue(old[i], null);
|
||||
}
|
||||
converted = array;
|
||||
}
|
||||
else {
|
||||
converted = orig;
|
||||
}
|
||||
v.init(converted);
|
||||
}
|
||||
|
||||
private static void finishAnnotationValueInit()
|
||||
{
|
||||
int depth = 0;
|
||||
while (mAnnotationValuesNeedingInit.size() > 0) {
|
||||
HashSet<AnnotationValue> set = mAnnotationValuesNeedingInit;
|
||||
mAnnotationValuesNeedingInit = new HashSet();
|
||||
for (AnnotationValue o: set) {
|
||||
AnnotationValueInfo v = mAnnotationValues.get(o);
|
||||
initAnnotationValue(o, v);
|
||||
}
|
||||
depth++;
|
||||
}
|
||||
mAnnotationValuesNeedingInit = null;
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
|
||||
public class DocFile
|
||||
{
|
||||
private static final Pattern LINE = Pattern.compile("(.*)[\r]?\n",
|
||||
Pattern.MULTILINE);
|
||||
private static final Pattern PROP = Pattern.compile("([^=]+)=(.*)");
|
||||
|
||||
public static String readFile(String filename)
|
||||
{
|
||||
try {
|
||||
File f = new File(filename);
|
||||
int length = (int)f.length();
|
||||
FileInputStream is = new FileInputStream(f);
|
||||
InputStreamReader reader = new InputStreamReader(is, "UTF-8");
|
||||
char[] buf = new char[length];
|
||||
int index = 0;
|
||||
int amt;
|
||||
while (true) {
|
||||
amt = reader.read(buf, index, length-index);
|
||||
|
||||
if (amt < 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
index += amt;
|
||||
}
|
||||
return new String(buf, 0, index);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void writePage(String docfile, String relative,
|
||||
String outfile)
|
||||
{
|
||||
HDF hdf = DroidDoc.makeHDF();
|
||||
|
||||
/*
|
||||
System.out.println("docfile='" + docfile
|
||||
+ "' relative='" + relative + "'"
|
||||
+ "' outfile='" + outfile + "'");
|
||||
*/
|
||||
|
||||
String filedata = readFile(docfile);
|
||||
|
||||
// The document is properties up until the line "@jd:body".
|
||||
// Any blank lines are ignored.
|
||||
int start = -1;
|
||||
int lineno = 1;
|
||||
Matcher lines = LINE.matcher(filedata);
|
||||
String line = null;
|
||||
while (lines.find()) {
|
||||
line = lines.group(1);
|
||||
if (line.length() > 0) {
|
||||
if (line.equals("@jd:body")) {
|
||||
start = lines.end();
|
||||
break;
|
||||
}
|
||||
Matcher prop = PROP.matcher(line);
|
||||
if (prop.matches()) {
|
||||
String key = prop.group(1);
|
||||
String value = prop.group(2);
|
||||
hdf.setValue(key, value);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
lineno++;
|
||||
}
|
||||
if (start < 0) {
|
||||
System.err.println(docfile + ":" + lineno + ": error parsing docfile");
|
||||
if (line != null) {
|
||||
System.err.println(docfile + ":" + lineno + ":" + line);
|
||||
}
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// if they asked to only be for a certain template, maybe skip it
|
||||
String fromTemplate = hdf.getValue("template.which", "");
|
||||
String fromPage = hdf.getValue("page.onlyfortemplate", "");
|
||||
if (!"".equals(fromPage) && !fromTemplate.equals(fromPage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// and the actual text after that
|
||||
String commentText = filedata.substring(start);
|
||||
|
||||
Comment comment = new Comment(commentText, null,
|
||||
new SourcePositionInfo(docfile, lineno, 1));
|
||||
TagInfo[] tags = comment.tags();
|
||||
|
||||
TagInfo.makeHDF(hdf, "root.descr", tags);
|
||||
|
||||
hdf.setValue("commentText", commentText);
|
||||
|
||||
// write the page using the appropriate root template, based on the
|
||||
// whichdoc value supplied by build
|
||||
String fromWhichmodule = hdf.getValue("android.whichmodule", "");
|
||||
if (fromWhichmodule.equals("online-pdk")) {
|
||||
//leaving this in just for temporary compatibility with pdk doc
|
||||
hdf.setValue("online-pdk", "true");
|
||||
// add any conditional login for root template here (such as
|
||||
// for custom left nav based on tab etc.
|
||||
ClearPage.write(hdf, "docpage.cs", outfile);
|
||||
} else {
|
||||
if (outfile.indexOf("sdk/") != -1) {
|
||||
hdf.setValue("sdk", "true");
|
||||
if ((outfile.indexOf("index.html") != -1) || (outfile.indexOf("features.html") != -1)) {
|
||||
ClearPage.write(hdf, "sdkpage.cs", outfile);
|
||||
} else {
|
||||
ClearPage.write(hdf, "docpage.cs", outfile);
|
||||
}
|
||||
} else if (outfile.indexOf("guide/") != -1) {
|
||||
hdf.setValue("guide", "true");
|
||||
ClearPage.write(hdf, "docpage.cs", outfile);
|
||||
} else if (outfile.indexOf("resources/") != -1) {
|
||||
hdf.setValue("resources", "true");
|
||||
ClearPage.write(hdf, "docpage.cs", outfile);
|
||||
} else {
|
||||
ClearPage.write(hdf, "nosidenavpage.cs", outfile);
|
||||
}
|
||||
}
|
||||
} //writePage
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public abstract class DocInfo
|
||||
{
|
||||
public DocInfo(String rawCommentText, SourcePositionInfo sp)
|
||||
{
|
||||
mRawCommentText = rawCommentText;
|
||||
mPosition = sp;
|
||||
}
|
||||
|
||||
public boolean isHidden()
|
||||
{
|
||||
return comment().isHidden();
|
||||
}
|
||||
|
||||
public boolean isDocOnly() {
|
||||
return comment().isDocOnly();
|
||||
}
|
||||
|
||||
public String getRawCommentText()
|
||||
{
|
||||
return mRawCommentText;
|
||||
}
|
||||
|
||||
public Comment comment()
|
||||
{
|
||||
if (mComment == null) {
|
||||
mComment = new Comment(mRawCommentText, parent(), mPosition);
|
||||
}
|
||||
return mComment;
|
||||
}
|
||||
|
||||
public SourcePositionInfo position()
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public abstract ContainerInfo parent();
|
||||
|
||||
public void setSince(String since) {
|
||||
mSince = since;
|
||||
}
|
||||
|
||||
public String getSince() {
|
||||
return mSince;
|
||||
}
|
||||
|
||||
private String mRawCommentText;
|
||||
Comment mComment;
|
||||
SourcePositionInfo mPosition;
|
||||
private String mSince;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class Errors
|
||||
{
|
||||
public static boolean hadError = false;
|
||||
private static boolean warningsAreErrors = false;
|
||||
private static TreeSet<Message> allErrors = new TreeSet<Message>();
|
||||
|
||||
private static class Message implements Comparable {
|
||||
SourcePositionInfo pos;
|
||||
int level;
|
||||
String msg;
|
||||
|
||||
Message(SourcePositionInfo p, int l, String m) {
|
||||
pos = p;
|
||||
level = l;
|
||||
msg = m;
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
Message that = (Message)o;
|
||||
int r = this.pos.compareTo(that.pos);
|
||||
if (r != 0) return r;
|
||||
return this.msg.compareTo(that.msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String whereText = this.pos == null ? "unknown: " : this.pos.toString() + ':';
|
||||
return whereText + this.msg;
|
||||
}
|
||||
}
|
||||
|
||||
public static void error(Error error, SourcePositionInfo where, String text) {
|
||||
if (error.level == HIDDEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
int level = (!warningsAreErrors && error.level == WARNING) ? WARNING : ERROR;
|
||||
String which = level == WARNING ? " warning " : " error ";
|
||||
String message = which + error.code + ": " + text;
|
||||
|
||||
if (where == null) {
|
||||
where = new SourcePositionInfo("unknown", 0, 0);
|
||||
}
|
||||
|
||||
allErrors.add(new Message(where, level, message));
|
||||
|
||||
if (error.level == ERROR || (warningsAreErrors && error.level == WARNING)) {
|
||||
hadError = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static void printErrors() {
|
||||
for (Message m: allErrors) {
|
||||
if (m.level == WARNING) {
|
||||
System.err.println(m.toString());
|
||||
}
|
||||
}
|
||||
for (Message m: allErrors) {
|
||||
if (m.level == ERROR) {
|
||||
System.err.println(m.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int HIDDEN = 0;
|
||||
public static int WARNING = 1;
|
||||
public static int ERROR = 2;
|
||||
|
||||
public static void setWarningsAreErrors(boolean val) {
|
||||
warningsAreErrors = val;
|
||||
}
|
||||
|
||||
public static class Error {
|
||||
public int code;
|
||||
public int level;
|
||||
|
||||
public Error(int code, int level)
|
||||
{
|
||||
this.code = code;
|
||||
this.level = level;
|
||||
}
|
||||
}
|
||||
|
||||
public static Error UNRESOLVED_LINK = new Error(1, WARNING);
|
||||
public static Error BAD_INCLUDE_TAG = new Error(2, WARNING);
|
||||
public static Error UNKNOWN_TAG = new Error(3, WARNING);
|
||||
public static Error UNKNOWN_PARAM_TAG_NAME = new Error(4, WARNING);
|
||||
public static Error UNDOCUMENTED_PARAMETER = new Error(5, HIDDEN);
|
||||
public static Error BAD_ATTR_TAG = new Error(6, ERROR);
|
||||
public static Error BAD_INHERITDOC = new Error(7, HIDDEN);
|
||||
public static Error HIDDEN_LINK = new Error(8, WARNING);
|
||||
public static Error HIDDEN_CONSTRUCTOR = new Error(9, WARNING);
|
||||
public static Error UNAVAILABLE_SYMBOL = new Error(10, ERROR);
|
||||
public static Error HIDDEN_SUPERCLASS = new Error(11, WARNING);
|
||||
public static Error DEPRECATED = new Error(12, HIDDEN);
|
||||
public static Error DEPRECATION_MISMATCH = new Error(13, WARNING);
|
||||
public static Error MISSING_COMMENT = new Error(14, WARNING);
|
||||
public static Error IO_ERROR = new Error(15, HIDDEN);
|
||||
public static Error NO_SINCE_DATA = new Error(16, HIDDEN);
|
||||
|
||||
public static Error[] ERRORS = {
|
||||
UNRESOLVED_LINK,
|
||||
BAD_INCLUDE_TAG,
|
||||
UNKNOWN_TAG,
|
||||
UNKNOWN_PARAM_TAG_NAME,
|
||||
UNDOCUMENTED_PARAMETER,
|
||||
BAD_ATTR_TAG,
|
||||
BAD_INHERITDOC,
|
||||
HIDDEN_LINK,
|
||||
HIDDEN_CONSTRUCTOR,
|
||||
UNAVAILABLE_SYMBOL,
|
||||
HIDDEN_SUPERCLASS,
|
||||
DEPRECATED,
|
||||
IO_ERROR,
|
||||
NO_SINCE_DATA,
|
||||
};
|
||||
|
||||
public static boolean setErrorLevel(int code, int level) {
|
||||
for (Error e: ERRORS) {
|
||||
if (e.code == code) {
|
||||
e.level = level;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,317 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
public class FieldInfo extends MemberInfo
|
||||
{
|
||||
public static final Comparator<FieldInfo> comparator = new Comparator<FieldInfo>() {
|
||||
public int compare(FieldInfo a, FieldInfo b) {
|
||||
return a.name().compareTo(b.name());
|
||||
}
|
||||
};
|
||||
|
||||
public FieldInfo(String name, ClassInfo containingClass, ClassInfo realContainingClass,
|
||||
boolean isPublic, boolean isProtected,
|
||||
boolean isPackagePrivate, boolean isPrivate,
|
||||
boolean isFinal, boolean isStatic, boolean isTransient, boolean isVolatile,
|
||||
boolean isSynthetic, TypeInfo type, String rawCommentText,
|
||||
Object constantValue,
|
||||
SourcePositionInfo position,
|
||||
AnnotationInstanceInfo[] annotations)
|
||||
{
|
||||
super(rawCommentText, name, null, containingClass, realContainingClass,
|
||||
isPublic, isProtected, isPackagePrivate, isPrivate,
|
||||
isFinal, isStatic, isSynthetic, chooseKind(isFinal, isStatic), position,
|
||||
annotations);
|
||||
mIsTransient = isTransient;
|
||||
mIsVolatile = isVolatile;
|
||||
mType = type;
|
||||
mConstantValue = constantValue;
|
||||
}
|
||||
|
||||
public FieldInfo cloneForClass(ClassInfo newContainingClass) {
|
||||
return new FieldInfo(name(), newContainingClass, realContainingClass(),
|
||||
isPublic(), isProtected(), isPackagePrivate(),
|
||||
isPrivate(), isFinal(), isStatic(), isTransient(), isVolatile(),
|
||||
isSynthetic(), mType, getRawCommentText(), mConstantValue, position(),
|
||||
annotations());
|
||||
}
|
||||
|
||||
static String chooseKind(boolean isFinal, boolean isStatic)
|
||||
{
|
||||
if (isStatic && isFinal) {
|
||||
return "constant";
|
||||
} else {
|
||||
return "field";
|
||||
}
|
||||
}
|
||||
|
||||
public TypeInfo type()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
public boolean isConstant()
|
||||
{
|
||||
return isStatic() && isFinal();
|
||||
}
|
||||
|
||||
public TagInfo[] firstSentenceTags()
|
||||
{
|
||||
return comment().briefTags();
|
||||
}
|
||||
|
||||
public TagInfo[] inlineTags()
|
||||
{
|
||||
return comment().tags();
|
||||
}
|
||||
|
||||
public Object constantValue()
|
||||
{
|
||||
return mConstantValue;
|
||||
}
|
||||
|
||||
public String constantLiteralValue()
|
||||
{
|
||||
return constantLiteralValue(mConstantValue);
|
||||
}
|
||||
|
||||
public boolean isDeprecated() {
|
||||
boolean deprecated = false;
|
||||
if (!mDeprecatedKnown) {
|
||||
boolean commentDeprecated = (comment().deprecatedTags().length > 0);
|
||||
boolean annotationDeprecated = false;
|
||||
for (AnnotationInstanceInfo annotation : annotations()) {
|
||||
if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
|
||||
annotationDeprecated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (commentDeprecated != annotationDeprecated) {
|
||||
Errors.error(Errors.DEPRECATION_MISMATCH, position(),
|
||||
"Field " + mContainingClass.qualifiedName() + "." + name()
|
||||
+ ": @Deprecated annotation and @deprecated comment do not match");
|
||||
}
|
||||
|
||||
mIsDeprecated = commentDeprecated | annotationDeprecated;
|
||||
mDeprecatedKnown = true;
|
||||
}
|
||||
return mIsDeprecated;
|
||||
}
|
||||
|
||||
public static String constantLiteralValue(Object val)
|
||||
{
|
||||
String str = null;
|
||||
if (val != null) {
|
||||
if (val instanceof Boolean
|
||||
|| val instanceof Byte
|
||||
|| val instanceof Short
|
||||
|| val instanceof Integer)
|
||||
{
|
||||
str = val.toString();
|
||||
}
|
||||
//catch all special values
|
||||
else if (val instanceof Double){
|
||||
Double dbl = (Double) val;
|
||||
if (dbl.toString().equals("Infinity")){
|
||||
str = "(1.0 / 0.0)";
|
||||
} else if (dbl.toString().equals("-Infinity")) {
|
||||
str = "(-1.0 / 0.0)";
|
||||
} else if (dbl.isNaN()) {
|
||||
str = "(0.0 / 0.0)";
|
||||
} else {
|
||||
str = dbl.toString();
|
||||
}
|
||||
}
|
||||
else if (val instanceof Long) {
|
||||
str = val.toString() + "L";
|
||||
}
|
||||
else if (val instanceof Float) {
|
||||
Float fl = (Float) val;
|
||||
if (fl.toString().equals("Infinity")) {
|
||||
str = "(1.0f / 0.0f)";
|
||||
} else if (fl.toString().equals("-Infinity")) {
|
||||
str = "(-1.0f / 0.0f)";
|
||||
} else if (fl.isNaN()) {
|
||||
str = "(0.0f / 0.0f)";
|
||||
} else {
|
||||
str = val.toString() + "f";
|
||||
}
|
||||
}
|
||||
else if (val instanceof Character) {
|
||||
str = String.format("\'\\u%04x\'", val);
|
||||
}
|
||||
else if (val instanceof String) {
|
||||
str = "\"" + javaEscapeString((String)val) + "\"";
|
||||
}
|
||||
else {
|
||||
str = "<<<<" +val.toString() + ">>>>";
|
||||
}
|
||||
}
|
||||
if (str == null) {
|
||||
str = "null";
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static String javaEscapeString(String str) {
|
||||
String result = "";
|
||||
final int N = str.length();
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c == '\\') {
|
||||
result += "\\\\";
|
||||
}
|
||||
else if (c == '\t') {
|
||||
result += "\\t";
|
||||
}
|
||||
else if (c == '\b') {
|
||||
result += "\\b";
|
||||
}
|
||||
else if (c == '\r') {
|
||||
result += "\\r";
|
||||
}
|
||||
else if (c == '\n') {
|
||||
result += "\\n";
|
||||
}
|
||||
else if (c == '\f') {
|
||||
result += "\\f";
|
||||
}
|
||||
else if (c == '\'') {
|
||||
result += "\\'";
|
||||
}
|
||||
else if (c == '\"') {
|
||||
result += "\\\"";
|
||||
}
|
||||
else if (c >= ' ' && c <= '~') {
|
||||
result += c;
|
||||
}
|
||||
else {
|
||||
result += String.format("\\u%04x", new Integer((int)c));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".kind", kind());
|
||||
type().makeHDF(data, base + ".type");
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".href", htmlPage());
|
||||
data.setValue(base + ".anchor", anchor());
|
||||
TagInfo.makeHDF(data, base + ".shortDescr", firstSentenceTags());
|
||||
TagInfo.makeHDF(data, base + ".descr", inlineTags());
|
||||
TagInfo.makeHDF(data, base + ".deprecated", comment().deprecatedTags());
|
||||
TagInfo.makeHDF(data, base + ".seeAlso", comment().seeTags());
|
||||
data.setValue(base + ".since", getSince());
|
||||
data.setValue(base + ".final", isFinal() ? "final" : "");
|
||||
data.setValue(base + ".static", isStatic() ? "static" : "");
|
||||
if (isPublic()) {
|
||||
data.setValue(base + ".scope", "public");
|
||||
}
|
||||
else if (isProtected()) {
|
||||
data.setValue(base + ".scope", "protected");
|
||||
}
|
||||
else if (isPackagePrivate()) {
|
||||
data.setValue(base + ".scope", "");
|
||||
}
|
||||
else if (isPrivate()) {
|
||||
data.setValue(base + ".scope", "private");
|
||||
}
|
||||
Object val = mConstantValue;
|
||||
if (val != null) {
|
||||
String dec = null;
|
||||
String hex = null;
|
||||
String str = null;
|
||||
|
||||
if (val instanceof Boolean) {
|
||||
str = ((Boolean)val).toString();
|
||||
}
|
||||
else if (val instanceof Byte) {
|
||||
dec = String.format("%d", val);
|
||||
hex = String.format("0x%02x", val);
|
||||
}
|
||||
else if (val instanceof Character) {
|
||||
dec = String.format("\'%c\'", val);
|
||||
hex = String.format("0x%04x", val);
|
||||
}
|
||||
else if (val instanceof Double) {
|
||||
str = ((Double)val).toString();
|
||||
}
|
||||
else if (val instanceof Float) {
|
||||
str = ((Float)val).toString();
|
||||
}
|
||||
else if (val instanceof Integer) {
|
||||
dec = String.format("%d", val);
|
||||
hex = String.format("0x%08x", val);
|
||||
}
|
||||
else if (val instanceof Long) {
|
||||
dec = String.format("%d", val);
|
||||
hex = String.format("0x%016x", val);
|
||||
}
|
||||
else if (val instanceof Short) {
|
||||
dec = String.format("%d", val);
|
||||
hex = String.format("0x%04x", val);
|
||||
}
|
||||
else if (val instanceof String) {
|
||||
str = "\"" + ((String)val) + "\"";
|
||||
}
|
||||
else {
|
||||
str = "";
|
||||
}
|
||||
|
||||
if (dec != null && hex != null) {
|
||||
data.setValue(base + ".constantValue.dec", DroidDoc.escape(dec));
|
||||
data.setValue(base + ".constantValue.hex", DroidDoc.escape(hex));
|
||||
}
|
||||
else {
|
||||
data.setValue(base + ".constantValue.str", DroidDoc.escape(str));
|
||||
data.setValue(base + ".constantValue.isString", "1");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecutable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isTransient()
|
||||
{
|
||||
return mIsTransient;
|
||||
}
|
||||
|
||||
public boolean isVolatile()
|
||||
{
|
||||
return mIsVolatile;
|
||||
}
|
||||
|
||||
boolean mIsTransient;
|
||||
boolean mIsVolatile;
|
||||
boolean mDeprecatedKnown;
|
||||
boolean mIsDeprecated;
|
||||
TypeInfo mType;
|
||||
Object mConstantValue;
|
||||
}
|
||||
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.Set;
|
||||
import org.clearsilver.HDF;
|
||||
|
||||
public class Hierarchy
|
||||
{
|
||||
public static void makeHierarchy(HDF hdf, ClassInfo[] classes)
|
||||
{
|
||||
HashMap<String,TreeSet<String>> nodes
|
||||
= new HashMap<String,TreeSet<String>>();
|
||||
|
||||
for (ClassInfo cl: classes) {
|
||||
String name = cl.qualifiedName();
|
||||
|
||||
TreeSet<String> me = nodes.get(name);
|
||||
if (me == null) {
|
||||
me = new TreeSet<String>();
|
||||
nodes.put(name, me);
|
||||
}
|
||||
|
||||
ClassInfo superclass = cl.superclass();
|
||||
String sname = superclass != null
|
||||
? superclass.qualifiedName() : null;
|
||||
if (sname != null) {
|
||||
TreeSet<String> s = nodes.get(sname);
|
||||
if (s == null) {
|
||||
s = new TreeSet<String>();
|
||||
nodes.put(sname, s);
|
||||
}
|
||||
s.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Set<String> keys = nodes.keySet();
|
||||
for (String n: keys) {
|
||||
System.out.println("class: " + n);
|
||||
|
||||
TreeSet<String> values = nodes.get(n);
|
||||
for (String v: values) {
|
||||
System.out.println(" - " + v);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
int depth = depth(nodes, "java.lang.Object");
|
||||
|
||||
hdf.setValue("classes.0", "");
|
||||
hdf.setValue("colspan", "" + depth);
|
||||
|
||||
recurse(nodes, "java.lang.Object", hdf.getObj("classes.0"),depth,depth);
|
||||
|
||||
if (false) {
|
||||
Set<String> keys = nodes.keySet();
|
||||
if (keys.size() > 0) {
|
||||
System.err.println("The following classes are hidden but"
|
||||
+ " are superclasses of not-hidden classes");
|
||||
for (String n: keys) {
|
||||
System.err.println(" " + n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int depth(HashMap<String,TreeSet<String>> nodes,
|
||||
String name)
|
||||
{
|
||||
int d = 0;
|
||||
TreeSet<String> derived = nodes.get(name);
|
||||
if (derived != null && derived.size() > 0) {
|
||||
for (String s: derived) {
|
||||
int n = depth(nodes, s);
|
||||
if (n > d) {
|
||||
d = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return d + 1;
|
||||
}
|
||||
|
||||
private static boolean exists(ClassInfo cl)
|
||||
{
|
||||
return cl != null && !cl.isHidden() && cl.isIncluded();
|
||||
}
|
||||
|
||||
private static void recurse(HashMap<String,TreeSet<String>> nodes,
|
||||
String name, HDF hdf,
|
||||
int totalDepth, int remainingDepth)
|
||||
{
|
||||
int i;
|
||||
|
||||
hdf.setValue("indent", "" + (totalDepth-remainingDepth-1));
|
||||
hdf.setValue("colspan", "" + remainingDepth);
|
||||
|
||||
ClassInfo cl = Converter.obtainClass(name);
|
||||
|
||||
hdf.setValue("class.label", cl.name());
|
||||
hdf.setValue("class.qualified", cl.qualifiedName());
|
||||
if (cl.checkLevel()) {
|
||||
hdf.setValue("class.link", cl.htmlPage());
|
||||
}
|
||||
|
||||
if (exists(cl)) {
|
||||
hdf.setValue("exists", "1");
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for (ClassInfo iface: cl.interfaces()) {
|
||||
hdf.setValue("interfaces." + i + ".class.label", iface.name());
|
||||
hdf.setValue("interfaces." + i + ".class.qualified", iface.qualifiedName());
|
||||
if (iface.checkLevel()) {
|
||||
hdf.setValue("interfaces." + i + ".class.link", iface.htmlPage());
|
||||
}
|
||||
if (exists(cl)) {
|
||||
hdf.setValue("interfaces." + i + ".exists", "1");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
TreeSet<String> derived = nodes.get(name);
|
||||
if (derived != null && derived.size() > 0) {
|
||||
hdf.setValue("derived", "");
|
||||
HDF children = hdf.getObj("derived");
|
||||
i = 0;
|
||||
remainingDepth--;
|
||||
for (String s: derived) {
|
||||
String index = "" + i;
|
||||
children.setValue(index, "");
|
||||
recurse(nodes, s, children.getObj(index), totalDepth,
|
||||
remainingDepth);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
nodes.remove(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public interface InheritedTags
|
||||
{
|
||||
TagInfo[] tags();
|
||||
InheritedTags inherited();
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
class KeywordEntry implements Comparable
|
||||
{
|
||||
KeywordEntry(String label, String href, String comment)
|
||||
{
|
||||
this.label = label;
|
||||
this.href = href;
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".label", this.label);
|
||||
data.setValue(base + ".href", this.href);
|
||||
data.setValue(base + ".comment", this.comment);
|
||||
}
|
||||
|
||||
public char firstChar()
|
||||
{
|
||||
return Character.toUpperCase(this.label.charAt(0));
|
||||
}
|
||||
|
||||
public int compareTo(Object that)
|
||||
{
|
||||
return this.label.compareToIgnoreCase(((KeywordEntry)that).label);
|
||||
}
|
||||
|
||||
private String label;
|
||||
private String href;
|
||||
private String comment;
|
||||
}
|
||||
|
||||
|
|
@ -1,446 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Class that represents what you see in an link or see tag. This is
|
||||
* factored out of SeeTagInfo so it can be used elsewhere (like AttrTagInfo).
|
||||
*/
|
||||
public class LinkReference {
|
||||
|
||||
/** The original text. */
|
||||
public String text;
|
||||
|
||||
/** The kind of this tag, if we have a new suggestion after parsing. */
|
||||
public String kind;
|
||||
|
||||
/** The user visible text. */
|
||||
public String label;
|
||||
|
||||
/** The link. */
|
||||
public String href;
|
||||
|
||||
/** The {@link PackageInfo} if any. */
|
||||
public PackageInfo packageInfo;
|
||||
|
||||
/** The {@link ClassInfo} if any. */
|
||||
public ClassInfo classInfo;
|
||||
|
||||
/** The {@link MemberInfo} if any. */
|
||||
public MemberInfo memberInfo;
|
||||
|
||||
/** The name of the referenced member PackageInfo} if any. */
|
||||
public String referencedMemberName;
|
||||
|
||||
/** Set to true if everything is a-ok */
|
||||
public boolean good;
|
||||
|
||||
/**
|
||||
* regex pattern to use when matching explicit "<a href" reference text
|
||||
*/
|
||||
private static final Pattern HREF_PATTERN
|
||||
= Pattern.compile("^<a href=\"([^\"]*)\">([^<]*)</a>[ \n\r\t]*$",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* regex pattern to use when matching double-quoted reference text
|
||||
*/
|
||||
private static final Pattern QUOTE_PATTERN
|
||||
= Pattern.compile("^\"([^\"]*)\"[ \n\r\t]*$");
|
||||
|
||||
/**
|
||||
* Parse and resolve a link string.
|
||||
*
|
||||
* @param text the original text
|
||||
* @param base the class or whatever that this link is on
|
||||
* @param pos the original position in the source document
|
||||
* @return a new link reference. It always returns something. If there was an
|
||||
* error, it logs it and fills in href and label with error text.
|
||||
*/
|
||||
public static LinkReference parse(String text, ContainerInfo base, SourcePositionInfo pos,
|
||||
boolean printOnErrors) {
|
||||
LinkReference result = new LinkReference();
|
||||
result.text = text;
|
||||
|
||||
int index;
|
||||
int len = text.length();
|
||||
int pairs = 0;
|
||||
int pound = -1;
|
||||
// split the string
|
||||
done: {
|
||||
for (index=0; index<len; index++) {
|
||||
char c = text.charAt(index);
|
||||
switch (c)
|
||||
{
|
||||
case '(':
|
||||
pairs++;
|
||||
break;
|
||||
case '[':
|
||||
pairs++;
|
||||
break;
|
||||
case ')':
|
||||
pairs--;
|
||||
break;
|
||||
case ']':
|
||||
pairs--;
|
||||
break;
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\r':
|
||||
case '\n':
|
||||
if (pairs == 0) {
|
||||
break done;
|
||||
}
|
||||
break;
|
||||
case '#':
|
||||
if (pound < 0) {
|
||||
pound = index;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index == len && pairs != 0) {
|
||||
Errors.error(Errors.UNRESOLVED_LINK, pos,
|
||||
"unable to parse link/see tag: " + text.trim());
|
||||
return result;
|
||||
}
|
||||
|
||||
int linkend = index;
|
||||
|
||||
for (; index<len; index++) {
|
||||
char c = text.charAt(index);
|
||||
if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.label = text.substring(index);
|
||||
|
||||
String ref;
|
||||
String mem;
|
||||
if (pound == 0) {
|
||||
ref = null;
|
||||
mem = text.substring(1, linkend);
|
||||
}
|
||||
else if (pound > 0) {
|
||||
ref = text.substring(0, pound);
|
||||
mem = text.substring(pound+1, linkend);
|
||||
}
|
||||
else {
|
||||
ref = text.substring(0, linkend);
|
||||
mem = null;
|
||||
}
|
||||
|
||||
// parse parameters, if any
|
||||
String[] params = null;
|
||||
String[] paramDimensions = null;
|
||||
if (mem != null) {
|
||||
index = mem.indexOf('(');
|
||||
if (index > 0) {
|
||||
ArrayList<String> paramList = new ArrayList<String>();
|
||||
ArrayList<String> paramDimensionList = new ArrayList<String>();
|
||||
len = mem.length();
|
||||
int start = index+1;
|
||||
final int START = 0;
|
||||
final int TYPE = 1;
|
||||
final int NAME = 2;
|
||||
int dimension = 0;
|
||||
int arraypair = 0;
|
||||
int state = START;
|
||||
int typestart = 0;
|
||||
int typeend = -1;
|
||||
for (int i=start; i<len; i++) {
|
||||
char c = mem.charAt(i);
|
||||
switch (state)
|
||||
{
|
||||
case START:
|
||||
if (c!=' ' && c!='\t' && c!='\r' && c!='\n') {
|
||||
state = TYPE;
|
||||
typestart = i;
|
||||
}
|
||||
break;
|
||||
case TYPE:
|
||||
if (c == '[') {
|
||||
if (typeend < 0) {
|
||||
typeend = i;
|
||||
}
|
||||
dimension++;
|
||||
arraypair++;
|
||||
}
|
||||
else if (c == ']') {
|
||||
arraypair--;
|
||||
}
|
||||
else if (c==' ' || c=='\t' || c=='\r' || c=='\n') {
|
||||
if (typeend < 0) {
|
||||
typeend = i;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (typeend >= 0 || c == ')' || c == ',') {
|
||||
if (typeend < 0) {
|
||||
typeend = i;
|
||||
}
|
||||
String s = mem.substring(typestart, typeend);
|
||||
paramList.add(s);
|
||||
s = "";
|
||||
for (int j=0; j<dimension; j++) {
|
||||
s += "[]";
|
||||
}
|
||||
paramDimensionList.add(s);
|
||||
state = START;
|
||||
typeend = -1;
|
||||
dimension = 0;
|
||||
if (c == ',' || c == ')') {
|
||||
state = START;
|
||||
} else {
|
||||
state = NAME;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NAME:
|
||||
if (c == ',' || c == ')') {
|
||||
state = START;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
params = paramList.toArray(new String[paramList.size()]);
|
||||
paramDimensions = paramDimensionList.toArray(new String[paramList.size()]);
|
||||
mem = mem.substring(0, index);
|
||||
}
|
||||
}
|
||||
|
||||
ClassInfo cl = null;
|
||||
if (base instanceof ClassInfo) {
|
||||
cl = (ClassInfo)base;
|
||||
}
|
||||
|
||||
if (ref == null) {
|
||||
// no class or package was provided, assume it's this class
|
||||
if (cl != null) {
|
||||
result.classInfo = cl;
|
||||
}
|
||||
} else {
|
||||
// they provided something, maybe it's a class or a package
|
||||
if (cl != null) {
|
||||
result.classInfo = cl.extendedFindClass(ref);
|
||||
if (result.classInfo == null) {
|
||||
result.classInfo = cl.findClass(ref);
|
||||
}
|
||||
if (result.classInfo == null) {
|
||||
result.classInfo = cl.findInnerClass(ref);
|
||||
}
|
||||
}
|
||||
if (result.classInfo == null) {
|
||||
result.classInfo = Converter.obtainClass(ref);
|
||||
}
|
||||
if (result.classInfo == null) {
|
||||
result.packageInfo = Converter.obtainPackage(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.classInfo != null && mem != null) {
|
||||
// it's either a field or a method, prefer a field
|
||||
if (params == null) {
|
||||
FieldInfo field = result.classInfo.findField(mem);
|
||||
// findField looks in containing classes, so it might actually
|
||||
// be somewhere else; link to where it really is, not what they
|
||||
// typed.
|
||||
if (field != null) {
|
||||
result.classInfo = field.containingClass();
|
||||
result.memberInfo = field;
|
||||
}
|
||||
}
|
||||
if (result.memberInfo == null) {
|
||||
MethodInfo method = result.classInfo.findMethod(mem, params, paramDimensions);
|
||||
if (method != null) {
|
||||
result.classInfo = method.containingClass();
|
||||
result.memberInfo = method;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.referencedMemberName = mem;
|
||||
if (params != null) {
|
||||
result.referencedMemberName = result.referencedMemberName + '(';
|
||||
len = params.length;
|
||||
if (len > 0) {
|
||||
len--;
|
||||
for (int i=0; i<len; i++) {
|
||||
result.referencedMemberName = result.referencedMemberName + params[i]
|
||||
+ paramDimensions[i] + ", ";
|
||||
}
|
||||
result.referencedMemberName = result.referencedMemberName + params[len]
|
||||
+ paramDimensions[len];
|
||||
}
|
||||
result.referencedMemberName = result.referencedMemberName + ")";
|
||||
}
|
||||
|
||||
// debugging spew
|
||||
if (false) {
|
||||
result.label = result.label + "/" + ref + "/" + mem + '/';
|
||||
if (params != null) {
|
||||
for (int i=0; i<params.length; i++) {
|
||||
result.label += params[i] + "|";
|
||||
}
|
||||
}
|
||||
|
||||
FieldInfo f = (result.memberInfo instanceof FieldInfo)
|
||||
? (FieldInfo)result.memberInfo
|
||||
: null;
|
||||
MethodInfo m = (result.memberInfo instanceof MethodInfo)
|
||||
? (MethodInfo)result.memberInfo
|
||||
: null;
|
||||
result.label = result.label
|
||||
+ "/package=" + (result.packageInfo!=null?result.packageInfo.name():"")
|
||||
+ "/class=" + (result.classInfo!=null?result.classInfo.qualifiedName():"")
|
||||
+ "/field=" + (f!=null?f.name():"")
|
||||
+ "/method=" + (m!=null?m.name():"");
|
||||
|
||||
}
|
||||
|
||||
MethodInfo method = null;
|
||||
boolean skipHref = false;
|
||||
|
||||
if (result.memberInfo != null && result.memberInfo.isExecutable()) {
|
||||
method = (MethodInfo)result.memberInfo;
|
||||
}
|
||||
|
||||
if (text.startsWith("\"")) {
|
||||
// literal quoted reference (e.g., a book title)
|
||||
Matcher matcher = QUOTE_PATTERN.matcher(text);
|
||||
if (! matcher.matches()) {
|
||||
Errors.error(Errors.UNRESOLVED_LINK, pos,
|
||||
"unbalanced quoted link/see tag: " + text.trim());
|
||||
result.makeError();
|
||||
return result;
|
||||
}
|
||||
skipHref = true;
|
||||
result.label = matcher.group(1);
|
||||
result.kind = "@seeJustLabel";
|
||||
}
|
||||
else if (text.startsWith("<")) {
|
||||
// explicit "<a href" form
|
||||
Matcher matcher = HREF_PATTERN.matcher(text);
|
||||
if (! matcher.matches()) {
|
||||
Errors.error(Errors.UNRESOLVED_LINK, pos,
|
||||
"invalid <a> link/see tag: " + text.trim());
|
||||
result.makeError();
|
||||
return result;
|
||||
}
|
||||
result.href = matcher.group(1);
|
||||
result.label = matcher.group(2);
|
||||
result.kind = "@seeHref";
|
||||
}
|
||||
else if (result.packageInfo != null) {
|
||||
result.href = result.packageInfo.htmlPage();
|
||||
if (result.label.length() == 0) {
|
||||
result.href = result.packageInfo.htmlPage();
|
||||
result.label = result.packageInfo.name();
|
||||
}
|
||||
}
|
||||
else if (result.classInfo != null && result.referencedMemberName == null) {
|
||||
// class reference
|
||||
if (result.label.length() == 0) {
|
||||
result.label = result.classInfo.name();
|
||||
}
|
||||
result.href = result.classInfo.htmlPage();
|
||||
}
|
||||
else if (result.memberInfo != null) {
|
||||
// member reference
|
||||
ClassInfo containing = result.memberInfo.containingClass();
|
||||
if (result.memberInfo.isExecutable()) {
|
||||
if (result.referencedMemberName.indexOf('(') < 0) {
|
||||
result.referencedMemberName += method.flatSignature();
|
||||
}
|
||||
}
|
||||
if (result.label.length() == 0) {
|
||||
result.label = result.referencedMemberName;
|
||||
}
|
||||
result.href = containing.htmlPage() + '#' + result.memberInfo.anchor();
|
||||
}
|
||||
|
||||
if (result.href == null && !skipHref) {
|
||||
if (printOnErrors && (base == null || base.checkLevel())) {
|
||||
Errors.error(Errors.UNRESOLVED_LINK, pos,
|
||||
"Unresolved link/see tag \"" + text.trim()
|
||||
+ "\" in " + ((base != null) ? base.qualifiedName() : "[null]"));
|
||||
}
|
||||
result.makeError();
|
||||
}
|
||||
else if (result.memberInfo != null && !result.memberInfo.checkLevel()) {
|
||||
if (printOnErrors && (base == null || base.checkLevel())) {
|
||||
Errors.error(Errors.HIDDEN_LINK, pos,
|
||||
"Link to hidden member: " + text.trim());
|
||||
result.href = null;
|
||||
}
|
||||
result.kind = "@seeJustLabel";
|
||||
}
|
||||
else if (result.classInfo != null && !result.classInfo.checkLevel()) {
|
||||
if (printOnErrors && (base == null || base.checkLevel())) {
|
||||
Errors.error(Errors.HIDDEN_LINK, pos,
|
||||
"Link to hidden class: " + text.trim() + " label=" + result.label);
|
||||
result.href = null;
|
||||
}
|
||||
result.kind = "@seeJustLabel";
|
||||
}
|
||||
else if (result.packageInfo != null && !result.packageInfo.checkLevel()) {
|
||||
if (printOnErrors && (base == null || base.checkLevel())) {
|
||||
Errors.error(Errors.HIDDEN_LINK, pos,
|
||||
"Link to hidden package: " + text.trim());
|
||||
result.href = null;
|
||||
}
|
||||
result.kind = "@seeJustLabel";
|
||||
}
|
||||
|
||||
result.good = true;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean checkLevel() {
|
||||
if (memberInfo != null) {
|
||||
return memberInfo.checkLevel();
|
||||
}
|
||||
if (classInfo != null) {
|
||||
return classInfo.checkLevel();
|
||||
}
|
||||
if (packageInfo != null) {
|
||||
return packageInfo.checkLevel();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** turn this LinkReference into one with an error message */
|
||||
private void makeError() {
|
||||
//this.href = "ERROR(" + this.text.trim() + ")";
|
||||
this.href = null;
|
||||
if (this.label == null) {
|
||||
this.label = "";
|
||||
}
|
||||
this.label = "ERROR(" + this.label + "/" + text.trim() + ")";
|
||||
}
|
||||
|
||||
/** private. **/
|
||||
private LinkReference() {
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public class LiteralTagInfo extends TagInfo
|
||||
{
|
||||
private static String encode(String t)
|
||||
{
|
||||
t = t.replace("&", "&");
|
||||
t = t.replace("<", "<");
|
||||
t = t.replace(">", ">");
|
||||
return t;
|
||||
}
|
||||
|
||||
public LiteralTagInfo(String n, String k, String t, SourcePositionInfo sp)
|
||||
{
|
||||
super("Text", "Text", encode(t), sp);
|
||||
}
|
||||
}
|
|
@ -1,155 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public abstract class MemberInfo extends DocInfo implements Comparable, Scoped
|
||||
{
|
||||
public MemberInfo(String rawCommentText, String name, String signature,
|
||||
ClassInfo containingClass, ClassInfo realContainingClass,
|
||||
boolean isPublic, boolean isProtected,
|
||||
boolean isPackagePrivate, boolean isPrivate,
|
||||
boolean isFinal, boolean isStatic, boolean isSynthetic,
|
||||
String kind,
|
||||
SourcePositionInfo position,
|
||||
AnnotationInstanceInfo[] annotations)
|
||||
{
|
||||
super(rawCommentText, position);
|
||||
mName = name;
|
||||
mSignature = signature;
|
||||
mContainingClass = containingClass;
|
||||
mRealContainingClass = realContainingClass;
|
||||
mIsPublic = isPublic;
|
||||
mIsProtected = isProtected;
|
||||
mIsPackagePrivate = isPackagePrivate;
|
||||
mIsPrivate = isPrivate;
|
||||
mIsFinal = isFinal;
|
||||
mIsStatic = isStatic;
|
||||
mIsSynthetic = isSynthetic;
|
||||
mKind = kind;
|
||||
mAnnotations = annotations;
|
||||
}
|
||||
|
||||
public abstract boolean isExecutable();
|
||||
|
||||
public String anchor()
|
||||
{
|
||||
if (mSignature != null) {
|
||||
return mName + mSignature;
|
||||
} else {
|
||||
return mName;
|
||||
}
|
||||
}
|
||||
|
||||
public String htmlPage() {
|
||||
return mContainingClass.htmlPage() + "#" + anchor();
|
||||
}
|
||||
|
||||
public int compareTo(Object that) {
|
||||
return this.htmlPage().compareTo(((MemberInfo)that).htmlPage());
|
||||
}
|
||||
|
||||
public String name()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String signature()
|
||||
{
|
||||
return mSignature;
|
||||
}
|
||||
|
||||
public ClassInfo realContainingClass()
|
||||
{
|
||||
return mRealContainingClass;
|
||||
}
|
||||
|
||||
public ClassInfo containingClass()
|
||||
{
|
||||
return mContainingClass;
|
||||
}
|
||||
|
||||
public boolean isPublic()
|
||||
{
|
||||
return mIsPublic;
|
||||
}
|
||||
|
||||
public boolean isProtected()
|
||||
{
|
||||
return mIsProtected;
|
||||
}
|
||||
|
||||
public boolean isPackagePrivate()
|
||||
{
|
||||
return mIsPackagePrivate;
|
||||
}
|
||||
|
||||
public boolean isPrivate()
|
||||
{
|
||||
return mIsPrivate;
|
||||
}
|
||||
|
||||
public boolean isStatic()
|
||||
{
|
||||
return mIsStatic;
|
||||
}
|
||||
|
||||
public boolean isFinal()
|
||||
{
|
||||
return mIsFinal;
|
||||
}
|
||||
|
||||
public boolean isSynthetic()
|
||||
{
|
||||
return mIsSynthetic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerInfo parent()
|
||||
{
|
||||
return mContainingClass;
|
||||
}
|
||||
|
||||
public boolean checkLevel()
|
||||
{
|
||||
return DroidDoc.checkLevel(mIsPublic, mIsProtected,
|
||||
mIsPackagePrivate, mIsPrivate, isHidden());
|
||||
}
|
||||
|
||||
public String kind()
|
||||
{
|
||||
return mKind;
|
||||
}
|
||||
|
||||
public AnnotationInstanceInfo[] annotations()
|
||||
{
|
||||
return mAnnotations;
|
||||
}
|
||||
|
||||
ClassInfo mContainingClass;
|
||||
ClassInfo mRealContainingClass;
|
||||
String mName;
|
||||
String mSignature;
|
||||
boolean mIsPublic;
|
||||
boolean mIsProtected;
|
||||
boolean mIsPackagePrivate;
|
||||
boolean mIsPrivate;
|
||||
boolean mIsFinal;
|
||||
boolean mIsStatic;
|
||||
boolean mIsSynthetic;
|
||||
String mKind;
|
||||
private AnnotationInstanceInfo[] mAnnotations;
|
||||
|
||||
}
|
||||
|
|
@ -1,670 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MethodInfo extends MemberInfo
|
||||
{
|
||||
public static final Comparator<MethodInfo> comparator = new Comparator<MethodInfo>() {
|
||||
public int compare(MethodInfo a, MethodInfo b) {
|
||||
return a.name().compareTo(b.name());
|
||||
}
|
||||
};
|
||||
|
||||
private class InlineTags implements InheritedTags
|
||||
{
|
||||
public TagInfo[] tags()
|
||||
{
|
||||
return comment().tags();
|
||||
}
|
||||
public InheritedTags inherited()
|
||||
{
|
||||
MethodInfo m = findOverriddenMethod(name(), signature());
|
||||
if (m != null) {
|
||||
return m.inlineTags();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
|
||||
{
|
||||
for (ClassInfo i: ifaces) {
|
||||
queue.add(i);
|
||||
}
|
||||
for (ClassInfo i: ifaces) {
|
||||
addInterfaces(i.interfaces(), queue);
|
||||
}
|
||||
}
|
||||
|
||||
// first looks for a superclass, and then does a breadth first search to
|
||||
// find the least far away match
|
||||
public MethodInfo findOverriddenMethod(String name, String signature)
|
||||
{
|
||||
if (mReturnType == null) {
|
||||
// ctor
|
||||
return null;
|
||||
}
|
||||
if (mOverriddenMethod != null) {
|
||||
return mOverriddenMethod;
|
||||
}
|
||||
|
||||
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
|
||||
addInterfaces(containingClass().interfaces(), queue);
|
||||
for (ClassInfo iface: queue) {
|
||||
for (MethodInfo me: iface.methods()) {
|
||||
if (me.name().equals(name)
|
||||
&& me.signature().equals(signature)
|
||||
&& me.inlineTags().tags() != null
|
||||
&& me.inlineTags().tags().length > 0) {
|
||||
return me;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void addRealInterfaces(ClassInfo[] ifaces, ArrayList<ClassInfo> queue)
|
||||
{
|
||||
for (ClassInfo i: ifaces) {
|
||||
queue.add(i);
|
||||
if (i.realSuperclass() != null && i.realSuperclass().isAbstract()) {
|
||||
queue.add(i.superclass());
|
||||
}
|
||||
}
|
||||
for (ClassInfo i: ifaces) {
|
||||
addInterfaces(i.realInterfaces(), queue);
|
||||
}
|
||||
}
|
||||
|
||||
public MethodInfo findRealOverriddenMethod(String name, String signature, HashSet notStrippable) {
|
||||
if (mReturnType == null) {
|
||||
// ctor
|
||||
return null;
|
||||
}
|
||||
if (mOverriddenMethod != null) {
|
||||
return mOverriddenMethod;
|
||||
}
|
||||
|
||||
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
|
||||
if (containingClass().realSuperclass() != null &&
|
||||
containingClass().realSuperclass().isAbstract()) {
|
||||
queue.add(containingClass());
|
||||
}
|
||||
addInterfaces(containingClass().realInterfaces(), queue);
|
||||
for (ClassInfo iface: queue) {
|
||||
for (MethodInfo me: iface.methods()) {
|
||||
if (me.name().equals(name)
|
||||
&& me.signature().equals(signature)
|
||||
&& me.inlineTags().tags() != null
|
||||
&& me.inlineTags().tags().length > 0
|
||||
&& notStrippable.contains(me.containingClass())) {
|
||||
return me;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public MethodInfo findSuperclassImplementation(HashSet notStrippable) {
|
||||
if (mReturnType == null) {
|
||||
// ctor
|
||||
return null;
|
||||
}
|
||||
if (mOverriddenMethod != null) {
|
||||
// Even if we're told outright that this was the overridden method, we want to
|
||||
// be conservative and ignore mismatches of parameter types -- they arise from
|
||||
// extending generic specializations, and we want to consider the derived-class
|
||||
// method to be a non-override.
|
||||
if (this.signature().equals(mOverriddenMethod.signature())) {
|
||||
return mOverriddenMethod;
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
|
||||
if (containingClass().realSuperclass() != null &&
|
||||
containingClass().realSuperclass().isAbstract()) {
|
||||
queue.add(containingClass());
|
||||
}
|
||||
addInterfaces(containingClass().realInterfaces(), queue);
|
||||
for (ClassInfo iface: queue) {
|
||||
for (MethodInfo me: iface.methods()) {
|
||||
if (me.name().equals(this.name())
|
||||
&& me.signature().equals(this.signature())
|
||||
&& notStrippable.contains(me.containingClass())) {
|
||||
return me;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ClassInfo findRealOverriddenClass(String name, String signature) {
|
||||
if (mReturnType == null) {
|
||||
// ctor
|
||||
return null;
|
||||
}
|
||||
if (mOverriddenMethod != null) {
|
||||
return mOverriddenMethod.mRealContainingClass;
|
||||
}
|
||||
|
||||
ArrayList<ClassInfo> queue = new ArrayList<ClassInfo>();
|
||||
if (containingClass().realSuperclass() != null &&
|
||||
containingClass().realSuperclass().isAbstract()) {
|
||||
queue.add(containingClass());
|
||||
}
|
||||
addInterfaces(containingClass().realInterfaces(), queue);
|
||||
for (ClassInfo iface: queue) {
|
||||
for (MethodInfo me: iface.methods()) {
|
||||
if (me.name().equals(name)
|
||||
&& me.signature().equals(signature)
|
||||
&& me.inlineTags().tags() != null
|
||||
&& me.inlineTags().tags().length > 0) {
|
||||
return iface;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private class FirstSentenceTags implements InheritedTags
|
||||
{
|
||||
public TagInfo[] tags()
|
||||
{
|
||||
return comment().briefTags();
|
||||
}
|
||||
public InheritedTags inherited()
|
||||
{
|
||||
MethodInfo m = findOverriddenMethod(name(), signature());
|
||||
if (m != null) {
|
||||
return m.firstSentenceTags();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ReturnTags implements InheritedTags {
|
||||
public TagInfo[] tags() {
|
||||
return comment().returnTags();
|
||||
}
|
||||
public InheritedTags inherited() {
|
||||
MethodInfo m = findOverriddenMethod(name(), signature());
|
||||
if (m != null) {
|
||||
return m.returnTags();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isDeprecated() {
|
||||
boolean deprecated = false;
|
||||
if (!mDeprecatedKnown) {
|
||||
boolean commentDeprecated = (comment().deprecatedTags().length > 0);
|
||||
boolean annotationDeprecated = false;
|
||||
for (AnnotationInstanceInfo annotation : annotations()) {
|
||||
if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
|
||||
annotationDeprecated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (commentDeprecated != annotationDeprecated) {
|
||||
Errors.error(Errors.DEPRECATION_MISMATCH, position(),
|
||||
"Method " + mContainingClass.qualifiedName() + "." + name()
|
||||
+ ": @Deprecated annotation and @deprecated doc tag do not match");
|
||||
}
|
||||
|
||||
mIsDeprecated = commentDeprecated | annotationDeprecated;
|
||||
mDeprecatedKnown = true;
|
||||
}
|
||||
return mIsDeprecated;
|
||||
}
|
||||
|
||||
public TypeInfo[] getTypeParameters(){
|
||||
return mTypeParameters;
|
||||
}
|
||||
|
||||
public MethodInfo cloneForClass(ClassInfo newContainingClass) {
|
||||
MethodInfo result = new MethodInfo(getRawCommentText(), mTypeParameters,
|
||||
name(), signature(), newContainingClass, realContainingClass(),
|
||||
isPublic(), isProtected(), isPackagePrivate(), isPrivate(), isFinal(), isStatic(),
|
||||
isSynthetic(), mIsAbstract, mIsSynchronized, mIsNative, mIsAnnotationElement,
|
||||
kind(), mFlatSignature, mOverriddenMethod,
|
||||
mReturnType, mParameters, mThrownExceptions, position(), annotations());
|
||||
result.init(mDefaultAnnotationElementValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
public MethodInfo(String rawCommentText, TypeInfo[] typeParameters, String name,
|
||||
String signature, ClassInfo containingClass, ClassInfo realContainingClass,
|
||||
boolean isPublic, boolean isProtected,
|
||||
boolean isPackagePrivate, boolean isPrivate,
|
||||
boolean isFinal, boolean isStatic, boolean isSynthetic,
|
||||
boolean isAbstract, boolean isSynchronized, boolean isNative,
|
||||
boolean isAnnotationElement, String kind,
|
||||
String flatSignature, MethodInfo overriddenMethod,
|
||||
TypeInfo returnType, ParameterInfo[] parameters,
|
||||
ClassInfo[] thrownExceptions, SourcePositionInfo position,
|
||||
AnnotationInstanceInfo[] annotations)
|
||||
{
|
||||
// Explicitly coerce 'final' state of Java6-compiled enum values() method, to match
|
||||
// the Java5-emitted base API description.
|
||||
super(rawCommentText, name, signature, containingClass, realContainingClass,
|
||||
isPublic, isProtected, isPackagePrivate, isPrivate,
|
||||
((name.equals("values") && containingClass.isEnum()) ? true : isFinal),
|
||||
isStatic, isSynthetic, kind, position, annotations);
|
||||
|
||||
// The underlying MethodDoc for an interface's declared methods winds up being marked
|
||||
// non-abstract. Correct that here by looking at the immediate-parent class, and marking
|
||||
// this method abstract if it is an unimplemented interface method.
|
||||
if (containingClass.isInterface()) {
|
||||
isAbstract = true;
|
||||
}
|
||||
|
||||
mReasonOpened = "0:0";
|
||||
mIsAnnotationElement = isAnnotationElement;
|
||||
mTypeParameters = typeParameters;
|
||||
mIsAbstract = isAbstract;
|
||||
mIsSynchronized = isSynchronized;
|
||||
mIsNative = isNative;
|
||||
mFlatSignature = flatSignature;
|
||||
mOverriddenMethod = overriddenMethod;
|
||||
mReturnType = returnType;
|
||||
mParameters = parameters;
|
||||
mThrownExceptions = thrownExceptions;
|
||||
}
|
||||
|
||||
public void init(AnnotationValueInfo defaultAnnotationElementValue)
|
||||
{
|
||||
mDefaultAnnotationElementValue = defaultAnnotationElementValue;
|
||||
}
|
||||
|
||||
public boolean isAbstract()
|
||||
{
|
||||
return mIsAbstract;
|
||||
}
|
||||
|
||||
public boolean isSynchronized()
|
||||
{
|
||||
return mIsSynchronized;
|
||||
}
|
||||
|
||||
public boolean isNative()
|
||||
{
|
||||
return mIsNative;
|
||||
}
|
||||
|
||||
public String flatSignature()
|
||||
{
|
||||
return mFlatSignature;
|
||||
}
|
||||
|
||||
public InheritedTags inlineTags()
|
||||
{
|
||||
return new InlineTags();
|
||||
}
|
||||
|
||||
public InheritedTags firstSentenceTags()
|
||||
{
|
||||
return new FirstSentenceTags();
|
||||
}
|
||||
|
||||
public InheritedTags returnTags() {
|
||||
return new ReturnTags();
|
||||
}
|
||||
|
||||
public TypeInfo returnType()
|
||||
{
|
||||
return mReturnType;
|
||||
}
|
||||
|
||||
public String prettySignature()
|
||||
{
|
||||
String s = "(";
|
||||
int N = mParameters.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
ParameterInfo p = mParameters[i];
|
||||
TypeInfo t = p.type();
|
||||
if (t.isPrimitive()) {
|
||||
s += t.simpleTypeName();
|
||||
} else {
|
||||
s += t.asClassInfo().name();
|
||||
}
|
||||
if (i != N-1) {
|
||||
s += ',';
|
||||
}
|
||||
}
|
||||
s += ')';
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a name consistent with the {@link
|
||||
* com.android.apicheck.MethodInfo#getHashableName()}.
|
||||
*/
|
||||
public String getHashableName() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append(name());
|
||||
for (int p = 0; p < mParameters.length; p++) {
|
||||
result.append(":");
|
||||
if (p == mParameters.length - 1 && isVarArgs()) {
|
||||
// TODO: note that this does not attempt to handle hypothetical
|
||||
// vararg methods whose last parameter is a list of arrays, e.g.
|
||||
// "Object[]...".
|
||||
result.append(mParameters[p].type().fullNameNoDimension(typeVariables()))
|
||||
.append("...");
|
||||
} else {
|
||||
result.append(mParameters[p].type().fullName(typeVariables()));
|
||||
}
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private boolean inList(ClassInfo item, ThrowsTagInfo[] list)
|
||||
{
|
||||
int len = list.length;
|
||||
String qn = item.qualifiedName();
|
||||
for (int i=0; i<len; i++) {
|
||||
ClassInfo ex = list[i].exception();
|
||||
if (ex != null && ex.qualifiedName().equals(qn)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ThrowsTagInfo[] throwsTags()
|
||||
{
|
||||
if (mThrowsTags == null) {
|
||||
ThrowsTagInfo[] documented = comment().throwsTags();
|
||||
ArrayList<ThrowsTagInfo> rv = new ArrayList<ThrowsTagInfo>();
|
||||
|
||||
int len = documented.length;
|
||||
for (int i=0; i<len; i++) {
|
||||
rv.add(documented[i]);
|
||||
}
|
||||
|
||||
ClassInfo[] all = mThrownExceptions;
|
||||
len = all.length;
|
||||
for (int i=0; i<len; i++) {
|
||||
ClassInfo cl = all[i];
|
||||
if (documented == null || !inList(cl, documented)) {
|
||||
rv.add(new ThrowsTagInfo("@throws", "@throws",
|
||||
cl.qualifiedName(), cl, "",
|
||||
containingClass(), position()));
|
||||
}
|
||||
}
|
||||
mThrowsTags = rv.toArray(new ThrowsTagInfo[rv.size()]);
|
||||
}
|
||||
return mThrowsTags;
|
||||
}
|
||||
|
||||
private static int indexOfParam(String name, String[] list)
|
||||
{
|
||||
final int N = list.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
if (name.equals(list[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public ParamTagInfo[] paramTags()
|
||||
{
|
||||
if (mParamTags == null) {
|
||||
final int N = mParameters.length;
|
||||
|
||||
String[] names = new String[N];
|
||||
String[] comments = new String[N];
|
||||
SourcePositionInfo[] positions = new SourcePositionInfo[N];
|
||||
|
||||
// get the right names so we can handle our names being different from
|
||||
// our parent's names.
|
||||
for (int i=0; i<N; i++) {
|
||||
names[i] = mParameters[i].name();
|
||||
comments[i] = "";
|
||||
positions[i] = mParameters[i].position();
|
||||
}
|
||||
|
||||
// gather our comments, and complain about misnamed @param tags
|
||||
for (ParamTagInfo tag: comment().paramTags()) {
|
||||
int index = indexOfParam(tag.parameterName(), names);
|
||||
if (index >= 0) {
|
||||
comments[index] = tag.parameterComment();
|
||||
positions[index] = tag.position();
|
||||
} else {
|
||||
Errors.error(Errors.UNKNOWN_PARAM_TAG_NAME, tag.position(),
|
||||
"@param tag with name that doesn't match the parameter list: '"
|
||||
+ tag.parameterName() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
// get our parent's tags to fill in the blanks
|
||||
MethodInfo overridden = this.findOverriddenMethod(name(), signature());
|
||||
if (overridden != null) {
|
||||
ParamTagInfo[] maternal = overridden.paramTags();
|
||||
for (int i=0; i<N; i++) {
|
||||
if (comments[i].equals("")) {
|
||||
comments[i] = maternal[i].parameterComment();
|
||||
positions[i] = maternal[i].position();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// construct the results, and cache them for next time
|
||||
mParamTags = new ParamTagInfo[N];
|
||||
for (int i=0; i<N; i++) {
|
||||
mParamTags[i] = new ParamTagInfo("@param", "@param", names[i] + " " + comments[i],
|
||||
parent(), positions[i]);
|
||||
|
||||
// while we're here, if we find any parameters that are still undocumented at this
|
||||
// point, complain. (this warning is off by default, because it's really, really
|
||||
// common; but, it's good to be able to enforce it)
|
||||
if (comments[i].equals("")) {
|
||||
Errors.error(Errors.UNDOCUMENTED_PARAMETER, positions[i],
|
||||
"Undocumented parameter '" + names[i] + "' on method '"
|
||||
+ name() + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
return mParamTags;
|
||||
}
|
||||
|
||||
public SeeTagInfo[] seeTags()
|
||||
{
|
||||
SeeTagInfo[] result = comment().seeTags();
|
||||
if (result == null) {
|
||||
if (mOverriddenMethod != null) {
|
||||
result = mOverriddenMethod.seeTags();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public TagInfo[] deprecatedTags()
|
||||
{
|
||||
TagInfo[] result = comment().deprecatedTags();
|
||||
if (result.length == 0) {
|
||||
if (comment().undeprecateTags().length == 0) {
|
||||
if (mOverriddenMethod != null) {
|
||||
result = mOverriddenMethod.deprecatedTags();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public ParameterInfo[] parameters()
|
||||
{
|
||||
return mParameters;
|
||||
}
|
||||
|
||||
|
||||
public boolean matchesParams(String[] params, String[] dimensions)
|
||||
{
|
||||
if (mParamStrings == null) {
|
||||
ParameterInfo[] mine = mParameters;
|
||||
int len = mine.length;
|
||||
if (len != params.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i=0; i<len; i++) {
|
||||
TypeInfo t = mine[i].type();
|
||||
if (!t.dimension().equals(dimensions[i])) {
|
||||
return false;
|
||||
}
|
||||
String qn = t.qualifiedTypeName();
|
||||
String s = params[i];
|
||||
int slen = s.length();
|
||||
int qnlen = qn.length();
|
||||
if (!(qn.equals(s) ||
|
||||
((slen+1)<qnlen && qn.charAt(qnlen-slen-1)=='.'
|
||||
&& qn.endsWith(s)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".kind", kind());
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".href", htmlPage());
|
||||
data.setValue(base + ".anchor", anchor());
|
||||
|
||||
if (mReturnType != null) {
|
||||
returnType().makeHDF(data, base + ".returnType", false, typeVariables());
|
||||
data.setValue(base + ".abstract", mIsAbstract ? "abstract" : "");
|
||||
}
|
||||
|
||||
data.setValue(base + ".synchronized", mIsSynchronized ? "synchronized" : "");
|
||||
data.setValue(base + ".final", isFinal() ? "final" : "");
|
||||
data.setValue(base + ".static", isStatic() ? "static" : "");
|
||||
|
||||
TagInfo.makeHDF(data, base + ".shortDescr", firstSentenceTags());
|
||||
TagInfo.makeHDF(data, base + ".descr", inlineTags());
|
||||
TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
|
||||
TagInfo.makeHDF(data, base + ".seeAlso", seeTags());
|
||||
data.setValue(base + ".since", getSince());
|
||||
ParamTagInfo.makeHDF(data, base + ".paramTags", paramTags());
|
||||
AttrTagInfo.makeReferenceHDF(data, base + ".attrRefs", comment().attrTags());
|
||||
ThrowsTagInfo.makeHDF(data, base + ".throws", throwsTags());
|
||||
ParameterInfo.makeHDF(data, base + ".params", parameters(), isVarArgs(), typeVariables());
|
||||
if (isProtected()) {
|
||||
data.setValue(base + ".scope", "protected");
|
||||
}
|
||||
else if (isPublic()) {
|
||||
data.setValue(base + ".scope", "public");
|
||||
}
|
||||
TagInfo.makeHDF(data, base + ".returns", returnTags());
|
||||
|
||||
if (mTypeParameters != null) {
|
||||
TypeInfo.makeHDF(data, base + ".generic.typeArguments", mTypeParameters, false);
|
||||
}
|
||||
}
|
||||
|
||||
public HashSet<String> typeVariables()
|
||||
{
|
||||
HashSet<String> result = TypeInfo.typeVariables(mTypeParameters);
|
||||
ClassInfo cl = containingClass();
|
||||
while (cl != null) {
|
||||
TypeInfo[] types = cl.asTypeInfo().typeArguments();
|
||||
if (types != null) {
|
||||
TypeInfo.typeVariables(types, result);
|
||||
}
|
||||
cl = cl.containingClass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecutable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public ClassInfo[] thrownExceptions()
|
||||
{
|
||||
return mThrownExceptions;
|
||||
}
|
||||
|
||||
public String typeArgumentsName(HashSet<String> typeVars)
|
||||
{
|
||||
if (mTypeParameters == null || mTypeParameters.length == 0) {
|
||||
return "";
|
||||
} else {
|
||||
return TypeInfo.typeArgumentsName(mTypeParameters, typeVars);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAnnotationElement()
|
||||
{
|
||||
return mIsAnnotationElement;
|
||||
}
|
||||
|
||||
public AnnotationValueInfo defaultAnnotationElementValue()
|
||||
{
|
||||
return mDefaultAnnotationElementValue;
|
||||
}
|
||||
|
||||
public void setVarargs(boolean set){
|
||||
mIsVarargs = set;
|
||||
}
|
||||
public boolean isVarArgs(){
|
||||
return mIsVarargs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return this.name();
|
||||
}
|
||||
|
||||
public void setReason(String reason) {
|
||||
mReasonOpened = reason;
|
||||
}
|
||||
|
||||
public String getReason() {
|
||||
return mReasonOpened;
|
||||
}
|
||||
|
||||
private String mFlatSignature;
|
||||
private MethodInfo mOverriddenMethod;
|
||||
private TypeInfo mReturnType;
|
||||
private boolean mIsAnnotationElement;
|
||||
private boolean mIsAbstract;
|
||||
private boolean mIsSynchronized;
|
||||
private boolean mIsNative;
|
||||
private boolean mIsVarargs;
|
||||
private boolean mDeprecatedKnown;
|
||||
private boolean mIsDeprecated;
|
||||
private ParameterInfo[] mParameters;
|
||||
private ClassInfo[] mThrownExceptions;
|
||||
private String[] mParamStrings;
|
||||
ThrowsTagInfo[] mThrowsTags;
|
||||
private ParamTagInfo[] mParamTags;
|
||||
private TypeInfo[] mTypeParameters;
|
||||
private AnnotationValueInfo mDefaultAnnotationElementValue;
|
||||
private String mReasonOpened;
|
||||
}
|
||||
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class NavTree {
|
||||
|
||||
public static void writeNavTree(String dir) {
|
||||
ArrayList<Node> children = new ArrayList();
|
||||
for (PackageInfo pkg: DroidDoc.choosePackages()) {
|
||||
children.add(makePackageNode(pkg));
|
||||
}
|
||||
Node node = new Node("Reference", dir + "packages.html", children, null);
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (false) {
|
||||
// if you want a root node
|
||||
buf.append("[");
|
||||
node.render(buf);
|
||||
buf.append("]");
|
||||
} else {
|
||||
// if you don't want a root node
|
||||
node.renderChildren(buf);
|
||||
}
|
||||
|
||||
HDF data = DroidDoc.makeHDF();
|
||||
data.setValue("reference_tree", buf.toString());
|
||||
ClearPage.write(data, "navtree_data.cs", "navtree_data.js");
|
||||
}
|
||||
|
||||
private static Node makePackageNode(PackageInfo pkg) {
|
||||
ArrayList<Node> children = new ArrayList();
|
||||
|
||||
children.add(new Node("Description", pkg.fullDescriptionHtmlPage(), null, null));
|
||||
|
||||
addClassNodes(children, "Interfaces", pkg.interfaces());
|
||||
addClassNodes(children, "Classes", pkg.ordinaryClasses());
|
||||
addClassNodes(children, "Enums", pkg.enums());
|
||||
addClassNodes(children, "Exceptions", pkg.exceptions());
|
||||
addClassNodes(children, "Errors", pkg.errors());
|
||||
|
||||
return new Node(pkg.name(), pkg.htmlPage(), children, pkg.getSince());
|
||||
}
|
||||
|
||||
private static void addClassNodes(ArrayList<Node> parent, String label, ClassInfo[] classes) {
|
||||
ArrayList<Node> children = new ArrayList();
|
||||
|
||||
for (ClassInfo cl: classes) {
|
||||
if (cl.checkLevel()) {
|
||||
children.add(new Node(cl.name(), cl.htmlPage(), null, cl.getSince()));
|
||||
}
|
||||
}
|
||||
|
||||
if (children.size() > 0) {
|
||||
parent.add(new Node(label, null, children, null));
|
||||
}
|
||||
}
|
||||
|
||||
private static class Node {
|
||||
private String mLabel;
|
||||
private String mLink;
|
||||
ArrayList<Node> mChildren;
|
||||
private String mSince;
|
||||
|
||||
Node(String label, String link, ArrayList<Node> children, String since) {
|
||||
mLabel = label;
|
||||
mLink = link;
|
||||
mChildren = children;
|
||||
mSince = since;
|
||||
}
|
||||
|
||||
static void renderString(StringBuilder buf, String s) {
|
||||
if (s == null) {
|
||||
buf.append("null");
|
||||
} else {
|
||||
buf.append('"');
|
||||
final int N = s.length();
|
||||
for (int i=0; i<N; i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c >= ' ' && c <= '~' && c != '"' && c != '\\') {
|
||||
buf.append(c);
|
||||
} else {
|
||||
buf.append("\\u");
|
||||
for (int j=0; i<4; i++) {
|
||||
char x = (char)(c & 0x000f);
|
||||
if (x > 10) {
|
||||
x = (char)(x - 10 + 'a');
|
||||
} else {
|
||||
x = (char)(x + '0');
|
||||
}
|
||||
buf.append(x);
|
||||
c >>= 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append('"');
|
||||
}
|
||||
}
|
||||
|
||||
void renderChildren(StringBuilder buf) {
|
||||
ArrayList<Node> list = mChildren;
|
||||
if (list == null || list.size() == 0) {
|
||||
// We output null for no children. That way empty lists here can just
|
||||
// be a byproduct of how we generate the lists.
|
||||
buf.append("null");
|
||||
} else {
|
||||
buf.append("[ ");
|
||||
final int N = list.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
list.get(i).render(buf);
|
||||
if (i != N-1) {
|
||||
buf.append(", ");
|
||||
}
|
||||
}
|
||||
buf.append(" ]\n");
|
||||
}
|
||||
}
|
||||
|
||||
void render(StringBuilder buf) {
|
||||
buf.append("[ ");
|
||||
renderString(buf, mLabel);
|
||||
buf.append(", ");
|
||||
renderString(buf, mLink);
|
||||
buf.append(", ");
|
||||
renderChildren(buf);
|
||||
buf.append(", ");
|
||||
renderString(buf, mSince);
|
||||
buf.append(" ]");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import com.sun.javadoc.*;
|
||||
import com.sun.tools.doclets.*;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public class PackageInfo extends DocInfo implements ContainerInfo
|
||||
{
|
||||
public static final Comparator<PackageInfo> comparator = new Comparator<PackageInfo>() {
|
||||
public int compare(PackageInfo a, PackageInfo b) {
|
||||
return a.name().compareTo(b.name());
|
||||
}
|
||||
};
|
||||
|
||||
public PackageInfo(PackageDoc pkg, String name, SourcePositionInfo position)
|
||||
{
|
||||
super(pkg.getRawCommentText(), position);
|
||||
mName = name;
|
||||
|
||||
if (pkg == null) {
|
||||
throw new RuntimeException("pkg is null");
|
||||
}
|
||||
mPackage = pkg;
|
||||
}
|
||||
|
||||
public String htmlPage()
|
||||
{
|
||||
String s = mName;
|
||||
s = s.replace('.', '/');
|
||||
s += "/package-summary.html";
|
||||
s = DroidDoc.javadocDir + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
public String fullDescriptionHtmlPage() {
|
||||
String s = mName;
|
||||
s = s.replace('.', '/');
|
||||
s += "/package-descr.html";
|
||||
s = DroidDoc.javadocDir + s;
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerInfo parent()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden()
|
||||
{
|
||||
return comment().isHidden();
|
||||
}
|
||||
|
||||
public boolean checkLevel() {
|
||||
// TODO should return false if all classes are hidden but the package isn't.
|
||||
// We don't have this so I'm not doing it now.
|
||||
return !isHidden();
|
||||
}
|
||||
|
||||
public String name()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
public String qualifiedName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
public TagInfo[] inlineTags()
|
||||
{
|
||||
return comment().tags();
|
||||
}
|
||||
|
||||
public TagInfo[] firstSentenceTags()
|
||||
{
|
||||
return comment().briefTags();
|
||||
}
|
||||
|
||||
public static ClassInfo[] filterHidden(ClassInfo[] classes)
|
||||
{
|
||||
ArrayList<ClassInfo> out = new ArrayList<ClassInfo>();
|
||||
|
||||
for (ClassInfo cl: classes) {
|
||||
if (!cl.isHidden()) {
|
||||
out.add(cl);
|
||||
}
|
||||
}
|
||||
|
||||
return out.toArray(new ClassInfo[0]);
|
||||
}
|
||||
|
||||
public void makeLink(HDF data, String base)
|
||||
{
|
||||
if (checkLevel()) {
|
||||
data.setValue(base + ".link", htmlPage());
|
||||
}
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".since", getSince());
|
||||
}
|
||||
|
||||
public void makeClassLinkListHDF(HDF data, String base)
|
||||
{
|
||||
makeLink(data, base);
|
||||
ClassInfo.makeLinkListHDF(data, base + ".interfaces", interfaces());
|
||||
ClassInfo.makeLinkListHDF(data, base + ".classes", ordinaryClasses());
|
||||
ClassInfo.makeLinkListHDF(data, base + ".enums", enums());
|
||||
ClassInfo.makeLinkListHDF(data, base + ".exceptions", exceptions());
|
||||
ClassInfo.makeLinkListHDF(data, base + ".errors", errors());
|
||||
data.setValue(base + ".since", getSince());
|
||||
}
|
||||
|
||||
public ClassInfo[] interfaces()
|
||||
{
|
||||
if (mInterfaces == null) {
|
||||
mInterfaces = ClassInfo.sortByName(filterHidden(Converter.convertClasses(
|
||||
mPackage.interfaces())));
|
||||
}
|
||||
return mInterfaces;
|
||||
}
|
||||
|
||||
public ClassInfo[] ordinaryClasses()
|
||||
{
|
||||
if (mOrdinaryClasses == null) {
|
||||
mOrdinaryClasses = ClassInfo.sortByName(filterHidden(Converter.convertClasses(
|
||||
mPackage.ordinaryClasses())));
|
||||
}
|
||||
return mOrdinaryClasses;
|
||||
}
|
||||
|
||||
public ClassInfo[] enums()
|
||||
{
|
||||
if (mEnums == null) {
|
||||
mEnums = ClassInfo.sortByName(filterHidden(Converter.convertClasses(mPackage.enums())));
|
||||
}
|
||||
return mEnums;
|
||||
}
|
||||
|
||||
public ClassInfo[] exceptions()
|
||||
{
|
||||
if (mExceptions == null) {
|
||||
mExceptions = ClassInfo.sortByName(filterHidden(Converter.convertClasses(
|
||||
mPackage.exceptions())));
|
||||
}
|
||||
return mExceptions;
|
||||
}
|
||||
|
||||
public ClassInfo[] errors()
|
||||
{
|
||||
if (mErrors == null) {
|
||||
mErrors = ClassInfo.sortByName(filterHidden(Converter.convertClasses(
|
||||
mPackage.errors())));
|
||||
}
|
||||
return mErrors;
|
||||
}
|
||||
|
||||
// in hashed containers, treat the name as the key
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mName.hashCode();
|
||||
}
|
||||
|
||||
private String mName;
|
||||
private PackageDoc mPackage;
|
||||
private ClassInfo[] mInterfaces;
|
||||
private ClassInfo[] mOrdinaryClasses;
|
||||
private ClassInfo[] mEnums;
|
||||
private ClassInfo[] mExceptions;
|
||||
private ClassInfo[] mErrors;
|
||||
}
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
public class ParamTagInfo extends ParsedTagInfo
|
||||
{
|
||||
static final Pattern PATTERN = Pattern.compile(
|
||||
"([^ \t\r\n]+)[ \t\r\n]+(.*)",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private boolean mIsTypeParameter;
|
||||
private String mParameterComment;
|
||||
private String mParameterName;
|
||||
|
||||
ParamTagInfo(String name, String kind, String text, ContainerInfo base,
|
||||
SourcePositionInfo sp)
|
||||
{
|
||||
super(name, kind, text, base, sp);
|
||||
|
||||
Matcher m = PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
mParameterName = m.group(1);
|
||||
mParameterComment = m.group(2);
|
||||
int len = mParameterName.length();
|
||||
mIsTypeParameter = len > 2
|
||||
&& mParameterName.charAt(0) == '<'
|
||||
&& mParameterName.charAt(len-1) == '>';
|
||||
} else {
|
||||
mParameterName = text.trim();
|
||||
mParameterComment = "";
|
||||
mIsTypeParameter = false;
|
||||
}
|
||||
setCommentText(mParameterComment);
|
||||
}
|
||||
|
||||
ParamTagInfo(String name, String kind, String text,
|
||||
boolean isTypeParameter, String parameterComment,
|
||||
String parameterName, ContainerInfo base,
|
||||
SourcePositionInfo sp)
|
||||
{
|
||||
super(name, kind, text, base, sp);
|
||||
mIsTypeParameter = isTypeParameter;
|
||||
mParameterComment = parameterComment;
|
||||
mParameterName = parameterName;
|
||||
}
|
||||
|
||||
public boolean isTypeParameter()
|
||||
{
|
||||
return mIsTypeParameter;
|
||||
}
|
||||
|
||||
public String parameterComment()
|
||||
{
|
||||
return mParameterComment;
|
||||
}
|
||||
|
||||
public String parameterName()
|
||||
{
|
||||
return mParameterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".name", parameterName());
|
||||
data.setValue(base + ".isTypeParameter", isTypeParameter() ? "1" : "0");
|
||||
TagInfo.makeHDF(data, base + ".comment", commentTags());
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, ParamTagInfo[] tags)
|
||||
{
|
||||
for (int i=0; i<tags.length; i++) {
|
||||
// don't output if the comment is ""
|
||||
if (!"".equals(tags[i].parameterComment())) {
|
||||
tags[i].makeHDF(data, base + "." + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.HashSet;
|
||||
|
||||
public class ParameterInfo
|
||||
{
|
||||
ParameterInfo(String name, String typeName, TypeInfo type, SourcePositionInfo position)
|
||||
{
|
||||
mName = name;
|
||||
mTypeName = typeName;
|
||||
mType = type;
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
TypeInfo type()
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
String name()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
String typeName()
|
||||
{
|
||||
return mTypeName;
|
||||
}
|
||||
|
||||
SourcePositionInfo position()
|
||||
{
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base, boolean isLastVararg,
|
||||
HashSet<String> typeVariables)
|
||||
{
|
||||
data.setValue(base + ".name", this.name());
|
||||
type().makeHDF(data, base + ".type", isLastVararg, typeVariables);
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, ParameterInfo[] params,
|
||||
boolean isVararg, HashSet<String> typeVariables)
|
||||
{
|
||||
for (int i=0; i<params.length; i++) {
|
||||
params[i].makeHDF(data, base + "." + i,
|
||||
isVararg && (i == params.length - 1), typeVariables);
|
||||
}
|
||||
}
|
||||
|
||||
String mName;
|
||||
String mTypeName;
|
||||
TypeInfo mType;
|
||||
SourcePositionInfo mPosition;
|
||||
}
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ParsedTagInfo extends TagInfo
|
||||
{
|
||||
private ContainerInfo mContainer;
|
||||
private String mCommentText;
|
||||
private Comment mComment;
|
||||
|
||||
ParsedTagInfo(String name, String kind, String text, ContainerInfo base, SourcePositionInfo sp)
|
||||
{
|
||||
super(name, kind, text, SourcePositionInfo.findBeginning(sp, text));
|
||||
mContainer = base;
|
||||
mCommentText = text;
|
||||
}
|
||||
|
||||
public TagInfo[] commentTags()
|
||||
{
|
||||
if (mComment == null) {
|
||||
mComment = new Comment(mCommentText, mContainer, position());
|
||||
}
|
||||
return mComment.tags();
|
||||
}
|
||||
|
||||
protected void setCommentText(String comment)
|
||||
{
|
||||
mCommentText = comment;
|
||||
}
|
||||
|
||||
public static <T extends ParsedTagInfo> TagInfo[]
|
||||
joinTags(T[] tags)
|
||||
{
|
||||
ArrayList<TagInfo> list = new ArrayList<TagInfo>();
|
||||
final int N = tags.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
TagInfo[] t = tags[i].commentTags();
|
||||
final int M = t.length;
|
||||
for (int j=0; j<M; j++) {
|
||||
list.add(t[j]);
|
||||
}
|
||||
}
|
||||
return list.toArray(new TagInfo[list.size()]);
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.FileWriter;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class Proofread
|
||||
{
|
||||
static FileWriter out = null;
|
||||
static final Pattern WHITESPACE = Pattern.compile("\\r?\\n");
|
||||
static final String INDENT = " ";
|
||||
static final String NEWLINE = "\n" + INDENT;
|
||||
|
||||
public static void initProofread(String filename)
|
||||
{
|
||||
try {
|
||||
out = new FileWriter(filename);
|
||||
out.write("javadoc proofread file: " + filename + "\n");
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
}
|
||||
out = null;
|
||||
}
|
||||
System.err.println("error opening file: " + filename);
|
||||
}
|
||||
}
|
||||
|
||||
public static void finishProofread(String filename)
|
||||
{
|
||||
if (out == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
out.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(String s)
|
||||
{
|
||||
if (out == null) {
|
||||
return ;
|
||||
}
|
||||
try {
|
||||
out.write(s);
|
||||
}
|
||||
catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeIndented(String s)
|
||||
{
|
||||
s = s.trim();
|
||||
Matcher m = WHITESPACE.matcher(s);
|
||||
s = m.replaceAll(NEWLINE);
|
||||
write(INDENT);
|
||||
write(s);
|
||||
write("\n");
|
||||
}
|
||||
|
||||
public static void writeFileHeader(String filename)
|
||||
{
|
||||
write("\n\n=== ");
|
||||
write(filename);
|
||||
write(" ===\n");
|
||||
}
|
||||
|
||||
public static void writeTagList(TagInfo[] tags)
|
||||
{
|
||||
if (out == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TagInfo t: tags) {
|
||||
String k = t.kind();
|
||||
if ("Text".equals(t.name())) {
|
||||
writeIndented(t.text());
|
||||
}
|
||||
else if ("@more".equals(k)) {
|
||||
writeIndented("");
|
||||
}
|
||||
else if ("@see".equals(k)) {
|
||||
SeeTagInfo see = (SeeTagInfo)t;
|
||||
String label = see.label();
|
||||
if (label == null) {
|
||||
label = "";
|
||||
}
|
||||
writeIndented("{" + see.name() + " ... " + label + "}");
|
||||
}
|
||||
else if ("@code".equals(k)) {
|
||||
writeIndented(t.text());
|
||||
}
|
||||
else if ("@samplecode".equals(k)) {
|
||||
writeIndented(t.text());
|
||||
}
|
||||
else {
|
||||
writeIndented("{" + (t.name() != null ? t.name() : "") + "/" +
|
||||
t.text() + "}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void writePackages(String filename, TagInfo[] tags)
|
||||
{
|
||||
if (out == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
writeFileHeader(filename);
|
||||
writeTagList(tags);
|
||||
}
|
||||
|
||||
public static void writePackage(String filename, TagInfo[] tags)
|
||||
{
|
||||
if (out == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
writeFileHeader(filename);
|
||||
writeTagList(tags);
|
||||
}
|
||||
|
||||
public static void writeClass(String filename, ClassInfo cl)
|
||||
{
|
||||
if (out == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
writeFileHeader(filename);
|
||||
writeTagList(cl.inlineTags());
|
||||
|
||||
// enum constants
|
||||
for (FieldInfo f: cl.enumConstants()) {
|
||||
write("ENUM: " + f.name() + "\n");
|
||||
writeTagList(f.inlineTags());
|
||||
}
|
||||
|
||||
// fields
|
||||
for (FieldInfo f: cl.selfFields()) {
|
||||
write("FIELD: " + f.name() + "\n");
|
||||
writeTagList(f.inlineTags());
|
||||
}
|
||||
|
||||
// constructors
|
||||
for (MethodInfo m: cl.constructors()) {
|
||||
write("CONSTRUCTOR: " + m.name() + "\n");
|
||||
writeTagList(m.inlineTags().tags());
|
||||
}
|
||||
|
||||
// methods
|
||||
for (MethodInfo m: cl.selfMethods()) {
|
||||
write("METHOD: " + m.name() + "\n");
|
||||
writeTagList(m.inlineTags().tags());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,178 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
|
||||
public class SampleCode {
|
||||
String mSource;
|
||||
String mDest;
|
||||
String mTitle;
|
||||
|
||||
public SampleCode(String source, String dest, String title) {
|
||||
mSource = source;
|
||||
mTitle = title;
|
||||
int len = dest.length();
|
||||
if (len > 1 && dest.charAt(len-1) != '/') {
|
||||
mDest = dest + '/';
|
||||
} else {
|
||||
mDest = dest;
|
||||
}
|
||||
}
|
||||
|
||||
public void write(boolean offlineMode) {
|
||||
File f = new File(mSource);
|
||||
if (!f.isDirectory()) {
|
||||
System.out.println("-samplecode not a directory: " + mSource);
|
||||
return;
|
||||
}
|
||||
if (offlineMode) writeIndexOnly(f, mDest, offlineMode);
|
||||
else writeDirectory(f, mDest);
|
||||
}
|
||||
|
||||
public static String convertExtension(String s, String ext) {
|
||||
return s.substring(0, s.lastIndexOf('.')) + ext;
|
||||
}
|
||||
|
||||
public static String[] IMAGES = { ".png", ".jpg", ".gif" };
|
||||
public static String[] TEMPLATED = { ".java", ".xml" };
|
||||
|
||||
public static boolean inList(String s, String[] list) {
|
||||
for (String t: list) {
|
||||
if (s.endsWith(t)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void writeDirectory(File dir, String relative) {
|
||||
TreeSet<String> dirs = new TreeSet<String>();
|
||||
TreeSet<String> files = new TreeSet<String>();
|
||||
|
||||
String subdir = relative; //.substring(mDest.length());
|
||||
|
||||
for (File f: dir.listFiles()) {
|
||||
String name = f.getName();
|
||||
if (name.startsWith(".") || name.startsWith("_")) {
|
||||
continue;
|
||||
}
|
||||
if (f.isFile()) {
|
||||
String out = relative + name;
|
||||
|
||||
if (inList(out, IMAGES)) {
|
||||
// copied directly
|
||||
ClearPage.copyFile(f, out);
|
||||
writeImagePage(f, convertExtension(out, DroidDoc.htmlExtension), subdir);
|
||||
files.add(name);
|
||||
}
|
||||
if (inList(out, TEMPLATED)) {
|
||||
// copied and goes through the template
|
||||
ClearPage.copyFile(f, out);
|
||||
writePage(f, convertExtension(out, DroidDoc.htmlExtension), subdir);
|
||||
files.add(name);
|
||||
}
|
||||
// else ignored
|
||||
}
|
||||
else if (f.isDirectory()) {
|
||||
writeDirectory(f, relative + name + "/");
|
||||
dirs.add(name);
|
||||
}
|
||||
}
|
||||
|
||||
// write the index page
|
||||
int i;
|
||||
|
||||
HDF hdf = writeIndex(dir);
|
||||
hdf.setValue("subdir", subdir);
|
||||
i=0;
|
||||
for (String d: dirs) {
|
||||
hdf.setValue("subdirs." + i + ".name", d);
|
||||
i++;
|
||||
}
|
||||
i=0;
|
||||
for (String f: files) {
|
||||
hdf.setValue("files." + i + ".name", f);
|
||||
hdf.setValue("files." + i + ".href", convertExtension(f, ".html"));
|
||||
i++;
|
||||
}
|
||||
|
||||
ClearPage.write(hdf, "sampleindex.cs", relative + "/index" + DroidDoc.htmlExtension);
|
||||
}
|
||||
|
||||
public void writeIndexOnly(File dir, String relative, Boolean offline) {
|
||||
HDF hdf = writeIndex(dir);
|
||||
if (!offline) relative = "/" + relative;
|
||||
ClearPage.write(hdf, "sampleindex.cs", relative + "index" +
|
||||
DroidDoc.htmlExtension);
|
||||
}
|
||||
|
||||
public HDF writeIndex(File dir) {
|
||||
HDF hdf = DroidDoc.makeHDF();
|
||||
|
||||
hdf.setValue("page.title", dir.getName() + " - " + mTitle);
|
||||
hdf.setValue("projectTitle", mTitle);
|
||||
|
||||
String filename = dir.getPath() + "/_index.html";
|
||||
String summary = SampleTagInfo.readFile(new SourcePositionInfo(filename,
|
||||
-1,-1), filename, "sample code", true, false, true);
|
||||
|
||||
if (summary == null) {
|
||||
summary = "";
|
||||
}
|
||||
hdf.setValue("summary", summary);
|
||||
|
||||
return hdf;
|
||||
}
|
||||
|
||||
public void writePage(File f, String out, String subdir) {
|
||||
String name = f.getName();
|
||||
|
||||
String filename = f.getPath();
|
||||
String data = SampleTagInfo.readFile(new SourcePositionInfo(filename, -1,-1), filename,
|
||||
"sample code", true, true, true);
|
||||
data = DroidDoc.escape(data);
|
||||
|
||||
HDF hdf = DroidDoc.makeHDF();
|
||||
|
||||
hdf.setValue("page.title", name);
|
||||
hdf.setValue("subdir", subdir);
|
||||
hdf.setValue("realFile", name);
|
||||
hdf.setValue("fileContents", data);
|
||||
|
||||
ClearPage.write(hdf, "sample.cs", out);
|
||||
}
|
||||
|
||||
public void writeImagePage(File f, String out, String subdir) {
|
||||
String name = f.getName();
|
||||
|
||||
String data = "<img src=\"" + name + "\" title=\"" + name + "\" />";
|
||||
|
||||
HDF hdf = DroidDoc.makeHDF();
|
||||
|
||||
hdf.setValue("page.title", name);
|
||||
hdf.setValue("subdir", subdir);
|
||||
hdf.setValue("realFile", name);
|
||||
hdf.setValue("fileContents", data);
|
||||
|
||||
ClearPage.write(hdf, "sample.cs", out);
|
||||
}
|
||||
}
|
|
@ -1,289 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.IOException;
|
||||
import java.io.FileReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/*
|
||||
* SampleTagInfo copies text from a given file into the javadoc comment.
|
||||
*
|
||||
* The @include tag copies the text verbatim from the given file.
|
||||
*
|
||||
* The @sample tag copies the text from the given file, stripping leading and
|
||||
* trailing whitespace, and reducing the indent level of the text to the indent
|
||||
* level of the first non-whitespace line.
|
||||
*
|
||||
* Both tags accept either a filename and an id or just a filename. If no id
|
||||
* is provided, the entire file is copied. If an id is provided, the lines
|
||||
* in the given file between the first two lines containing BEGIN_INCLUDE(id)
|
||||
* and END_INCLUDE(id), for the given id, are copied. The id may be only
|
||||
* letters, numbers and underscore (_).
|
||||
*
|
||||
* Four examples:
|
||||
* {@include samples/ApiDemos/src/com/google/app/Notification1.java}
|
||||
* {@sample samples/ApiDemos/src/com/google/app/Notification1.java}
|
||||
* {@include samples/ApiDemos/src/com/google/app/Notification1.java Bleh}
|
||||
* {@sample samples/ApiDemos/src/com/google/app/Notification1.java Bleh}
|
||||
*
|
||||
*/
|
||||
public class SampleTagInfo extends TagInfo
|
||||
{
|
||||
static final int STATE_BEGIN = 0;
|
||||
static final int STATE_MATCHING = 1;
|
||||
|
||||
static final Pattern TEXT = Pattern.compile(
|
||||
"[\r\n \t]*([^\r\n \t]*)[\r\n \t]*([0-9A-Za-z_]*)[\r\n \t]*",
|
||||
Pattern.DOTALL);
|
||||
|
||||
private static final String BEGIN_INCLUDE = "BEGIN_INCLUDE";
|
||||
private static final String END_INCLUDE = "END_INCLUDE";
|
||||
|
||||
private ContainerInfo mBase;
|
||||
private String mIncluded;
|
||||
|
||||
public static String escapeHtml(String str) {
|
||||
return str.replace("&", "&").replace("<", "<").replace(">", ">");
|
||||
}
|
||||
|
||||
private static boolean isIncludeLine(String str) {
|
||||
return str.indexOf(BEGIN_INCLUDE)>=0 || str.indexOf(END_INCLUDE)>=0;
|
||||
}
|
||||
|
||||
SampleTagInfo(String name, String kind, String text, ContainerInfo base,
|
||||
SourcePositionInfo position)
|
||||
{
|
||||
super(name, kind, text, position);
|
||||
mBase = base;
|
||||
|
||||
Matcher m = TEXT.matcher(text);
|
||||
if (!m.matches()) {
|
||||
Errors.error(Errors.BAD_INCLUDE_TAG, position, "Bad @include tag: "
|
||||
+ text);
|
||||
return;
|
||||
}
|
||||
String filename = m.group(1);
|
||||
String id = m.group(2);
|
||||
boolean trim = "@sample".equals(name);
|
||||
|
||||
if (id == null || "".equals(id)) {
|
||||
mIncluded = readFile(position, filename, id, trim, true, false);
|
||||
} else {
|
||||
mIncluded = loadInclude(position, filename, id, trim);
|
||||
}
|
||||
|
||||
if (mIncluded == null) {
|
||||
Errors.error(Errors.BAD_INCLUDE_TAG, position, "include tag '" + id
|
||||
+ "' not found in file: " + filename);
|
||||
}
|
||||
}
|
||||
|
||||
static String getTrimString(String line)
|
||||
{
|
||||
int i = 0;
|
||||
int len = line.length();
|
||||
for (; i<len; i++) {
|
||||
char c = line.charAt(i);
|
||||
if (c != ' ' && c != '\t') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == len) {
|
||||
return null;
|
||||
} else {
|
||||
return line.substring(0, i);
|
||||
}
|
||||
}
|
||||
|
||||
static String loadInclude(SourcePositionInfo pos, String filename,
|
||||
String id, boolean trim)
|
||||
{
|
||||
Reader input = null;
|
||||
StringBuilder result = new StringBuilder();
|
||||
|
||||
String begin = BEGIN_INCLUDE + "(" + id + ")";
|
||||
String end = END_INCLUDE + "(" + id + ")";
|
||||
|
||||
try {
|
||||
input = new FileReader(filename);
|
||||
LineNumberReader lines = new LineNumberReader(input);
|
||||
|
||||
int state = STATE_BEGIN;
|
||||
|
||||
int trimLength = -1;
|
||||
String trimString = null;
|
||||
int trailing = 0;
|
||||
|
||||
while (true) {
|
||||
String line = lines.readLine();
|
||||
if (line == null) {
|
||||
return null;
|
||||
}
|
||||
switch (state) {
|
||||
case STATE_BEGIN:
|
||||
if (line.indexOf(begin) >= 0) {
|
||||
state = STATE_MATCHING;
|
||||
}
|
||||
break;
|
||||
case STATE_MATCHING:
|
||||
if (line.indexOf(end) >= 0) {
|
||||
return result.substring(0);
|
||||
} else {
|
||||
boolean empty = "".equals(line.trim());
|
||||
if (trim) {
|
||||
if (isIncludeLine(line)) {
|
||||
continue;
|
||||
}
|
||||
if (trimLength < 0 && !empty) {
|
||||
trimString = getTrimString(line);
|
||||
if (trimString != null) {
|
||||
trimLength = trimString.length();
|
||||
}
|
||||
}
|
||||
if (trimLength >= 0 && line.length() > trimLength) {
|
||||
boolean trimThisLine = true;
|
||||
for (int i=0; i<trimLength; i++) {
|
||||
if (line.charAt(i) != trimString.charAt(i)){
|
||||
trimThisLine = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trimThisLine) {
|
||||
line = line.substring(trimLength);
|
||||
}
|
||||
}
|
||||
if (trimLength >= 0) {
|
||||
if (!empty) {
|
||||
for (int i=0; i<trailing; i++) {
|
||||
result.append('\n');
|
||||
}
|
||||
line = escapeHtml(line);
|
||||
result.append(line);
|
||||
trailing = 1; // add \n next time, maybe
|
||||
} else {
|
||||
trailing++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(line);
|
||||
result.append('\n');
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
Errors.error(Errors.BAD_INCLUDE_TAG, pos, "Error reading file for"
|
||||
+ " include \"" + id + "\" " + filename);
|
||||
}
|
||||
finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
Errors.error(Errors.BAD_INCLUDE_TAG, pos, "Did not find " + end
|
||||
+ " in file " + filename);
|
||||
return null;
|
||||
}
|
||||
|
||||
static String readFile(SourcePositionInfo pos, String filename,
|
||||
String id, boolean trim, boolean escape,
|
||||
boolean errorOk)
|
||||
{
|
||||
Reader input = null;
|
||||
StringBuilder result = new StringBuilder();
|
||||
int trailing = 0;
|
||||
boolean started = false;
|
||||
try {
|
||||
input = new FileReader(filename);
|
||||
LineNumberReader lines = new LineNumberReader(input);
|
||||
|
||||
while (true) {
|
||||
String line = lines.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
if (trim) {
|
||||
if (isIncludeLine(line)) {
|
||||
continue;
|
||||
}
|
||||
if (!"".equals(line.trim())) {
|
||||
if (started) {
|
||||
for (int i=0; i<trailing; i++) {
|
||||
result.append('\n');
|
||||
}
|
||||
}
|
||||
if (escape) {
|
||||
line = escapeHtml(line);
|
||||
}
|
||||
result.append(line);
|
||||
trailing = 1; // add \n next time, maybe
|
||||
started = true;
|
||||
} else {
|
||||
if (started) {
|
||||
trailing++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.append(line);
|
||||
result.append('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
if (errorOk) {
|
||||
return null;
|
||||
} else {
|
||||
Errors.error(Errors.BAD_INCLUDE_TAG, pos, "Error reading file for"
|
||||
+ " include \"" + id + "\" " + filename);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (input != null) {
|
||||
try {
|
||||
input.close();
|
||||
}
|
||||
catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
return result.substring(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".kind", kind());
|
||||
if (mIncluded != null) {
|
||||
data.setValue(base + ".text", mIncluded);
|
||||
} else {
|
||||
data.setValue(base + ".text", "INCLUDE_ERROR");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public interface Scoped {
|
||||
boolean isPublic();
|
||||
boolean isProtected();
|
||||
boolean isPackagePrivate();
|
||||
boolean isPrivate();
|
||||
boolean isHidden();
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SeeTagInfo extends TagInfo
|
||||
{
|
||||
private ContainerInfo mBase;
|
||||
LinkReference mLink;
|
||||
|
||||
SeeTagInfo(String name, String kind, String text, ContainerInfo base,
|
||||
SourcePositionInfo position)
|
||||
{
|
||||
super(name, kind, text, position);
|
||||
mBase = base;
|
||||
}
|
||||
|
||||
protected LinkReference linkReference() {
|
||||
if (mLink == null) {
|
||||
mLink = LinkReference.parse(text(), mBase, position(),
|
||||
(!"@see".equals(name())) && (mBase != null ? mBase.checkLevel() : true));
|
||||
}
|
||||
return mLink;
|
||||
}
|
||||
|
||||
public String label()
|
||||
{
|
||||
return linkReference().label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
LinkReference linkRef = linkReference();
|
||||
if (linkRef.kind != null) {
|
||||
// if they have a better suggestion about "kind" use that.
|
||||
// do this before super.makeHDF() so it picks it up
|
||||
setKind(linkRef.kind);
|
||||
}
|
||||
|
||||
super.makeHDF(data, base);
|
||||
|
||||
data.setValue(base + ".label", linkRef.label);
|
||||
if (linkRef.href != null) {
|
||||
data.setValue(base + ".href", linkRef.href);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkLevel() {
|
||||
return linkReference().checkLevel();
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, SeeTagInfo[] tags)
|
||||
{
|
||||
int j=0;
|
||||
for (SeeTagInfo tag: tags) {
|
||||
if (tag.mBase.checkLevel() && tag.checkLevel()) {
|
||||
tag.makeHDF(data, base + "." + j);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,237 +0,0 @@
|
|||
// Copyright 2009 Google Inc. All Rights Reserved.
|
||||
|
||||
import com.android.apicheck.ApiCheck;
|
||||
import com.android.apicheck.ApiInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
|
||||
/**
|
||||
* Applies version information to the DroidDoc class model from apicheck XML
|
||||
* files. Sample usage:
|
||||
* <pre>
|
||||
* ClassInfo[] classInfos = ...
|
||||
*
|
||||
* SinceTagger sinceTagger = new SinceTagger()
|
||||
* sinceTagger.addVersion("frameworks/base/api/1.xml", "Android 1.0")
|
||||
* sinceTagger.addVersion("frameworks/base/api/2.xml", "Android 1.5")
|
||||
* sinceTagger.tagAll(...);
|
||||
* </pre>
|
||||
*/
|
||||
public class SinceTagger {
|
||||
|
||||
private final Map<String, String> xmlToName
|
||||
= new LinkedHashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Specifies the apicheck XML file and the API version it holds. Calls to
|
||||
* this method should be called in order from oldest version to newest.
|
||||
*/
|
||||
public void addVersion(String file, String name) {
|
||||
xmlToName.put(file, name);
|
||||
}
|
||||
|
||||
public void tagAll(ClassInfo[] classDocs) {
|
||||
// read through the XML files in order, applying their since information
|
||||
// to the Javadoc models
|
||||
for (Map.Entry<String, String> versionSpec : xmlToName.entrySet()) {
|
||||
String xmlFile = versionSpec.getKey();
|
||||
String versionName = versionSpec.getValue();
|
||||
ApiInfo specApi = new ApiCheck().parseApi(xmlFile);
|
||||
|
||||
applyVersionsFromSpec(versionName, specApi, classDocs);
|
||||
}
|
||||
|
||||
if (!xmlToName.isEmpty()) {
|
||||
warnForMissingVersions(classDocs);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an index of the version names to {@code data}.
|
||||
*/
|
||||
public void writeVersionNames(HDF data) {
|
||||
int index = 1;
|
||||
for (String version : xmlToName.values()) {
|
||||
data.setValue("since." + index + ".name", version);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the version information to {@code classDocs} where not already
|
||||
* present.
|
||||
*
|
||||
* @param versionName the version name
|
||||
* @param specApi the spec for this version. If a symbol is in this spec, it
|
||||
* was present in the named version
|
||||
* @param classDocs the doc model to update
|
||||
*/
|
||||
private void applyVersionsFromSpec(String versionName,
|
||||
ApiInfo specApi, ClassInfo[] classDocs) {
|
||||
for (ClassInfo classDoc : classDocs) {
|
||||
com.android.apicheck.PackageInfo packageSpec
|
||||
= specApi.getPackages().get(classDoc.containingPackage().name());
|
||||
|
||||
if (packageSpec == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
com.android.apicheck.ClassInfo classSpec
|
||||
= packageSpec.allClasses().get(classDoc.name());
|
||||
|
||||
if (classSpec == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
versionPackage(versionName, classDoc.containingPackage());
|
||||
versionClass(versionName, classDoc);
|
||||
versionConstructors(versionName, classSpec, classDoc);
|
||||
versionFields(versionName, classSpec, classDoc);
|
||||
versionMethods(versionName, classSpec, classDoc);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies version information to {@code doc} where not already present.
|
||||
*/
|
||||
private void versionPackage(String versionName, PackageInfo doc) {
|
||||
if (doc.getSince() == null) {
|
||||
doc.setSince(versionName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies version information to {@code doc} where not already present.
|
||||
*/
|
||||
private void versionClass(String versionName, ClassInfo doc) {
|
||||
if (doc.getSince() == null) {
|
||||
doc.setSince(versionName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies version information from {@code spec} to {@code doc} where not
|
||||
* already present.
|
||||
*/
|
||||
private void versionConstructors(String versionName,
|
||||
com.android.apicheck.ClassInfo spec, ClassInfo doc) {
|
||||
for (MethodInfo constructor : doc.constructors()) {
|
||||
if (constructor.getSince() == null
|
||||
&& spec.allConstructors().containsKey(constructor.getHashableName())) {
|
||||
constructor.setSince(versionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies version information from {@code spec} to {@code doc} where not
|
||||
* already present.
|
||||
*/
|
||||
private void versionFields(String versionName,
|
||||
com.android.apicheck.ClassInfo spec, ClassInfo doc) {
|
||||
for (FieldInfo field : doc.fields()) {
|
||||
if (field.getSince() == null
|
||||
&& spec.allFields().containsKey(field.name())) {
|
||||
field.setSince(versionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies version information from {@code spec} to {@code doc} where not
|
||||
* already present.
|
||||
*/
|
||||
private void versionMethods(String versionName,
|
||||
com.android.apicheck.ClassInfo spec, ClassInfo doc) {
|
||||
for (MethodInfo method : doc.methods()) {
|
||||
if (method.getSince() != null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (com.android.apicheck.ClassInfo superclass : spec.hierarchy()) {
|
||||
if (superclass.allMethods().containsKey(method.getHashableName())) {
|
||||
method.setSince(versionName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warns if any symbols are missing version information. When configured
|
||||
* properly, this will yield zero warnings because {@code apicheck}
|
||||
* guarantees that all symbols are present in the most recent API.
|
||||
*/
|
||||
private void warnForMissingVersions(ClassInfo[] classDocs) {
|
||||
for (ClassInfo claz : classDocs) {
|
||||
if (!checkLevelRecursive(claz)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (claz.getSince() == null) {
|
||||
Errors.error(Errors.NO_SINCE_DATA, claz.position(),
|
||||
"XML missing class " + claz.qualifiedName());
|
||||
}
|
||||
|
||||
for (FieldInfo field : missingVersions(claz.fields())) {
|
||||
Errors.error(Errors.NO_SINCE_DATA, field.position(),
|
||||
"XML missing field " + claz.qualifiedName()
|
||||
+ "#" + field.name());
|
||||
}
|
||||
|
||||
for (MethodInfo constructor : missingVersions(claz.constructors())) {
|
||||
Errors.error(Errors.NO_SINCE_DATA, constructor.position(),
|
||||
"XML missing constructor " + claz.qualifiedName()
|
||||
+ "#" + constructor.getHashableName());
|
||||
}
|
||||
|
||||
for (MethodInfo method : missingVersions(claz.methods())) {
|
||||
Errors.error(Errors.NO_SINCE_DATA, method.position(),
|
||||
"XML missing method " + claz.qualifiedName()
|
||||
+ "#" + method.getHashableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the DocInfos in {@code all} that are documented but do not have
|
||||
* since tags.
|
||||
*/
|
||||
private <T extends MemberInfo> Iterable<T> missingVersions(T[] all) {
|
||||
List<T> result = Collections.emptyList();
|
||||
for (T t : all) {
|
||||
// if this member has version info or isn't documented, skip it
|
||||
if (t.getSince() != null
|
||||
|| t.isHidden()
|
||||
|| !checkLevelRecursive(t.realContainingClass())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = new ArrayList<T>(); // lazily construct a mutable list
|
||||
}
|
||||
result.add(t);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@code claz} and all containing classes are documented.
|
||||
* The result may be used to filter out members that exist in the API
|
||||
* data structure but aren't a part of the API.
|
||||
*/
|
||||
private boolean checkLevelRecursive(ClassInfo claz) {
|
||||
for (ClassInfo c = claz; c != null; c = c.containingClass()) {
|
||||
if (!c.checkLevel()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public class Sorter implements Comparable
|
||||
{
|
||||
public String label;
|
||||
public Object data;
|
||||
|
||||
public Sorter(String l, Object d)
|
||||
{
|
||||
label = l;
|
||||
data = d;
|
||||
}
|
||||
|
||||
public int compareTo(Object other)
|
||||
{
|
||||
return label.compareToIgnoreCase(((Sorter)other).label);
|
||||
}
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public class SourcePositionInfo implements Comparable
|
||||
{
|
||||
public SourcePositionInfo() {
|
||||
this.file = "<unknown>";
|
||||
this.line = 0;
|
||||
this.column = 0;
|
||||
}
|
||||
|
||||
public SourcePositionInfo(String file, int line, int column)
|
||||
{
|
||||
this.file = file;
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
}
|
||||
|
||||
public SourcePositionInfo(SourcePositionInfo that)
|
||||
{
|
||||
this.file = that.file;
|
||||
this.line = that.line;
|
||||
this.column = that.column;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given this position and str which occurs at that position, as well as str an index into str,
|
||||
* find the SourcePositionInfo.
|
||||
*
|
||||
* @throw StringIndexOutOfBoundsException if index > str.length()
|
||||
*/
|
||||
public static SourcePositionInfo add(SourcePositionInfo that, String str, int index)
|
||||
{
|
||||
if (that == null) {
|
||||
return null;
|
||||
}
|
||||
int line = that.line;
|
||||
char prev = 0;
|
||||
for (int i=0; i<index; i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c == '\r' || (c == '\n' && prev != '\r')) {
|
||||
line++;
|
||||
}
|
||||
prev = c;
|
||||
}
|
||||
return new SourcePositionInfo(that.file, line, 0);
|
||||
}
|
||||
|
||||
public static SourcePositionInfo findBeginning(SourcePositionInfo that, String str)
|
||||
{
|
||||
if (that == null) {
|
||||
return null;
|
||||
}
|
||||
int line = that.line-1; // -1 because, well, it seems to work
|
||||
int prev = 0;
|
||||
for (int i=str.length()-1; i>=0; i--) {
|
||||
char c = str.charAt(i);
|
||||
if ((c == '\r' && prev != '\n') || (c == '\n')) {
|
||||
line--;
|
||||
}
|
||||
prev = c;
|
||||
}
|
||||
return new SourcePositionInfo(that.file, line, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return file + ':' + line;
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
SourcePositionInfo that = (SourcePositionInfo)o;
|
||||
int r = this.file.compareTo(that.file);
|
||||
if (r != 0) return r;
|
||||
return this.line - that.line;
|
||||
}
|
||||
|
||||
public String file;
|
||||
public int line;
|
||||
public int column;
|
||||
}
|
|
@ -1,999 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.Comparator;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
public class Stubs {
|
||||
private static HashSet<ClassInfo> notStrippable;
|
||||
public static void writeStubs(String stubsDir, Boolean writeXML, String xmlFile,
|
||||
HashSet<String> stubPackages) {
|
||||
// figure out which classes we need
|
||||
notStrippable = new HashSet();
|
||||
ClassInfo[] all = Converter.allClasses();
|
||||
File xml = new File(xmlFile);
|
||||
xml.getParentFile().mkdirs();
|
||||
PrintStream xmlWriter = null;
|
||||
if (writeXML) {
|
||||
try {
|
||||
xmlWriter = new PrintStream(xml);
|
||||
} catch (FileNotFoundException e) {
|
||||
Errors.error(Errors.IO_ERROR, new SourcePositionInfo(xmlFile, 0, 0),
|
||||
"Cannot open file for write.");
|
||||
}
|
||||
}
|
||||
// If a class is public or protected, not hidden, and marked as included,
|
||||
// then we can't strip it
|
||||
for (ClassInfo cl: all) {
|
||||
if (cl.checkLevel() && cl.isIncluded()) {
|
||||
cantStripThis(cl, notStrippable, "0:0");
|
||||
}
|
||||
}
|
||||
|
||||
// complain about anything that looks includeable but is not supposed to
|
||||
// be written, e.g. hidden things
|
||||
for (ClassInfo cl: notStrippable) {
|
||||
if (!cl.isHidden()) {
|
||||
MethodInfo[] methods = cl.selfMethods();
|
||||
for (MethodInfo m: methods) {
|
||||
if (m.isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL,
|
||||
m.position(), "Reference to hidden method "
|
||||
+ m.name());
|
||||
} else if (m.isDeprecated()) {
|
||||
// don't bother reporting deprecated methods
|
||||
// unless they are public
|
||||
Errors.error(Errors.DEPRECATED,
|
||||
m.position(), "Method "
|
||||
+ cl.qualifiedName() + "." + m.name()
|
||||
+ " is deprecated");
|
||||
}
|
||||
|
||||
ClassInfo returnClass = m.returnType().asClassInfo();
|
||||
if (returnClass != null && returnClass.isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(),
|
||||
"Method " + cl.qualifiedName() + "." + m.name()
|
||||
+ " returns unavailable type " + returnClass.name());
|
||||
}
|
||||
|
||||
ParameterInfo[] params = m.parameters();
|
||||
for (ParameterInfo p: params) {
|
||||
TypeInfo t = p.type();
|
||||
if (!t.isPrimitive()) {
|
||||
if (t.asClassInfo().isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL,
|
||||
m.position(), "Parameter of hidden type "
|
||||
+ t.fullName() + " in "
|
||||
+ cl.qualifiedName() + "." + m.name() + "()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// annotations are handled like methods
|
||||
methods = cl.annotationElements();
|
||||
for (MethodInfo m: methods) {
|
||||
if (m.isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL,
|
||||
m.position(), "Reference to hidden annotation "
|
||||
+ m.name());
|
||||
}
|
||||
|
||||
ClassInfo returnClass = m.returnType().asClassInfo();
|
||||
if (returnClass != null && returnClass.isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL,
|
||||
m.position(), "Annotation '" + m.name()
|
||||
+ "' returns unavailable type " + returnClass.name());
|
||||
}
|
||||
|
||||
ParameterInfo[] params = m.parameters();
|
||||
for (ParameterInfo p: params) {
|
||||
TypeInfo t = p.type();
|
||||
if (!t.isPrimitive()) {
|
||||
if (t.asClassInfo().isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL,
|
||||
p.position(), "Reference to unavailable annotation class "
|
||||
+ t.fullName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cl.isDeprecated()) {
|
||||
// not hidden, but deprecated
|
||||
Errors.error(Errors.DEPRECATED,
|
||||
cl.position(), "Class " + cl.qualifiedName()
|
||||
+ " is deprecated");
|
||||
}
|
||||
}
|
||||
|
||||
// write out the stubs
|
||||
HashMap<PackageInfo, List<ClassInfo>> packages = new HashMap<PackageInfo, List<ClassInfo>>();
|
||||
for (ClassInfo cl: notStrippable) {
|
||||
if (!cl.isDocOnly()) {
|
||||
if (stubPackages == null || stubPackages.contains(cl.containingPackage().name())) {
|
||||
writeClassFile(stubsDir, cl);
|
||||
if (packages.containsKey(cl.containingPackage())) {
|
||||
packages.get(cl.containingPackage()).add(cl);
|
||||
} else {
|
||||
ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>();
|
||||
classes.add(cl);
|
||||
packages.put(cl.containingPackage(), classes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write out the XML
|
||||
if (writeXML && xmlWriter != null) {
|
||||
writeXML(xmlWriter, packages, notStrippable);
|
||||
}
|
||||
|
||||
if (xmlWriter != null) {
|
||||
xmlWriter.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable, String why) {
|
||||
|
||||
if (!notStrippable.add(cl)) {
|
||||
// slight optimization: if it already contains cl, it already contains
|
||||
// all of cl's parents
|
||||
return;
|
||||
}
|
||||
cl.setReasonIncluded(why);
|
||||
|
||||
// cant strip annotations
|
||||
/*if (cl.annotations() != null){
|
||||
for (AnnotationInstanceInfo ai : cl.annotations()){
|
||||
if (ai.type() != null){
|
||||
cantStripThis(ai.type(), notStrippable, "1:" + cl.qualifiedName());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// cant strip any public fields or their generics
|
||||
if (cl.allSelfFields() != null){
|
||||
for (FieldInfo fInfo : cl.allSelfFields()){
|
||||
if (fInfo.type() != null){
|
||||
if (fInfo.type().asClassInfo() != null){
|
||||
cantStripThis(fInfo.type().asClassInfo(), notStrippable,
|
||||
"2:" + cl.qualifiedName());
|
||||
}
|
||||
if (fInfo.type().typeArguments() != null){
|
||||
for (TypeInfo tTypeInfo : fInfo.type().typeArguments()){
|
||||
if (tTypeInfo.asClassInfo() != null){
|
||||
cantStripThis(tTypeInfo.asClassInfo(), notStrippable,
|
||||
"3:" + cl.qualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//cant strip any of the type's generics
|
||||
if (cl.asTypeInfo() != null){
|
||||
if (cl.asTypeInfo().typeArguments() != null){
|
||||
for (TypeInfo tInfo : cl.asTypeInfo().typeArguments()){
|
||||
if (tInfo.asClassInfo() != null){
|
||||
cantStripThis(tInfo.asClassInfo(), notStrippable, "4:" + cl.qualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//cant strip any of the annotation elements
|
||||
//cantStripThis(cl.annotationElements(), notStrippable);
|
||||
// take care of methods
|
||||
cantStripThis(cl.allSelfMethods(), notStrippable);
|
||||
cantStripThis(cl.allConstructors(), notStrippable);
|
||||
// blow the outer class open if this is an inner class
|
||||
if(cl.containingClass() != null){
|
||||
cantStripThis(cl.containingClass(), notStrippable, "5:" + cl.qualifiedName());
|
||||
}
|
||||
// blow open super class and interfaces
|
||||
ClassInfo supr = cl.realSuperclass();
|
||||
if (supr != null) {
|
||||
if (supr.isHidden()) {
|
||||
// cl is a public class declared as extending a hidden superclass.
|
||||
// this is not a desired practice but it's happened, so we deal
|
||||
// with it by stripping off the superclass relation for purposes of
|
||||
// generating the doc & stub information, and proceeding normally.
|
||||
cl.init(cl.asTypeInfo(), cl.realInterfaces(), cl.realInterfaceTypes(),
|
||||
cl.innerClasses(), cl.allConstructors(), cl.allSelfMethods(),
|
||||
cl.annotationElements(), cl.allSelfFields(), cl.enumConstants(),
|
||||
cl.containingPackage(), cl.containingClass(),
|
||||
null, null, cl.annotations());
|
||||
Errors.error(Errors.HIDDEN_SUPERCLASS,
|
||||
cl.position(), "Public class " + cl.qualifiedName()
|
||||
+ " stripped of unavailable superclass "
|
||||
+ supr.qualifiedName());
|
||||
} else {
|
||||
cantStripThis(supr, notStrippable, "6:" + cl.realSuperclass().name()
|
||||
+ cl.qualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void cantStripThis(MethodInfo[] mInfos , HashSet<ClassInfo> notStrippable) {
|
||||
//for each method, blow open the parameters, throws and return types. also blow open their generics
|
||||
if (mInfos != null){
|
||||
for (MethodInfo mInfo : mInfos){
|
||||
if (mInfo.getTypeParameters() != null){
|
||||
for (TypeInfo tInfo : mInfo.getTypeParameters()){
|
||||
if (tInfo.asClassInfo() != null){
|
||||
cantStripThis(tInfo.asClassInfo(), notStrippable, "8:" +
|
||||
mInfo.realContainingClass().qualifiedName() + ":" +
|
||||
mInfo.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mInfo.parameters() != null){
|
||||
for (ParameterInfo pInfo : mInfo.parameters()){
|
||||
if (pInfo.type() != null && pInfo.type().asClassInfo() != null){
|
||||
cantStripThis(pInfo.type().asClassInfo(), notStrippable,
|
||||
"9:"+ mInfo.realContainingClass().qualifiedName()
|
||||
+ ":" + mInfo.name());
|
||||
if (pInfo.type().typeArguments() != null){
|
||||
for (TypeInfo tInfoType : pInfo.type().typeArguments()){
|
||||
if (tInfoType.asClassInfo() != null){
|
||||
ClassInfo tcl = tInfoType.asClassInfo();
|
||||
if (tcl.isHidden()) {
|
||||
Errors.error(Errors.UNAVAILABLE_SYMBOL, mInfo.position(),
|
||||
"Parameter of hidden type "
|
||||
+ tInfoType.fullName() + " in "
|
||||
+ mInfo.containingClass().qualifiedName()
|
||||
+ '.' + mInfo.name() + "()");
|
||||
} else {
|
||||
cantStripThis(tcl, notStrippable,
|
||||
"10:" +
|
||||
mInfo.realContainingClass().qualifiedName() + ":" +
|
||||
mInfo.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (ClassInfo thrown : mInfo.thrownExceptions()){
|
||||
cantStripThis(thrown, notStrippable, "11:" +
|
||||
mInfo.realContainingClass().qualifiedName()
|
||||
+":" + mInfo.name());
|
||||
}
|
||||
if (mInfo.returnType() != null && mInfo.returnType().asClassInfo() != null){
|
||||
cantStripThis(mInfo.returnType().asClassInfo(), notStrippable,
|
||||
"12:" + mInfo.realContainingClass().qualifiedName() +
|
||||
":" + mInfo.name());
|
||||
if (mInfo.returnType().typeArguments() != null){
|
||||
for (TypeInfo tyInfo: mInfo.returnType().typeArguments() ){
|
||||
if (tyInfo.asClassInfo() != null){
|
||||
cantStripThis(tyInfo.asClassInfo(), notStrippable,
|
||||
"13:" +
|
||||
mInfo.realContainingClass().qualifiedName()
|
||||
+ ":" + mInfo.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static String javaFileName(ClassInfo cl) {
|
||||
String dir = "";
|
||||
PackageInfo pkg = cl.containingPackage();
|
||||
if (pkg != null) {
|
||||
dir = pkg.name();
|
||||
dir = dir.replace('.', '/') + '/';
|
||||
}
|
||||
return dir + cl.name() + ".java";
|
||||
}
|
||||
|
||||
static void writeClassFile(String stubsDir, ClassInfo cl) {
|
||||
// inner classes are written by their containing class
|
||||
if (cl.containingClass() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Work around the bogus "Array" class we invent for
|
||||
// Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
|
||||
if (cl.containingPackage() != null && cl.containingPackage().name().equals("")) {
|
||||
return;
|
||||
}
|
||||
|
||||
String filename = stubsDir + '/' + javaFileName(cl);
|
||||
File file = new File(filename);
|
||||
ClearPage.ensureDirectory(file);
|
||||
|
||||
PrintStream stream = null;
|
||||
try {
|
||||
stream = new PrintStream(file);
|
||||
writeClassFile(stream, cl);
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
System.err.println("error writing file: " + filename);
|
||||
}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void writeClassFile(PrintStream stream, ClassInfo cl) {
|
||||
PackageInfo pkg = cl.containingPackage();
|
||||
if (pkg != null) {
|
||||
stream.println("package " + pkg.name() + ";");
|
||||
}
|
||||
writeClass(stream, cl);
|
||||
}
|
||||
|
||||
static void writeClass(PrintStream stream, ClassInfo cl) {
|
||||
writeAnnotations(stream, cl.annotations());
|
||||
|
||||
stream.print(DroidDoc.scope(cl) + " ");
|
||||
if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) {
|
||||
stream.print("abstract ");
|
||||
}
|
||||
if (cl.isStatic()){
|
||||
stream.print("static ");
|
||||
}
|
||||
if (cl.isFinal() && !cl.isEnum()) {
|
||||
stream.print("final ");
|
||||
}
|
||||
if (false) {
|
||||
stream.print("strictfp ");
|
||||
}
|
||||
|
||||
HashSet<String> classDeclTypeVars = new HashSet();
|
||||
String leafName = cl.asTypeInfo().fullName(classDeclTypeVars);
|
||||
int bracket = leafName.indexOf('<');
|
||||
if (bracket < 0) bracket = leafName.length() - 1;
|
||||
int period = leafName.lastIndexOf('.', bracket);
|
||||
if (period < 0) period = -1;
|
||||
leafName = leafName.substring(period+1);
|
||||
|
||||
String kind = cl.kind();
|
||||
stream.println(kind + " " + leafName);
|
||||
|
||||
TypeInfo base = cl.superclassType();
|
||||
|
||||
if (!"enum".equals(kind)) {
|
||||
if (base != null && !"java.lang.Object".equals(base.qualifiedTypeName())) {
|
||||
stream.println(" extends " + base.fullName(classDeclTypeVars));
|
||||
}
|
||||
}
|
||||
|
||||
TypeInfo[] interfaces = cl.realInterfaceTypes();
|
||||
List<TypeInfo> usedInterfaces = new ArrayList<TypeInfo>();
|
||||
for (TypeInfo iface : interfaces) {
|
||||
if (notStrippable.contains(iface.asClassInfo())
|
||||
&& !iface.asClassInfo().isDocOnly()) {
|
||||
usedInterfaces.add(iface);
|
||||
}
|
||||
}
|
||||
if (usedInterfaces.size() > 0 && !cl.isAnnotation()) {
|
||||
// can java annotations extend other ones?
|
||||
if (cl.isInterface() || cl.isAnnotation()) {
|
||||
stream.print(" extends ");
|
||||
} else {
|
||||
stream.print(" implements ");
|
||||
}
|
||||
String comma = "";
|
||||
for (TypeInfo iface: usedInterfaces) {
|
||||
stream.print(comma + iface.fullName(classDeclTypeVars));
|
||||
comma = ", ";
|
||||
}
|
||||
stream.println();
|
||||
}
|
||||
|
||||
stream.println("{");
|
||||
|
||||
FieldInfo[] enumConstants = cl.enumConstants();
|
||||
int N = enumConstants.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
FieldInfo field = enumConstants[i];
|
||||
if (!field.constantLiteralValue().equals("null")){
|
||||
stream.println(field.name() + "(" + field.constantLiteralValue()
|
||||
+ (i==N-1 ? ");" : "),"));
|
||||
}else{
|
||||
stream.println(field.name() + "(" + (i==N-1 ? ");" : "),"));
|
||||
}
|
||||
}
|
||||
|
||||
for (ClassInfo inner: cl.getRealInnerClasses()) {
|
||||
if (notStrippable.contains(inner)
|
||||
&& !inner.isDocOnly()){
|
||||
writeClass(stream, inner);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (MethodInfo method: cl.constructors()) {
|
||||
if (!method.isDocOnly()) {
|
||||
writeMethod(stream, method, true);
|
||||
}
|
||||
}
|
||||
|
||||
boolean fieldNeedsInitialization = false;
|
||||
boolean staticFieldNeedsInitialization = false;
|
||||
for (FieldInfo field: cl.allSelfFields()) {
|
||||
if (!field.isDocOnly()) {
|
||||
if (!field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
|
||||
fieldNeedsInitialization = true;
|
||||
}
|
||||
if (field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
|
||||
staticFieldNeedsInitialization = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The compiler includes a default public constructor that calls the super classes
|
||||
// default constructor in the case where there are no written constructors.
|
||||
// So, if we hide all the constructors, java may put in a constructor
|
||||
// that calls a nonexistent super class constructor. So, if there are no constructors,
|
||||
// and the super class doesn't have a default constructor, write in a private constructor
|
||||
// that works. TODO -- we generate this as protected, but we really should generate
|
||||
// it as private unless it also exists in the real code.
|
||||
if ((cl.constructors().length == 0 && (cl.getNonWrittenConstructors().length != 0
|
||||
|| fieldNeedsInitialization))
|
||||
&& !cl.isAnnotation()
|
||||
&& !cl.isInterface()
|
||||
&& !cl.isEnum() ) {
|
||||
//Errors.error(Errors.HIDDEN_CONSTRUCTOR,
|
||||
// cl.position(), "No constructors " +
|
||||
// "found and superclass has no parameterless constructor. A constructor " +
|
||||
// "that calls an appropriate superclass constructor " +
|
||||
// "was automatically written to stubs.\n");
|
||||
stream.println(cl.leafName()
|
||||
+ "() { " + superCtorCall(cl,null)
|
||||
+ "throw new" + " RuntimeException(\"Stub!\"); }");
|
||||
}
|
||||
|
||||
for (MethodInfo method: cl.allSelfMethods()) {
|
||||
if (cl.isEnum()) {
|
||||
if (("values".equals(method.name())
|
||||
&& "()".equals(method.signature()))
|
||||
|| ("valueOf".equals(method.name())
|
||||
&& "(java.lang.String)".equals(method.signature()))) {
|
||||
// skip these two methods on enums, because they're synthetic,
|
||||
// although for some reason javadoc doesn't mark them as synthetic,
|
||||
// maybe because they still want them documented
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!method.isDocOnly()) {
|
||||
writeMethod(stream, method, false);
|
||||
}
|
||||
}
|
||||
//Write all methods that are hidden, but override abstract methods or interface methods.
|
||||
//These can't be hidden.
|
||||
for (MethodInfo method : cl.getHiddenMethods()){
|
||||
MethodInfo overriddenMethod = method.findRealOverriddenMethod(method.name(), method.signature(), notStrippable);
|
||||
ClassInfo classContainingMethod = method.findRealOverriddenClass(method.name(),
|
||||
method.signature());
|
||||
if (overriddenMethod != null && !overriddenMethod.isHidden()
|
||||
&& !overriddenMethod.isDocOnly() &&
|
||||
(overriddenMethod.isAbstract() ||
|
||||
overriddenMethod.containingClass().isInterface())) {
|
||||
method.setReason("1:" + classContainingMethod.qualifiedName());
|
||||
cl.addMethod(method);
|
||||
writeMethod(stream, method, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (MethodInfo element: cl.annotationElements()) {
|
||||
if (!element.isDocOnly()) {
|
||||
writeAnnotationElement(stream, element);
|
||||
}
|
||||
}
|
||||
|
||||
for (FieldInfo field: cl.allSelfFields()) {
|
||||
if (!field.isDocOnly()) {
|
||||
writeField(stream, field);
|
||||
}
|
||||
}
|
||||
|
||||
if (staticFieldNeedsInitialization) {
|
||||
stream.print("static { ");
|
||||
for (FieldInfo field: cl.allSelfFields()) {
|
||||
if (!field.isDocOnly() && field.isStatic() && field.isFinal()
|
||||
&& !fieldIsInitialized(field) && field.constantValue() == null) {
|
||||
stream.print(field.name() + " = " + field.type().defaultValue()
|
||||
+ "; ");
|
||||
}
|
||||
}
|
||||
stream.println("}");
|
||||
}
|
||||
|
||||
stream.println("}");
|
||||
}
|
||||
|
||||
|
||||
static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) {
|
||||
String comma;
|
||||
|
||||
stream.print(DroidDoc.scope(method) + " ");
|
||||
if (method.isStatic()) {
|
||||
stream.print("static ");
|
||||
}
|
||||
if (method.isFinal()) {
|
||||
stream.print("final ");
|
||||
}
|
||||
if (method.isAbstract()) {
|
||||
stream.print("abstract ");
|
||||
}
|
||||
if (method.isSynchronized()) {
|
||||
stream.print("synchronized ");
|
||||
}
|
||||
if (method.isNative()) {
|
||||
stream.print("native ");
|
||||
}
|
||||
if (false /*method.isStictFP()*/) {
|
||||
stream.print("strictfp ");
|
||||
}
|
||||
|
||||
stream.print(method.typeArgumentsName(new HashSet()) + " ");
|
||||
|
||||
if (!isConstructor) {
|
||||
stream.print(method.returnType().fullName(method.typeVariables()) + " ");
|
||||
}
|
||||
String n = method.name();
|
||||
int pos = n.lastIndexOf('.');
|
||||
if (pos >= 0) {
|
||||
n = n.substring(pos + 1);
|
||||
}
|
||||
stream.print(n + "(");
|
||||
comma = "";
|
||||
int count = 1;
|
||||
int size = method.parameters().length;
|
||||
for (ParameterInfo param: method.parameters()) {
|
||||
stream.print(comma + fullParameterTypeName(method, param.type(), count == size)
|
||||
+ " " + param.name());
|
||||
comma = ", ";
|
||||
count++;
|
||||
}
|
||||
stream.print(")");
|
||||
|
||||
comma = "";
|
||||
if (method.thrownExceptions().length > 0) {
|
||||
stream.print(" throws ");
|
||||
for (ClassInfo thrown: method.thrownExceptions()) {
|
||||
stream.print(comma + thrown.qualifiedName());
|
||||
comma = ", ";
|
||||
}
|
||||
}
|
||||
if (method.isAbstract() || method.isNative() || method.containingClass().isInterface()) {
|
||||
stream.println(";");
|
||||
} else {
|
||||
stream.print(" { ");
|
||||
if (isConstructor) {
|
||||
stream.print(superCtorCall(method.containingClass(), method.thrownExceptions()));
|
||||
}
|
||||
stream.println("throw new RuntimeException(\"Stub!\"); }");
|
||||
}
|
||||
}
|
||||
|
||||
static void writeField(PrintStream stream, FieldInfo field) {
|
||||
stream.print(DroidDoc.scope(field) + " ");
|
||||
if (field.isStatic()) {
|
||||
stream.print("static ");
|
||||
}
|
||||
if (field.isFinal()) {
|
||||
stream.print("final ");
|
||||
}
|
||||
if (field.isTransient()) {
|
||||
stream.print("transient ");
|
||||
}
|
||||
if (field.isVolatile()) {
|
||||
stream.print("volatile ");
|
||||
}
|
||||
|
||||
stream.print(field.type().fullName());
|
||||
stream.print(" ");
|
||||
stream.print(field.name());
|
||||
|
||||
if (fieldIsInitialized(field)) {
|
||||
stream.print(" = " + field.constantLiteralValue());
|
||||
}
|
||||
|
||||
stream.println(";");
|
||||
}
|
||||
|
||||
static boolean fieldIsInitialized(FieldInfo field) {
|
||||
return (field.isFinal() && field.constantValue() != null)
|
||||
|| !field.type().dimension().equals("")
|
||||
|| field.containingClass().isInterface();
|
||||
}
|
||||
|
||||
// Returns 'true' if the method is an @Override of a visible parent
|
||||
// method implementation, and thus does not affect the API.
|
||||
static boolean methodIsOverride(MethodInfo mi) {
|
||||
// Abstract/static/final methods are always listed in the API description
|
||||
if (mi.isAbstract() || mi.isStatic() || mi.isFinal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find any relevant ancestor declaration and inspect it
|
||||
MethodInfo om = mi.findSuperclassImplementation(notStrippable);
|
||||
if (om != null) {
|
||||
// Visibility mismatch is an API change, so check for it
|
||||
if (mi.mIsPrivate == om.mIsPrivate
|
||||
&& mi.mIsPublic == om.mIsPublic
|
||||
&& mi.mIsProtected == om.mIsProtected) {
|
||||
// Look only for overrides of an ancestor class implementation,
|
||||
// not of e.g. an abstract or interface method declaration
|
||||
if (!om.isAbstract()) {
|
||||
// If the parent is hidden, we can't rely on it to provide
|
||||
// the API
|
||||
if (!om.isHidden()) {
|
||||
// If the only "override" turns out to be in our own class
|
||||
// (which sometimes happens in concrete subclasses of
|
||||
// abstract base classes), it's not really an override
|
||||
if (!mi.mContainingClass.equals(om.mContainingClass)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean canCallMethod(ClassInfo from, MethodInfo m) {
|
||||
if (m.isPublic() || m.isProtected()) {
|
||||
return true;
|
||||
}
|
||||
if (m.isPackagePrivate()) {
|
||||
String fromPkg = from.containingPackage().name();
|
||||
String pkg = m.containingClass().containingPackage().name();
|
||||
if (fromPkg.equals(pkg)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// call a constructor, any constructor on this class's superclass.
|
||||
static String superCtorCall(ClassInfo cl, ClassInfo[] thrownExceptions) {
|
||||
ClassInfo base = cl.realSuperclass();
|
||||
if (base == null) {
|
||||
return "";
|
||||
}
|
||||
HashSet<String> exceptionNames = new HashSet<String>();
|
||||
if (thrownExceptions != null ){
|
||||
for (ClassInfo thrown : thrownExceptions){
|
||||
exceptionNames.add(thrown.name());
|
||||
}
|
||||
}
|
||||
MethodInfo[] ctors = base.constructors();
|
||||
MethodInfo ctor = null;
|
||||
//bad exception indicates that the exceptions thrown by the super constructor
|
||||
//are incompatible with the constructor we're using for the sub class.
|
||||
Boolean badException = false;
|
||||
for (MethodInfo m: ctors) {
|
||||
if (canCallMethod(cl, m)) {
|
||||
if (m.thrownExceptions() != null){
|
||||
for (ClassInfo thrown : m.thrownExceptions()){
|
||||
if (!exceptionNames.contains(thrown.name())){
|
||||
badException = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (badException){
|
||||
badException = false;
|
||||
continue;
|
||||
}
|
||||
// if it has no args, we're done
|
||||
if (m.parameters().length == 0) {
|
||||
return "";
|
||||
}
|
||||
ctor = m;
|
||||
}
|
||||
}
|
||||
if (ctor != null) {
|
||||
String result = "";
|
||||
result+= "super(";
|
||||
ParameterInfo[] params = ctor.parameters();
|
||||
int N = params.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
TypeInfo t = params[i].type();
|
||||
if (t.isPrimitive() && t.dimension().equals("")) {
|
||||
String n = t.simpleTypeName();
|
||||
if (("byte".equals(n)
|
||||
|| "short".equals(n)
|
||||
|| "int".equals(n)
|
||||
|| "long".equals(n)
|
||||
|| "float".equals(n)
|
||||
|| "double".equals(n)) && t.dimension().equals("")) {
|
||||
result += "0";
|
||||
}
|
||||
else if ("char".equals(n)) {
|
||||
result += "'\\0'";
|
||||
}
|
||||
else if ("boolean".equals(n)) {
|
||||
result += "false";
|
||||
}
|
||||
else {
|
||||
result += "<<unknown-" + n + ">>";
|
||||
}
|
||||
} else {
|
||||
//put null in each super class method. Cast null to the correct type
|
||||
//to avoid collisions with other constructors. If the type is generic
|
||||
//don't cast it
|
||||
result += (!t.isTypeVariable() ? "(" + t.qualifiedTypeName() + t.dimension() +
|
||||
")" : "") + "null";
|
||||
}
|
||||
if (i != N-1) {
|
||||
result += ",";
|
||||
}
|
||||
}
|
||||
result += "); ";
|
||||
return result;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
static void writeAnnotations(PrintStream stream, AnnotationInstanceInfo[] annotations) {
|
||||
for (AnnotationInstanceInfo ann: annotations) {
|
||||
if (!ann.type().isHidden()) {
|
||||
stream.println(ann.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void writeAnnotationElement(PrintStream stream, MethodInfo ann) {
|
||||
stream.print(ann.returnType().fullName());
|
||||
stream.print(" ");
|
||||
stream.print(ann.name());
|
||||
stream.print("()");
|
||||
AnnotationValueInfo def = ann.defaultAnnotationElementValue();
|
||||
if (def != null) {
|
||||
stream.print(" default ");
|
||||
stream.print(def.valueString());
|
||||
}
|
||||
stream.println(";");
|
||||
}
|
||||
|
||||
static void writeXML(PrintStream xmlWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses,
|
||||
HashSet notStrippable) {
|
||||
// extract the set of packages, sort them by name, and write them out in that order
|
||||
Set<PackageInfo> allClassKeys = allClasses.keySet();
|
||||
PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
|
||||
Arrays.sort(allPackages, PackageInfo.comparator);
|
||||
|
||||
xmlWriter.println("<api>");
|
||||
for (PackageInfo pack : allPackages) {
|
||||
writePackageXML(xmlWriter, pack, allClasses.get(pack), notStrippable);
|
||||
}
|
||||
xmlWriter.println("</api>");
|
||||
}
|
||||
|
||||
static void writePackageXML(PrintStream xmlWriter, PackageInfo pack, List<ClassInfo> classList,
|
||||
HashSet notStrippable) {
|
||||
ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
|
||||
Arrays.sort(classes, ClassInfo.comparator);
|
||||
// Work around the bogus "Array" class we invent for
|
||||
// Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
|
||||
if (pack.name().equals("")) {
|
||||
return;
|
||||
}
|
||||
xmlWriter.println("<package name=\"" + pack.name() + "\"\n"
|
||||
//+ " source=\"" + pack.position() + "\"\n"
|
||||
+ ">");
|
||||
for (ClassInfo cl : classes) {
|
||||
writeClassXML(xmlWriter, cl, notStrippable);
|
||||
}
|
||||
xmlWriter.println("</package>");
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void writeClassXML(PrintStream xmlWriter, ClassInfo cl, HashSet notStrippable) {
|
||||
String scope = DroidDoc.scope(cl);
|
||||
String deprecatedString = "";
|
||||
String declString = (cl.isInterface()) ? "interface" : "class";
|
||||
if (cl.isDeprecated()) {
|
||||
deprecatedString = "deprecated";
|
||||
} else {
|
||||
deprecatedString = "not deprecated";
|
||||
}
|
||||
xmlWriter.println("<" + declString + " name=\"" + cl.name() + "\"");
|
||||
if (!cl.isInterface() && !cl.qualifiedName().equals("java.lang.Object")) {
|
||||
xmlWriter.println(" extends=\"" + ((cl.realSuperclass() == null)
|
||||
? "java.lang.Object"
|
||||
: cl.realSuperclass().qualifiedName()) + "\"");
|
||||
}
|
||||
xmlWriter.println(" abstract=\"" + cl.isAbstract() + "\"\n"
|
||||
+ " static=\"" + cl.isStatic() + "\"\n"
|
||||
+ " final=\"" + cl.isFinal() + "\"\n"
|
||||
+ " deprecated=\"" + deprecatedString + "\"\n"
|
||||
+ " visibility=\"" + scope + "\"\n"
|
||||
//+ " source=\"" + cl.position() + "\"\n"
|
||||
+ ">");
|
||||
|
||||
ClassInfo[] interfaces = cl.realInterfaces();
|
||||
Arrays.sort(interfaces, ClassInfo.comparator);
|
||||
for (ClassInfo iface : interfaces) {
|
||||
if (notStrippable.contains(iface)) {
|
||||
xmlWriter.println("<implements name=\"" + iface.qualifiedName() + "\">");
|
||||
xmlWriter.println("</implements>");
|
||||
}
|
||||
}
|
||||
|
||||
MethodInfo[] constructors = cl.constructors();
|
||||
Arrays.sort(constructors, MethodInfo.comparator);
|
||||
for (MethodInfo mi : constructors) {
|
||||
writeConstructorXML(xmlWriter, mi);
|
||||
}
|
||||
|
||||
MethodInfo[] methods = cl.allSelfMethods();
|
||||
Arrays.sort(methods, MethodInfo.comparator);
|
||||
for (MethodInfo mi : methods) {
|
||||
if (!methodIsOverride(mi)) {
|
||||
writeMethodXML(xmlWriter, mi);
|
||||
}
|
||||
}
|
||||
|
||||
FieldInfo[] fields = cl.allSelfFields();
|
||||
Arrays.sort(fields, FieldInfo.comparator);
|
||||
for (FieldInfo fi : fields) {
|
||||
writeFieldXML(xmlWriter, fi);
|
||||
}
|
||||
xmlWriter.println("</" + declString + ">");
|
||||
|
||||
}
|
||||
|
||||
static void writeMethodXML(PrintStream xmlWriter, MethodInfo mi) {
|
||||
String scope = DroidDoc.scope(mi);
|
||||
|
||||
String deprecatedString = "";
|
||||
if (mi.isDeprecated()) {
|
||||
deprecatedString = "deprecated";
|
||||
} else {
|
||||
deprecatedString = "not deprecated";
|
||||
}
|
||||
xmlWriter.println("<method name=\"" + mi.name() + "\"\n"
|
||||
+ ((mi.returnType() != null)
|
||||
? " return=\"" + makeXMLcompliant(fullParameterTypeName(mi, mi.returnType(), false)) + "\"\n"
|
||||
: "")
|
||||
+ " abstract=\"" + mi.isAbstract() + "\"\n"
|
||||
+ " native=\"" + mi.isNative() + "\"\n"
|
||||
+ " synchronized=\"" + mi.isSynchronized() + "\"\n"
|
||||
+ " static=\"" + mi.isStatic() + "\"\n"
|
||||
+ " final=\"" + mi.isFinal() + "\"\n"
|
||||
+ " deprecated=\""+ deprecatedString + "\"\n"
|
||||
+ " visibility=\"" + scope + "\"\n"
|
||||
//+ " source=\"" + mi.position() + "\"\n"
|
||||
+ ">");
|
||||
|
||||
// write parameters in declaration order
|
||||
int numParameters = mi.parameters().length;
|
||||
int count = 0;
|
||||
for (ParameterInfo pi : mi.parameters()) {
|
||||
count++;
|
||||
writeParameterXML(xmlWriter, mi, pi, count == numParameters);
|
||||
}
|
||||
|
||||
// but write exceptions in canonicalized order
|
||||
ClassInfo[] exceptions = mi.thrownExceptions();
|
||||
Arrays.sort(exceptions, ClassInfo.comparator);
|
||||
for (ClassInfo pi : exceptions) {
|
||||
xmlWriter.println("<exception name=\"" + pi.name() +"\" type=\"" + pi.qualifiedName()
|
||||
+ "\">");
|
||||
xmlWriter.println("</exception>");
|
||||
}
|
||||
xmlWriter.println("</method>");
|
||||
}
|
||||
|
||||
static void writeConstructorXML(PrintStream xmlWriter, MethodInfo mi) {
|
||||
String scope = DroidDoc.scope(mi);
|
||||
String deprecatedString = "";
|
||||
if (mi.isDeprecated()) {
|
||||
deprecatedString = "deprecated";
|
||||
} else {
|
||||
deprecatedString = "not deprecated";
|
||||
}
|
||||
xmlWriter.println("<constructor name=\"" + mi.name() + "\"\n"
|
||||
+ " type=\"" + mi.containingClass().qualifiedName() + "\"\n"
|
||||
+ " static=\"" + mi.isStatic() + "\"\n"
|
||||
+ " final=\"" + mi.isFinal() + "\"\n"
|
||||
+ " deprecated=\"" + deprecatedString + "\"\n"
|
||||
+ " visibility=\"" + scope +"\"\n"
|
||||
//+ " source=\"" + mi.position() + "\"\n"
|
||||
+ ">");
|
||||
|
||||
int numParameters = mi.parameters().length;
|
||||
int count = 0;
|
||||
for (ParameterInfo pi : mi.parameters()) {
|
||||
count++;
|
||||
writeParameterXML(xmlWriter, mi, pi, count == numParameters);
|
||||
}
|
||||
|
||||
ClassInfo[] exceptions = mi.thrownExceptions();
|
||||
Arrays.sort(exceptions, ClassInfo.comparator);
|
||||
for (ClassInfo pi : exceptions) {
|
||||
xmlWriter.println("<exception name=\"" + pi.name() +"\" type=\"" + pi.qualifiedName()
|
||||
+ "\">");
|
||||
xmlWriter.println("</exception>");
|
||||
}
|
||||
xmlWriter.println("</constructor>");
|
||||
}
|
||||
|
||||
static void writeParameterXML(PrintStream xmlWriter, MethodInfo method,
|
||||
ParameterInfo pi, boolean isLast) {
|
||||
xmlWriter.println("<parameter name=\"" + pi.name() + "\" type=\"" +
|
||||
makeXMLcompliant(fullParameterTypeName(method, pi.type(), isLast)) + "\">");
|
||||
xmlWriter.println("</parameter>");
|
||||
}
|
||||
|
||||
static void writeFieldXML(PrintStream xmlWriter, FieldInfo fi) {
|
||||
String scope = DroidDoc.scope(fi);
|
||||
String deprecatedString = "";
|
||||
if (fi.isDeprecated()) {
|
||||
deprecatedString = "deprecated";
|
||||
} else {
|
||||
deprecatedString = "not deprecated";
|
||||
}
|
||||
//need to make sure value is valid XML
|
||||
String value = makeXMLcompliant(fi.constantLiteralValue());
|
||||
|
||||
String fullTypeName = makeXMLcompliant(fi.type().qualifiedTypeName())
|
||||
+ fi.type().dimension();
|
||||
|
||||
xmlWriter.println("<field name=\"" + fi.name() +"\"\n"
|
||||
+ " type=\"" + fullTypeName + "\"\n"
|
||||
+ " transient=\"" + fi.isTransient() + "\"\n"
|
||||
+ " volatile=\"" + fi.isVolatile() + "\"\n"
|
||||
+ (fieldIsInitialized(fi) ? " value=\"" + value + "\"\n" : "")
|
||||
+ " static=\"" + fi.isStatic() + "\"\n"
|
||||
+ " final=\"" + fi.isFinal() + "\"\n"
|
||||
+ " deprecated=\"" + deprecatedString + "\"\n"
|
||||
+ " visibility=\"" + scope + "\"\n"
|
||||
//+ " source=\"" + fi.position() + "\"\n"
|
||||
+ ">");
|
||||
xmlWriter.println("</field>");
|
||||
}
|
||||
|
||||
static String makeXMLcompliant(String s) {
|
||||
String returnString = "";
|
||||
returnString = s.replaceAll("&", "&");
|
||||
returnString = returnString.replaceAll("<", "<");
|
||||
returnString = returnString.replaceAll(">", ">");
|
||||
returnString = returnString.replaceAll("\"", """);
|
||||
returnString = returnString.replaceAll("'", "&pos;");
|
||||
return returnString;
|
||||
}
|
||||
|
||||
static String fullParameterTypeName(MethodInfo method, TypeInfo type, boolean isLast) {
|
||||
String fullTypeName = type.fullName(method.typeVariables());
|
||||
if (isLast && method.isVarArgs()) {
|
||||
// TODO: note that this does not attempt to handle hypothetical
|
||||
// vararg methods whose last parameter is a list of arrays, e.g.
|
||||
// "Object[]...".
|
||||
fullTypeName = type.fullNameNoDimension(method.typeVariables()) + "...";
|
||||
}
|
||||
return fullTypeName;
|
||||
}
|
||||
}
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
|
||||
public class TagInfo
|
||||
{
|
||||
private String mName;
|
||||
private String mText;
|
||||
private String mKind;
|
||||
private SourcePositionInfo mPosition;
|
||||
|
||||
TagInfo(String n, String k, String t, SourcePositionInfo sp)
|
||||
{
|
||||
mName = n;
|
||||
mText = t;
|
||||
mKind = k;
|
||||
mPosition = sp;
|
||||
}
|
||||
|
||||
String name()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
String text()
|
||||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
String kind()
|
||||
{
|
||||
return mKind;
|
||||
}
|
||||
|
||||
SourcePositionInfo position() {
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
void setKind(String kind) {
|
||||
mKind = kind;
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
data.setValue(base + ".name", name());
|
||||
data.setValue(base + ".text", text());
|
||||
data.setValue(base + ".kind", kind());
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, TagInfo[] tags)
|
||||
{
|
||||
makeHDF(data, base, tags, null, 0, 0);
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, InheritedTags tags)
|
||||
{
|
||||
makeHDF(data, base, tags.tags(), tags.inherited(), 0, 0);
|
||||
}
|
||||
|
||||
private static int makeHDF(HDF data, String base, TagInfo[] tags,
|
||||
InheritedTags inherited, int j, int depth)
|
||||
{
|
||||
int i;
|
||||
int len = tags.length;
|
||||
if (len == 0 && inherited != null) {
|
||||
j = makeHDF(data, base, inherited.tags(), inherited.inherited(), j, depth+1);
|
||||
} else {
|
||||
for (i=0; i<len; i++, j++) {
|
||||
TagInfo t = tags[i];
|
||||
if (inherited != null && t.name().equals("@inheritDoc")) {
|
||||
j = makeHDF(data, base, inherited.tags(),
|
||||
inherited.inherited(), j, depth+1);
|
||||
} else {
|
||||
if (t.name().equals("@inheritDoc")) {
|
||||
Errors.error(Errors.BAD_INHERITDOC, t.mPosition,
|
||||
"@inheritDoc on class/method that is not inherited");
|
||||
}
|
||||
t.makeHDF(data, base + "." + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
public class TextTagInfo extends TagInfo {
|
||||
TextTagInfo(String n, String k, String t, SourcePositionInfo p) {
|
||||
super(n, k, DroidDoc.escape(t), p);
|
||||
}
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
public class ThrowsTagInfo extends ParsedTagInfo
|
||||
{
|
||||
static final Pattern PATTERN = Pattern.compile(
|
||||
"(\\S+)\\s+(.*)",
|
||||
Pattern.DOTALL);
|
||||
private ClassInfo mException;
|
||||
|
||||
public ThrowsTagInfo(String name, String kind, String text,
|
||||
ContainerInfo base, SourcePositionInfo sp)
|
||||
{
|
||||
super(name, kind, text, base, sp);
|
||||
|
||||
Matcher m = PATTERN.matcher(text);
|
||||
if (m.matches()) {
|
||||
setCommentText(m.group(2));
|
||||
String className = m.group(1);
|
||||
if (base instanceof ClassInfo) {
|
||||
mException = ((ClassInfo)base).findClass(className);
|
||||
}
|
||||
if (mException == null) {
|
||||
mException = Converter.obtainClass(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ThrowsTagInfo(String name, String kind, String text,
|
||||
ClassInfo exception, String exceptionComment,
|
||||
ContainerInfo base, SourcePositionInfo sp)
|
||||
{
|
||||
super(name, kind, text, base, sp);
|
||||
mException = exception;
|
||||
setCommentText(exceptionComment);
|
||||
}
|
||||
|
||||
public ClassInfo exception()
|
||||
{
|
||||
return mException;
|
||||
}
|
||||
|
||||
public TypeInfo exceptionType()
|
||||
{
|
||||
if (mException != null) {
|
||||
return mException.asTypeInfo();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, ThrowsTagInfo[] tags)
|
||||
{
|
||||
for (int i=0; i<tags.length; i++) {
|
||||
TagInfo.makeHDF(data, base + '.' + i + ".comment",
|
||||
tags[i].commentTags());
|
||||
if (tags[i].exceptionType() != null) {
|
||||
tags[i].exceptionType().makeHDF(data, base + "." + i + ".type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public class TodoFile {
|
||||
|
||||
public static final String MISSING = "No description text";
|
||||
|
||||
public static boolean areTagsUseful(InheritedTags tags) {
|
||||
while (tags != null) {
|
||||
if (areTagsUseful(tags.tags())) {
|
||||
return true;
|
||||
}
|
||||
tags = tags.inherited();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean areTagsUseful(TagInfo[] tags) {
|
||||
for (TagInfo t: tags) {
|
||||
if ("Text".equals(t.name()) && t.text().trim().length() != 0) {
|
||||
return true;
|
||||
}
|
||||
if ("@inheritDoc".equals(t.name())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setHDF(HDF data, String base, SourcePositionInfo pos, String name,
|
||||
String descr) {
|
||||
data.setValue(base + ".pos", pos.toString());
|
||||
data.setValue(base + ".name", name);
|
||||
data.setValue(base + ".descr", descr);
|
||||
}
|
||||
|
||||
static class PackageStats {
|
||||
String name;
|
||||
public int total;
|
||||
public int errors;
|
||||
}
|
||||
|
||||
public static String percent(int a, int b) {
|
||||
return ""+Math.round((((b-a)/(float)b))*100) + "%";
|
||||
}
|
||||
|
||||
public static void writeTodoFile(String filename) {
|
||||
HDF data = DroidDoc.makeHDF();
|
||||
DroidDoc.setPageTitle(data, "Missing Documentation");
|
||||
TreeMap<String,PackageStats> packageStats = new TreeMap<String,PackageStats>();
|
||||
|
||||
ClassInfo[] classes = Converter.rootClasses();
|
||||
Arrays.sort(classes);
|
||||
|
||||
int classIndex = 0;
|
||||
|
||||
for (ClassInfo cl: classes) {
|
||||
if (cl.isHidden()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String classBase = "classes." + classIndex;
|
||||
|
||||
String base = classBase + ".errors.";
|
||||
int errors = 0;
|
||||
int total = 1;
|
||||
|
||||
if (!areTagsUseful(cl.inlineTags())) {
|
||||
setHDF(data, base + errors, cl.position(), "<class comment>", MISSING);
|
||||
errors++;
|
||||
}
|
||||
|
||||
|
||||
for (MethodInfo m: cl.constructors()) {
|
||||
boolean good = true;
|
||||
total++;
|
||||
if (m.checkLevel()) {
|
||||
if (!areTagsUseful(m.inlineTags())) {
|
||||
setHDF(data, base + errors, m.position(), m.name() + m.prettySignature(),
|
||||
MISSING);
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
for (MethodInfo m: cl.selfMethods()) {
|
||||
boolean good = true;
|
||||
total++;
|
||||
if (m.checkLevel()) {
|
||||
if (!areTagsUseful(m.inlineTags())) {
|
||||
setHDF(data, base + errors, m.position(), m.name() + m.prettySignature(),
|
||||
MISSING);
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (FieldInfo f: cl.enumConstants()) {
|
||||
boolean good = true;
|
||||
total++;
|
||||
if (f.checkLevel()) {
|
||||
if (!areTagsUseful(f.inlineTags())) {
|
||||
setHDF(data, base + errors, f.position(), f.name(), MISSING);
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
for (FieldInfo f: cl.selfFields()) {
|
||||
boolean good = true;
|
||||
total++;
|
||||
if (f.checkLevel()) {
|
||||
if (!areTagsUseful(f.inlineTags())) {
|
||||
setHDF(data, base + errors, f.position(), f.name(), MISSING);
|
||||
good = false;
|
||||
}
|
||||
}
|
||||
if (!good) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errors > 0) {
|
||||
data.setValue(classBase + ".qualified", cl.qualifiedName());
|
||||
data.setValue(classBase + ".errorCount", ""+errors);
|
||||
data.setValue(classBase + ".totalCount", ""+total);
|
||||
data.setValue(classBase + ".percentGood", percent(errors, total));
|
||||
}
|
||||
|
||||
PackageInfo pkg = cl.containingPackage();
|
||||
String pkgName = pkg != null ? pkg.name() : "";
|
||||
PackageStats ps = packageStats.get(pkgName);
|
||||
if (ps == null) {
|
||||
ps = new PackageStats();
|
||||
ps.name = pkgName;
|
||||
packageStats.put(pkgName, ps);
|
||||
}
|
||||
ps.total += total;
|
||||
ps.errors += errors;
|
||||
|
||||
classIndex++;
|
||||
}
|
||||
|
||||
int allTotal = 0;
|
||||
int allErrors = 0;
|
||||
|
||||
int i = 0;
|
||||
for (PackageStats ps: packageStats.values()) {
|
||||
data.setValue("packages." + i + ".name", ""+ps.name);
|
||||
data.setValue("packages." + i + ".errorCount", ""+ps.errors);
|
||||
data.setValue("packages." + i + ".totalCount", ""+ps.total);
|
||||
data.setValue("packages." + i + ".percentGood", percent(ps.errors, ps.total));
|
||||
|
||||
allTotal += ps.total;
|
||||
allErrors += ps.errors;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
data.setValue("all.errorCount", ""+allErrors);
|
||||
data.setValue("all.totalCount", ""+allTotal);
|
||||
data.setValue("all.percentGood", percent(allErrors, allTotal));
|
||||
|
||||
ClearPage.write(data, "todo.cs", filename, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2008 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.
|
||||
*/
|
||||
|
||||
import org.clearsilver.HDF;
|
||||
import org.clearsilver.CS;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
public class TypeInfo
|
||||
{
|
||||
public TypeInfo(boolean isPrimitive, String dimension,
|
||||
String simpleTypeName, String qualifiedTypeName,
|
||||
ClassInfo cl)
|
||||
{
|
||||
mIsPrimitive = isPrimitive;
|
||||
mDimension = dimension;
|
||||
mSimpleTypeName = simpleTypeName;
|
||||
mQualifiedTypeName = qualifiedTypeName;
|
||||
mClass = cl;
|
||||
}
|
||||
|
||||
public ClassInfo asClassInfo()
|
||||
{
|
||||
return mClass;
|
||||
}
|
||||
|
||||
public boolean isPrimitive()
|
||||
{
|
||||
return mIsPrimitive;
|
||||
}
|
||||
|
||||
public String dimension()
|
||||
{
|
||||
return mDimension;
|
||||
}
|
||||
|
||||
public String simpleTypeName()
|
||||
{
|
||||
return mSimpleTypeName;
|
||||
}
|
||||
|
||||
public String qualifiedTypeName()
|
||||
{
|
||||
return mQualifiedTypeName;
|
||||
}
|
||||
|
||||
public String fullName()
|
||||
{
|
||||
if (mFullName != null) {
|
||||
return mFullName;
|
||||
} else {
|
||||
return fullName(new HashSet());
|
||||
}
|
||||
}
|
||||
|
||||
public static String typeArgumentsName(TypeInfo[] args, HashSet<String> typeVars)
|
||||
{
|
||||
String result = "<";
|
||||
for (int i=0; i<args.length; i++) {
|
||||
result += args[i].fullName(typeVars);
|
||||
if (i != args.length-1) {
|
||||
result += ", ";
|
||||
}
|
||||
}
|
||||
result += ">";
|
||||
return result;
|
||||
}
|
||||
|
||||
public String fullName(HashSet<String> typeVars)
|
||||
{
|
||||
mFullName = fullNameNoDimension(typeVars) + mDimension;
|
||||
return mFullName;
|
||||
}
|
||||
|
||||
public String fullNameNoDimension(HashSet<String> typeVars)
|
||||
{
|
||||
String fullName = null;
|
||||
if (mIsTypeVariable) {
|
||||
if (typeVars.contains(mQualifiedTypeName)) {
|
||||
// don't recurse forever with the parameters. This handles
|
||||
// Enum<K extends Enum<K>>
|
||||
return mQualifiedTypeName;
|
||||
}
|
||||
typeVars.add(mQualifiedTypeName);
|
||||
}
|
||||
/*
|
||||
if (fullName != null) {
|
||||
return fullName;
|
||||
}
|
||||
*/
|
||||
fullName = mQualifiedTypeName;
|
||||
if (mTypeArguments != null && mTypeArguments.length > 0) {
|
||||
fullName += typeArgumentsName(mTypeArguments, typeVars);
|
||||
}
|
||||
else if (mSuperBounds != null && mSuperBounds.length > 0) {
|
||||
fullName += " super " + mSuperBounds[0].fullName(typeVars);
|
||||
for (int i=1; i<mSuperBounds.length; i++) {
|
||||
fullName += " & " + mSuperBounds[i].fullName(typeVars);
|
||||
}
|
||||
}
|
||||
else if (mExtendsBounds != null && mExtendsBounds.length > 0) {
|
||||
fullName += " extends " + mExtendsBounds[0].fullName(typeVars);
|
||||
for (int i=1; i<mExtendsBounds.length; i++) {
|
||||
fullName += " & " + mExtendsBounds[i].fullName(typeVars);
|
||||
}
|
||||
}
|
||||
return fullName;
|
||||
}
|
||||
|
||||
public TypeInfo[] typeArguments()
|
||||
{
|
||||
return mTypeArguments;
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base)
|
||||
{
|
||||
makeHDFRecursive(data, base, false, false, new HashSet<String>());
|
||||
}
|
||||
|
||||
public void makeQualifiedHDF(HDF data, String base)
|
||||
{
|
||||
makeHDFRecursive(data, base, true, false, new HashSet<String>());
|
||||
}
|
||||
|
||||
public void makeHDF(HDF data, String base, boolean isLastVararg,
|
||||
HashSet<String> typeVariables)
|
||||
{
|
||||
makeHDFRecursive(data, base, false, isLastVararg, typeVariables);
|
||||
}
|
||||
|
||||
public void makeQualifiedHDF(HDF data, String base, HashSet<String> typeVariables)
|
||||
{
|
||||
makeHDFRecursive(data, base, true, false, typeVariables);
|
||||
}
|
||||
|
||||
private void makeHDFRecursive(HDF data, String base, boolean qualified,
|
||||
boolean isLastVararg, HashSet<String> typeVars)
|
||||
{
|
||||
String label = qualified ? qualifiedTypeName() : simpleTypeName();
|
||||
label += (isLastVararg) ? "..." : dimension();
|
||||
data.setValue(base + ".label", label);
|
||||
ClassInfo cl = asClassInfo();
|
||||
if (mIsTypeVariable || mIsWildcard) {
|
||||
// could link to an @param tag on the class to describe this
|
||||
// but for now, just don't make it a link
|
||||
}
|
||||
else if (!isPrimitive() && cl != null && cl.isIncluded()) {
|
||||
data.setValue(base + ".link", cl.htmlPage());
|
||||
data.setValue(base + ".since", cl.getSince());
|
||||
}
|
||||
|
||||
if (mIsTypeVariable) {
|
||||
if (typeVars.contains(qualifiedTypeName())) {
|
||||
// don't recurse forever with the parameters. This handles
|
||||
// Enum<K extends Enum<K>>
|
||||
return;
|
||||
}
|
||||
typeVars.add(qualifiedTypeName());
|
||||
}
|
||||
if (mTypeArguments != null) {
|
||||
TypeInfo.makeHDF(data, base + ".typeArguments", mTypeArguments, qualified, typeVars);
|
||||
}
|
||||
if (mSuperBounds != null) {
|
||||
TypeInfo.makeHDF(data, base + ".superBounds", mSuperBounds, qualified, typeVars);
|
||||
}
|
||||
if (mExtendsBounds != null) {
|
||||
TypeInfo.makeHDF(data, base + ".extendsBounds", mExtendsBounds, qualified, typeVars);
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, TypeInfo[] types, boolean qualified,
|
||||
HashSet<String> typeVariables)
|
||||
{
|
||||
final int N = types.length;
|
||||
for (int i=0; i<N; i++) {
|
||||
types[i].makeHDFRecursive(data, base + "." + i, qualified, false, typeVariables);
|
||||
}
|
||||
}
|
||||
|
||||
public static void makeHDF(HDF data, String base, TypeInfo[] types, boolean qualified)
|
||||
{
|
||||
makeHDF(data, base, types, qualified, new HashSet<String>());
|
||||
}
|
||||
|
||||
void setTypeArguments(TypeInfo[] args)
|
||||
{
|
||||
mTypeArguments = args;
|
||||
}
|
||||
|
||||
void setBounds(TypeInfo[] superBounds, TypeInfo[] extendsBounds)
|
||||
{
|
||||
mSuperBounds = superBounds;
|
||||
mExtendsBounds = extendsBounds;
|
||||
}
|
||||
|
||||
void setIsTypeVariable(boolean b)
|
||||
{
|
||||
mIsTypeVariable = b;
|
||||
}
|
||||
|
||||
void setIsWildcard(boolean b)
|
||||
{
|
||||
mIsWildcard = b;
|
||||
}
|
||||
|
||||
static HashSet<String> typeVariables(TypeInfo[] params)
|
||||
{
|
||||
return typeVariables(params, new HashSet());
|
||||
}
|
||||
|
||||
static HashSet<String> typeVariables(TypeInfo[] params, HashSet<String> result)
|
||||
{
|
||||
for (TypeInfo t: params) {
|
||||
if (t.mIsTypeVariable) {
|
||||
result.add(t.mQualifiedTypeName);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public boolean isTypeVariable()
|
||||
{
|
||||
return mIsTypeVariable;
|
||||
}
|
||||
|
||||
public String defaultValue() {
|
||||
if (mIsPrimitive) {
|
||||
if ("boolean".equals(mSimpleTypeName)) {
|
||||
return "false";
|
||||
} else {
|
||||
return "0";
|
||||
}
|
||||
} else {
|
||||
return "null";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
String returnString = "";
|
||||
returnString += "Primitive?: " + mIsPrimitive + " TypeVariable?: " +
|
||||
mIsTypeVariable + " Wildcard?: " + mIsWildcard + " Dimension: " + mDimension
|
||||
+ " QualifedTypeName: " + mQualifiedTypeName;
|
||||
|
||||
if (mTypeArguments != null){
|
||||
returnString += "\nTypeArguments: ";
|
||||
for (TypeInfo tA : mTypeArguments){
|
||||
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
|
||||
}
|
||||
}
|
||||
if (mSuperBounds != null){
|
||||
returnString += "\nSuperBounds: ";
|
||||
for (TypeInfo tA : mSuperBounds){
|
||||
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
|
||||
}
|
||||
}
|
||||
if (mExtendsBounds != null){
|
||||
returnString += "\nExtendsBounds: ";
|
||||
for (TypeInfo tA : mExtendsBounds){
|
||||
returnString += tA.qualifiedTypeName() + "(" + tA + ") ";
|
||||
}
|
||||
}
|
||||
return returnString;
|
||||
}
|
||||
|
||||
private boolean mIsPrimitive;
|
||||
private boolean mIsTypeVariable;
|
||||
private boolean mIsWildcard;
|
||||
private String mDimension;
|
||||
private String mSimpleTypeName;
|
||||
private String mQualifiedTypeName;
|
||||
private ClassInfo mClass;
|
||||
private TypeInfo[] mTypeArguments;
|
||||
private TypeInfo[] mSuperBounds;
|
||||
private TypeInfo[] mExtendsBounds;
|
||||
private String mFullName;
|
||||
}
|
Loading…
Reference in New Issue