Lines 1-5
Link Here
|
1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2000, 2010 IBM Corporation and others. |
2 |
* Copyright (c) 2000, 2011 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
Lines 10-21
Link Here
|
10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
11 |
package org.eclipse.jdt.internal.codeassist; |
11 |
package org.eclipse.jdt.internal.codeassist; |
12 |
|
12 |
|
|
|
13 |
import java.util.ArrayList; |
14 |
import java.util.Iterator; |
13 |
import java.util.Locale; |
15 |
import java.util.Locale; |
14 |
import java.util.Map; |
16 |
import java.util.Map; |
15 |
|
17 |
|
16 |
import org.eclipse.core.resources.IFile; |
18 |
import org.eclipse.core.resources.IFile; |
17 |
import org.eclipse.core.runtime.IProgressMonitor; |
19 |
import org.eclipse.core.runtime.IProgressMonitor; |
18 |
import org.eclipse.core.runtime.OperationCanceledException; |
20 |
import org.eclipse.core.runtime.OperationCanceledException; |
|
|
21 |
import org.eclipse.jdt.core.IBuffer; |
22 |
import org.eclipse.jdt.core.IMember; |
23 |
import org.eclipse.jdt.core.IOpenable; |
24 |
import org.eclipse.jdt.core.ISourceRange; |
19 |
import org.eclipse.jdt.core.IType; |
25 |
import org.eclipse.jdt.core.IType; |
20 |
import org.eclipse.jdt.core.JavaModelException; |
26 |
import org.eclipse.jdt.core.JavaModelException; |
21 |
import org.eclipse.jdt.core.Signature; |
27 |
import org.eclipse.jdt.core.Signature; |
Lines 1106-1112
Link Here
|
1106 |
} |
1112 |
} |
1107 |
this.acceptedAnswer = true; |
1113 |
this.acceptedAnswer = true; |
1108 |
} else if (binding instanceof MethodBinding) { |
1114 |
} else if (binding instanceof MethodBinding) { |
1109 |
MethodBinding methodBinding = (MethodBinding) binding; |
1115 |
MethodBinding methodBinding = getCorrectMethodBinding((MethodBinding) binding); |
1110 |
this.noProposal = false; |
1116 |
this.noProposal = false; |
1111 |
|
1117 |
|
1112 |
boolean isValuesOrValueOf = false; |
1118 |
boolean isValuesOrValueOf = false; |
Lines 1608-1611
Link Here
|
1608 |
|
1614 |
|
1609 |
return false; |
1615 |
return false; |
1610 |
} |
1616 |
} |
|
|
1617 |
|
1618 |
/* |
1619 |
* Returns the correct method binding according to whether the selection is on the method declaration |
1620 |
* or on the inheritDoc tag in its javadoc. |
1621 |
*/ |
1622 |
private MethodBinding getCorrectMethodBinding(MethodBinding binding) { |
1623 |
if (this.parser.javadocParser instanceof SelectionJavadocParser) { |
1624 |
if (((SelectionJavadocParser)this.parser.javadocParser).inheritDocTagSelected){ |
1625 |
try { |
1626 |
Object res = findMethodWithAttachedDocInHierarchy(binding); |
1627 |
if (res instanceof MethodBinding) { |
1628 |
return (MethodBinding) res; |
1629 |
} |
1630 |
} catch (JavaModelException e) { |
1631 |
return null; |
1632 |
} |
1633 |
} |
1634 |
} |
1635 |
return binding; |
1636 |
} |
1637 |
|
1638 |
protected MethodBinding findOverriddenMethodInType(ReferenceBinding overriddenType, MethodBinding overriding) throws JavaModelException { |
1639 |
if (overriddenType == null) |
1640 |
return null; |
1641 |
MethodBinding[] overriddenMethods= overriddenType.availableMethods(); |
1642 |
LookupEnvironment lookupEnv = this.lookupEnvironment; |
1643 |
if (lookupEnv != null && overriddenMethods != null) { |
1644 |
for (int i= 0; i < overriddenMethods.length; i++) { |
1645 |
if (lookupEnv.methodVerifier().isMethodSubsignature(overriding, overriddenMethods[i])) { |
1646 |
return overriddenMethods[i]; |
1647 |
} |
1648 |
} |
1649 |
} |
1650 |
return null; |
1651 |
} |
1652 |
|
1653 |
private Object findMethodWithAttachedDocInHierarchy(final MethodBinding method) throws JavaModelException { |
1654 |
ReferenceBinding type= method.declaringClass; |
1655 |
final SelectionRequestor requestor1 = (SelectionRequestor) this.requestor; |
1656 |
return new InheritDocVisitor() { |
1657 |
public Object visit(ReferenceBinding currType) throws JavaModelException { |
1658 |
MethodBinding overridden = findOverriddenMethodInType(currType, method); |
1659 |
if (overridden == null) |
1660 |
return InheritDocVisitor.CONTINUE; |
1661 |
TypeBinding args[] = overridden.parameters; |
1662 |
String names[] = new String[args.length]; |
1663 |
for (int i = 0; i < args.length; i++) { |
1664 |
names[i] = Signature.createTypeSignature(args[i].sourceName(), false); |
1665 |
} |
1666 |
IMember member = (IMember) requestor1.findMethodFromBinding(overridden, names, overridden.declaringClass); |
1667 |
if (member == null) |
1668 |
return InheritDocVisitor.CONTINUE; |
1669 |
if (member.getAttachedJavadoc(null) != null ) { |
1670 |
// for binary methods with attached javadoc and no source attached |
1671 |
return overridden; |
1672 |
} |
1673 |
IOpenable openable = member.getOpenable(); |
1674 |
if (openable == null) |
1675 |
return InheritDocVisitor.CONTINUE; |
1676 |
IBuffer buf= openable.getBuffer(); |
1677 |
if (buf == null) { |
1678 |
// no source attachment found. This method maybe the one. Stop. |
1679 |
return InheritDocVisitor.STOP_BRANCH; |
1680 |
} |
1681 |
|
1682 |
ISourceRange javadocRange= member.getJavadocRange(); |
1683 |
if (javadocRange == null) |
1684 |
return InheritDocVisitor.CONTINUE; // this method doesn't have javadoc, continue to look. |
1685 |
String rawJavadoc= buf.getText(javadocRange.getOffset(), javadocRange.getLength()); |
1686 |
if (rawJavadoc != null) { |
1687 |
return overridden; |
1688 |
} |
1689 |
return InheritDocVisitor.CONTINUE; |
1690 |
} |
1691 |
}.visitInheritDoc(type); |
1692 |
} |
1693 |
|
1694 |
/** |
1695 |
* Implements the "Algorithm for Inheriting Method Comments" as specified for |
1696 |
* <a href="http://java.sun.com/j2se/1.4.2/docs/tooldocs/solaris/javadoc.html#inheritingcomments">1.4.2</a>, |
1697 |
* <a href="http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#inheritingcomments">1.5</a>, and |
1698 |
* <a href="http://java.sun.com/javase/6/docs/technotes/tools/windows/javadoc.html#inheritingcomments">1.6</a>. |
1699 |
* |
1700 |
* <p> |
1701 |
* Unfortunately, the implementation is broken in Javadoc implementations since 1.5, see |
1702 |
* <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6376959">Sun's bug</a>. |
1703 |
* </p> |
1704 |
* |
1705 |
* <p> |
1706 |
* We adhere to the spec. |
1707 |
* </p> |
1708 |
*/ |
1709 |
static abstract class InheritDocVisitor { |
1710 |
public static final Object STOP_BRANCH= new Object() { |
1711 |
public String toString() { return "STOP_BRANCH"; } //$NON-NLS-1$ |
1712 |
}; |
1713 |
public static final Object CONTINUE= new Object() { |
1714 |
public String toString() { return "CONTINUE"; } //$NON-NLS-1$ |
1715 |
}; |
1716 |
|
1717 |
/** |
1718 |
* Visits a type and decides how the visitor should proceed. |
1719 |
* |
1720 |
* @param currType the current type |
1721 |
* @return <ul> |
1722 |
* <li>{@link #STOP_BRANCH} to indicate that no Javadoc has been found and visiting |
1723 |
* super types should stop here</li> |
1724 |
* <li>{@link #CONTINUE} to indicate that no Javadoc has been found and visiting |
1725 |
* super types should continue</li> |
1726 |
* <li>an {@link Object} or <code>null</code>, to indicate that visiting should be |
1727 |
* cancelled immediately. The returned value is the result of |
1728 |
* {@link #visitInheritDoc(ReferenceBinding)}</li> |
1729 |
* </ul> |
1730 |
* @throws JavaModelException unexpected problem |
1731 |
* @see #visitInheritDoc(ReferenceBinding) |
1732 |
*/ |
1733 |
public abstract Object visit(ReferenceBinding currType) throws JavaModelException; |
1734 |
|
1735 |
/** |
1736 |
* Visits the super types of the given <code>currentType</code>. |
1737 |
* |
1738 |
* @param currentType the starting type |
1739 |
* @return the result from a call to {@link #visit(ReferenceBinding)}, or <code>null</code> if none of |
1740 |
* the calls returned a result |
1741 |
* @throws JavaModelException unexpected problem |
1742 |
*/ |
1743 |
public Object visitInheritDoc(ReferenceBinding currentType) throws JavaModelException { |
1744 |
ArrayList visited= new ArrayList(); |
1745 |
visited.add(currentType); |
1746 |
Object result= visitInheritDocInterfaces(visited, currentType); |
1747 |
if (result != InheritDocVisitor.CONTINUE) |
1748 |
return result; |
1749 |
|
1750 |
ReferenceBinding superClass= currentType.superclass(); |
1751 |
|
1752 |
while (superClass != null && ! visited.contains(superClass)) { |
1753 |
result= visit(superClass); |
1754 |
if (result == InheritDocVisitor.STOP_BRANCH) { |
1755 |
return null; |
1756 |
} else if (result == InheritDocVisitor.CONTINUE) { |
1757 |
visited.add(superClass); |
1758 |
result= visitInheritDocInterfaces(visited, superClass); |
1759 |
if (result != InheritDocVisitor.CONTINUE) |
1760 |
return result; |
1761 |
else |
1762 |
superClass= superClass.superclass(); |
1763 |
} else { |
1764 |
return result; |
1765 |
} |
1766 |
} |
1767 |
|
1768 |
return null; |
1769 |
} |
1770 |
|
1771 |
/** |
1772 |
* Visits the super interfaces of the given type in the given hierarchy, thereby skipping already visited types. |
1773 |
* |
1774 |
* @param visited set of visited types |
1775 |
* @param currentType type whose super interfaces should be visited |
1776 |
* @return the result, or {@link #CONTINUE} if no result has been found |
1777 |
* @throws JavaModelException unexpected problem |
1778 |
*/ |
1779 |
private Object visitInheritDocInterfaces(ArrayList visited, ReferenceBinding currentType) throws JavaModelException { |
1780 |
ArrayList toVisitChildren= new ArrayList(); |
1781 |
ReferenceBinding[] superInterfaces= currentType.superInterfaces(); |
1782 |
for (int i= 0; i < superInterfaces.length; i++) { |
1783 |
ReferenceBinding superInterface= superInterfaces[i]; |
1784 |
if (visited.contains(superInterface)) |
1785 |
continue; |
1786 |
visited.add(superInterface); |
1787 |
Object result= visit(superInterface); |
1788 |
if (result == InheritDocVisitor.STOP_BRANCH) { |
1789 |
//skip |
1790 |
} else if (result == InheritDocVisitor.CONTINUE) { |
1791 |
toVisitChildren.add(superInterface); |
1792 |
} else { |
1793 |
return result; |
1794 |
} |
1795 |
} |
1796 |
for (Iterator iter= toVisitChildren.iterator(); iter.hasNext(); ) { |
1797 |
ReferenceBinding child= (ReferenceBinding) iter.next(); |
1798 |
Object result= visitInheritDocInterfaces(visited, child); |
1799 |
if (result != InheritDocVisitor.CONTINUE) |
1800 |
return result; |
1801 |
} |
1802 |
return InheritDocVisitor.CONTINUE; |
1803 |
} |
1804 |
} |
1611 |
} |
1805 |
} |