
io.vertx.codegen.doc.Token Maven / Gradle / Ivy
package io.vertx.codegen.doc;
import io.vertx.codegen.Helper;
import io.vertx.codegen.type.TypeMirrorFactory;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* A comment token.
*
* @author Julien Viet
*/
public abstract class Token {
private static final Pattern TOKEN_SPLITTER = Pattern.compile("(\\{@\\p{Alpha}[^\\}]*\\})|(\\r?\\n)");
private static final Pattern INLINE_TAG_PATTERN = Pattern.compile("\\{@([^\\p{javaWhitespace}]+)((?:.|\\n)*)\\}");
/**
* Tokenize the string.
*
* @param s the string to tokenize
* @return the tokens after analysis
*/
public static List tokenize(String s) {
ArrayList events = new ArrayList<>();
parse(s, 0, TOKEN_SPLITTER.matcher(s), events);
return events;
}
private static void parse(String s, int prev, Matcher matcher, ArrayList events) {
if (matcher.find()) {
if (matcher.start() > prev) {
events.add(new Token.Text(s.substring(prev, matcher.start())));
}
String value = s.substring(matcher.start(), matcher.end());
if (matcher.group(1) != null) {
Matcher tagMatcher = INLINE_TAG_PATTERN.matcher(value);
if (!tagMatcher.matches()) {
// If we are here, it means the INLINE_TAG_PATTERN matches less then TOKEN_SPLITTER and this is a bug.
// so we should know at least the value that raised it
throw new AssertionError("bug -->" + value + "<--");
}
events.add(new Token.InlineTag(value, new Tag(tagMatcher.group(1), tagMatcher.group(2))));
} else {
events.add(new Token.LineBreak(value));
}
parse(s, matcher.end(), matcher, events);
} else {
if (prev < s.length()) {
events.add(new Token.Text(s.substring(prev, s.length())));
}
}
}
final String value;
public Token(String value) {
this.value = value;
}
/**
* @return true if the token is text
*/
public boolean isText() {
return false;
}
/**
* @return true if the token is an inline tag
*/
public boolean isInlineTag() {
return false;
}
/**
* @return true if the token is line break
*/
public boolean isLineBreak() {
return false;
}
/**
* @return the token text
*/
public String getValue() {
return value;
}
public static class Text extends Token {
public Text(String value) {
super(value);
}
@Override
public boolean isText() {
return true;
}
}
public static class LineBreak extends Token {
public LineBreak(String value) {
super(value);
}
@Override
public boolean isLineBreak() {
return true;
}
}
public static class InlineTag extends Token {
private final Tag tag;
public InlineTag(String value, Tag tag) {
super(value);
this.tag = tag;
}
@Override
public boolean isInlineTag() {
return true;
}
/**
* @return the parsed tag
*/
public Tag getTag() {
return tag;
}
}
// Slight modification to accomodate left whitespace trimming
private static final Pattern LINK_REFERENCE_PATTERN = Pattern.compile(
"^\\s*(" +
Helper.LINK_REFERENCE_PATTERN.pattern() +
")");
/**
* Create a tag mapper that remaps tags with extra contexutal info like @link tags.
*
* @param elementUtils the element utils
* @param typeUtils the type utils
* @param ownerElt the type element in which this tag is declared
* @return the mapper
*/
public static Function tagMapper(
Elements elementUtils, Types typeUtils, TypeElement ownerElt) {
TypeMirrorFactory typeFactory = new TypeMirrorFactory(elementUtils, typeUtils);
return token -> {
if (token.isInlineTag()) {
Tag tag = ((Token.InlineTag) token).getTag();
if (tag.getName().equals("link")) {
Matcher matcher = LINK_REFERENCE_PATTERN.matcher(tag.getValue());
if (matcher.find()) {
Element resolvedElt = Helper.resolveSignature(
elementUtils,
typeUtils,
ownerElt,
matcher.group(1));
if (resolvedElt != null) {
TypeElement resolvedTypeElt = Helper.getElementTypeOf(resolvedElt);
if (resolvedTypeElt != null) {
DeclaredType resolvedType = (DeclaredType) resolvedTypeElt.asType();
Tag.Link tagLink = new Tag.Link(
tag.getValue(),
resolvedElt,
typeFactory.create(resolvedType),
tag.getValue().substring(matcher.end()));
token = new Token.InlineTag(token.getValue(), tagLink);
}
}
}
}
}
return token;
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy