diff --git a/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java b/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java index 7cd514f..5c92680 100644 --- a/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java +++ b/src/main/java/io/github/jeddict/ai/JavaCompletionProvider.java @@ -22,7 +22,6 @@ import io.github.jeddict.ai.scanner.MyTreePathScanner; import com.sun.source.tree.ClassTree; import java.util.*; -import java.util.concurrent.atomic.AtomicReference; import javax.swing.text.JTextComponent; @@ -78,6 +77,7 @@ import static io.github.jeddict.ai.scanner.ProjectClassScanner.getJeddictChatModel; import io.github.jeddict.ai.settings.AIClassContext; import io.github.jeddict.ai.settings.PreferencesManager; +import static io.github.jeddict.ai.util.MimeUtil.JAVA_MIME; import static io.github.jeddict.ai.util.StringUtil.removeAllSpaces; import static io.github.jeddict.ai.util.StringUtil.trimLeadingSpaces; import java.io.OutputStream; @@ -85,9 +85,9 @@ import org.netbeans.api.editor.completion.Completion; import static org.netbeans.spi.editor.completion.CompletionProvider.COMPLETION_QUERY_TYPE; -@MimeRegistration(mimeType = "text/x-java", service = CompletionProvider.class, position = 100) //NOI18N +@MimeRegistration(mimeType = "", service = CompletionProvider.class, position = 100) //NOI18N public class JavaCompletionProvider implements CompletionProvider { - + private static final PreferencesManager prefsManager = PreferencesManager.getInstance(); @Override @@ -269,7 +269,9 @@ protected void query(CompletionResultSet resultSet, Document doc, int caretOffse } done = true; this.caretOffset = caretOffset; - if (COMPLETION_QUERY_TYPE == queryType && isJavaContext(component.getDocument(), caretOffset, true)) { + String mimeType = (String) doc.getProperty("mimeType"); + if (COMPLETION_QUERY_TYPE == queryType && JAVA_MIME.equals(mimeType) + && isJavaContext(component.getDocument(), caretOffset, true)) { JavacTask task = getJavacTask(doc); Iterable ast = task.parse(); task.analyze(); @@ -425,7 +427,7 @@ protected void query(CompletionResultSet resultSet, Document doc, int caretOffse } else { System.out.println(path.getLeaf().getKind() + " " + path.getLeaf().toString()); } - } else { + } else if(COMPLETION_QUERY_TYPE == queryType && JAVA_MIME.equals(mimeType)) { String line = getLineText(doc, caretOffset); JavacTask task = getJavacTask(doc); Iterable ast = task.parse(); @@ -464,10 +466,17 @@ protected void query(CompletionResultSet resultSet, Document doc, int caretOffse } JeddictItem var = new JeddictItem(null, null, varName, Collections.emptyList(), newcaretOffset, true, false, -1); resultSet.addItem(var); - } - } - + } + } else { + String currentLine = getLineText(doc, caretOffset); + FileObject fileObject = getFileObjectFromEditor(doc); + String updateddoc = insertPlaceholderAtCaret(doc, caretOffset, "${SUGGEST_CODE_LIST}"); + List sugs = getJeddictChatModel(fileObject).suggestNextLineCode(updateddoc, currentLine, mimeType); + for (Snippet varName : sugs) { + JeddictItem var = new JeddictItem(null, null, varName.getSnippet(), Collections.emptyList(), caretOffset, true, false, -1); + resultSet.addItem(var); + } } } catch (Exception e) { Exceptions.printStackTrace(e); diff --git a/src/main/java/io/github/jeddict/ai/JeddictChatModel.java b/src/main/java/io/github/jeddict/ai/JeddictChatModel.java index 8f9959f..9c39b92 100644 --- a/src/main/java/io/github/jeddict/ai/JeddictChatModel.java +++ b/src/main/java/io/github/jeddict/ai/JeddictChatModel.java @@ -21,11 +21,13 @@ /** * * @author Gaurav Gupta + * @author Shiwani Gupta */ import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import dev.langchain4j.model.openai.OpenAiChatModel; import io.github.jeddict.ai.settings.PreferencesManager; +import static io.github.jeddict.ai.util.MimeUtil.MIME_TYPE_DESCRIPTIONS; import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers; import java.util.ArrayList; import java.util.Arrays; @@ -479,11 +481,13 @@ public List parseJsonToSnippets(String jsonResponse) { for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); - // Extract the "imports" array - JSONArray importsJsonArray = jsonObject.getJSONArray("imports"); List importsList = new ArrayList<>(); - for (int j = 0; j < importsJsonArray.length(); j++) { - importsList.add(importsJsonArray.getString(j)); + if (jsonObject.has("imports")) { + // Extract the "imports" array + JSONArray importsJsonArray = jsonObject.getJSONArray("imports"); + for (int j = 0; j < importsJsonArray.length(); j++) { + importsList.add(importsJsonArray.getString(j)); + } } // Extract the "snippet" field @@ -647,4 +651,27 @@ public String generateHtmlDescriptionForClass(String classContent, String previo return answer; } + public List suggestNextLineCode(String fileContent, String currentLine, String mimeType) { + StringBuilder description = new StringBuilder(MIME_TYPE_DESCRIPTIONS.getOrDefault(mimeType, "code snippets")); + StringBuilder prompt = new StringBuilder("You are an API server that provides ").append(description).append(" suggestions based on the file content. "); + if (currentLine == null || currentLine.isEmpty()) { + prompt.append("Analyze the content and recommend appropriate additions at the placeholder ${SUGGEST_CODE_LIST}. "); + } else { + prompt.append("Analyze the content and the current line: \n") + .append(currentLine) + .append("\nRecommend appropriate additions at the placeholder ${SUGGEST_CODE_LIST}. "); + } + prompt.append(""" + Ensure the suggestions align with the file's context and structure. + Respond with a JSON array containing a few of the best options. + Each entry should have one field, 'snippet', holding the recommended code block. + The code block can contain multiple lines, formatted as a single string using \\n for line breaks. + + File Content: + """).append(fileContent); + String jsonResponse = generate(prompt.toString()); + List nextLines = parseJsonToSnippets(jsonResponse); + return nextLines; + } + } diff --git a/src/main/java/io/github/jeddict/ai/util/MimeUtil.java b/src/main/java/io/github/jeddict/ai/util/MimeUtil.java new file mode 100644 index 0000000..aaf05b0 --- /dev/null +++ b/src/main/java/io/github/jeddict/ai/util/MimeUtil.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package io.github.jeddict.ai.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * + * @author Shiwani Gupta + */ +public class MimeUtil { + + public static final String JAVA_MIME = "text/x-java"; + public static final String MIME_HTML = "text/html"; + public static final String MIME_CSS = "text/css"; + public static final String MIME_SCSS = "text/scss"; + public static final String MIME_SASS = "text/sass"; + public static final String MIME_LESS = "text/less"; + public static final String MIME_XHTML = "text/xhtml"; + public static final String MIME_JS = "application/javascript"; + public static final String MIME_JS_ALT = "text/x-javascript"; + public static final String MIME_JADE = "text/jade"; + public static final String MIME_MAVEN_POM = "text/x-maven-pom+xml"; + public static final String MIME_GRADLE = "text/x-gradle+x-groovy"; + public static final String MIME_NETBEANS_LAYER = "text/x-netbeans-layer+xml"; + public static final String MIME_BEANS_JAKARTA = "text/x-beans-jakarta+xml"; + public static final String MIME_BEANS = "text/x-beans+xml"; + public static final String MIME_JSP = "text/x-jsp"; + public static final String MIME_JSON = "text/x-json"; + public static final String MIME_YAML = "text/x-yaml"; + public static final String MIME_TOML = "text/x-toml"; + public static final String MIME_PROPERTIES = "text/x-properties"; + public static final String MIME_GROOVY = "text/x-groovy"; + public static final String MIME_DOCKERFILE = "text/x-dockerfile"; + public static final String MIME_SQL = "text/x-sql"; + public static final String MIME_XML_DTD = "application/xml-dtd"; + public static final String MIME_XML = "text/xml"; + public static final String MIME_TESTNG = "text/x-testng+xml"; + public static final String MIME_FXML = "text/x-fxml+xml"; + public static final String MIME_RUST = "text/x-rust"; + public static final String MIME_TAG = "text/x-tag"; + public static final String MIME_PHP5 = "text/x-php5"; + public static final String MIME_TWIG = "text/x-twig"; + public static final String MIME_TPL = "x-tpl"; + public static final String MIME_LATTE = "text/x-latte"; + public static final String MIME_KO_DATA_BIND = "text/ko-data-bind"; + public static final String MIME_TYPESCRIPT = "application/x-typescript"; + public static final String MIME_ANT_XML = "text/x-ant+xml"; + public static final String MIME_PLAIN_TEXT = "text/plain"; + public static final String MIME_REPL = "text/x-repl"; + public static final String MIME_SHELL = "text/sh"; + + public static final Map MIME_TYPE_DESCRIPTIONS = new HashMap<>(); + + static { + MIME_TYPE_DESCRIPTIONS.put(MIME_HTML, "HTML elements and attributes"); + MIME_TYPE_DESCRIPTIONS.put(MIME_CSS, "CSS styles"); + MIME_TYPE_DESCRIPTIONS.put(MIME_SCSS, "SCSS styles (Sassy CSS extension)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_SASS, "SASS styles (Syntactically Awesome Style Sheets)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_LESS, "LESS styles (Leaner CSS extension)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_XHTML, "JSF page (Java Server Faces)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_JS, "JavaScript code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_JS_ALT, "JavaScript code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_JADE, "JavaScript Jade template code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_MAVEN_POM, "Maven pom.xml file"); + MIME_TYPE_DESCRIPTIONS.put(MIME_GRADLE, "Gradle build script (Groovy DSL)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_NETBEANS_LAYER, "NetBeans module configuration XML (Layer XML)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_BEANS_JAKARTA, "Jakarta EE Beans XML"); + MIME_TYPE_DESCRIPTIONS.put(MIME_BEANS, "JavaBeans XML (general bean configuration)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_JSP, "JavaServer Pages (JSP) code for server-side Java web applications"); + MIME_TYPE_DESCRIPTIONS.put(MIME_JSON, "JSON"); + MIME_TYPE_DESCRIPTIONS.put(MIME_YAML, "YAML"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TOML, "Tom's Obvious, Minimal Language (TOML) for configuration files"); + MIME_TYPE_DESCRIPTIONS.put(MIME_PROPERTIES, "Properties file (key-value pairs for configuration)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_GROOVY, "Groovy scripting language"); + MIME_TYPE_DESCRIPTIONS.put(MIME_DOCKERFILE, "Dockerfile for defining container images"); + MIME_TYPE_DESCRIPTIONS.put(MIME_SQL, "Structured Query Language (SQL) queries"); + MIME_TYPE_DESCRIPTIONS.put(MIME_XML_DTD, "XML Document Type Definition (DTD) for defining XML structure"); + MIME_TYPE_DESCRIPTIONS.put(MIME_XML, "XML data (Extensible Markup Language)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TESTNG, "TestNG configuration XML (for TestNG testing framework)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_FXML, "FXML (JavaFX interface markup)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_RUST, "Rust code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TAG, "Custom tag file (Java-based custom JSP tags)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_PHP5, "PHP5 code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TWIG, "Twig template engine for PHP"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TPL, "PHP TPL template"); + MIME_TYPE_DESCRIPTIONS.put(MIME_LATTE, "Latte template engine for PHP"); + MIME_TYPE_DESCRIPTIONS.put(MIME_KO_DATA_BIND, "KnockoutJS data binding"); + MIME_TYPE_DESCRIPTIONS.put(MIME_TYPESCRIPT, "TypeScript code"); + MIME_TYPE_DESCRIPTIONS.put(MIME_ANT_XML, "Apache Ant build script XML"); + MIME_TYPE_DESCRIPTIONS.put(MIME_PLAIN_TEXT, "Plain text (no special formatting or markup)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_REPL, "REPL code (Read-Eval-Print Loop, interactive programming environment)"); + MIME_TYPE_DESCRIPTIONS.put(MIME_SHELL, "Shell script (commands for Unix/Linux shell environments)"); + } +}