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

Commit

Permalink
May Release For 2020 (#34)
Browse files Browse the repository at this point in the history
* not document package private (default modifier) elements (#32)

* resolve the uid for context in @link (#33)

* add items in specForJava to localLookup context

* add fuzzy resolve for @link content
  • Loading branch information
anmeng10101 authored May 13, 2020
1 parent de69fe1 commit f1575f7
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 74 deletions.
20 changes: 18 additions & 2 deletions src/main/java/com/microsoft/build/Lookup.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static org.apache.commons.lang3.RegExUtils.replaceAll;

import com.microsoft.model.MetadataFile;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
Expand Down Expand Up @@ -54,6 +55,8 @@ private void consume(List<MetadataFile> metadataFiles) {
* Logic of {@link YmlFilesBuilder#resolveUidByLookup} based on this for case when @link starts from '#'
*/
Map<String, String> map = new LinkedHashMap<>();
Map<String, String> specForJavaMap = new LinkedHashMap<>();

file.getItems().forEach(item -> {
String uid = item.getUid();
String nameWithType = item.getNameWithType();
Expand All @@ -71,13 +74,26 @@ private void consume(List<MetadataFile> metadataFiles) {
map.put(replaceAll(removeAll(uid, UID_PACKAGE_NAME_REGEXP), ",", ", "), uid);
map.put(replaceAll(removeAll(nameWithTypeWithoutGenerics, METHOD_PARAMS_REGEXP), ", ", ","), uid);
});

file.getReferences().forEach(item -> {
map.put(item.getNameWithType(), item.getUid());
map.put(item.getUid(), item.getUid());

// complex types are recorded in "specForJava" as arrayList of items, thus it has no "NameWithType"
// thus we need to get every reference item from specForJava, and add to localLookup
if (item.getNameWithType() == null || item.getNameWithType().isEmpty()) {
item.getSpecForJava().forEach(spec -> {
specForJavaMap.put(spec.getName(), spec.getUid());
specForJavaMap.put(spec.getFullName(), spec.getUid());
});
} else {
map.put(item.getNameWithType(), item.getUid());
}
});

localLookupByFileName.put(file.getFileNameWithPath(), map);
// to avoid conflict, the items from specForJava should only add to localLookup
globalLookup.putAll(map);
map.putAll(specForJavaMap);
localLookupByFileName.put(file.getFileNameWithPath(), map);
});
}
}
90 changes: 60 additions & 30 deletions src/main/java/com/microsoft/build/YmlFilesBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,46 +4,30 @@
import com.microsoft.lookup.ClassItemsLookup;
import com.microsoft.lookup.ClassLookup;
import com.microsoft.lookup.PackageLookup;
import com.microsoft.model.MetadataFile;
import com.microsoft.model.MetadataFileItem;
import com.microsoft.model.SpecViewModel;
import com.microsoft.model.TocFile;
import com.microsoft.model.TocItem;
import com.microsoft.model.*;
import com.microsoft.util.ElementUtil;
import com.microsoft.util.FileUtil;
import com.microsoft.util.YamlUtil;
import jdk.javadoc.doclet.DocletEnvironment;
import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.lang.model.element.*;
import javax.lang.model.util.ElementFilter;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;

import jdk.javadoc.doclet.DocletEnvironment;

import org.apache.commons.lang3.RegExUtils;
import org.apache.commons.lang3.StringUtils;


public class YmlFilesBuilder {

private final static String[] LANGS = {"java"};
private final Pattern XREF_LINK_PATTERN = Pattern.compile("<xref uid=\".*?\" .*?>.*?</xref>");
private final Pattern XREF_LINK_CONTENT_PATTERN = Pattern.compile("(?<=<xref uid=\").*?(?=\" .*?>.*?</xref>)");
private final Pattern XREF_LINK_RESOLVE_PATTERN = Pattern.compile("(?<class>\\w+)\\#(?<member>\\w+)(\\((?<param>.*)\\))?");

private DocletEnvironment environment;
private String outputPath;
Expand Down Expand Up @@ -182,7 +166,7 @@ void addChildren(TypeElement classElement, List<String> children) {

List<? extends Element> filterPrivateElements(List<? extends Element> elements) {
return elements.stream()
.filter(element -> !element.getModifiers().contains(Modifier.PRIVATE)).collect(Collectors.toList());
.filter(element -> !ElementUtil.isPrivateOrPackagePrivate(element)).collect(Collectors.toList());
}

void collect(TypeElement classElement, List<String> children,
Expand All @@ -209,7 +193,7 @@ void addConstructorsInfo(TypeElement classElement, MetadataFile classMetadataFil

void addMethodsInfo(TypeElement classElement, MetadataFile classMetadataFile) {
ElementFilter.methodsIn(classElement.getEnclosedElements()).stream()
.filter(methodElement -> !methodElement.getModifiers().contains(Modifier.PRIVATE))
.filter(methodElement -> !ElementUtil.isPrivateOrPackagePrivate(methodElement))
.forEach(methodElement -> {
MetadataFileItem methodItem = buildMetadataFileItem(methodElement);
methodItem.setOverload(classItemsLookup.extractOverload(methodElement));
Expand All @@ -228,7 +212,7 @@ void addMethodsInfo(TypeElement classElement, MetadataFile classMetadataFile) {

void addFieldsInfo(TypeElement classElement, MetadataFile classMetadataFile) {
ElementFilter.fieldsIn(classElement.getEnclosedElements()).stream()
.filter(fieldElement -> !fieldElement.getModifiers().contains(Modifier.PRIVATE))
.filter(fieldElement -> !ElementUtil.isPrivateOrPackagePrivate(fieldElement))
.forEach(fieldElement -> {
MetadataFileItem fieldItem = buildMetadataFileItem(fieldElement);
fieldItem.setContent(classItemsLookup.extractFieldContent(fieldElement));
Expand Down Expand Up @@ -392,25 +376,40 @@ String populateUidValues(String text, LookupContext lookupContext) {
}

String linkContent = linkContentMatcher.group();
String uid = resolveUidByLookup(linkContent, lookupContext);
String uid = resolveUidFromLinkContent(linkContent, lookupContext);
String updatedLink = linkContentMatcher.replaceAll(uid);
text = StringUtils.replace(text, link, updatedLink);
}
return text;
}

String resolveUidByLookup(String linkContent, LookupContext lookupContext) {
/**
* The linkContent could be in following format
* #memeber
* Class#member
* Class#method()
* Class#method(params)
*/
String resolveUidFromLinkContent(String linkContent, LookupContext lookupContext) {
if (StringUtils.isBlank(linkContent)) {
return "";
}

linkContent = linkContent.trim();

// complete class name for class internal link
if (linkContent.startsWith("#")) {
String firstKey = lookupContext.getOwnerUid();
linkContent = firstKey + linkContent;
}

// fuzzy resolve, target for items from project external references
String fuzzyResolvedUid = resolveUidFromReference(linkContent, lookupContext);

// exact resolve in lookupContext
linkContent = linkContent.replace("#", ".");
return lookupContext.containsKey(linkContent) ? lookupContext.resolve(linkContent) : "";
String exactResolveUid = resolveUidByLookup(linkContent, lookupContext);
return exactResolveUid.isEmpty() ? fuzzyResolvedUid : exactResolveUid;
}

List<String> splitUidWithGenericsIntoClassNames(String uid) {
Expand Down Expand Up @@ -464,4 +463,35 @@ else if (uid != "")

return specList;
}

/**
* this method is used to do fuzzy resolve
* "*" will be added at the end of uid for method for xerf service resolve purpose
*/
String resolveUidFromReference(String linkContent, LookupContext lookupContext) {
String uid = "";
Matcher matcher = XREF_LINK_RESOLVE_PATTERN.matcher(linkContent);

if (matcher.find()) {
String className = matcher.group("class");
String memberName = matcher.group("member");
uid = resolveUidByLookup(className, lookupContext);
if (!uid.isEmpty()) {
uid = uid.concat(".").concat(memberName);

// linkContent targets a method
if (!StringUtils.isBlank(matcher.group(3))) {
uid = uid.concat("*");
}
}
}
return uid;
}

String resolveUidByLookup(String signature, LookupContext lookupContext){
if (StringUtils.isBlank(signature) || lookupContext == null) {
return "";
}
return lookupContext.containsKey(signature) ? lookupContext.resolve(signature) : "";
}
}
15 changes: 7 additions & 8 deletions src/main/java/com/microsoft/lookup/ClassLookup.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,18 @@
import com.microsoft.lookup.model.ExtendedMetadataFileItem;
import com.microsoft.model.MetadataFileItem;
import com.microsoft.model.TypeParameter;
import com.microsoft.util.ElementUtil;
import jdk.javadoc.doclet.DocletEnvironment;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;

import jdk.javadoc.doclet.DocletEnvironment;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.stream.Collectors;

public class ClassLookup extends BaseLookup<TypeElement> {

Expand Down Expand Up @@ -147,7 +146,7 @@ void appendInheritedMethods(TypeElement element, List<ExtendedMetadataFileItem>
.orElse(0);

for (Element m : members) {
if (m.getKind() == ElementKind.METHOD && !m.getModifiers().contains(Modifier.PRIVATE)) {
if (m.getKind() == ElementKind.METHOD && !ElementUtil.isPrivateOrPackagePrivate(m)) {
String uid = element.getQualifiedName().toString().concat(".") + String.valueOf(m);

ExtendedMetadataFileItem item = new ExtendedMetadataFileItem(uid);
Expand Down
32 changes: 27 additions & 5 deletions src/main/java/com/microsoft/util/ElementUtil.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package com.microsoft.util;

import org.apache.commons.lang3.StringUtils;

import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.ElementFilter;
import org.apache.commons.lang3.StringUtils;

public class ElementUtil {

Expand Down Expand Up @@ -49,4 +51,24 @@ boolean matchAnyPattern(Set<Pattern> patterns, String stringToCheck) {
}
return false;
}

public static boolean isPackagePrivate(Element e) {
return !(isPublic(e) || isPrivate(e) || isProtected(e));
}

public static boolean isPrivate(Element e) {
return e.getModifiers().contains(Modifier.PRIVATE);
}

public static boolean isProtected(Element e) {
return e.getModifiers().contains(Modifier.PROTECTED);
}

public static boolean isPublic(Element e) {
return e.getModifiers().contains(Modifier.PUBLIC);
}

public static boolean isPrivateOrPackagePrivate(Element e) {
return isPrivate(e) || isPackagePrivate(e);
}
}
30 changes: 16 additions & 14 deletions src/test/java/com/microsoft/build/YmlFilesBuilderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.microsoft.model.MethodParameter;
import com.microsoft.model.Syntax;
import com.sun.source.util.DocTrees;

import java.io.File;
import java.util.Arrays;
import java.util.Collection;
Expand All @@ -22,6 +23,7 @@
import java.util.stream.Collectors;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;

import jdk.javadoc.doclet.DocletEnvironment;
import org.apache.commons.lang3.RegExUtils;
import org.junit.Before;
Expand Down Expand Up @@ -113,29 +115,29 @@ public void populateUidValues() {
ymlFilesBuilder.populateUidValues(Collections.emptyList(), Arrays.asList(classMetadataFile));

assertThat("Wrong summary for unknown class", item1.getSummary(),
is("Bla bla <xref uid=\"\" data-throw-if-not-resolved=\"false\">UnknownClass</xref> bla"));
is("Bla bla <xref uid=\"\" data-throw-if-not-resolved=\"false\">UnknownClass</xref> bla"));
assertThat("Wrong syntax description", item1.getSyntax().getParameters().get(0).getDescription(),
is("One two <xref uid=\"a.b.SomeClass.someMethod(String param)\" data-throw-if-not-resolved=\"false\">SomeClass#someMethod(String param)</xref> three"));
is("One two <xref uid=\"a.b.SomeClass.someMethod(String param)\" data-throw-if-not-resolved=\"false\">SomeClass#someMethod(String param)</xref> three"));
assertThat("Wrong summary for known class", item2.getSummary(),
is("Bla bla <xref uid=\"a.b.SomeClass.someMethod(String param)\" data-throw-if-not-resolved=\"false\">SomeClass#someMethod(String param)</xref> bla"));
is("Bla bla <xref uid=\"a.b.SomeClass.someMethod(String param)\" data-throw-if-not-resolved=\"false\">SomeClass#someMethod(String param)</xref> bla"));
assertThat("Wrong summary for method", item3.getSummary(),
is("Bla bla <xref uid=\"a.b.OwnerClass.someMethod2(String p1, String p2)\" data-throw-if-not-resolved=\"false\">#someMethod2(String p1, String p2)</xref> bla"));
is("Bla bla <xref uid=\"a.b.OwnerClass.someMethod2(String p1, String p2)\" data-throw-if-not-resolved=\"false\">#someMethod2(String p1, String p2)</xref> bla"));

}

private MetadataFileItem buildMetadataFileItem(String uid, String value) {
MetadataFileItem item = new MetadataFileItem(uid);
item.setSummary(
String.format("Bla bla <xref uid=\"%s\" data-throw-if-not-resolved=\"false\">%s</xref> bla", value, value));
String.format("Bla bla <xref uid=\"%s\" data-throw-if-not-resolved=\"false\">%s</xref> bla", value, value));
return item;
}

private void populateSyntax(MetadataFileItem item, String value) {
Syntax syntax = new Syntax();
String methodParamDescription = String
.format("One two <xref uid=\"%s\" data-throw-if-not-resolved=\"false\">%s</xref> three", value, value);
.format("One two <xref uid=\"%s\" data-throw-if-not-resolved=\"false\">%s</xref> three", value, value);
syntax.setParameters(
Arrays.asList(new MethodParameter("method param id", "method param type", methodParamDescription)));
Arrays.asList(new MethodParameter("method param id", "method param type", methodParamDescription)));
item.setSyntax(syntax);
}

Expand All @@ -149,15 +151,15 @@ public void determineUidByLinkContent() {

LookupContext lookupContext = new LookupContext(lookup, lookup);
assertThat("Wrong result for class", ymlFilesBuilder.
resolveUidByLookup("SomeClass", lookupContext), is("a.b.c.SomeClass"));
resolveUidByLookup("SomeClass", lookupContext), is("a.b.c.SomeClass"));
assertThat("Wrong result for method", ymlFilesBuilder.
resolveUidByLookup("SomeClass#someMethod()", lookupContext), is("a.b.c.SomeClass.someMethod()"));
resolveUidFromLinkContent("SomeClass#someMethod()", lookupContext), is("a.b.c.SomeClass.someMethod()"));
assertThat("Wrong result for method with param", ymlFilesBuilder.
resolveUidByLookup("SomeClass#someMethod(String param)", lookupContext),
is("a.b.c.SomeClass.someMethod(String param)"));
resolveUidFromLinkContent("SomeClass#someMethod(String param)", lookupContext),
is("a.b.c.SomeClass.someMethod(String param)"));

assertThat("Wrong result for unknown class", ymlFilesBuilder.
resolveUidByLookup("UnknownClass", lookupContext), is(""));
resolveUidByLookup("UnknownClass", lookupContext), is(""));
assertThat("Wrong result for null", ymlFilesBuilder.resolveUidByLookup(null, lookupContext), is(""));
assertThat("Wrong result for whitespace", ymlFilesBuilder.resolveUidByLookup(" ", lookupContext), is(""));
}
Expand All @@ -181,7 +183,7 @@ public void expandComplexGenericsInReferences() {

assertThat("Wrong references amount", references.size(), is(4));
assertThat("Wrong references content",
references.stream().map(MetadataFileItem::getUid).collect(Collectors.toList()),
hasItems("a.b.c.List", "df.mn.ClassOne", "tr.T", "a.b.c.List<df.mn.ClassOne<tr.T>>"));
references.stream().map(MetadataFileItem::getUid).collect(Collectors.toList()),
hasItems("a.b.c.List", "df.mn.ClassOne", "tr.T", "a.b.c.List<df.mn.ClassOne<tr.T>>"));
}
}
Loading

0 comments on commit f1575f7

Please sign in to comment.