blob: 7dcdd25d215400029dcc6969363bbaca21275c89 [file] [log] [blame]
/* gnu.classpath.tools.gjdoc.ExecutableMemberDocImpl
Copyright (C) 2001 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
package gnu.classpath.tools.gjdoc;
import java.util.*;
import java.io.*;
import com.sun.javadoc.*;
public class ExecutableMemberDocImpl extends MemberDocImpl implements ExecutableMemberDoc {
protected ExecutableMemberDocImpl(ClassDoc containingClass,
PackageDoc containingPackage,
SourcePosition position) {
super(containingClass,
containingPackage,
position);
}
protected boolean processModifier(String word) {
if (super.processModifier(word)) {
return true;
}
else if (word.equals("synchronized")) {
isSynchronized=true;
return true;
}
else if (word.equals("native")) {
isNative=true;
return true;
}
else if (word.equals("abstract")) {
isAbstract=true;
return true;
}
else {
return false;
}
}
private boolean isAbstract=false;
private boolean isNative=false;
private boolean isSynchronized=false;
public boolean isAbstract() { return isAbstract; }
public boolean isNative() { return isNative; }
public boolean isSynchronized() { return isSynchronized; }
public ClassDoc[] thrownExceptions() { return thrownExceptions; }
public Parameter[] parameters() { return parameters; }
public ThrowsTag[] throwsTags() {
return (ThrowsTag[])getTagArr("throws", throwsTagEmptyArr);
}
public ParamTag[] paramTags() {
return (ParamTag[])getTagArr("param", paramTagEmptyArr);
}
public String signature() { return signature; }
public String flatSignature() { return flatSignature; }
public ClassDoc overriddenClass() {
for (ClassDoc cdi=(ClassDoc)containingClass().superclass(); cdi!=null; cdi=(ClassDoc)cdi.superclass()) {
if (null!=ClassDocImpl.findMethod(cdi, name(), signature()))
return cdi;
}
return null;
}
public static ExecutableMemberDocImpl createFromSource(ClassDoc containingClass,
PackageDoc containingPackage,
char[] source, int startIndex, int endIndex) throws IOException, ParseException {
int lastchar=32;
StringBuffer methodName=new StringBuffer();
for (int i=startIndex; i<endIndex && source[i]!='('; ++i) {
if ((Parser.WHITESPACE.indexOf(lastchar)>=0 && Parser.WHITESPACE.indexOf(source[i])<0)
|| (lastchar == ']' && Parser.WHITESPACE.indexOf(source[i])<0 && '[' != source[i])) {
methodName.setLength(0);
methodName.append(source[i]);
}
else if (Parser.WHITESPACE.indexOf(source[i])<0) {
methodName.append(source[i]);
}
lastchar=source[i];
}
ExecutableMemberDocImpl rc;
SourcePosition position = DocImpl.getPosition(containingClass, source, startIndex);
if (methodName.toString().equals(((ClassDocImpl)containingClass).getClassName())) {
// Constructor
rc=new ConstructorDocImpl(containingClass,
containingPackage,
position);
}
else {
// Normal method
rc=new MethodDocImpl(containingClass,
containingPackage,
position);
}
if (containingClass.isInterface())
rc.accessLevel=ACCESS_PUBLIC;
int ndx=rc.parseModifiers(source, startIndex, endIndex);
StringBuffer name = new StringBuffer();
final int STATE_NORMAL=1;
final int STATE_STARC=2;
final int STATE_SLASHC=3;
int state=STATE_NORMAL;
while (source[ndx]!='(' && ndx<endIndex) {
if (state==STATE_NORMAL) {
if (ndx<endIndex-1 && source[ndx]=='/' && source[ndx+1]=='/') {
++ndx;
state=STATE_SLASHC;
}
else if (ndx<endIndex-1 && source[ndx]=='/' && source[ndx+1]=='*') {
++ndx;
state=STATE_STARC;
}
else {
name.append(source[ndx]);
}
}
else if (state==STATE_SLASHC) {
if (source[ndx]=='\n')
state=STATE_NORMAL;
}
else if (state==STATE_STARC) {
if (ndx<endIndex-1 && source[ndx]=='*' && source[ndx+1]=='/') {
++ndx;
state=STATE_NORMAL;
}
}
++ndx;
}
rc.setName(name.toString().trim());
state=STATE_NORMAL;
++ndx;
int endx;
String param="";
List parameterList=new ArrayList();
for (endx=ndx; endx<endIndex; ++endx) {
if (state==STATE_SLASHC) {
if (source[endx]=='\n') {
state=STATE_NORMAL;
}
}
else if (state==STATE_STARC) {
if (source[endx]=='*' && source[endx+1]=='/') {
state=STATE_NORMAL;
++endx;
}
}
else if (source[endx]=='/' && source[endx+1]=='*') {
state=STATE_STARC;
++endx;
}
else if (source[endx]=='/' && source[endx+1]=='/') {
state=STATE_SLASHC;
++endx;
}
else if (source[endx]==',' || source[endx]==')') {
param=param.trim();
if (param.length()>0) {
int n = param.length()-1;
int paramNameStart = 0;
while (n >= 0) {
char c = param.charAt(n);
if ('[' == c || ']' == c || Parser.WHITESPACE.indexOf(c)>=0) {
paramNameStart = n + 1;
break;
}
else {
-- n;
}
}
while (n >= 0 && ('[' == param.charAt(n)
|| ']' == param.charAt(n)
|| Parser.WHITESPACE.indexOf(param.charAt(n))>=0)) {
-- n;
}
int paramTypeEnd = n + 1;
int paramTypeStart = 0;
while (n >= 0) {
char c = param.charAt(n);
if ('[' == c || ']' == c || Parser.WHITESPACE.indexOf(c)>=0) {
paramTypeStart = n + 1;
break;
}
else {
-- n;
}
}
String paramType;
String paramName;
if (0 != paramNameStart) {
paramType=param.substring(paramTypeStart, paramTypeEnd);
paramName=param.substring(paramNameStart);
}
else {
paramName = "";
StringBuffer paramTypeBuffer = new StringBuffer();
for (int i=0; i<param.length(); ++i) {
char c = param.charAt(i);
if ('[' != c && ']' != c && Parser.WHITESPACE.indexOf(c)<0) {
paramTypeBuffer.append(c);
}
}
paramType = paramTypeBuffer.toString();
}
String dimSuffix="";
for (int i=0; i<param.length(); ++i) {
if ('[' == param.charAt(i)) {
dimSuffix += "[]";
}
}
paramType+=dimSuffix;
if (paramType.startsWith("[")) {
System.err.println("broken param type in " + rc + " in " +containingClass);
}
parameterList.add(new ParameterImpl(paramName, paramType,
((ClassDocImpl)containingClass).typeForString(paramType)));
param="";
}
}
else
param+=source[endx];
if (source[endx]==')' && state==STATE_NORMAL)
break;
}
rc.setParameters((Parameter[])parameterList.toArray(new Parameter[0]));
++endx;
String word="";
String dimSuffix="";
boolean haveThrowsKeyword=false;
List thrownExceptionsList=new ArrayList();
state=STATE_NORMAL;
for (; endx<endIndex; ++endx) {
if (state==STATE_SLASHC) {
if (source[endx]=='\n') state=STATE_NORMAL;
}
else if (state==STATE_STARC) {
if (source[endx]=='*' && source[endx+1]=='/') {
state=STATE_NORMAL;
++endx;
}
}
else if (source[endx]=='/' && source[endx+1]=='*') {
state=STATE_STARC;
++endx;
}
else if (source[endx]=='/' && source[endx+1]=='/') {
state=STATE_SLASHC;
++endx;
}
else if (Parser.WHITESPACE.indexOf(source[endx])>=0) {
word=word.trim();
if (!haveThrowsKeyword && word.length()>0) {
if (word.equals("throws")) haveThrowsKeyword=true;
else System.err.println("ARGH! "+word);
word="";
}
}
else if (source[endx]=='[' || source[endx]==']') {
dimSuffix += source[endx];
}
else if (source[endx]==',' || source[endx]=='{' || source[endx]==';') {
word=word.trim();
if (word.length()>0) {
ClassDoc exceptionType=rc.containingClass().findClass(word);
if (exceptionType==null) {
exceptionType=new ClassDocProxy(word,
rc.containingClass());
}
thrownExceptionsList.add(exceptionType);
}
if (source[endx]=='{') {
break;
}
else {
word="";
}
}
else {
word+=source[endx];
}
}
if (dimSuffix.length()>0) {
rc.setTypeName(rc.getTypeName()+dimSuffix);
}
rc.setThrownExceptions((ClassDoc[])thrownExceptionsList.toArray(new ClassDoc[0]));
return rc;
}
private ClassDoc[] thrownExceptions;
private Parameter[] parameters;
private String signature;
private String flatSignature;
void setParameters(Parameter[] parameters) {
this.parameters=parameters;
}
void setThrownExceptions(ClassDoc[] thrownExceptions) {
this.thrownExceptions=thrownExceptions;
}
void resolve() {
for (int i=0; i<thrownExceptions.length; ++i) {
if (thrownExceptions[i] instanceof ClassDocProxy) {
String className=thrownExceptions[i].qualifiedName();
ClassDoc realClassDoc=containingClass().findClass(className);
if (realClassDoc!=null)
thrownExceptions[i]=realClassDoc;
}
}
StringBuffer signatureBuf=new StringBuffer();
StringBuffer flatSignatureBuf=new StringBuffer();
for (int i=0; i<parameters.length; ++i) {
((ParameterImpl)parameters[i]).resolve(containingClass());
if (signatureBuf.length()>0) {
signatureBuf.append(",");
flatSignatureBuf.append(",");
}
signatureBuf.append(parameters[i].type().qualifiedTypeName());
flatSignatureBuf.append(parameters[i].type().typeName());
signatureBuf.append(parameters[i].type().dimension());
flatSignatureBuf.append(parameters[i].type().dimension());
}
this.signature="("+signatureBuf.toString()+")";
this.flatSignature="("+flatSignatureBuf.toString()+")";
super.resolve();
}
public int compareTo(Object other) {
int rc;
if (other instanceof MemberDocImpl) {
MemberDocImpl otherMember = (MemberDocImpl)other;
rc = name().compareTo(otherMember.name());
if (0 == rc) {
if (other instanceof ExecutableMemberDocImpl) {
rc = signature().compareTo(((ExecutableMemberDocImpl)other).signature());
if (0 == rc) {
return containingClass().compareTo(otherMember.containingClass());
}
}
else {
rc = 1;
}
}
}
else {
rc = 1;
}
return rc;
}
}