package org.eclipse.jdt.internal.ui.text.correction;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.TagElement;
import org.eclipse.jdt.core.dom.TextElement;
import org.eclipse.jdt.core.dom.TypeParameter;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
public class JavadocTagsSubProcessorCore {
public static Set<String> getPreviousTypeParamNames(List<TypeParameter> typeParams, ASTNode missingNode) {
Set<String> previousNames= new HashSet<>();
for (TypeParameter curr : typeParams) {
if (curr == missingNode) {
return previousNames;
}
previousNames.add('<' + curr.getName().getIdentifier() + '>');
}
return previousNames;
}
public static TagElement findTag(Javadoc javadoc, String name, String arg) {
List<TagElement> tags= javadoc.tags();
for (TagElement curr : tags) {
if (name.equals(curr.getTagName())) {
if (arg != null) {
String argument= getArgument(curr);
if (arg.equals(argument)) {
return curr;
}
} else {
return curr;
}
}
}
return null;
}
public static TagElement findParamTag(Javadoc javadoc, String arg) {
List<TagElement> tags= javadoc.tags();
for (TagElement curr : tags) {
String currName= curr.getTagName();
if (TagElement.TAG_PARAM.equals(currName)) {
String argument= getArgument(curr);
if (arg.equals(argument)) {
return curr;
}
}
}
return null;
}
public static TagElement findThrowsTag(Javadoc javadoc, String arg) {
List<TagElement> tags= javadoc.tags();
for (TagElement curr : tags) {
String currName= curr.getTagName();
if (TagElement.TAG_THROWS.equals(currName) || TagElement.TAG_EXCEPTION.equals(currName)) {
String argument= getArgument(curr);
if (arg.equals(argument)) {
return curr;
}
}
}
return null;
}
public static void insertTag(ListRewrite rewriter, TagElement newElement, Set<String> sameKindLeadingNames) {
insertTag(rewriter, newElement, sameKindLeadingNames, null);
}
public static void insertTag(ListRewrite rewriter, TagElement newElement, Set<String> sameKindLeadingNames, TextEditGroup groupDescription) {
List<? extends ASTNode> tags= rewriter.getRewrittenList();
String insertedTagName= newElement.getTagName();
ASTNode after= null;
int tagRanking= getTagRanking(insertedTagName);
for (int i= tags.size() - 1; i >= 0; i--) {
TagElement curr= (TagElement) tags.get(i);
String tagName= curr.getTagName();
if (tagName == null || tagRanking > getTagRanking(tagName)) {
after= curr;
break;
}
if (sameKindLeadingNames != null && isSameTag(insertedTagName, tagName)) {
String arg= getArgument(curr);
if (arg != null && sameKindLeadingNames.contains(arg)) {
after= curr;
break;
}
}
}
if (after != null) {
rewriter.insertAfter(newElement, after, groupDescription);
} else {
rewriter.insertFirst(newElement, groupDescription);
}
}
private static boolean isSameTag(String insertedTagName, String tagName) {
if (insertedTagName.equals(tagName)) {
return true;
}
if (TagElement.TAG_EXCEPTION.equals(tagName)) {
return TagElement.TAG_THROWS.equals(insertedTagName);
}
return false;
}
private static String[] TAG_ORDER= {
TagElement.TAG_AUTHOR,
TagElement.TAG_VERSION,
TagElement.TAG_PARAM,
TagElement.TAG_RETURN,
TagElement.TAG_THROWS,
TagElement.TAG_SEE,
TagElement.TAG_SINCE,
TagElement.TAG_SERIAL,
TagElement.TAG_DEPRECATED
};
private static int getTagRanking(String tagName) {
if (tagName.equals(TagElement.TAG_EXCEPTION)) {
tagName= TagElement.TAG_THROWS;
}
for (int i= 0; i < TAG_ORDER.length; i++) {
if (tagName.equals(TAG_ORDER[i])) {
return i;
}
}
return TAG_ORDER.length;
}
private static String getArgument(TagElement curr) {
List<? extends ASTNode> fragments= curr.fragments();
if (!fragments.isEmpty()) {
Object first= fragments.get(0);
if (first instanceof Name) {
return ASTNodes.getSimpleNameIdentifier((Name) first);
} else if (first instanceof TextElement && TagElement.TAG_PARAM.equals(curr.getTagName())) {
String text= ((TextElement) first).getText();
if ("<".equals(text) && fragments.size() >= 3) {
Object second= fragments.get(1);
Object third= fragments.get(2);
if (second instanceof Name && third instanceof TextElement && ">".equals(((TextElement) third).getText())) {
return '<' + ASTNodes.getSimpleNameIdentifier((Name) second) + '>';
}
} else if (text.startsWith(String.valueOf('<')) && text.endsWith(String.valueOf('>')) && text.length() > 2) {
return text.substring(1, text.length() - 1);
}
}
}
return null;
}
}