001: /*
002: * Copyright 2006 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.doctool;
017:
018: import com.sun.javadoc.ClassDoc;
019: import com.sun.javadoc.Doc;
020: import com.sun.javadoc.MemberDoc;
021: import com.sun.javadoc.MethodDoc;
022: import com.sun.javadoc.PackageDoc;
023: import com.sun.javadoc.Parameter;
024: import com.sun.javadoc.SourcePosition;
025: import com.sun.javadoc.Tag;
026:
027: /**
028: * Methods related to resolving cross-references in source.
029: */
030: public class LinkResolver {
031:
032: /**
033: * Abstracts out mechanisms for finding different bits of doc.
034: */
035: public interface ExtraClassResolver {
036: ClassDoc findClass(String className);
037: }
038:
039: public static SourcePosition resolveLink(Tag tag) {
040: return resolveLink(tag, null);
041: }
042:
043: public static SourcePosition resolveLink(Tag tag,
044: ExtraClassResolver classResolver) {
045: String linkText = tag.text();
046: String className;
047: String methodSig;
048: int pos = linkText.indexOf('#');
049: if (pos >= 0) {
050: className = linkText.substring(0, pos);
051: methodSig = linkText.substring(pos + 1);
052: } else {
053: className = linkText;
054: methodSig = null;
055: }
056:
057: ClassDoc containingClass = null;
058: Doc holder = tag.holder();
059: if (holder instanceof ClassDoc) {
060: containingClass = (ClassDoc) holder;
061: } else if (holder instanceof MemberDoc) {
062: containingClass = ((MemberDoc) holder).containingClass();
063: }
064:
065: ClassDoc targetClass = null;
066: if (className.length() == 0) {
067: targetClass = containingClass;
068: } else if (holder instanceof PackageDoc) {
069: targetClass = ((PackageDoc) holder).findClass(className);
070: } else {
071: targetClass = containingClass.findClass(className);
072: }
073:
074: if (targetClass == null) {
075: if (classResolver != null) {
076: targetClass = classResolver.findClass(className);
077: }
078: if (targetClass == null) {
079: System.err.println(tag.position().toString()
080: + ": unable to resolve class " + className
081: + " for " + tag);
082: System.exit(1);
083: }
084: }
085:
086: if (methodSig == null) {
087: return targetClass.position();
088: }
089:
090: String paramSig = methodSig.substring(
091: methodSig.indexOf('(') + 1, methodSig.lastIndexOf(')'));
092: String[] resolvedParamTypes;
093: if (paramSig.length() > 0) {
094: String[] unresolvedParamTypes = paramSig.split("\\s*,\\s*");
095: resolvedParamTypes = new String[unresolvedParamTypes.length];
096: for (int i = 0; i < unresolvedParamTypes.length; ++i) {
097: ClassDoc paramType = containingClass
098: .findClass(unresolvedParamTypes[i]);
099: if (paramType == null && classResolver != null) {
100: paramType = classResolver
101: .findClass(unresolvedParamTypes[i]);
102: }
103: if (paramType == null) {
104: System.err.println(tag.position().toString()
105: + ": unable to resolve class "
106: + unresolvedParamTypes[i] + " for " + tag);
107: System.exit(1);
108: }
109: resolvedParamTypes[i] = paramType.qualifiedTypeName();
110: }
111: } else {
112: resolvedParamTypes = new String[0];
113: }
114:
115: String possibleOverloads = "";
116:
117: MethodDoc[] methods = targetClass.methods();
118: outer: for (int i = 0; i < methods.length; ++i) {
119: MethodDoc methodDoc = methods[i];
120: if (methodSig.startsWith(methodDoc.name())) {
121: possibleOverloads += "\n" + methodDoc.flatSignature();
122: Parameter[] tryParams = methodDoc.parameters();
123: if (resolvedParamTypes.length != tryParams.length) {
124: // param count mismatch
125: continue outer;
126: }
127: for (int j = 0; j < tryParams.length; ++j) {
128: if (!tryParams[j].type().qualifiedTypeName()
129: .equals(resolvedParamTypes[j])) {
130: // param type mismatch
131: continue outer;
132: }
133: }
134: return methodDoc.position();
135: }
136: }
137:
138: System.err.println(tag.position().toString()
139: + ": unable to resolve method for " + tag);
140: if (possibleOverloads.length() > 0) {
141: System.err.println("Possible overloads: "
142: + possibleOverloads);
143: }
144: System.exit(1);
145: return null;
146: }
147:
148: }
|