Skip to content
This repository was archived by the owner on Aug 9, 2022. It is now read-only.

Commit 7732efa

Browse files
committed
implement comment inheritance for methods (#40)
1 parent 6b05484 commit 7732efa

22 files changed

Lines changed: 1568 additions & 4 deletions

src/main/java/com/microsoft/lookup/ClassItemsLookup.java

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package com.microsoft.lookup;
22

33
import com.microsoft.lookup.model.ExtendedMetadataFileItem;
4+
45
import com.microsoft.model.ExceptionItem;
56
import com.microsoft.model.MethodParameter;
67
import com.microsoft.model.Return;
8+
9+
import com.microsoft.util.CommentHelper;
710
import com.microsoft.util.Utils;
11+
12+
import com.sun.source.doctree.DocTree;
813
import com.sun.source.doctree.DocTree.Kind;
914
import com.sun.source.doctree.ParamTree;
1015
import com.sun.source.doctree.ReturnTree;
1116
import com.sun.source.doctree.ThrowsTree;
1217

18+
import java.util.ArrayList;
1319
import java.util.List;
1420
import java.util.stream.Collectors;
21+
1522
import javax.lang.model.element.*;
1623
import javax.lang.model.type.TypeKind;
1724

@@ -64,6 +71,7 @@ protected ExtendedMetadataFileItem buildMetadataFileItem(Element element) {
6471
result.setReturn(extractReturn(exeElement));
6572
if (exeElement.getKind() == ElementKind.METHOD) {
6673
result.setOverridden(extractOverriddenUid(utils.overriddenMethod(exeElement)));
74+
result.setSummary(getInheritedInlineCommentString(exeElement));
6775
}
6876
}
6977
result.setNameWithType(String.format("%s.%s", classSNameWithGenericsSupport, result.getName()));
@@ -145,4 +153,46 @@ String extractOverriddenUid(ExecutableElement ovr) {
145153

146154
return "";
147155
}
156+
157+
/**
158+
* If the item being inherited from is declared from external compiled package,
159+
* or is declared in the packages like java.lang.Object,
160+
* comments may be not available as doclet resolves from byte code.
161+
*/
162+
String getInheritedInlineCommentString(ExecutableElement exeElement) {
163+
CommentHelper ch = getInheritedInlineTags(new CommentHelper(exeElement, utils));
164+
// Remove unresolved "@inheritDoc" tag.
165+
List<? extends DocTree> dctree = utils.removeBlockTag(ch.inlineTags, DocTree.Kind.INHERIT_DOC);
166+
return replaceLinksAndCodes(dctree);
167+
}
168+
169+
CommentHelper getInheritedInlineTags(CommentHelper input) {
170+
CommentHelper output = input.copy();
171+
if (!output.hasInheritDocTag()&& !output.isSimpleOverride()) {
172+
return output;
173+
}
174+
175+
CommentHelper inheritedSearchInput = input.copy();
176+
ExecutableElement overriddenMethod = utils.overriddenMethod((ExecutableElement) input.element);
177+
178+
if (overriddenMethod != null) {
179+
inheritedSearchInput.element = overriddenMethod;
180+
CommentHelper ch = getInheritedInlineTags(inheritedSearchInput);
181+
if (!ch.isSimpleOverride()) {
182+
output = output.inherit(ch);
183+
}
184+
}
185+
186+
TypeElement encl = utils.getEnclosingTypeElement(input.element);
187+
List<Element> implementedMethods = utils.getImplementedMethods(input.element.toString(), encl, new ArrayList<Element>());
188+
for (Element implementedMethod : implementedMethods) {
189+
inheritedSearchInput.element = implementedMethod;
190+
CommentHelper ch = getInheritedInlineTags(inheritedSearchInput);
191+
if (!ch.isSimpleOverride()) {
192+
output = output.inherit(ch);
193+
}
194+
}
195+
196+
return output;
197+
}
148198
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.microsoft.util;
2+
3+
import com.sun.source.doctree.DocTree;
4+
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
10+
import javax.lang.model.element.Element;
11+
12+
public class CommentHelper {
13+
public Element element;
14+
public List<? extends DocTree> inlineTags = Collections.emptyList();
15+
private Utils utils;
16+
private boolean hasInheritDocTag = false;
17+
18+
public CommentHelper(Element element, Utils utils) {
19+
this.element = element;
20+
this.utils = utils;
21+
this.inlineTags = utils.getFullBody(element);
22+
this.hasInheritDocTag = utils.hasInlineTag(inlineTags, DocTree.Kind.INHERIT_DOC);
23+
}
24+
25+
public CommentHelper(Element element, Utils utils, List<? extends DocTree> inlineTags) {
26+
this.element = element;
27+
this.utils = utils;
28+
this.inlineTags = inlineTags;
29+
this.hasInheritDocTag = utils.hasInlineTag(inlineTags, DocTree.Kind.INHERIT_DOC);
30+
}
31+
32+
/**
33+
* Returns true if the method has no comments, or a lone &commat;inheritDoc.
34+
*
35+
* @return true if there are no comments, false otherwise
36+
*/
37+
public boolean isSimpleOverride() {
38+
return inlineTags.isEmpty() ||
39+
(inlineTags.size() == 1 && hasInheritDocTag);
40+
}
41+
42+
public boolean hasInheritDocTag(){
43+
return this.hasInheritDocTag;
44+
}
45+
46+
public CommentHelper copy() {
47+
if (this.element == null) {
48+
throw new NullPointerException();
49+
}
50+
CommentHelper clone = new CommentHelper(this.element, this.utils);
51+
return clone;
52+
}
53+
54+
public CommentHelper inherit(CommentHelper chInheritFrom) {
55+
List<? extends DocTree> mergedTags = new ArrayList<>();
56+
57+
if (this.isSimpleOverride())
58+
mergedTags = chInheritFrom.inlineTags;
59+
else {
60+
mergedTags = inheritInlineTags(this, chInheritFrom);
61+
}
62+
63+
return new CommentHelper(this.element, this.utils, mergedTags);
64+
}
65+
66+
List<? extends DocTree> inheritInlineTags(CommentHelper origin, CommentHelper chInheritFrom) {
67+
List<DocTree> mergedTags = new ArrayList<>();
68+
if (!origin.isSimpleOverride() && !origin.hasInheritDocTag) {
69+
return origin.inlineTags;
70+
}
71+
72+
// Get the index of "{@inheritedDoc}".
73+
int index = origin.inlineTags.stream().map(e -> e.getKind())
74+
.collect(Collectors.toList())
75+
.indexOf(DocTree.Kind.INHERIT_DOC);
76+
77+
// Replace the "{@inheritedDoc}" with inherited inlineTags.
78+
mergedTags = origin.inlineTags.stream().collect(Collectors.toList());
79+
mergedTags.remove(index);
80+
81+
for (DocTree d : chInheritFrom.inlineTags
82+
) {
83+
mergedTags.add(index, d);
84+
index++;
85+
}
86+
87+
return mergedTags;
88+
}
89+
}

src/main/java/com/microsoft/util/Utils.java

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,7 @@
1010
import javax.lang.model.util.SimpleElementVisitor9;
1111
import javax.lang.model.util.Types;
1212

13-
import java.util.ArrayList;
14-
import java.util.Collections;
15-
import java.util.List;
16-
import java.util.Optional;
13+
import java.util.*;
1714
import java.util.stream.Collectors;
1815

1916
import jdk.javadoc.doclet.DocletEnvironment;
@@ -77,6 +74,21 @@ public boolean isSimpleOverride(ExecutableElement m) {
7774
(fullBody.size() == 1 && fullBody.get(0).getKind().equals(DocTree.Kind.INHERIT_DOC));
7875
}
7976

77+
public boolean hasInlineTag(List<? extends DocTree> inlineTags, DocTree.Kind kind) {
78+
for (DocTree dt : inlineTags) {
79+
if (dt.getKind() == kind) {
80+
return true;
81+
}
82+
}
83+
return false;
84+
}
85+
86+
public Element getMemberBySignature(TypeElement te, ElementKind kind, String signature) {
87+
return getMembers(te, kind).stream()
88+
.filter(e -> e.toString().equals(signature))
89+
.findFirst().orElse(null);
90+
}
91+
8092
public TypeElement getObjectType() {
8193
return elementUtils.getTypeElement("java.lang.Object");
8294
}
@@ -193,6 +205,12 @@ public List<? extends DocTree> getBlockTags(Element element) {
193205
return getBlockTags0(element, (DocTree.Kind[]) null);
194206
}
195207

208+
public List<? extends DocTree> removeBlockTag(List<? extends DocTree> dctree, DocTree.Kind kind) {
209+
return dctree.stream()
210+
.filter(dc -> !dc.getKind().equals(kind))
211+
.collect(Collectors.toList());
212+
}
213+
196214
/**
197215
* Returns a list of visible enclosed members of given kind,
198216
* declared in this type element, and does not include
@@ -205,4 +223,39 @@ public List<? extends Element> getMembers(TypeElement te, ElementKind kind) {
205223
.filter(e -> e.getKind() == kind && !isPrivateOrPackagePrivate(e))
206224
.collect(Collectors.toList());
207225
}
226+
227+
/**
228+
* Returns a list of methods being implemented by given method.
229+
* When a method in an interface overrides a method its superinterface,
230+
* it will be considered as "implemented", instead of "overridden".
231+
*
232+
* @return a list of implemented methods
233+
*/
234+
public List<Element> getImplementedMethods(String signature, TypeElement encl, List<Element> implementedMethods) {
235+
if (encl == null) {
236+
return implementedMethods;
237+
}
238+
239+
for (TypeElement interfaceType : getImplementedInterfaces(encl)) {
240+
Element implementedMethod = getMemberBySignature(interfaceType, ElementKind.METHOD, signature);
241+
if (implementedMethod != null) {
242+
implementedMethods.add(implementedMethod);
243+
}
244+
// We need to search every implemented interface of the Inheritance chain.
245+
getImplementedMethods(signature, interfaceType, implementedMethods);
246+
}
247+
return implementedMethods;
248+
}
249+
250+
/**
251+
* Returns a list of implemented interface type elements of given type element.
252+
* Follow Standard doclet, search in the order of appearance following the word implements in declaration.
253+
*
254+
* @return a list of implemented interfaces
255+
*/
256+
public List<TypeElement> getImplementedInterfaces(TypeElement element) {
257+
return element.getInterfaces().stream()
258+
.map(e -> asTypeElement(e))
259+
.collect(Collectors.toList());
260+
}
208261
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.microsoft.samples.commentinheritance;
2+
3+
/**
4+
* Animal.
5+
*/
6+
public abstract class Animal implements Organism{
7+
/**
8+
* Breathe.
9+
*/
10+
public void breathe() {
11+
}
12+
13+
/**
14+
* Communicate verbally.
15+
*/
16+
public abstract void verballyCommunicate();
17+
18+
/**
19+
* Feed offspring.
20+
*/
21+
public abstract void feed();
22+
23+
/**
24+
* {@inheritDoc}
25+
* Get kind from Animal.
26+
*/
27+
public abstract String getKind();
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.microsoft.samples.commentinheritance;
2+
3+
/**
4+
* Marks an Animal that eats other animals.
5+
*/
6+
public interface Carnivorous {
7+
/**
8+
* Eat the provided animal.
9+
*
10+
* @param animalBeingEaten Animal that will be eaten.
11+
*/
12+
void eat(Animal animalBeingEaten);
13+
14+
/**
15+
* Get kind from Carnivorous.
16+
*/
17+
String getKind();
18+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.microsoft.samples.commentinheritance;
2+
3+
import java.awt.Color;
4+
5+
import static java.lang.System.out;
6+
7+
/**
8+
* Canine and man's best friend.
9+
*/
10+
public class Dog extends Mammal implements Omnivorous, Viviparous {
11+
private final Color hairColor = null;
12+
13+
/**
14+
* {@inheritDoc}
15+
*
16+
* @param otherAnimal Tasty treat.
17+
*/
18+
@Override
19+
public void eat(final Animal otherAnimal) {
20+
}
21+
22+
/**
23+
* {@inheritDoc}
24+
*
25+
* @param plantToBeEaten Plant that this dog will eat.
26+
*/
27+
@Override
28+
public void eat(final Plant plantToBeEaten) {
29+
}
30+
31+
/**
32+
* {@inheritDoc} Bark.
33+
*/
34+
public void verballyCommunicate() {
35+
out.println("Woof!");
36+
}
37+
38+
/**
39+
* {@inheritDoc}
40+
*
41+
* @param numberPuppies Number of puppies being born.
42+
*/
43+
@Override
44+
public void giveBirth(final int numberPuppies) {
45+
}
46+
47+
/**
48+
* Provide the color of the dog's hair.
49+
*
50+
* @return Color of the dog's fur.
51+
*/
52+
public Color getHairColor() {
53+
return hairColor;
54+
}
55+
56+
/**
57+
* {@inheritDoc}
58+
*/
59+
@Override
60+
public void feed() {
61+
}
62+
63+
/**
64+
* {@inheritDoc}
65+
* Get kind from Dog.
66+
*/
67+
@Override
68+
public String getKind() {
69+
return "Dog";
70+
}
71+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.microsoft.samples.commentinheritance;
2+
3+
/**
4+
* Marks animals that eat plants.
5+
*/
6+
public interface Herbivorous {
7+
/**
8+
* Eat the provided plant.
9+
*
10+
* @param plantToBeEaten Plant that will be eaten.
11+
*/
12+
void eat(Plant plantToBeEaten);
13+
14+
/**
15+
* Get kind from Herbivorous.
16+
*/
17+
String getKind();
18+
19+
public class Plant {
20+
}
21+
22+
}

0 commit comments

Comments
 (0)