mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-14 01:24:09 +00:00
JSDoc tag rendering for HoverInfo
This commit is contained in:
1 parent
9b1ffb4992
commit
edffd7aaaf
2 files changed
+216
-7
No files matched your search
+162
-4
@@ -5,6 +5,10 @@ import noppes.npcs.client.gui.util.script.interpreter.field.AssignmentInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.field.EnumConstantInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.field.FieldAccessInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.field.FieldInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocParamTag;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocReturnTag;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocTypeTag;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.method.MethodCallInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.method.MethodInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.token.Token;
|
||||
@@ -46,6 +50,9 @@ public class TokenHoverInfo {
|
||||
|
||||
/** Javadoc/documentation comment lines */
|
||||
private List<String> documentation = new ArrayList<>();
|
||||
|
||||
/** JSDoc-formatted documentation with colored segments (sections like Params, Returns) */
|
||||
private List<DocumentationLine> jsDocLines = new ArrayList<>();
|
||||
|
||||
/** Error messages (shown in red) */
|
||||
private List<String> errors = new ArrayList<>();
|
||||
@@ -56,6 +63,32 @@ public class TokenHoverInfo {
|
||||
/** The token this info was built from */
|
||||
private final Token token;
|
||||
|
||||
// ==================== DOCUMENTATION LINE ====================
|
||||
|
||||
/**
|
||||
* A line of documentation that may contain colored segments.
|
||||
* Used for JSDoc-style rendering with "Params:", parameter names, etc.
|
||||
*/
|
||||
public static class DocumentationLine {
|
||||
public final List<TextSegment> segments;
|
||||
|
||||
public DocumentationLine() {
|
||||
this.segments = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addSegment(String text, int color) {
|
||||
segments.add(new TextSegment(text, color));
|
||||
}
|
||||
|
||||
public void addText(String text) {
|
||||
segments.add(new TextSegment(text, TextSegment.COLOR_DEFAULT));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return segments.isEmpty() || segments.stream().allMatch(s -> s.text == null || s.text.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== TEXT SEGMENT ====================
|
||||
|
||||
/**
|
||||
@@ -712,7 +745,10 @@ public class TokenHoverInfo {
|
||||
iconIndicator = "f";
|
||||
|
||||
// Add documentation if available
|
||||
if (fieldInfo.getDocumentation() != null && !fieldInfo.getDocumentation().isEmpty()) {
|
||||
JSDocInfo jsDoc = fieldInfo.getJSDocInfo();
|
||||
if (jsDoc != null) {
|
||||
formatJSDocumentation(jsDoc, null);
|
||||
} else if (fieldInfo.getDocumentation() != null && !fieldInfo.getDocumentation().isEmpty()) {
|
||||
String[] docLines = fieldInfo.getDocumentation().split("\n");
|
||||
for (String line : docLines) {
|
||||
documentation.add(line);
|
||||
@@ -1035,8 +1071,12 @@ public class TokenHoverInfo {
|
||||
}
|
||||
addSegment(")", TokenType.DEFAULT.getHexColor());
|
||||
|
||||
// Add documentation if available
|
||||
if (methodInfo.getDocumentation() != null && !methodInfo.getDocumentation().isEmpty()) {
|
||||
// Add documentation if available - use JSDoc formatting if we have JSDocInfo
|
||||
JSDocInfo jsDoc = methodInfo.getJSDocInfo();
|
||||
if (jsDoc != null) {
|
||||
formatJSDocumentation(jsDoc, methodInfo.getParameters());
|
||||
} else if (methodInfo.getDocumentation() != null && !methodInfo.getDocumentation().isEmpty()) {
|
||||
// Fallback to raw documentation
|
||||
String[] docLines = methodInfo.getDocumentation().split("\n");
|
||||
for (String line : docLines) {
|
||||
documentation.add(line);
|
||||
@@ -1044,6 +1084,116 @@ public class TokenHoverInfo {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Format JSDoc information in IntelliJ-style with "Params:" and "Returns:" sections.
|
||||
* Creates colored documentation lines with parameter names highlighted.
|
||||
*/
|
||||
private void formatJSDocumentation(JSDocInfo jsDoc, List<FieldInfo> methodParams) {
|
||||
// Add description if available (without @tags)
|
||||
String description = jsDoc.getDescription();
|
||||
if (description != null && !description.isEmpty()) {
|
||||
// Clean up the description - remove leading/trailing whitespace and asterisks
|
||||
String[] descLines = description.split("\n");
|
||||
for (String line : descLines) {
|
||||
line = line.trim();
|
||||
if (line.startsWith("*")) {
|
||||
line = line.substring(1).trim();
|
||||
}
|
||||
if (!line.isEmpty() && !line.startsWith("@")) {
|
||||
documentation.add(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add Returns section if there's a @return tag
|
||||
JSDocTypeTag typeTag = jsDoc.getTypeTag();
|
||||
if (typeTag != null) {
|
||||
// "Type:" header
|
||||
DocumentationLine typeLine = new DocumentationLine();
|
||||
typeLine.addSegment("Type:", TokenType.JSDOC_TAG.getHexColor());
|
||||
|
||||
// Type if available
|
||||
if (typeTag.hasType()) {
|
||||
typeLine.addText(" ");
|
||||
typeLine.addSegment("{", TokenType.JSDOC_TYPE.getHexColor());
|
||||
typeLine.addSegment(typeTag.getTypeName(), TokenType.getColor(typeTag.getTypeInfo()));
|
||||
typeLine.addSegment("}", TokenType.JSDOC_TYPE.getHexColor());
|
||||
}
|
||||
|
||||
// Description if available
|
||||
String typeDesc = typeTag.getDescription();
|
||||
if (typeDesc != null && !typeDesc.isEmpty()) {
|
||||
typeLine.addText(" - ");
|
||||
typeLine.addText(typeDesc.trim());
|
||||
}
|
||||
|
||||
jsDocLines.add(typeLine);
|
||||
}
|
||||
|
||||
// Add Params section if there are @param tags
|
||||
List<JSDocParamTag> paramTags = jsDoc.getParamTags();
|
||||
if (paramTags != null && !paramTags.isEmpty()) {
|
||||
// "Params:" header
|
||||
DocumentationLine paramsHeader = new DocumentationLine();
|
||||
paramsHeader.addSegment("Params:", TokenType.JSDOC_TAG.getHexColor());
|
||||
jsDocLines.add(paramsHeader);
|
||||
|
||||
// Add each parameter
|
||||
for (JSDocParamTag paramTag : paramTags) {
|
||||
DocumentationLine paramLine = new DocumentationLine();
|
||||
|
||||
// Indent and parameter name
|
||||
String paramName = paramTag.getParamName();
|
||||
boolean paramExists = methodParams != null && methodParams.stream()
|
||||
.anyMatch(p -> p.getName().equals(paramName));
|
||||
paramLine.addSegment(paramName,
|
||||
paramExists ? TokenType.PARAMETER.getHexColor() : TokenType.UNDEFINED_VAR.getHexColor());
|
||||
|
||||
// Type if available
|
||||
if (paramTag.hasType()) {
|
||||
paramLine.addSegment(" {", TokenType.JSDOC_TYPE.getHexColor());
|
||||
paramLine.addSegment(paramTag.getTypeName(), TokenType.getColor(paramTag.getTypeInfo()));
|
||||
paramLine.addSegment("}", TokenType.JSDOC_TYPE.getHexColor());
|
||||
}
|
||||
|
||||
// Description if available
|
||||
String paramDesc = paramTag.getDescription();
|
||||
if (paramDesc != null && !paramDesc.isEmpty()) {
|
||||
paramLine.addText(" - ");
|
||||
paramLine.addText(paramDesc.trim());
|
||||
}
|
||||
|
||||
jsDocLines.add(paramLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Add Returns section if there's a @return tag
|
||||
JSDocReturnTag returnTag = jsDoc.getReturnTag();
|
||||
if (returnTag != null) {
|
||||
DocumentationLine returnLine = new DocumentationLine();
|
||||
|
||||
//"Returns:" header
|
||||
returnLine.addSegment("Returns:", TokenType.JSDOC_TAG.getHexColor());
|
||||
|
||||
// Type if available
|
||||
if (returnTag.hasType()) {
|
||||
returnLine.addText(" ");
|
||||
returnLine.addSegment("{", TokenType.JSDOC_TYPE.getHexColor());
|
||||
returnLine.addSegment(returnTag.getTypeName(), TokenType.getColor(returnTag.getTypeInfo()));
|
||||
returnLine.addSegment("}", TokenType.JSDOC_TYPE.getHexColor());
|
||||
}
|
||||
|
||||
// Description if available
|
||||
String returnDesc = returnTag.getDescription();
|
||||
if (returnDesc != null && !returnDesc.isEmpty()) {
|
||||
returnLine.addText(" - ");
|
||||
returnLine.addText(returnDesc.trim());
|
||||
}
|
||||
|
||||
jsDocLines.add(returnLine);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractJavadoc(Method method) {
|
||||
// Java reflection doesn't provide Javadoc at runtime
|
||||
@@ -1242,12 +1392,20 @@ public class TokenHoverInfo {
|
||||
return declaration;
|
||||
}
|
||||
public List<String> getDocumentation() { return documentation; }
|
||||
|
||||
public List<DocumentationLine> getJSDocLines() {
|
||||
return jsDocLines;
|
||||
}
|
||||
public List<String> getErrors() { return errors; }
|
||||
public List<String> getAdditionalInfo() { return additionalInfo; }
|
||||
public Token getToken() { return token; }
|
||||
|
||||
public boolean hasContent() {
|
||||
return !declaration.isEmpty() || !errors.isEmpty() || !documentation.isEmpty();
|
||||
return !declaration.isEmpty() || !errors.isEmpty() || !documentation.isEmpty() || !jsDocLines.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasJSDocContent() {
|
||||
return !jsDocLines.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasErrors() {
|
||||
|
||||
+54
-3
@@ -203,7 +203,8 @@ public class TokenHoverRenderer {
|
||||
currentY = drawWrappedSegments(textX, currentY, wrapWidth, declaration);
|
||||
currentY += LINE_SPACING;
|
||||
}
|
||||
// Draw documentation
|
||||
|
||||
// Draw documentation (plain text)
|
||||
if (!docs.isEmpty()) {
|
||||
// Draw separator line before documentation
|
||||
Gui.drawRect(textX, currentY, x + boxWidth - PADDING, currentY + SEPARATOR_HEIGHT, BORDER_COLOR);
|
||||
@@ -217,6 +218,26 @@ public class TokenHoverRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
// Draw JSDoc-formatted documentation with colored segments
|
||||
List<TokenHoverInfo.DocumentationLine> jsDocLines = info.getJSDocLines();
|
||||
if (!jsDocLines.isEmpty()) {
|
||||
// Draw separator line if there was plain documentation or declaration
|
||||
if (docs.isEmpty() && !declaration.isEmpty()) {
|
||||
Gui.drawRect(textX, currentY, x + boxWidth - PADDING, currentY + SEPARATOR_HEIGHT, BORDER_COLOR);
|
||||
currentY += SEPARATOR_HEIGHT + SEPARATOR_SPACING;
|
||||
}
|
||||
|
||||
for (TokenHoverInfo.DocumentationLine docLine : jsDocLines) {
|
||||
if (!docLine.isEmpty()) {
|
||||
currentY = drawWrappedSegments(textX, currentY, wrapWidth, docLine.segments);
|
||||
currentY += LINE_SPACING;
|
||||
} else {
|
||||
// Empty line - just add spacing
|
||||
currentY += lineHeight + LINE_SPACING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw additional info
|
||||
|
||||
if (!additionalInfo.isEmpty()) {
|
||||
@@ -368,6 +389,17 @@ public class TokenHoverRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc-formatted documentation lines
|
||||
List<TokenHoverInfo.DocumentationLine> jsDocLines = info.getJSDocLines();
|
||||
if (jsDocLines != null) {
|
||||
for (TokenHoverInfo.DocumentationLine docLine : jsDocLines) {
|
||||
if (!docLine.isEmpty()) {
|
||||
int lineLongest = calculateSegmentsLongestLine(maxWidth, docLine.segments);
|
||||
longestLineWidth = Math.max(longestLineWidth, lineLongest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Additional info
|
||||
for (String line : info.getAdditionalInfo()) {
|
||||
List<String> wrappedLines = wrapText(line, maxWidth);
|
||||
@@ -391,6 +423,7 @@ public class TokenHoverRenderer {
|
||||
String packageName = info.getPackageName();
|
||||
List<TokenHoverInfo.TextSegment> declaration = info.getDeclaration();
|
||||
List<String> docs = info.getDocumentation();
|
||||
List<TokenHoverInfo.DocumentationLine> jsDocLines = info.getJSDocLines();
|
||||
List<String> additionalInfo = info.getAdditionalInfo();
|
||||
|
||||
// Errors
|
||||
@@ -402,7 +435,7 @@ public class TokenHoverRenderer {
|
||||
}
|
||||
|
||||
boolean onlyErrors = errors != null && !errors.isEmpty() && (packageName == null || packageName.isEmpty()) && (declaration == null ||
|
||||
declaration.isEmpty()) && (docs == null || docs.isEmpty()) && (additionalInfo == null || additionalInfo.isEmpty());
|
||||
declaration.isEmpty()) && (docs == null || docs.isEmpty()) && (jsDocLines == null || jsDocLines.isEmpty()) && (additionalInfo == null || additionalInfo.isEmpty());
|
||||
|
||||
if (!onlyErrors) //Add error separator height
|
||||
totalHeight += (SEPARATOR_SPACING + SEPARATOR_HEIGHT) * 2 - 5;
|
||||
@@ -423,7 +456,7 @@ public class TokenHoverRenderer {
|
||||
totalHeight += LINE_SPACING;
|
||||
}
|
||||
|
||||
// Documentation
|
||||
// Documentation (plain text)
|
||||
if (!docs.isEmpty()) {
|
||||
// Add space for separator line and spacing
|
||||
totalHeight += SEPARATOR_SPACING + SEPARATOR_HEIGHT;
|
||||
@@ -433,6 +466,24 @@ public class TokenHoverRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc-formatted documentation lines
|
||||
if (jsDocLines != null && !jsDocLines.isEmpty()) {
|
||||
// Add separator if there was plain documentation or declaration but no plain docs
|
||||
if (docs.isEmpty() && !declaration.isEmpty()) {
|
||||
// totalHeight += SEPARATOR_SPACING + SEPARATOR_HEIGHT;
|
||||
}
|
||||
|
||||
for (TokenHoverInfo.DocumentationLine docLine : jsDocLines) {
|
||||
if (!docLine.isEmpty()) {
|
||||
totalHeight += calculateSegmentsHeight(contentWidth, docLine.segments);
|
||||
//. totalHeight += LINE_SPACING;
|
||||
} else {
|
||||
// Empty line
|
||||
// totalHeight += lineHeight + LINE_SPACING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Additional info
|
||||
if (!additionalInfo.isEmpty()) {
|
||||
totalHeight += LINE_SPACING;
|
||||
|
||||
Reference in new issue
Block a user