|
5 | 5 | import java.util.AbstractMap; |
6 | 6 | import java.util.Arrays; |
7 | 7 | import java.util.Collections; |
| 8 | +import java.util.HashMap; |
8 | 9 | import java.util.concurrent.CompletableFuture; |
9 | 10 | import java.util.concurrent.ExecutionException; |
10 | 11 | import java.util.HashSet; |
@@ -305,47 +306,79 @@ CompletionItem convertCompletionCandidate(CompletionCandidate c) { |
305 | 306 | CompletionItem item = new CompletionItem(); |
306 | 307 | item.setLabel(c.getElementName()); |
307 | 308 | item.setInsertTextFormat(InsertTextFormat.Snippet); |
308 | | - String insert = c.getCompletionString(); |
309 | | - if (insert.contains("( )")) { |
310 | | - insert = insert.replace("( )", "($1)"); |
311 | | - } else if (insert.contains(",")) { |
312 | | - int n = 1; |
313 | | - char[] chs = insert.replace("(,", "($1,").toCharArray(); |
314 | | - //insert = ""; |
315 | | - StringBuilder newInsert = new StringBuilder(); |
316 | | - for (char ch : chs) { |
317 | | - if (ch == ',') { |
318 | | - n += 1; |
319 | | - //insert += ",$" + n; |
320 | | - newInsert.append(",$").append(n); |
321 | | - } |
322 | | - //insert += ch; |
323 | | - newInsert.append(ch); |
324 | | - } |
325 | | - insert = newInsert.toString(); |
326 | | - } |
327 | | - item.setInsertText(insert); |
| 309 | + |
328 | 310 | CompletionItemKind kind = switch (c.getType()) { |
329 | | - case 0 -> // PREDEF_CLASS |
330 | | - CompletionItemKind.Class; |
331 | | - case 1 -> // PREDEF_FIELD |
332 | | - CompletionItemKind.Constant; |
333 | | - case 2 -> // PREDEF_METHOD |
334 | | - CompletionItemKind.Function; |
335 | | - case 3 -> // LOCAL_CLASS |
336 | | - CompletionItemKind.Class; |
337 | | - case 4 -> // LOCAL_METHOD |
338 | | - CompletionItemKind.Method; |
339 | | - case 5 -> // LOCAL_FIELD |
340 | | - CompletionItemKind.Field; |
341 | | - case 6 -> // LOCAL_VARIABLE |
342 | | - CompletionItemKind.Variable; |
| 311 | + case 0 -> CompletionItemKind.Class; |
| 312 | + case 1 -> CompletionItemKind.Constant; |
| 313 | + case 2 -> CompletionItemKind.Function; |
| 314 | + case 3 -> CompletionItemKind.Class; |
| 315 | + case 4 -> CompletionItemKind.Method; |
| 316 | + case 5 -> CompletionItemKind.Field; |
| 317 | + case 6 -> CompletionItemKind.Variable; |
343 | 318 | default -> throw new IllegalArgumentException("Unknown completion type: " + c.getType()); |
344 | 319 | }; |
345 | 320 | item.setKind(kind); |
346 | | - item.setDetail(Jsoup.parse(c.getLabel()).text()); |
| 321 | + |
| 322 | + if (c.getType() == 2 || c.getType() == 4) { |
| 323 | + // PREDEF_METHOD or LOCAL_METHOD |
| 324 | + String methodName = c.getElementName(); |
| 325 | + |
| 326 | + if (methodKnownParameterNames.containsKey(methodName)) { |
| 327 | + item.setDetail(methodName + "(" + String.join(", ", methodKnownParameterNames.get(methodName)) + ")"); |
| 328 | + |
| 329 | + item.setInsertText(methodName + "($1)"); |
| 330 | + } else { |
| 331 | + String label = Jsoup.parse(c.getLabel()).text(); |
| 332 | + |
| 333 | + if (label.contains("(")) { |
| 334 | + String paramsPart = label.substring(label.indexOf("(") + 1, label.indexOf(")")); |
| 335 | + |
| 336 | + if (!paramsPart.trim().isEmpty()) { |
| 337 | + String[] paramTypes = paramsPart.split(",\\s*"); |
| 338 | + String[] paramNames = generateParameterNames(paramTypes); |
| 339 | + |
| 340 | + StringBuilder detailBuilder = new StringBuilder(methodName).append("("); |
| 341 | + for (int i = 0; i < paramNames.length; i++) { |
| 342 | + if (i > 0) detailBuilder.append(", "); |
| 343 | + detailBuilder.append(paramNames[i]); |
| 344 | + } |
| 345 | + detailBuilder.append(")"); |
| 346 | + item.setDetail(detailBuilder.toString()); |
| 347 | + |
| 348 | + item.setInsertText(methodName + "($1)"); |
| 349 | + } else { |
| 350 | + item.setDetail(methodName + "()"); |
| 351 | + item.setInsertText(methodName + "()"); |
| 352 | + } |
| 353 | + } else { |
| 354 | + item.setDetail(Jsoup.parse(c.getLabel()).text()); |
| 355 | + item.setInsertText(methodName + "($1)"); |
| 356 | + } |
| 357 | + } |
| 358 | + } else { |
| 359 | + item.setDetail(Jsoup.parse(c.getLabel()).text()); |
| 360 | + |
| 361 | + String insert = c.getCompletionString(); |
| 362 | + if (insert.contains("( )")) { |
| 363 | + insert = insert.replace("( )", "($1)"); |
| 364 | + } else if (insert.contains(",")) { |
| 365 | + int n = 1; |
| 366 | + char[] chs = insert.replace("(,", "($1,").toCharArray(); |
| 367 | + StringBuilder newInsert = new StringBuilder(); |
| 368 | + for (char ch : chs) { |
| 369 | + if (ch == ',') { |
| 370 | + n += 1; |
| 371 | + newInsert.append(",$").append(n); |
| 372 | + } |
| 373 | + newInsert.append(ch); |
| 374 | + } |
| 375 | + insert = newInsert.toString(); |
| 376 | + } |
| 377 | + item.setInsertText(insert); |
| 378 | + } |
| 379 | + |
347 | 380 | return item; |
348 | | - } |
| 381 | + } |
349 | 382 |
|
350 | 383 | Optional<String> parsePhrase(String text) { |
351 | 384 | return Optional.ofNullable(JavaTextArea.parsePhrase(text)); |
@@ -440,4 +473,101 @@ static class Offset { |
440 | 473 | this.col = col; |
441 | 474 | } |
442 | 475 | } |
| 476 | + |
| 477 | + // Map of known Processing methods and their parameter names |
| 478 | + private static final Map<String, String[]> methodKnownParameterNames = new HashMap<>(); |
| 479 | + static { |
| 480 | + // PApplet drawing methods |
| 481 | + methodKnownParameterNames.put("rect", new String[]{"x", "y", "width", "height"}); |
| 482 | + methodKnownParameterNames.put("ellipse", new String[]{"x", "y", "width", "height"}); |
| 483 | + methodKnownParameterNames.put("line", new String[]{"x1", "y1", "x2", "y2"}); |
| 484 | + methodKnownParameterNames.put("point", new String[]{"x", "y"}); |
| 485 | + methodKnownParameterNames.put("triangle", new String[]{"x1", "y1", "x2", "y2", "x3", "y3"}); |
| 486 | + methodKnownParameterNames.put("quad", new String[]{"x1", "y1", "x2", "y2", "x3", "y3", "x4", "y4"}); |
| 487 | + |
| 488 | + // Image methods |
| 489 | + methodKnownParameterNames.put("copy", new String[]{"sx", "sy", "sw", "sh", "dx", "dy", "dw", "dh"}); |
| 490 | + methodKnownParameterNames.put("image", new String[]{"img", "x", "y"}); |
| 491 | + methodKnownParameterNames.put("loadImage", new String[]{"filename"}); |
| 492 | + |
| 493 | + // Color methods |
| 494 | + methodKnownParameterNames.put("color", new String[]{"r", "g", "b"}); |
| 495 | + methodKnownParameterNames.put("fill", new String[]{"r", "g", "b", "a"}); |
| 496 | + methodKnownParameterNames.put("stroke", new String[]{"r", "g", "b", "a"}); |
| 497 | + |
| 498 | + // Text methods |
| 499 | + methodKnownParameterNames.put("text", new String[]{"str", "x", "y"}); |
| 500 | + methodKnownParameterNames.put("textSize", new String[]{"size"}); |
| 501 | + |
| 502 | + // Transform methods |
| 503 | + methodKnownParameterNames.put("translate", new String[]{"x", "y", "z"}); |
| 504 | + methodKnownParameterNames.put("rotate", new String[]{"angle"}); |
| 505 | + methodKnownParameterNames.put("scale", new String[]{"s"}); |
| 506 | + |
| 507 | + // Math methods |
| 508 | + methodKnownParameterNames.put("map", new String[]{"value", "start1", "stop1", "start2", "stop2"}); |
| 509 | + methodKnownParameterNames.put("constrain", new String[]{"amt", "low", "high"}); |
| 510 | + methodKnownParameterNames.put("lerp", new String[]{"start", "stop", "amt"}); |
| 511 | + |
| 512 | + // We can add more methods later |
| 513 | + } |
| 514 | + |
| 515 | + /** |
| 516 | + * Generate meaningful parameter names based on parameter types |
| 517 | + */ |
| 518 | + private String[] generateParameterNames(String[] paramTypes) { |
| 519 | + String[] paramNames = new String[paramTypes.length]; |
| 520 | + |
| 521 | + for (int i = 0; i < paramTypes.length; i++) { |
| 522 | + String type = paramTypes[i].trim(); |
| 523 | + |
| 524 | + if (type.contains("int")) { |
| 525 | + paramNames[i] = "n" + (i+1); |
| 526 | + } else if (type.contains("float")) { |
| 527 | + paramNames[i] = "val" + (i+1); |
| 528 | + } else if (type.contains("boolean")) { |
| 529 | + paramNames[i] = "flag" + (i+1); |
| 530 | + } else if (type.contains("String")) { |
| 531 | + paramNames[i] = "str" + (i+1); |
| 532 | + } else if (type.contains("PImage")) { |
| 533 | + paramNames[i] = "img"; |
| 534 | + } else if (type.contains("color")) { |
| 535 | + paramNames[i] = "col"; |
| 536 | + } else if (type.contains("char")) { |
| 537 | + paramNames[i] = "ch"; |
| 538 | + } else if (type.contains("Object")) { |
| 539 | + paramNames[i] = "obj"; |
| 540 | + } else if (type.contains("[]")) { |
| 541 | + paramNames[i] = "array"; |
| 542 | + } else { |
| 543 | + paramNames[i] = "param" + (i+1); |
| 544 | + } |
| 545 | + } |
| 546 | + |
| 547 | + // Special case handling for common parameter patterns |
| 548 | + if (paramNames.length == 2 && |
| 549 | + (paramTypes[0].contains("int") || paramTypes[0].contains("float")) && |
| 550 | + (paramTypes[1].contains("int") || paramTypes[1].contains("float"))) { |
| 551 | + paramNames[0] = "x"; |
| 552 | + paramNames[1] = "y"; |
| 553 | + } else if (paramNames.length == 3 && |
| 554 | + (paramTypes[0].contains("int") || paramTypes[0].contains("float")) && |
| 555 | + (paramTypes[1].contains("int") || paramTypes[1].contains("float")) && |
| 556 | + (paramTypes[2].contains("int") || paramTypes[2].contains("float"))) { |
| 557 | + paramNames[0] = "x"; |
| 558 | + paramNames[1] = "y"; |
| 559 | + paramNames[2] = "z"; |
| 560 | + } else if (paramNames.length == 4 && |
| 561 | + (paramTypes[0].contains("int") || paramTypes[0].contains("float")) && |
| 562 | + (paramTypes[1].contains("int") || paramTypes[1].contains("float")) && |
| 563 | + (paramTypes[2].contains("int") || paramTypes[2].contains("float")) && |
| 564 | + (paramTypes[3].contains("int") || paramTypes[3].contains("float"))) { |
| 565 | + paramNames[0] = "x"; |
| 566 | + paramNames[1] = "y"; |
| 567 | + paramNames[2] = "width"; |
| 568 | + paramNames[3] = "height"; |
| 569 | + } |
| 570 | + |
| 571 | + return paramNames; |
| 572 | + } |
443 | 573 | } |
0 commit comments