Skip to content

Commit 335473a

Browse files
committed
chore: update
1 parent e6e0d7a commit 335473a

File tree

1 file changed

+248
-45
lines changed

1 file changed

+248
-45
lines changed

jdtls.ext/com.microsoft.jdtls.ext.core/src/com/microsoft/jdtls/ext/core/parser/ContextResolver.java

Lines changed: 248 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -862,13 +862,15 @@ public static String generateClassDescription(org.eclipse.jdt.core.IType type, S
862862
// ================ JavaDoc Extraction Methods ================
863863

864864
/**
865-
* Extracts relevant code snippets from Javadoc.
866-
* This method is optimized to extract code from `<code>` tags and markdown code fences,
867-
* and formats them in an LLM-readable format.
865+
* Extracts relevant JavaDoc content including description text and code snippets.
866+
* This method extracts:
867+
* 1. Class description (first paragraph of text)
868+
* 2. Code snippets from <code>, <pre>, and ``` blocks
869+
* 3. @deprecated tag if present
868870
*
869871
* @param type the type to extract Javadoc from.
870872
* @param monitor the progress monitor.
871-
* @return A string containing all found code snippets, formatted as markdown code blocks.
873+
* @return A string containing description and code snippets in LLM-readable format.
872874
*/
873875
private static String extractRelevantJavaDocContent(org.eclipse.jdt.core.IType type, IProgressMonitor monitor) {
874876
try {
@@ -883,7 +885,6 @@ private static String extractRelevantJavaDocContent(org.eclipse.jdt.core.IType t
883885
}
884886

885887
String rawJavadoc;
886-
boolean isHtml = false;
887888

888889
// Extract JavaDoc from source code (fast - no I/O, no network, no HTML parsing)
889890
org.eclipse.jdt.core.ISourceRange javadocRange = type.getJavadocRange();
@@ -896,49 +897,118 @@ private static String extractRelevantJavaDocContent(org.eclipse.jdt.core.IType t
896897
return "";
897898
}
898899

899-
StringBuilder allCodeSnippets = new StringBuilder();
900+
StringBuilder result = new StringBuilder();
900901
Set<String> seenCodeSnippets = new HashSet<>();
902+
903+
// Clean Javadoc comment for processing
904+
String cleanedJavadoc = cleanJavadocComment(rawJavadoc);
905+
cleanedJavadoc = convertHtmlEntities(cleanedJavadoc);
906+
907+
// === High Priority: Extract class description text (first paragraph) ===
908+
String description = extractClassDescription(cleanedJavadoc);
909+
if (isNotEmpty(description)) {
910+
result.append("Description:\n").append(description).append("\n\n");
911+
}
912+
913+
// === High Priority: Check for @deprecated tag ===
914+
if (isDeprecated(cleanedJavadoc)) {
915+
result.append("⚠️ DEPRECATED: This class is deprecated and should not be used in new code.\n\n");
916+
}
901917

918+
// === Extract code snippets ===
902919
// 1. Extract markdown code blocks (```...```)
903920
Matcher markdownMatcher = MARKDOWN_CODE_PATTERN.matcher(rawJavadoc);
904921
while (markdownMatcher.find()) {
905922
String code = markdownMatcher.group(1).trim();
906923
if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
907-
allCodeSnippets.append("```java\n").append(code).append("\n```\n\n");
924+
result.append("Example:\n```java\n").append(code).append("\n```\n\n");
908925
}
909926
}
910927

911928
// 2. Extract HTML <pre> and <code> blocks
912-
// Clean Javadoc comment for HTML extraction
913-
String cleanedForHtml = isHtml ? rawJavadoc : cleanJavadocComment(rawJavadoc);
914-
cleanedForHtml = convertHtmlEntities(cleanedForHtml);
915-
916929
// Priority 1: <pre> blocks (often contain well-formatted code)
917-
Matcher preMatcher = HTML_PRE_PATTERN.matcher(cleanedForHtml);
930+
Matcher preMatcher = HTML_PRE_PATTERN.matcher(cleanedJavadoc);
918931
while (preMatcher.find()) {
919932
String code = preMatcher.group(1).replaceAll("(?i)<code[^>]*>", "").replaceAll("(?i)</code>", "").trim();
920933
if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
921-
allCodeSnippets.append("```java\n").append(code).append("\n```\n\n");
934+
result.append("Example:\n```java\n").append(code).append("\n```\n\n");
922935
}
923936
}
924937

925938
// Priority 2: <code> blocks (for inline snippets)
926-
Matcher codeMatcher = HTML_CODE_PATTERN.matcher(cleanedForHtml);
939+
Matcher codeMatcher = HTML_CODE_PATTERN.matcher(cleanedJavadoc);
927940
while (codeMatcher.find()) {
928941
String code = codeMatcher.group(1).trim();
929942
// Use HashSet for O(1) duplicate checking
930943
if (isNotEmpty(code) && seenCodeSnippets.add(code)) {
931-
allCodeSnippets.append("```java\n").append(code).append("\n```\n\n");
944+
result.append("Example:\n```java\n").append(code).append("\n```\n\n");
932945
}
933946
}
934947

935-
return allCodeSnippets.toString().trim();
948+
return result.toString().trim();
936949

937950
} catch (Exception e) {
938951
JdtlsExtActivator.logException("Error extracting relevant JavaDoc content for: " + type.getElementName(), e);
939952
return "";
940953
}
941954
}
955+
956+
/**
957+
* Extract the main description paragraph from class JavaDoc (before @tags and code blocks).
958+
* Returns the first paragraph of descriptive text, limited to reasonable length.
959+
*/
960+
private static String extractClassDescription(String cleanedJavadoc) {
961+
if (!isNotEmpty(cleanedJavadoc)) {
962+
return "";
963+
}
964+
965+
// Remove code blocks first to get pure text
966+
String textOnly = cleanedJavadoc;
967+
textOnly = MARKDOWN_CODE_PATTERN.matcher(textOnly).replaceAll("");
968+
textOnly = HTML_PRE_PATTERN.matcher(textOnly).replaceAll("");
969+
textOnly = HTML_CODE_PATTERN.matcher(textOnly).replaceAll("");
970+
971+
// Extract description before @tags
972+
String description = extractJavadocDescription(textOnly);
973+
974+
// Limit to first 2-3 sentences or ~200 characters
975+
if (description.length() > 200) {
976+
// Try to find a good break point (., !, ?)
977+
int[] boundaries = {
978+
description.indexOf(". ", 100),
979+
description.indexOf(".\n", 100),
980+
description.indexOf("! ", 100),
981+
description.indexOf("? ", 100)
982+
};
983+
984+
int breakPoint = -1;
985+
for (int boundary : boundaries) {
986+
if (boundary != -1 && boundary < 250 && (breakPoint == -1 || boundary < breakPoint)) {
987+
breakPoint = boundary;
988+
}
989+
}
990+
991+
if (breakPoint != -1) {
992+
description = description.substring(0, breakPoint + 1).trim();
993+
} else {
994+
// No good break point, just truncate with ellipsis
995+
int lastSpace = description.lastIndexOf(' ', 200);
996+
description = description.substring(0, lastSpace > 100 ? lastSpace : 200).trim() + "...";
997+
}
998+
}
999+
1000+
return description.trim();
1001+
}
1002+
1003+
/**
1004+
* Check if the JavaDoc contains @deprecated tag.
1005+
*/
1006+
private static boolean isDeprecated(String cleanedJavadoc) {
1007+
if (!isNotEmpty(cleanedJavadoc)) {
1008+
return false;
1009+
}
1010+
return cleanedJavadoc.contains("@deprecated");
1011+
}
9421012

9431013
/**
9441014
* Clean up raw JavaDoc comment by removing comment markers and asterisks
@@ -1001,11 +1071,142 @@ private static String convertHtmlEntities(String text) {
10011071
}
10021072

10031073
/**
1004-
* Extract summary description from method JavaDoc
1005-
* Returns the first sentence or paragraph of the JavaDoc as a brief description
1074+
* Extract detailed JavaDoc summary from method including @param, @return, and @throws tags.
1075+
* Returns a formatted string with the method description and parameter/return information.
10061076
*/
10071077
private static String extractMethodJavaDocSummary(IMethod method) {
1008-
return extractJavaDocSummaryFromElement(method);
1078+
try {
1079+
org.eclipse.jdt.core.ISourceRange javadocRange = method.getJavadocRange();
1080+
if (javadocRange == null) {
1081+
return "";
1082+
}
1083+
1084+
String rawJavadoc = method.getCompilationUnit().getSource()
1085+
.substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength());
1086+
1087+
if (!isNotEmpty(rawJavadoc)) {
1088+
return "";
1089+
}
1090+
1091+
String cleaned = cleanJavadocComment(rawJavadoc);
1092+
StringBuilder result = new StringBuilder();
1093+
1094+
// Extract main description (first sentence)
1095+
String description = extractJavadocDescription(cleaned);
1096+
String firstSentence = getFirstSentenceOrLimit(description, 120);
1097+
if (isNotEmpty(firstSentence)) {
1098+
result.append(firstSentence);
1099+
}
1100+
1101+
// === Medium Priority: Parse @param tags ===
1102+
List<String> params = extractJavadocTag(cleaned, "@param");
1103+
if (!params.isEmpty()) {
1104+
result.append(" | Params: ");
1105+
for (int i = 0; i < params.size() && i < 3; i++) { // Limit to 3 params
1106+
if (i > 0) result.append(", ");
1107+
result.append(params.get(i));
1108+
}
1109+
if (params.size() > 3) {
1110+
result.append("...");
1111+
}
1112+
}
1113+
1114+
// === Medium Priority: Parse @return tag ===
1115+
List<String> returns = extractJavadocTag(cleaned, "@return");
1116+
if (!returns.isEmpty()) {
1117+
String returnDesc = returns.get(0);
1118+
// Limit return description to 60 chars
1119+
if (returnDesc.length() > 60) {
1120+
returnDesc = returnDesc.substring(0, 57) + "...";
1121+
}
1122+
result.append(" | Returns: ").append(returnDesc);
1123+
}
1124+
1125+
// === Medium Priority: Parse @throws tags ===
1126+
List<String> throwsTags = extractJavadocTag(cleaned, "@throws");
1127+
if (throwsTags.isEmpty()) {
1128+
throwsTags = extractJavadocTag(cleaned, "@exception");
1129+
}
1130+
if (!throwsTags.isEmpty()) {
1131+
result.append(" | Throws: ");
1132+
for (int i = 0; i < throwsTags.size() && i < 2; i++) { // Limit to 2 exceptions
1133+
if (i > 0) result.append(", ");
1134+
// Extract just the exception class name (first word)
1135+
String exceptionInfo = throwsTags.get(i);
1136+
int spaceIndex = exceptionInfo.indexOf(' ');
1137+
if (spaceIndex != -1) {
1138+
result.append(exceptionInfo.substring(0, spaceIndex));
1139+
} else {
1140+
result.append(exceptionInfo);
1141+
}
1142+
}
1143+
if (throwsTags.size() > 2) {
1144+
result.append("...");
1145+
}
1146+
}
1147+
1148+
// === High Priority: Mark deprecated methods ===
1149+
if (cleaned.contains("@deprecated")) {
1150+
result.append(" [DEPRECATED]");
1151+
}
1152+
1153+
return result.toString();
1154+
1155+
} catch (Exception e) {
1156+
return "";
1157+
}
1158+
}
1159+
1160+
/**
1161+
* Extract JavaDoc tags of a specific type (e.g., @param, @return, @throws).
1162+
* Returns a list of tag values (without the tag name itself).
1163+
*
1164+
* @param cleanedJavadoc Cleaned JavaDoc text
1165+
* @param tagName Tag name to search for (e.g., "@param")
1166+
* @return List of tag values
1167+
*/
1168+
private static List<String> extractJavadocTag(String cleanedJavadoc, String tagName) {
1169+
List<String> results = new ArrayList<>();
1170+
1171+
if (!isNotEmpty(cleanedJavadoc)) {
1172+
return results;
1173+
}
1174+
1175+
String[] lines = cleanedJavadoc.split("\\n");
1176+
StringBuilder currentTag = null;
1177+
1178+
for (String line : lines) {
1179+
String trimmed = line.trim();
1180+
1181+
// Check if this line starts with the target tag
1182+
if (trimmed.startsWith(tagName + " ")) {
1183+
// Save previous tag if exists
1184+
if (currentTag != null) {
1185+
results.add(currentTag.toString().trim());
1186+
}
1187+
// Start new tag (remove tag name)
1188+
currentTag = new StringBuilder(trimmed.substring(tagName.length() + 1).trim());
1189+
}
1190+
// Check if this line starts with any other tag
1191+
else if (trimmed.startsWith("@")) {
1192+
// Save previous tag if exists
1193+
if (currentTag != null) {
1194+
results.add(currentTag.toString().trim());
1195+
currentTag = null;
1196+
}
1197+
}
1198+
// Continuation of current tag
1199+
else if (currentTag != null && isNotEmpty(trimmed)) {
1200+
currentTag.append(" ").append(trimmed);
1201+
}
1202+
}
1203+
1204+
// Don't forget the last tag
1205+
if (currentTag != null) {
1206+
results.add(currentTag.toString().trim());
1207+
}
1208+
1209+
return results;
10091210
}
10101211

10111212
/**
@@ -1074,10 +1275,35 @@ private static String getFirstSentenceOrLimit(String text, int maxLength) {
10741275
}
10751276

10761277
/**
1077-
* Extract summary description from field JavaDoc
1278+
* Extract summary description from field JavaDoc, including @deprecated marking.
10781279
*/
10791280
private static String extractFieldJavaDocSummary(org.eclipse.jdt.core.IField field) {
1080-
return extractJavaDocSummaryFromElement(field);
1281+
try {
1282+
org.eclipse.jdt.core.ISourceRange javadocRange = field.getJavadocRange();
1283+
if (javadocRange == null) {
1284+
return "";
1285+
}
1286+
1287+
String rawJavadoc = field.getCompilationUnit().getSource()
1288+
.substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength());
1289+
1290+
if (!isNotEmpty(rawJavadoc)) {
1291+
return "";
1292+
}
1293+
1294+
String cleaned = cleanJavadocComment(rawJavadoc);
1295+
String description = extractJavadocDescription(cleaned);
1296+
String summary = getFirstSentenceOrLimit(description, 120);
1297+
1298+
// === High Priority: Mark deprecated fields ===
1299+
if (cleaned.contains("@deprecated")) {
1300+
summary += " [DEPRECATED]";
1301+
}
1302+
1303+
return summary;
1304+
} catch (Exception e) {
1305+
return "";
1306+
}
10811307
}
10821308

10831309
/**
@@ -1228,30 +1454,7 @@ private static String simplifyTypeName(String qualifiedName) {
12281454
return lastDot == -1 ? qualifiedName : qualifiedName.substring(lastDot + 1);
12291455
}
12301456

1231-
/**
1232-
* Unified JavaDoc summary extractor for methods and fields
1233-
*/
1234-
private static String extractJavaDocSummaryFromElement(org.eclipse.jdt.core.IMember element) {
1235-
try {
1236-
org.eclipse.jdt.core.ISourceRange javadocRange = element.getJavadocRange();
1237-
if (javadocRange == null) {
1238-
return "";
1239-
}
1240-
1241-
String rawJavadoc = element.getCompilationUnit().getSource()
1242-
.substring(javadocRange.getOffset(), javadocRange.getOffset() + javadocRange.getLength());
1243-
1244-
if (rawJavadoc == null || rawJavadoc.isEmpty()) {
1245-
return "";
1246-
}
1247-
1248-
String cleaned = cleanJavadocComment(rawJavadoc);
1249-
String description = extractJavadocDescription(cleaned);
1250-
return getFirstSentenceOrLimit(description, 120);
1251-
} catch (Exception e) {
1252-
return "";
1253-
}
1254-
}
1457+
12551458

12561459
/**
12571460
* Unified method signature generator (handles both source and binary types)

0 commit comments

Comments
 (0)