Merge "Removed unused source files. Apicheck and droiddoc are now in external/doclava."

This commit is contained in:
Ben Dodson 2010-08-17 11:31:33 -07:00 committed by Android (Google) Code Review
commit 2cce260bba
56 changed files with 2 additions and 11986 deletions

View File

@ -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.

View File

@ -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)

View File

@ -1,2 +0,0 @@
Manifest-Version: 1.0
Main-Class: com.android.apicheck.ApiCheck

View File

@ -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);
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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 &gt; 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;
}

View File

@ -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.

View File

@ -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)

View File

@ -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();
}
}

View File

@ -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);
}
}
}

View File

@ -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++;
}
}
}
}
}

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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>();
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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() {
}
}

View File

@ -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("&", "&amp;");
t = t.replace("<", "&lt;");
t = t.replace(">", "&gt;");
return t;
}
public LiteralTagInfo(String n, String k, String t, SourcePositionInfo sp)
{
super("Text", "Text", encode(t), sp);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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(" ]");
}
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}

View File

@ -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()]);
}
}

View File

@ -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());
}
}
}

View File

@ -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);
}
}

View File

@ -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("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
}
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");
}
}
}

View File

@ -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();
}

View File

@ -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++;
}
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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 &gt; 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;
}

View File

@ -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("&", "&amp;");
returnString = returnString.replaceAll("<", "&lt;");
returnString = returnString.replaceAll(">", "&gt;");
returnString = returnString.replaceAll("\"", "&quot;");
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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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");
}
}
}
}

View File

@ -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(), "&lt;class comment&gt;", 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);
}
}

View File

@ -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;
}