Javadoc from Javadoc jars

This commit is contained in:
BoykoAlex
2016-11-18 20:01:26 -05:00
parent 2c9a250ec5
commit 26b95f3263
19 changed files with 5948 additions and 31 deletions

View File

@@ -29,6 +29,12 @@
<artifactId>jandex</artifactId>
<version>2.0.3.Final</version>
</dependency>
<!-- HTML <-> Markdown conversion -->
<dependency>
<groupId>com.kotcrab.remark</groupId>
<artifactId>remark</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>

View File

@@ -11,7 +11,6 @@ import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.PrimitiveType;
import org.jboss.jandex.Type;
@@ -30,6 +29,8 @@ import org.springframework.ide.vscode.commons.javadoc.IJavadoc;
public class Wrappers {
private static final String JANDEX_CONTRUCTOR_NAME = "<init>";
public static IType wrap(JandexIndex index, ClassInfo info, IJavadocProvider javadocProvider) {
if (info == null) {
return null;
@@ -80,9 +81,14 @@ public class Wrappers {
@Override
public boolean isInterface() {
return false;
return Flags.isInterface(info.flags());
}
@Override
public boolean isAnnotation() {
return Flags.isAnnotation(info.flags());
}
@Override
public String getFullyQualifiedName() {
return info.name().toString();
@@ -117,7 +123,7 @@ public class Wrappers {
public String toString() {
return info.toString();
}
};
}
@@ -180,6 +186,11 @@ public class Wrappers {
public int getFlags() {
return method.flags();
}
@Override
public boolean isConstructor() {
return method.name().equals(JANDEX_CONTRUCTOR_NAME);
}
@Override
public IType getDeclaringType() {
@@ -188,7 +199,7 @@ public class Wrappers {
@Override
public String getElementName() {
return method.name();
return isConstructor() ? getDeclaringType().getElementName() : method.name();
}
@Override
@@ -230,6 +241,7 @@ public class Wrappers {
public Stream<IJavaType> parameters() {
return method.parameters().stream().map(Wrappers::wrap);
}
};
}
@@ -289,13 +301,6 @@ public class Wrappers {
};
}
public static Type createParameterTypeFromSignature(IndexView index, String signature) {
if (signature == null) {
return null;
}
throw new UnsupportedOperationException("Not yet implemented");
}
public static IPrimitiveType wrap(PrimitiveType type) {
switch (type.primitive()) {
case SHORT:

View File

@@ -51,5 +51,7 @@ public interface IMethod extends IMember {
* @return
*/
Stream<IJavaType> parameters();
boolean isConstructor();
}

View File

@@ -23,6 +23,7 @@ public interface IType extends IMember {
boolean isClass();
boolean isEnum();
boolean isInterface();
boolean isAnnotation();
/**
* Returns the fully qualified name of this type,

View File

@@ -0,0 +1,45 @@
package org.springframework.ide.vscode.commons.javadoc;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.springframework.ide.vscode.commons.javadoc.internal.JavadocContents;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class DefaultHtmlJavadocIndex implements HtmlJavadocIndex {
private Cache<URL, JavadocContents> cache = CacheBuilder.newBuilder().build();
private static JavadocContents NO_HTML_CONTENT = new JavadocContents(null);
@Override
public JavadocContents getHtmlJavadoc(URL url) {
try {
JavadocContents content = cache.get(url, () -> {
InputStream stream = null;
try {
stream = url.openStream();
BufferedReader buffer = new BufferedReader(new InputStreamReader(stream));
return new JavadocContents(buffer.lines().collect(Collectors.joining("\n")));
} catch (IOException e) {
return NO_HTML_CONTENT;
} finally {
if (stream != null) {
stream.close();
}
}
});
return content == NO_HTML_CONTENT ? null : content;
} catch (ExecutionException e) {
return null;
}
}
}

View File

@@ -0,0 +1,35 @@
package org.springframework.ide.vscode.commons.javadoc;
import com.overzealous.remark.Remark;
public class HtmlJavadoc implements IJavadoc {
private String html;
private Remark remark;
public HtmlJavadoc(String html) {
this.html = html;
this.remark = new Remark();
}
@Override
public String raw() {
throw new UnsupportedOperationException("Not yet implemnted");
}
@Override
public String plainText() {
throw new UnsupportedOperationException("Not yet implemnted");
}
@Override
public String html() {
return html;
}
@Override
public String markdown() {
return remark.convertFragment(html);
}
}

View File

@@ -0,0 +1,14 @@
package org.springframework.ide.vscode.commons.javadoc;
import java.net.URL;
import org.springframework.ide.vscode.commons.javadoc.internal.JavadocContents;
public interface HtmlJavadocIndex {
public static final HtmlJavadocIndex DEFAULT = new DefaultHtmlJavadocIndex();
JavadocContents getHtmlJavadoc(URL url);
}

View File

@@ -0,0 +1,66 @@
package org.springframework.ide.vscode.commons.javadoc;
import java.net.URL;
import org.springframework.ide.vscode.commons.java.IAnnotation;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IMethod;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.javadoc.internal.JavadocContents;
import org.springframework.ide.vscode.commons.util.Log;
public class HtmlJavadocProvider implements IJavadocProvider {
private SourceUrlProvider htmlUrlProvider;
public HtmlJavadocProvider(SourceUrlProvider htmlUrlProvider) {
this.htmlUrlProvider = htmlUrlProvider;
}
@Override
public IJavadoc getJavadoc(IType type) {
try {
JavadocContents javadocContents = findHtml(type);
return new HtmlJavadoc(javadocContents.getTypeDoc(type));
} catch (Exception e) {
Log.log(e);
return null;
}
}
@Override
public IJavadoc getJavadoc(IField field) {
try {
IType declaringType = field.getDeclaringType();
JavadocContents javadocContents = findHtml(declaringType);
return new HtmlJavadoc(javadocContents.getFieldDoc(field));
} catch (Exception e) {
Log.log(e);
return null;
}
}
@Override
public IJavadoc getJavadoc(IMethod method) {
try {
IType declaringType = method.getDeclaringType();
JavadocContents javadocContents = findHtml(declaringType);
return new HtmlJavadoc(javadocContents.getMethodDoc(method));
} catch (Exception e) {
Log.log(e);
return null;
}
}
@Override
public IJavadoc getJavadoc(IAnnotation annotation) {
throw new UnsupportedOperationException("Not yet implemented");
}
private JavadocContents findHtml(IType type) throws Exception {
URL url = htmlUrlProvider.sourceUrl(type);
return HtmlJavadocIndex.DEFAULT.getHtmlJavadoc(url);
}
}

View File

@@ -24,6 +24,30 @@ public interface SourceUrlProviderFromSourceContainer {
return Paths.get(sourceContainerUrl.toURI()).resolve(type.getFullyQualifiedName().replaceAll("\\.", "/") + ".java").toUri().toURL();
};
public static final SourceUrlProviderFromSourceContainer JAR_JAVADOC_URL_PROVIDER = (javadocContainerUrl, type) -> {
StringBuilder sourceUrlStr = new StringBuilder();
sourceUrlStr.append("jar:");
sourceUrlStr.append(javadocContainerUrl);
sourceUrlStr.append("!");
sourceUrlStr.append('/');
// Inner classes are in separate Top.Nesting1.Nesting2.Nesting3.MyType.html files
sourceUrlStr.append(type.getFullyQualifiedName().replaceAll("\\.", "/").replaceAll("\\$", "."));
sourceUrlStr.append(".html");
return new URL(sourceUrlStr.toString());
};
public static final SourceUrlProviderFromSourceContainer JAVADOC_FOLDER_URL_SUPPLIER = (sourceContainerUrl, type) -> {
String urlStr = sourceContainerUrl.toString();
StringBuilder sb = new StringBuilder(urlStr);
if (!urlStr.endsWith("/")) {
sb.append('/');
}
// Inner classes are in separate Top.Nesting1.Nesting2.Nesting3.MyType.html files
sb.append(type.getFullyQualifiedName().replaceAll("\\.", "/").replaceAll("\\$", ".") + ".html");
return new URL(sb.toString());
};
URL sourceUrl(URL sourceContainerUrl, IType type) throws Exception;
}

View File

@@ -0,0 +1,158 @@
package org.springframework.ide.vscode.commons.javadoc.internal;
/**
* Hashtable of {Object --> int[] }
*/
public final class HashtableOfObjectToIntArray implements Cloneable {
// to avoid using Enumerations, walk the individual tables skipping nulls
public Object[] keyTable;
public int[][] valueTable;
public int elementSize; // number of elements in the table
int threshold;
public HashtableOfObjectToIntArray() {
this(13);
}
public HashtableOfObjectToIntArray(int size) {
this.elementSize = 0;
this.threshold = size; // size represents the expected number of elements
int extraRoom = (int) (size * 1.75f);
if (this.threshold == extraRoom)
extraRoom++;
this.keyTable = new Object[extraRoom];
this.valueTable = new int[extraRoom][];
}
public Object clone() throws CloneNotSupportedException {
HashtableOfObjectToIntArray result = (HashtableOfObjectToIntArray) super.clone();
result.elementSize = this.elementSize;
result.threshold = this.threshold;
int length = this.keyTable.length;
result.keyTable = new Object[length];
System.arraycopy(this.keyTable, 0, result.keyTable, 0, length);
length = this.valueTable.length;
result.valueTable = new int[length][];
System.arraycopy(this.valueTable, 0, result.valueTable, 0, length);
return result;
}
public boolean containsKey(Object key) {
int length = this.keyTable.length,
index = (key.hashCode()& 0x7FFFFFFF) % length;
Object currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.equals(key))
return true;
if (++index == length) {
index = 0;
}
}
return false;
}
public int[] get(Object key) {
int length = this.keyTable.length,
index = (key.hashCode()& 0x7FFFFFFF) % length;
Object currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.equals(key))
return this.valueTable[index];
if (++index == length) {
index = 0;
}
}
return null;
}
public void keysToArray(Object[] array) {
int index = 0;
for (int i=0, length=this.keyTable.length; i<length; i++) {
if (this.keyTable[i] != null)
array[index++] = this.keyTable[i];
}
}
public int[] put(Object key, int[] value) {
int length = this.keyTable.length,
index = (key.hashCode()& 0x7FFFFFFF) % length;
Object currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.equals(key))
return this.valueTable[index] = value;
if (++index == length) {
index = 0;
}
}
this.keyTable[index] = key;
this.valueTable[index] = value;
// assumes the threshold is never equal to the size of the table
if (++this.elementSize > this.threshold)
rehash();
return value;
}
public int[] removeKey(Object key) {
int length = this.keyTable.length,
index = (key.hashCode()& 0x7FFFFFFF) % length;
Object currentKey;
while ((currentKey = this.keyTable[index]) != null) {
if (currentKey.equals(key)) {
int[] value = this.valueTable[index];
this.elementSize--;
this.keyTable[index] = null;
rehash();
return value;
}
if (++index == length) {
index = 0;
}
}
return null;
}
private void rehash() {
HashtableOfObjectToIntArray newHashtable = new HashtableOfObjectToIntArray(this.elementSize * 2); // double the number of expected elements
Object currentKey;
for (int i = this.keyTable.length; --i >= 0;)
if ((currentKey = this.keyTable[i]) != null)
newHashtable.put(currentKey, this.valueTable[i]);
this.keyTable = newHashtable.keyTable;
this.valueTable = newHashtable.valueTable;
this.threshold = newHashtable.threshold;
}
public int size() {
return this.elementSize;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
Object key;
for (int i = 0, length = this.keyTable.length; i < length; i++) {
if ((key = this.keyTable[i]) != null) {
buffer.append(key).append(" -> "); //$NON-NLS-1$
int[] ints = this.valueTable[i];
buffer.append('[');
if (ints != null) {
for (int j = 0, max = ints.length; j < max; j++) {
if (j > 0) {
buffer.append(',');
}
buffer.append(ints[j]);
}
}
buffer.append("]\n"); //$NON-NLS-1$
}
}
return String.valueOf(buffer);
}
}

View File

@@ -0,0 +1,35 @@
package org.springframework.ide.vscode.commons.javadoc.internal;
public interface JavadocConstants {
String ANCHOR_PREFIX_END = "\""; //$NON-NLS-1$
char[] ANCHOR_PREFIX_START = "<A NAME=\"".toCharArray(); //$NON-NLS-1$
int ANCHOR_PREFIX_START_LENGHT = ANCHOR_PREFIX_START.length;
char[] ANCHOR_SUFFIX = "</A>".toCharArray(); //$NON-NLS-1$
int ANCHOR_SUFFIX_LENGTH = JavadocConstants.ANCHOR_SUFFIX.length;
char[] CONSTRUCTOR_DETAIL = "<!-- ========= CONSTRUCTOR DETAIL ======== -->".toCharArray(); //$NON-NLS-1$
char[] CONSTRUCTOR_SUMMARY = "<!-- ======== CONSTRUCTOR SUMMARY ======== -->".toCharArray(); //$NON-NLS-1$
char[] FIELD_DETAIL= "<!-- ============ FIELD DETAIL =========== -->".toCharArray(); //$NON-NLS-1$
char[] FIELD_SUMMARY = "<!-- =========== FIELD SUMMARY =========== -->".toCharArray(); //$NON-NLS-1$
char[] ENUM_CONSTANT_SUMMARY = "<!-- =========== ENUM CONSTANT SUMMARY =========== -->".toCharArray(); //$NON-NLS-1$
char[] ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = "<!-- =========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY =========== -->".toCharArray(); //$NON-NLS-1$
char[] ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY = "<!-- =========== ANNOTATION TYPE OPTIONAL MEMBER SUMMARY =========== -->".toCharArray(); //$NON-NLS-1$
char[] END_OF_CLASS_DATA = "<!-- ========= END OF CLASS DATA ========= -->".toCharArray(); //$NON-NLS-1$
String HTML_EXTENSION = ".html"; //$NON-NLS-1$
String INDEX_FILE_NAME = "index.html"; //$NON-NLS-1$
char[] METHOD_DETAIL = "<!-- ============ METHOD DETAIL ========== -->".toCharArray(); //$NON-NLS-1$
char[] METHOD_SUMMARY = "<!-- ========== METHOD SUMMARY =========== -->".toCharArray(); //$NON-NLS-1$
char[] NESTED_CLASS_SUMMARY = "<!-- ======== NESTED CLASS SUMMARY ======== -->".toCharArray(); //$NON-NLS-1$
String PACKAGE_FILE_NAME = "package-summary.html"; //$NON-NLS-1$
char[] PACKAGE_DESCRIPTION_START = "name=\"package_description\"".toCharArray(); //$NON-NLS-1$
char[] PACKAGE_DESCRIPTION_START2 = "name=\"package.description\"".toCharArray(); //$NON-NLS-1$
char[] H2_PREFIX = "<H2".toCharArray(); //$NON-NLS-1$
char[] H2_SUFFIX = "</H2>".toCharArray(); //$NON-NLS-1$
int H2_SUFFIX_LENGTH = H2_SUFFIX.length;
char[] BOTTOM_NAVBAR = "<!-- ======= START OF BOTTOM NAVBAR ====== -->".toCharArray(); //$NON-NLS-1$
char[] SEPARATOR_START = "<!-- =".toCharArray(); //$NON-NLS-1$
char[] START_OF_CLASS_DATA = "<!-- ======== START OF CLASS DATA ======== -->".toCharArray(); //$NON-NLS-1$
int START_OF_CLASS_DATA_LENGTH = JavadocConstants.START_OF_CLASS_DATA.length;
String P = "<P>"; //$NON-NLS-1$
String DIV_CLASS_BLOCK = "<DIV CLASS=\"BLOCK\">"; //$NON-NLS-1$
}

View File

@@ -0,0 +1,539 @@
package org.springframework.ide.vscode.commons.javadoc.internal;
import java.util.stream.Collectors;
import org.springframework.ide.vscode.commons.java.IField;
import org.springframework.ide.vscode.commons.java.IMethod;
import org.springframework.ide.vscode.commons.java.IType;
public class JavadocContents {
private static final int[] UNKNOWN_FORMAT = new int[0];
// private IType type;
private char[] content;
private int childrenStart;
private boolean hasComputedChildrenSections = false;
private int indexOfFieldDetails;
private int indexOfConstructorDetails;
private int indexOfMethodDetails;
private int indexOfEndOfClassData;
private int indexOfFieldsBottom;
private int indexOfAllMethodsTop;
private int indexOfAllMethodsBottom;
private int[] typeDocRange;
private HashtableOfObjectToIntArray fieldDocRanges;
private HashtableOfObjectToIntArray methodDocRanges;
private int[] fieldAnchorIndexes;
private int fieldAnchorIndexesCount;
private int fieldLastAnchorFoundIndex;
private int[] methodAnchorIndexes;
private int methodAnchorIndexesCount;
private int methodLastAnchorFoundIndex;
private int[] unknownFormatAnchorIndexes;
private int unknownFormatAnchorIndexesCount;
private int unknownFormatLastAnchorFoundIndex;
private int[] tempAnchorIndexes;
private int tempAnchorIndexesCount;
private int tempLastAnchorFoundIndex;
// public JavadocContents(IType type, String content) {
// this(content);
// this.type = type;
// }
public JavadocContents(String content) {
this.content = content != null ? content.toCharArray() : null;
}
/*
* Returns the part of the javadoc that describe the type
*/
public String getTypeDoc(IType type) throws Exception {
if (this.content == null) return null;
synchronized (this) {
if (this.typeDocRange == null) {
computeTypeRange(type);
}
}
if (this.typeDocRange != null) {
if (this.typeDocRange == UNKNOWN_FORMAT) throw new Exception("Unknown javadoc format " + type);
return String.valueOf(CharOperation.subarray(this.content, this.typeDocRange[0], this.typeDocRange[1]));
}
return null;
}
// public String getPackageDoc() throws JavaModelException {
// if (this.content == null) return null;
// int[] range = null;
// int index = CharOperation.indexOf(JavadocConstants.PACKAGE_DESCRIPTION_START2, this.content, false, 0);
// if (index == -1) {
// index = CharOperation.indexOf(JavadocConstants.PACKAGE_DESCRIPTION_START, this.content, false, 0);
// }
// if (index == -1) return null;
// index = CharOperation.indexOf(JavadocConstants.ANCHOR_SUFFIX, this.content, false, index);
// if (index == -1) return null;
//
// int start = CharOperation.indexOf(JavadocConstants.H2_PREFIX, this.content, false, index);
// if (start != -1) {
// start = CharOperation.indexOf(JavadocConstants.H2_SUFFIX, this.content, false, start);
// if (start != -1) index = start + JavadocConstants.H2_SUFFIX_LENGTH;
// }
// if (index != -1) {
// int end = CharOperation.indexOf(JavadocConstants.BOTTOM_NAVBAR, this.content, false, index);
// if (end == -1) end = this.content.length -1;
// range = new int[]{index, end};
// return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
// }
// return null;
// }
/*
* Returns the part of the javadoc that describe a field of the type
*/
public String getFieldDoc(IField child) throws Exception {
if (this.content == null) return null;
int[] range = null;
synchronized (this) {
if (this.fieldDocRanges == null) {
this.fieldDocRanges = new HashtableOfObjectToIntArray();
} else {
range = this.fieldDocRanges.get(child);
}
if (range == null) {
range = computeFieldRange(child);
this.fieldDocRanges.put(child, range);
}
}
if (range != null) {
if (range == UNKNOWN_FORMAT) throw new Exception("Unknown javadoc format " + child);
return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
}
return null;
}
/*
* Returns the part of the javadoc that describe a method of the type
*/
public String getMethodDoc(IMethod method) throws Exception {
if (this.content == null) return null;
int[] range = null;
synchronized (this) {
if (this.methodDocRanges == null) {
this.methodDocRanges = new HashtableOfObjectToIntArray();
} else {
range = this.methodDocRanges.get(method);
}
if (range == null) {
range = computeMethodRange(method);
this.methodDocRanges.put(method, range);
}
}
if (range != null) {
if (range == UNKNOWN_FORMAT) {
throw new Exception("Unknown javadoc format " + method);
}
return String.valueOf(CharOperation.subarray(this.content, range[0], range[1]));
}
return null;
}
/*
* Compute the ranges of the parts of the javadoc that describe each method of the type
*/
private int[] computeChildRange(char[] anchor, int indexOfSectionBottom) throws Exception {
// checks each known anchor locations
if (this.tempAnchorIndexesCount > 0) {
for (int i = 0; i < this.tempAnchorIndexesCount; i++) {
int anchorEndStart = this.tempAnchorIndexes[i];
if (anchorEndStart != -1 && CharOperation.prefixEquals(anchor, this.content, false, anchorEndStart)) {
this.tempAnchorIndexes[i] = -1;
return computeChildRange(anchorEndStart, anchor, indexOfSectionBottom);
}
}
}
int fromIndex = this.tempLastAnchorFoundIndex;
int index;
// check each next unknown anchor locations
while ((index = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START, this.content, false, fromIndex)) != -1 && (index < indexOfSectionBottom || indexOfSectionBottom == -1)) {
fromIndex = index + 1;
int anchorEndStart = index + JavadocConstants.ANCHOR_PREFIX_START_LENGHT;
this.tempLastAnchorFoundIndex = anchorEndStart;
if (CharOperation.prefixEquals(anchor, this.content, false, anchorEndStart)) {
return computeChildRange(anchorEndStart, anchor, indexOfSectionBottom);
} else {
if (this.tempAnchorIndexes.length == this.tempAnchorIndexesCount) {
System.arraycopy(this.tempAnchorIndexes, 0, this.tempAnchorIndexes = new int[this.tempAnchorIndexesCount + 20], 0, this.tempAnchorIndexesCount);
}
this.tempAnchorIndexes[this.tempAnchorIndexesCount++] = anchorEndStart;
}
}
return null;
}
private int[] computeChildRange(int anchorEndStart, char[] anchor, int indexOfBottom) {
int[] range = null;
// try to find the bottom of the section
if (indexOfBottom != -1) {
// try to find the end of the anchor
int indexOfEndLink = CharOperation.indexOf(JavadocConstants.ANCHOR_SUFFIX, this.content, false, anchorEndStart + anchor.length);
if (indexOfEndLink != -1) {
// try to find the next anchor
int indexOfNextElement = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START, this.content, false, indexOfEndLink);
int javadocStart = indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH;
int javadocEnd = indexOfNextElement == -1 ? indexOfBottom : Math.min(indexOfNextElement, indexOfBottom);
range = new int[]{javadocStart, javadocEnd};
} else {
// the anchor has no suffix
range = UNKNOWN_FORMAT;
}
} else {
// the detail section has no bottom
range = UNKNOWN_FORMAT;
}
return range;
}
private void computeChildrenSections() {
// try to find the next separator part
int lastIndex = CharOperation.indexOf(JavadocConstants.SEPARATOR_START, this.content, false, this.childrenStart);
lastIndex = lastIndex == -1 ? this.childrenStart : lastIndex;
// try to find field detail start
this.indexOfFieldDetails = CharOperation.indexOf(JavadocConstants.FIELD_DETAIL, this.content, false, lastIndex);
lastIndex = this.indexOfFieldDetails == -1 ? lastIndex : this.indexOfFieldDetails;
// try to find constructor detail start
this.indexOfConstructorDetails = CharOperation.indexOf(JavadocConstants.CONSTRUCTOR_DETAIL, this.content, false, lastIndex);
lastIndex = this.indexOfConstructorDetails == -1 ? lastIndex : this.indexOfConstructorDetails;
// try to find method detail start
this.indexOfMethodDetails = CharOperation.indexOf(JavadocConstants.METHOD_DETAIL, this.content, false, lastIndex);
lastIndex = this.indexOfMethodDetails == -1 ? lastIndex : this.indexOfMethodDetails;
// we take the end of class data
this.indexOfEndOfClassData = CharOperation.indexOf(JavadocConstants.END_OF_CLASS_DATA, this.content, false, lastIndex);
// try to find the field detail end
this.indexOfFieldsBottom =
this.indexOfConstructorDetails != -1 ? this.indexOfConstructorDetails :
this.indexOfMethodDetails != -1 ? this.indexOfMethodDetails:
this.indexOfEndOfClassData;
this.indexOfAllMethodsTop =
this.indexOfConstructorDetails != -1 ?
this.indexOfConstructorDetails :
this.indexOfMethodDetails;
this.indexOfAllMethodsBottom = this.indexOfEndOfClassData;
this.hasComputedChildrenSections = true;
}
/*
* Compute the ranges of the parts of the javadoc that describe each child of the type (fields, methods)
*/
private int[] computeFieldRange(IField field) throws Exception {
IType type = field.getDeclaringType();
if (!this.hasComputedChildrenSections) {
computeChildrenSections();
}
StringBuffer buffer = new StringBuffer(field.getElementName());
buffer.append(JavadocConstants.ANCHOR_PREFIX_END);
char[] anchor = String.valueOf(buffer).toCharArray();
int[] range = null;
if (this.indexOfFieldDetails == -1 || this.indexOfFieldsBottom == -1) {
// the detail section has no top or bottom, so the doc has an unknown format
if (this.unknownFormatAnchorIndexes == null) {
this.unknownFormatAnchorIndexes = new int[(int)type.getFields().count()];
this.unknownFormatAnchorIndexesCount = 0;
this.unknownFormatLastAnchorFoundIndex = this.childrenStart;
}
this.tempAnchorIndexes = this.unknownFormatAnchorIndexes;
this.tempAnchorIndexesCount = this.unknownFormatAnchorIndexesCount;
this.tempLastAnchorFoundIndex = this.unknownFormatLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfFieldsBottom);
this.unknownFormatLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.unknownFormatAnchorIndexesCount = this.tempAnchorIndexesCount;
this.unknownFormatAnchorIndexes = this.tempAnchorIndexes;
} else {
if (this.fieldAnchorIndexes == null) {
this.fieldAnchorIndexes = new int[(int)type.getFields().count()];
this.fieldAnchorIndexesCount = 0;
this.fieldLastAnchorFoundIndex = this.indexOfFieldDetails;
}
this.tempAnchorIndexes = this.fieldAnchorIndexes;
this.tempAnchorIndexesCount = this.fieldAnchorIndexesCount;
this.tempLastAnchorFoundIndex = this.fieldLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfFieldsBottom);
this.fieldLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.fieldAnchorIndexesCount = this.tempAnchorIndexesCount;
this.fieldAnchorIndexes = this.tempAnchorIndexes;
}
return range;
}
/*
* Compute the ranges of the parts of the javadoc that describe each method of the type
*/
private int[] computeMethodRange(IMethod method) throws Exception {
IType type = method.getDeclaringType();
if (!this.hasComputedChildrenSections) {
computeChildrenSections();
}
char[] anchor = computeMethodAnchorPrefixEnd(method).toCharArray();
int[] range = null;
if (this.indexOfAllMethodsTop == -1 || this.indexOfAllMethodsBottom == -1) {
// the detail section has no top or bottom, so the doc has an unknown format
if (this.unknownFormatAnchorIndexes == null) {
int childernCount = (int)(type.getMethods().count() + type.getFields().count());
this.unknownFormatAnchorIndexes = new int[childernCount];
this.unknownFormatAnchorIndexesCount = 0;
this.unknownFormatLastAnchorFoundIndex = this.childrenStart;
}
this.tempAnchorIndexes = this.unknownFormatAnchorIndexes;
this.tempAnchorIndexesCount = this.unknownFormatAnchorIndexesCount;
this.tempLastAnchorFoundIndex = this.unknownFormatLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfFieldsBottom);
if (range == null) {
range = computeChildRange(getJavadoc8Anchor(anchor), this.indexOfAllMethodsBottom);
}
this.unknownFormatLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.unknownFormatAnchorIndexesCount = this.tempAnchorIndexesCount;
this.unknownFormatAnchorIndexes = this.tempAnchorIndexes;
} else {
if (this.methodAnchorIndexes == null) {
this.methodAnchorIndexes = new int[(int)type.getMethods().count()];
this.methodAnchorIndexesCount = 0;
this.methodLastAnchorFoundIndex = this.indexOfAllMethodsTop;
}
this.tempAnchorIndexes = this.methodAnchorIndexes;
this.tempAnchorIndexesCount = this.methodAnchorIndexesCount;
this.tempLastAnchorFoundIndex = this.methodLastAnchorFoundIndex;
range = computeChildRange(anchor, this.indexOfAllMethodsBottom);
if (range == null) {
range = computeChildRange(getJavadoc8Anchor(anchor), this.indexOfAllMethodsBottom);
}
this.methodLastAnchorFoundIndex = this.tempLastAnchorFoundIndex;
this.methodAnchorIndexesCount = this.tempAnchorIndexesCount;
this.methodAnchorIndexes = this.tempAnchorIndexes;
}
return range;
}
private static char[] getJavadoc8Anchor(char[] anchor) {
// fix for bug 432284: [1.8] Javadoc-8-style anchors not found by IMethod#getAttachedJavadoc(..)
char[] anchor8 = new char[anchor.length];
int i8 = 0;
for (int i = 0; i < anchor.length; i++) {
char ch = anchor[i];
switch (ch) {
case '(':
case ')':
case ',':
anchor8[i8++] = '-';
break;
case '[':
anchor8[i8++] = ':';
anchor8[i8++] = 'A';
break;
case ' ': // handled by preceding ','
case ']': // handled by preceding '['
break;
default:
anchor8[i8++] = ch;
}
}
if (i8 != anchor.length) {
anchor8 = CharOperation.subarray(anchor8, 0, i8);
}
return anchor8;
}
private String computeMethodAnchorPrefixEnd(IMethod method) throws Exception {
// String typeQualifiedName = null;
// if (this.type.isMember()) {
// IType currentType = this.type;
// StringBuffer buffer = new StringBuffer();
// while (currentType != null) {
// buffer.insert(0, currentType.getElementName());
// currentType = currentType.getDeclaringType();
// if (currentType != null) {
// buffer.insert(0, '.');
// }
// }
// typeQualifiedName = new String(buffer.toString());
// } else {
// typeQualifiedName = this.type.getElementName();
// }
// String methodName = method.getElementName();
// if (method.getElementName().equals(method.getDeclaringType().getElementName())) {
// methodName = typeQualifiedName;
// }
String anchor = createMethodAnchor(method);
// char[] genericSignature = info.getGenericSignature();
// if (genericSignature != null) {
// genericSignature = CharOperation.replaceOnCopy(genericSignature, '/', '.');
// anchor = Util.toAnchor(0, genericSignature, methodName, Flags.isVarargs(method.getFlags()));
// if (anchor == null) throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.UNKNOWN_JAVADOC_FORMAT, method));
// } else {
// anchor = Signature.toString(method.getSignature().replace('/', '.'), methodName, null, true, false, Flags.isVarargs(method.getFlags()));
// }
// IType declaringType = /*this.type*/method.getDeclaringType();
// if (declaringType.isMember()) {
// // might need to remove a part of the signature corresponding to the synthetic argument (only for constructor)
// if (method.getElementName().equals(method.getDeclaringType().getElementName()) && !Flags.isStatic(declaringType.getFlags())) {
// int indexOfOpeningParen = anchor.indexOf('(');
// if (indexOfOpeningParen == -1) {
// // should not happen as this is a method signature
// return null;
// }
// int index = indexOfOpeningParen;
// indexOfOpeningParen++;
// int indexOfComma = anchor.indexOf(',', index);
// if (indexOfComma != -1) {
// index = indexOfComma + 2;
// } else {
// // no argument, but a synthetic argument
// index = anchor.indexOf(')', index);
// }
// anchor = anchor.substring(0, indexOfOpeningParen) + anchor.substring(index);
// }
// }
return anchor + JavadocConstants.ANCHOR_PREFIX_END;
}
private String createMethodAnchor(IMethod method) {
StringBuilder sb = new StringBuilder(method.getElementName());
sb.append('(');
sb.append(String.join(",", method.parameters().map(p -> p.toString()).collect(Collectors.toList())));
sb.append(')');
return sb.toString();
}
/*
* Compute the range of the part of the javadoc that describe the type
*/
private void computeTypeRange(IType type) throws Exception {
final int indexOfStartOfClassData = CharOperation.indexOf(JavadocConstants.START_OF_CLASS_DATA, this.content, false);
if (indexOfStartOfClassData == -1) {
this.typeDocRange = UNKNOWN_FORMAT;
return;
}
int indexOfNextSeparator = CharOperation.indexOf(JavadocConstants.SEPARATOR_START, this.content, false, indexOfStartOfClassData);
if (indexOfNextSeparator == -1) {
this.typeDocRange = UNKNOWN_FORMAT;
return;
}
int indexOfNextSummary = CharOperation.indexOf(JavadocConstants.NESTED_CLASS_SUMMARY, this.content, false, indexOfNextSeparator);
if (indexOfNextSummary == -1 && type.isEnum()) {
// try to find enum constant summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ENUM_CONSTANT_SUMMARY, this.content, false, indexOfNextSeparator);
}
if (indexOfNextSummary == -1 && type.isAnnotation()) {
// try to find required enum constant summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY, this.content, false, indexOfNextSeparator);
if (indexOfNextSummary == -1) {
// try to find optional enum constant summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.ANNOTATION_TYPE_OPTIONAL_MEMBER_SUMMARY, this.content, false, indexOfNextSeparator);
}
}
if (indexOfNextSummary == -1) {
// try to find field summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.FIELD_SUMMARY, this.content, false, indexOfNextSeparator);
}
if (indexOfNextSummary == -1) {
// try to find constructor summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.CONSTRUCTOR_SUMMARY, this.content, false, indexOfNextSeparator);
}
if (indexOfNextSummary == -1) {
// try to find method summary start
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.METHOD_SUMMARY, this.content, false, indexOfNextSeparator);
}
if (indexOfNextSummary == -1) {
// we take the end of class data
indexOfNextSummary = CharOperation.indexOf(JavadocConstants.END_OF_CLASS_DATA, this.content, false, indexOfNextSeparator);
} else {
// improve performance of computation of children ranges
this.childrenStart = indexOfNextSummary + 1;
}
if (indexOfNextSummary == -1) {
this.typeDocRange = UNKNOWN_FORMAT;
return;
}
/*
* Cut off the type hierarchy, see bug 119844.
* We remove the contents between the start of class data and where
* we guess the actual class comment starts.
*/
int start = indexOfStartOfClassData + JavadocConstants.START_OF_CLASS_DATA_LENGTH;
int indexOfFirstParagraph = CharOperation.indexOf(JavadocConstants.P.toCharArray(), this.content, false, start, indexOfNextSummary);
int indexOfFirstDiv = CharOperation.indexOf(JavadocConstants.DIV_CLASS_BLOCK.toCharArray(), this.content, false, start, indexOfNextSummary);
int afterHierarchy = indexOfNextSummary;
if (indexOfFirstParagraph != -1 && indexOfFirstParagraph < afterHierarchy) {
afterHierarchy = indexOfFirstParagraph;
}
if (indexOfFirstDiv != -1 && indexOfFirstDiv < afterHierarchy) {
afterHierarchy = indexOfFirstDiv;
}
if (afterHierarchy != indexOfNextSummary) {
start = afterHierarchy;
}
this.typeDocRange = new int[]{start, indexOfNextSummary};
}
}

View File

@@ -0,0 +1,569 @@
package org.springframework.ide.vscode.commons.javadoc.internal;
public class ScannerHelper {
// storage for internal flags (32 bits) BIT USAGE
public final static int Bit1 = 0x1; // return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
public final static int Bit2 = 0x2; // return type (operator) | name reference kind (name ref) | has local type (type, method, field decl) | if type elided (local)
public final static int Bit3 = 0x4; // return type (operator) | name reference kind (name ref) | implicit this (this ref) | is argument(local)
public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement) | can be static
public final static int Bit10= 0x200; // depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
public final static int Bit11 = 0x400; // depth (name ref, msg) | operator (operator) | is member type (type decl)
public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
public final static int Bit13 = 0x1000; // depth (name ref, msg) | is secondary type (type decl)
public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
public final static int Bit15 = 0x4000; // is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement)
public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg)
public final static int Bit17 = 0x10000; // compound assigned (reference lhs) | unchecked (msg, alloc, explicit constr call)
public final static int Bit18 = 0x20000; // non null (expression) | onDemand (import reference)
public final static int Bit19 = 0x40000; // didResolve (parameterized qualified type ref/parameterized single type ref) | empty (javadoc return statement) | needReceiverGenericCast (msg/fieldref)
public final static int Bit20 = 0x80000; // contains syntax errors (method declaration, type declaration, field declarations, initializer), typeref: <> name ref: lambda capture)
public final static int Bit21 = 0x100000;
public final static int Bit22 = 0x200000; // parenthesis count (expression) | used (import reference) shadows outer local (local declarations)
public final static int Bit23 = 0x400000; // parenthesis count (expression)
public final static int Bit24 = 0x800000; // parenthesis count (expression)
public final static int Bit25 = 0x1000000; // parenthesis count (expression)
public final static int Bit26 = 0x2000000; // parenthesis count (expression)
public final static int Bit27 = 0x4000000; // parenthesis count (expression)
public final static int Bit28 = 0x8000000; // parenthesis count (expression)
public final static int Bit29 = 0x10000000; // parenthesis count (expression)
public final static int Bit30 = 0x20000000; // elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement)
public final static int Bit31 = 0x40000000; // local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement)
public final static int Bit32 = 0x80000000; // reachable (statement)
// public final static long[] Bits = {
// ASTNode.Bit1, ASTNode.Bit2, ASTNode.Bit3, ASTNode.Bit4, ASTNode.Bit5, ASTNode.Bit6,
// ASTNode.Bit7, ASTNode.Bit8, ASTNode.Bit9, ASTNode.Bit10, ASTNode.Bit11, ASTNode.Bit12,
// ASTNode.Bit13, ASTNode.Bit14, ASTNode.Bit15, ASTNode.Bit16, ASTNode.Bit17, ASTNode.Bit18,
// ASTNode.Bit19, ASTNode.Bit20, ASTNode.Bit21, ASTNode.Bit22, ASTNode.Bit23, ASTNode.Bit24,
// ASTNode.Bit25, ASTNode.Bit26, ASTNode.Bit27, ASTNode.Bit28, ASTNode.Bit29, ASTNode.Bit30,
// ASTNode.Bit31, ASTNode.Bit32L, ASTNode.Bit33L, ASTNode.Bit34L, ASTNode.Bit35L, ASTNode.Bit36L,
// ASTNode.Bit37L, ASTNode.Bit38L, ASTNode.Bit39L, ASTNode.Bit40L, ASTNode.Bit41L, ASTNode.Bit42L,
// ASTNode.Bit43L, ASTNode.Bit44L, ASTNode.Bit45L, ASTNode.Bit46L, ASTNode.Bit47L, ASTNode.Bit48L,
// ASTNode.Bit49L, ASTNode.Bit50L, ASTNode.Bit51L, ASTNode.Bit52L, ASTNode.Bit53L, ASTNode.Bit54L,
// ASTNode.Bit55L, ASTNode.Bit56L, ASTNode.Bit57L, ASTNode.Bit58L, ASTNode.Bit59L, ASTNode.Bit60L,
// ASTNode.Bit61L, ASTNode.Bit62L, ASTNode.Bit63L, ASTNode.Bit64L,
// };
//
// private static final int START_INDEX = 0;
// private static final int PART_INDEX = 1;
//
// private static long[][][] Tables;
// private static long[][][] Tables7;
// private static long[][][] Tables8;
public final static int MAX_OBVIOUS = 128;
public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];
public final static int C_JLS_SPACE = Bit9;
public final static int C_SPECIAL = Bit8;
public final static int C_IDENT_START = Bit7;
public final static int C_UPPER_LETTER = Bit6;
public final static int C_LOWER_LETTER = Bit5;
public final static int C_IDENT_PART = Bit4;
public final static int C_DIGIT = Bit3;
public final static int C_SEPARATOR = Bit2;
public final static int C_SPACE = Bit1;
static {
OBVIOUS_IDENT_CHAR_NATURES[0] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[1] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[2] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[3] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[4] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[5] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[6] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[7] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[8] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[14] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[15] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[16] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[17] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[18] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[19] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[20] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[21] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[22] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[23] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[24] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[25] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[26] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[27] = C_IDENT_PART;
OBVIOUS_IDENT_CHAR_NATURES[127] = C_IDENT_PART;
for (int i = '0'; i <= '9'; i++)
OBVIOUS_IDENT_CHAR_NATURES[i] = C_DIGIT | C_IDENT_PART;
for (int i = 'a'; i <= 'z'; i++)
OBVIOUS_IDENT_CHAR_NATURES[i] = C_LOWER_LETTER | C_IDENT_PART | C_IDENT_START;
for (int i = 'A'; i <= 'Z'; i++)
OBVIOUS_IDENT_CHAR_NATURES[i] = C_UPPER_LETTER | C_IDENT_PART | C_IDENT_START;
OBVIOUS_IDENT_CHAR_NATURES['_'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;
OBVIOUS_IDENT_CHAR_NATURES['$'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;
OBVIOUS_IDENT_CHAR_NATURES[9] = C_SPACE | C_JLS_SPACE; // \ u0009: HORIZONTAL TABULATION
OBVIOUS_IDENT_CHAR_NATURES[10] = C_SPACE | C_JLS_SPACE; // \ u000a: LINE FEED
OBVIOUS_IDENT_CHAR_NATURES[11] = C_SPACE;
OBVIOUS_IDENT_CHAR_NATURES[12] = C_SPACE | C_JLS_SPACE; // \ u000c: FORM FEED
OBVIOUS_IDENT_CHAR_NATURES[13] = C_SPACE | C_JLS_SPACE; // \ u000d: CARRIAGE RETURN
OBVIOUS_IDENT_CHAR_NATURES[28] = C_SPACE;
OBVIOUS_IDENT_CHAR_NATURES[29] = C_SPACE;
OBVIOUS_IDENT_CHAR_NATURES[30] = C_SPACE;
OBVIOUS_IDENT_CHAR_NATURES[31] = C_SPACE;
OBVIOUS_IDENT_CHAR_NATURES[32] = C_SPACE | C_JLS_SPACE; // \ u0020: SPACE
OBVIOUS_IDENT_CHAR_NATURES['.'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES[':'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES[';'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES[','] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['['] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES[']'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['('] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES[')'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['{'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['}'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['+'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['-'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['*'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['/'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['='] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['&'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['|'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['?'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['<'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['>'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['!'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['%'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['^'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['~'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['"'] = C_SEPARATOR;
OBVIOUS_IDENT_CHAR_NATURES['\''] = C_SEPARATOR;
}
//static void initializeTable() {
// Tables = initializeTables("unicode"); //$NON-NLS-1$
//}
//static void initializeTable17() {
// Tables7 = initializeTables("unicode6"); //$NON-NLS-1$
//}
//static void initializeTable18() {
// Tables8 = initializeTables("unicode6_2"); //$NON-NLS-1$
//}
//static long[][][] initializeTables(String unicode_path) {
// long[][][] tempTable = new long[2][][];
// tempTable[START_INDEX] = new long[3][];
// tempTable[PART_INDEX] = new long[4][];
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start0.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[START_INDEX][0] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start1.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[START_INDEX][1] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start2.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[START_INDEX][2] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part0.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[PART_INDEX][0] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part1.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[PART_INDEX][1] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part2.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[PART_INDEX][2] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// try {
// DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part14.rsc"))); //$NON-NLS-1$
// long[] readValues = new long[1024];
// for (int i = 0; i < 1024; i++) {
// readValues[i] = inputStream.readLong();
// }
// inputStream.close();
// tempTable[PART_INDEX][3] = readValues;
// } catch (FileNotFoundException e) {
// e.printStackTrace();
// } catch (IOException e) {
// e.printStackTrace();
// }
// return tempTable;
//}
//private final static boolean isBitSet(long[] values, int i) {
// try {
// return (values[i / 64] & Bits[i % 64]) != 0;
// } catch (NullPointerException e) {
// return false;
// }
//}
//public static boolean isJavaIdentifierPart(char c) {
// if (c < MAX_OBVIOUS) {
// return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
// }
// return Character.isJavaIdentifierPart(c);
//}
///**
// * @param complianceLevel
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, char c) {
// if (c < MAX_OBVIOUS) {
// return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
// }
// return isJavaIdentifierPart(complianceLevel, (int) c);
//}
///**
// * @param complianceLevel
// * @param codePoint
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) {
// if (complianceLevel <= ClassFileConstants.JDK1_6) {
// if (Tables == null) {
// initializeTable();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables[PART_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables[PART_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables[PART_INDEX][2], codePoint & 0xFFFF);
// case 14 :
// return isBitSet(Tables[PART_INDEX][3], codePoint & 0xFFFF);
// }
// } else if (complianceLevel <= ClassFileConstants.JDK1_7) {
// // java 7 supports Unicode 6
// if (Tables7 == null) {
// initializeTable17();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables7[PART_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables7[PART_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables7[PART_INDEX][2], codePoint & 0xFFFF);
// case 14 :
// return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF);
// }
// } else {
// // java 7 supports Unicode 6.2
// if (Tables8 == null) {
// initializeTable18();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables8[PART_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables8[PART_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables8[PART_INDEX][2], codePoint & 0xFFFF);
// case 14 :
// return isBitSet(Tables8[PART_INDEX][3], codePoint & 0xFFFF);
// }
// }
// return false;
//}
///**
// * @param complianceLevel
// * @param high
// * @param low
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, char high, char low) {
// return isJavaIdentifierPart(complianceLevel, toCodePoint(high, low));
//}
///**
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierStart(char c) {
// if (c < MAX_OBVIOUS) {
// return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
// }
// return Character.isJavaIdentifierStart(c);
//}
///**
// * @param complianceLevel
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, char c) {
// if (c < MAX_OBVIOUS) {
// return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
// }
// return ScannerHelper.isJavaIdentifierStart(complianceLevel, (int) c);
//}
///**
// * @param complianceLevel
// * @param high
// * @param low
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, char high, char low) {
// return isJavaIdentifierStart(complianceLevel, toCodePoint(high, low));
//}
///**
// * @param complianceLevel
// * @param codePoint
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) {
// if (complianceLevel <= ClassFileConstants.JDK1_6) {
// if (Tables == null) {
// initializeTable();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables[START_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables[START_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables[START_INDEX][2], codePoint & 0xFFFF);
// }
// } else if (complianceLevel <= ClassFileConstants.JDK1_7) {
// // java 7 supports Unicode 6
// if (Tables7 == null) {
// initializeTable17();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables7[START_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables7[START_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF);
// }
// } else {
// // java 7 supports Unicode 6
// if (Tables8 == null) {
// initializeTable18();
// }
// switch((codePoint & 0x1F0000) >> 16) {
// case 0 :
// return isBitSet(Tables8[START_INDEX][0], codePoint & 0xFFFF);
// case 1 :
// return isBitSet(Tables8[START_INDEX][1], codePoint & 0xFFFF);
// case 2 :
// return isBitSet(Tables8[START_INDEX][2], codePoint & 0xFFFF);
// }
// }
// return false;
//}
//private static int toCodePoint(char high, char low) {
// return (high - Scanner.HIGH_SURROGATE_MIN_VALUE) * 0x400 + (low - Scanner.LOW_SURROGATE_MIN_VALUE) + 0x10000;
//}
//public static boolean isDigit(char c) throws InvalidInputException {
// if(c < ScannerHelper.MAX_OBVIOUS) {
// return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0;
// }
// if (Character.isDigit(c)) {
// throw new InvalidStateException(Scanner.INVALID_DIGIT);
// }
// return false;
//}
public static int digit(char c, int radix) {
if (c < ScannerHelper.MAX_OBVIOUS) {
switch(radix) {
case 8 :
if (c >= 48 && c <= 55) {
return c - 48;
}
return -1;
case 10 :
if (c >= 48 && c <= 57) {
return c - 48;
}
return -1;
case 16 :
if (c >= 48 && c <= 57) {
return c - 48;
}
if (c >= 65 && c <= 70) {
return c - 65 + 10;
}
if (c >= 97 && c <= 102) {
return c - 97 + 10;
}
return -1;
}
}
return Character.digit(c, radix);
}
public static int getNumericValue(char c) {
if (c < ScannerHelper.MAX_OBVIOUS) {
switch(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c]) {
case C_DIGIT :
return c - '0';
case C_LOWER_LETTER :
return 10 + c - 'a';
case C_UPPER_LETTER :
return 10 + c - 'A';
}
}
return Character.getNumericValue(c);
}
public static int getHexadecimalValue(char c) {
switch(c) {
case '0' :
return 0;
case '1' :
return 1;
case '2' :
return 2;
case '3' :
return 3;
case '4' :
return 4;
case '5' :
return 5;
case '6' :
return 6;
case '7' :
return 7;
case '8' :
return 8;
case '9' :
return 9;
case 'A' :
case 'a' :
return 10;
case 'B' :
case 'b' :
return 11;
case 'C' :
case 'c' :
return 12;
case 'D' :
case 'd' :
return 13;
case 'E' :
case 'e' :
return 14;
case 'F' :
case 'f' :
return 15;
default:
return -1;
}
}
public static char toUpperCase(char c) {
if (c < MAX_OBVIOUS) {
if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
return c;
} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
return (char) (c - 32);
}
}
return Character.toUpperCase(c);
}
public static char toLowerCase(char c) {
if (c < MAX_OBVIOUS) {
if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
return c;
} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
return (char) (32 + c);
}
}
return Character.toLowerCase(c);
}
public static boolean isLowerCase(char c) {
if (c < MAX_OBVIOUS) {
return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0;
}
return Character.isLowerCase(c);
}
public static boolean isUpperCase(char c) {
if (c < MAX_OBVIOUS) {
return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0;
}
return Character.isUpperCase(c);
}
/**
* Include also non JLS whitespaces.
*
* return true if Character.isWhitespace(c) would return true
*/
public static boolean isWhitespace(char c) {
if (c < MAX_OBVIOUS) {
return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_SPACE) != 0;
}
return Character.isWhitespace(c);
}
public static boolean isLetter(char c) {
if (c < MAX_OBVIOUS) {
return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER)) != 0;
}
return Character.isLetter(c);
}
public static boolean isLetterOrDigit(char c) {
if (c < MAX_OBVIOUS) {
return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_DIGIT)) != 0;
}
return Character.isLetterOrDigit(c);
}
}

View File

@@ -15,6 +15,8 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -49,6 +51,8 @@ import org.eclipse.aether.util.graph.transformer.SimpleOptionalitySelector;
import org.eclipse.aether.util.graph.visitor.CloningDependencyVisitor;
import org.eclipse.aether.util.graph.visitor.FilteringDependencyVisitor;
import org.springframework.ide.vscode.commons.jandex.JandexIndex;
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
import org.springframework.ide.vscode.commons.util.ExternalCommand;
import org.springframework.ide.vscode.commons.util.ExternalProcess;
import org.springframework.ide.vscode.commons.util.Log;
@@ -82,7 +86,22 @@ public class MavenCore {
private Supplier<JandexIndex> javaCoreIndex = Suppliers.memoize(() -> {
try {
return new JandexIndex(getJreLibs(), jarFile -> findIndexFile(jarFile), null);
return new JandexIndex(getJreLibs(), jarFile -> findIndexFile(jarFile), (classpathResource) -> {
try {
String javaVersion = "8";
try {
String fullVersion = getJavaRuntimeVersion();
javaVersion = fullVersion.substring(fullVersion.indexOf('.') + 1, fullVersion.lastIndexOf('.'));
} catch (MavenException e) {
Log.log("Cannot determine Java runtime version. Defaulting to version 8", e);
}
URL javadocUrl = new URL("http://docs.oracle.com/javase/" + javaVersion + "/docs/api/");
return new HtmlJavadocProvider((type) -> SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER.sourceUrl(javadocUrl, type));
} catch (MalformedURLException e) {
Log.log(e);
return null;
}
});
} catch (MavenException e) {
return null;
}
@@ -115,17 +134,34 @@ public class MavenCore {
* @param Path of the project
* @throws Exception
*/
public static void buildMavenProject(Path testProjectPath) throws Exception {
public static void buildMavenProject(Path projectPath) throws Exception {
Path mvnwPath = System.getProperty("os.name").toLowerCase().startsWith("win")
? testProjectPath.resolve("mvnw.cmd") : testProjectPath.resolve("mvnw");
? projectPath.resolve("mvnw.cmd") : projectPath.resolve("mvnw");
mvnwPath.toFile().setExecutable(true);
ExternalProcess process = new ExternalProcess(testProjectPath.toFile(),
ExternalProcess process = new ExternalProcess(projectPath.toFile(),
new ExternalCommand(mvnwPath.toAbsolutePath().toString(), "clean", "package", "-DskipTests"), true);
if (process.getExitValue() != 0) {
throw new RuntimeException("Failed to build test project");
}
}
/**
* Generate javadoc jar for maven project
*
* @param Path of the project
* @throws Exception
*/
public static void generateJavadocFolderForMavenProject(Path projectPath) throws Exception {
Path mvnwPath = System.getProperty("os.name").toLowerCase().startsWith("win")
? projectPath.resolve("mvnw.cmd") : projectPath.resolve("mvnw");
mvnwPath.toFile().setExecutable(true);
ExternalProcess process = new ExternalProcess(projectPath.toFile(),
new ExternalCommand(mvnwPath.toAbsolutePath().toString(), "javadoc:javadoc"), true);
if (process.getExitValue() != 0) {
throw new RuntimeException("Failed to build test project");
}
}
/**
* Creates Maven Project descriptor based on the pom file.
*

View File

@@ -27,6 +27,7 @@ import org.springframework.ide.vscode.commons.java.IJavadocProvider;
import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.java.parser.ParserJavadocProvider;
import org.springframework.ide.vscode.commons.java.roaster.RoasterJavadocProvider;
import org.springframework.ide.vscode.commons.javadoc.HtmlJavadocProvider;
import org.springframework.ide.vscode.commons.javadoc.SourceUrlProviderFromSourceContainer;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenException;
@@ -43,8 +44,14 @@ import com.google.common.base.Suppliers;
*/
public class MavenProjectClasspath implements IClasspath {
public static boolean USE_JAVA_PARSER = false;
public static JavadocProviderTypes providerType = JavadocProviderTypes.JAVA_PARSER;
public enum JavadocProviderTypes {
JAVA_PARSER,
ROASTER,
HTML
}
private MavenCore maven;
private MavenProject project;
private Supplier<JandexIndex> javaIndex;
@@ -64,7 +71,14 @@ public class MavenProjectClasspath implements IClasspath {
Log.log(e);
}
return new JandexIndex(classpathEntries, jarFile -> findIndexFile(jarFile), classpathResource -> {
return USE_JAVA_PARSER ? createParserJavadocProvider(classpathResource) : createRoasterJavadocProvider(classpathResource);
switch (providerType) {
case JAVA_PARSER:
return createParserJavadocProvider(classpathResource);
case ROASTER:
return createRoasterJavadocProvider(classpathResource);
default:
return createHtmlJavdocProvider(classpathResource);
}
}, maven.getJavaIndexForJreLibs());
});
}
@@ -105,7 +119,7 @@ public class MavenProjectClasspath implements IClasspath {
return Arrays.stream(scanner.getIncludedFiles());
});
}
private IJavadocProvider createRoasterJavadocProvider(File classpathResource) {
if (classpathResource.isDirectory()) {
if (classpathResource.toString().startsWith(project.getBuild().getOutputDirectory())) {
@@ -174,4 +188,38 @@ public class MavenProjectClasspath implements IClasspath {
}
}
private IJavadocProvider createHtmlJavdocProvider(File classpathResource) {
if (classpathResource.isDirectory()) {
if (classpathResource.toString().startsWith(project.getBuild().getOutputDirectory())) {
return new HtmlJavadocProvider(type -> {
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
.sourceUrl(new File(project.getModel().getReporting().getOutputDirectory(), "apidocs").toURI().toURL(), type);
});
} else if (classpathResource.toString().startsWith(project.getBuild().getTestOutputDirectory())) {
return new ParserJavadocProvider(type -> {
return SourceUrlProviderFromSourceContainer.JAVADOC_FOLDER_URL_SUPPLIER
.sourceUrl(new File(project.getModel().getReporting().getOutputDirectory(), "apidocs").toURI().toURL(), type);
});
} else {
throw new IllegalArgumentException("Cannot find source folder for " + classpathResource);
}
} else {
// Assume it's a JAR file
return new HtmlJavadocProvider(type -> {
try {
Artifact artifact = getArtifactFromJarFile(classpathResource).get();
URL sourceContainer = maven.getJavadoc(artifact).getFile().toURI().toURL();
return SourceUrlProviderFromSourceContainer.JAR_JAVADOC_URL_PROVIDER.sourceUrl(sourceContainer,
type);
} catch (MavenException e) {
Log.log("Failed to find sources JAR for " + classpathResource, e);
} catch (MalformedURLException e) {
Log.log("Invalid URL for sources JAR for " + classpathResource, e);
}
return null;
});
}
}
}

View File

@@ -3,6 +3,7 @@ package org.springframework.ide.vscode.commons.maven;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -18,6 +19,7 @@ import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.java.IVoidType;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectClasspath;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectClasspath.JavadocProviderTypes;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -89,7 +91,7 @@ public class JavaIndexTest {
IType type = project.findType("java.util.ArrayList");
assertNotNull(type);
IMethod m = type.getMethod("<init>", Stream.empty());
assertEquals("<init>", m.getElementName());
assertEquals(type.getElementName(), m.getElementName());
assertEquals(IVoidType.DEFAULT, m.getReturnType());
assertEquals(0, m.parameters().count());
}
@@ -100,14 +102,14 @@ public class JavaIndexTest {
IType type = project.findType("java.util.ArrayList");
assertNotNull(type);
IMethod m = type.getMethod("<init>", Stream.of(IPrimitiveType.INT));
assertEquals("<init>", m.getElementName());
assertEquals(m.getDeclaringType().getElementName(), m.getElementName());
assertEquals(IVoidType.DEFAULT, m.getReturnType());
assertEquals(Collections.singletonList(IPrimitiveType.INT), m.parameters().collect(Collectors.toList()));
}
@Test
public void parser_testClassJavadocForOutputFolder() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = true;
MavenProjectClasspath.providerType = JavadocProviderTypes.JAVA_PARSER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("hello.Greeting");
@@ -140,7 +142,7 @@ public class JavaIndexTest {
@Test
public void parser_testInnerClassJavadocForOutputFolder() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = true;
MavenProjectClasspath.providerType = JavadocProviderTypes.JAVA_PARSER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("hello.Greeting$TestInnerClass");
assertNotNull(type);
@@ -157,7 +159,7 @@ public class JavaIndexTest {
@Test
public void parser_testClassJavadocForJar() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = true;
MavenProjectClasspath.providerType = JavadocProviderTypes.JAVA_PARSER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener");
@@ -180,7 +182,7 @@ public class JavaIndexTest {
@Test
public void parser_testFieldAndMethodJavadocForJar() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = true;
MavenProjectClasspath.providerType = JavadocProviderTypes.JAVA_PARSER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("org.springframework.boot.SpringApplication");
@@ -206,7 +208,7 @@ public class JavaIndexTest {
@Test
public void roaster_testClassJavadocForOutputFolder() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = false;
MavenProjectClasspath.providerType = JavadocProviderTypes.ROASTER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("hello.Greeting");
@@ -224,7 +226,7 @@ public class JavaIndexTest {
@Test
public void roaster_testInnerClassJavadocForOutputFolder() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = false;
MavenProjectClasspath.providerType = JavadocProviderTypes.ROASTER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("hello.Greeting$TestInnerClass");
assertNotNull(type);
@@ -241,7 +243,8 @@ public class JavaIndexTest {
@Test
public void roaster_testClassJavadocForJar() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = false;
MavenProjectClasspath.providerType = JavadocProviderTypes.ROASTER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener");
@@ -256,7 +259,8 @@ public class JavaIndexTest {
@Test
public void roaster_testFieldAndMethodJavadocForJar() throws Exception {
MavenProjectClasspath.USE_JAVA_PARSER = false;
MavenProjectClasspath.providerType = JavadocProviderTypes.ROASTER;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("org.springframework.boot.SpringApplication");
@@ -273,4 +277,134 @@ public class JavaIndexTest {
}
@Test
public void html_testClassJavadoc() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("java.util.Map");
assertNotNull(type);
String expected = String.join("\n",
"<div class=\"block\">An object that maps keys to values. A map cannot contain duplicate keys;",
" each key can map to at most one value."
);
assertEquals(expected, type.getJavaDoc().html().substring(0, expected.length()));
}
@Test
public void html_testNestedClassJavadoc() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("java.util.Map$Entry");
assertNotNull(type);
String expected = String.join("\n",
"<div class=\"block\">A map entry (key-value pair). The <tt>Map.entrySet</tt> method returns",
" a collection-view of the map, whose elements are of this class. The");
assertEquals(expected, type.getJavaDoc().html().substring(0, expected.length()));
}
@Test
public void html_testMethodJavadoc() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("java.util.ArrayList");
assertNotNull(type);
IMethod method = type.getMethod("size", Stream.empty());
assertNotNull(method);
String expected = String.join("\n",
"",
"<ul class=\"blockList\">",
"<li class=\"blockList\">",
"<h4>size</h4>",
"<pre>public&nbsp;int&nbsp;size()</pre>",
"<div class=\"block\">Returns the number of elements in this list.</div>"
);
assertEquals(expected, method.getJavaDoc().html().substring(0, expected.length()));
}
@Test
public void html_testConstructorJavadoc() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("java.util.ArrayList");
assertNotNull(type);
IMethod method = type.getMethod("<init>", Stream.empty());
assertNotNull(method);
String expected = String.join("\n",
"",
"<ul class=\"blockList\">",
"<li class=\"blockList\">",
"<h4>ArrayList</h4>"
);
assertEquals(expected, method.getJavaDoc().html().substring(0, expected.length()));
}
@Test
public void html_testFieldAndMethodJavadocForJar() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
MavenJavaProject project = createMavenProject(projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"));
IType type = project.findType("org.springframework.boot.SpringApplication");
assertNotNull(type);
IField field = type.getField("BANNER_LOCATION_PROPERTY_VALUE");
assertNotNull(field);
assertTrue(field.getJavaDoc().html().contains("<h4>BANNER_LOCATION_PROPERTY_VALUE</h4>"));
IMethod method = type.getMethod("getListeners", Stream.empty());
assertNotNull(method);
String expected = String.join("\n",
"",
"<ul class=\"blockList\">",
"<li class=\"blockList\">",
"<h4>getListeners</h4>"
);
assertEquals(expected, method.getJavaDoc().html().substring(0, expected.length()));
}
@Test
public void html_testJavadocOutputFolder() throws Exception {
MavenProjectClasspath.providerType = JavadocProviderTypes.HTML;
Path projectPath = projectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
MavenCore.generateJavadocFolderForMavenProject(projectPath);
MavenJavaProject project = createMavenProject(projectPath);
IType type = project.findType("hello.Greeting");
assertNotNull(type);
String expected = "<div class=\"block\">Comment for Greeting class</div>";
assertEquals(expected, type.getJavaDoc().html().substring(0, expected.length()));
IField field = type.getField("id");
assertNotNull(field);
expected = String.join("\n",
"",
"<ul class=\"blockListLast\">",
"<li class=\"blockList\">",
"<h4>id</h4>"
);
assertEquals(expected, field.getJavaDoc().html().substring(0, expected.length()));
IMethod method = type.getMethod("getId", Stream.empty());
assertNotNull(method);
expected = String.join("\n",
"",
"<ul class=\"blockList\">",
"<li class=\"blockList\">",
"<h4>getId</h4>"
);
assertEquals(expected, method.getJavaDoc().html().substring(0, expected.length()));
}
}

View File

@@ -61,4 +61,14 @@
</plugins>
</build>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
</plugin>
</plugins>
</reporting>
</project>

View File

@@ -8,7 +8,7 @@ public class Greeting {
/**
* Comment for id field
*/
private final long id;
protected final long id;
private final String content;
public Greeting() {
@@ -35,7 +35,7 @@ public class Greeting {
/**
* Comment for inner class
*/
private static class TestInnerClass {
public class TestInnerClass {
/**
* Comment for inner field