block.\n\n"
+ + "If Full Java Class is in response then wrap it in
. "
+ + "If partial snippet of Java Class are in response then wrap it in
. "
+ + "Projects Content:\n" + projectContent + "\n\n"
+ + "Query:\n" + query;
+
+ // Generate the HTML description
+ String answer = generate(prompt);
+ System.out.println(answer);
+ return answer;
+ }
+
public String generateHtmlDescriptionForClass(String classContent) {
String prompt = "You are an API server that provides description of following class in HTML. "
+ "Do not include additional text or explanations outside of the HTML content.\n\n"
+ + "If Full Java Class is in response then wrap it in
. "
+ + "If partial snippet of Java Class are in response then wrap it in
. "
+ "Java Class Content:\n" + classContent;
// Generate the HTML description
@@ -725,10 +748,12 @@ public String generateHtmlDescriptionForClass(String classContent) {
System.out.println(answer);
return answer;
}
-
+
public String generateHtmlDescriptionForMethod(String methodContent) {
String prompt = "You are an API server that provides description of following Method in HTML. "
+ "Do not include additional text or explanations outside of the HTML content.\n\n"
+ + "If Full Java Class is in response then wrap it in
. "
+ + "If partial snippet of Java Class are in response then wrap it in
. "
+ "Java Method Content:\n" + methodContent;
// Generate the HTML description
@@ -737,12 +762,19 @@ public String generateHtmlDescriptionForMethod(String methodContent) {
return answer;
}
- public String generateHtmlDescription(String classContent, String methodContent, String previousChatResponse, String userQuery) {
+ public String generateHtmlDescription(
+ String projectContent, String classContent, String methodContent,
+ String previousChatResponse, String userQuery) {
String prompt;
String promptExtend;
if (methodContent != null) {
promptExtend = "Method Content:\n" + methodContent + "\n\n"
+ "Do not return complete Java Class, return only Method and wrap it in . \n";
+ } else if (projectContent != null) {
+ promptExtend = "Project Full Content:\n" + classContent + "\n\n"
+ + "If Full Java Class is in response then wrap it in . "
+ + "If partial snippet of Java Class are in response then wrap it in . ";
+
} else {
promptExtend = "Orignal Java Class Content:\n" + classContent + "\n\n"
+ "If Full Java Class is in response then wrap it in . "
diff --git a/src/main/java/io/github/jeddict/ai/actions/AskAIPackageAction.java b/src/main/java/io/github/jeddict/ai/actions/AskAIPackageAction.java
new file mode 100644
index 0000000..afe4444
--- /dev/null
+++ b/src/main/java/io/github/jeddict/ai/actions/AskAIPackageAction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.actions;
+
+import io.github.jeddict.ai.hints.LearnFix;
+import io.github.jeddict.ai.settings.PreferencesManager;
+import static io.github.jeddict.ai.util.UIUtil.askQuery;
+import java.awt.event.ActionEvent;
+import java.util.Collection;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.awt.DynamicMenuContent;
+import org.openide.filesystems.FileObject;
+import org.openide.util.ContextAwareAction;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(
+ category = "Project",
+ id = "io.github.jeddict.ai.actions.AskAIPackageAction")
+@ActionRegistration(
+ displayName = "#CTL_AskAIPackageAction", lazy = false, asynchronous = true)
+@ActionReference(path = "Projects/package/Actions", position = 100)
+@Messages({"CTL_AskAIPackageAction=Ask AI"})
+public final class AskAIPackageAction extends AbstractAction implements ContextAwareAction {
+
+ @Override
+ public void actionPerformed(ActionEvent ev) {
+ }
+
+ @Override
+ public Action createContextAwareInstance(Lookup actionContext) {
+ if (actionContext != null) {
+ return new AskAIPackageAction.ContextAction(
+ PreferencesManager.getInstance().isAiAssistantActivated(),
+ actionContext.lookupAll(FileObject.class)
+ );
+ }
+ return new AskAIPackageAction.ContextAction(false, null);
+ }
+
+ private static final class ContextAction extends AbstractAction {
+
+ private final Collection extends FileObject> selectedPackages;
+
+ private ContextAction(boolean enable, Collection extends FileObject> selectedPackages) {
+ super(Bundle.CTL_AskAIPackageAction());
+ this.putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
+ this.setEnabled(enable);
+ this.selectedPackages = selectedPackages;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent evt) {
+ String query = askQuery();
+ if (query == null) {
+ return;
+ }
+ LearnFix learnFix = new LearnFix(io.github.jeddict.ai.completion.Action.QUERY);
+ learnFix.askQueryForPackage(selectedPackages, query);
+ }
+
+ }
+}
diff --git a/src/main/java/io/github/jeddict/ai/actions/AskAIProjectAction.java b/src/main/java/io/github/jeddict/ai/actions/AskAIProjectAction.java
new file mode 100644
index 0000000..a50bede
--- /dev/null
+++ b/src/main/java/io/github/jeddict/ai/actions/AskAIProjectAction.java
@@ -0,0 +1,84 @@
+/*
+ * 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.actions;
+
+import io.github.jeddict.ai.hints.LearnFix;
+import io.github.jeddict.ai.settings.PreferencesManager;
+import static io.github.jeddict.ai.util.UIUtil.askQuery;
+import java.awt.event.ActionEvent;
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import org.netbeans.api.project.Project;
+import org.openide.awt.ActionID;
+import org.openide.awt.ActionReference;
+import org.openide.awt.ActionReferences;
+import org.openide.awt.ActionRegistration;
+import org.openide.awt.DynamicMenuContent;
+import org.openide.util.ContextAwareAction;
+import org.openide.util.Lookup;
+import org.openide.util.NbBundle.Messages;
+
+@ActionID(
+ category = "Project",
+ id = "io.github.jeddict.ai.actions.AskAIProjectAction")
+@ActionRegistration(
+ displayName = "#CTL_AskAIProjectAction", lazy = false, asynchronous = true)
+@ActionReferences({
+ @ActionReference(path = "Projects/Actions", position = 100),})
+@Messages({"CTL_AskAIProjectAction=Ask AI"})
+public final class AskAIProjectAction extends AbstractAction implements ContextAwareAction {
+
+ @Override
+ public void actionPerformed(ActionEvent ev) {
+ }
+
+ @Override
+ public Action createContextAwareInstance(Lookup actionContext) {
+ if (actionContext != null) {
+ return new AskAIProjectAction.ContextAction(
+ PreferencesManager.getInstance().isAiAssistantActivated(),
+ actionContext.lookup(Project.class)
+ );
+ }
+ return new AskAIProjectAction.ContextAction(false, null);
+ }
+
+ private static final class ContextAction extends AbstractAction {
+
+ private final Project project;
+
+ private ContextAction(boolean enable, Project project) {
+ super(Bundle.CTL_AskAIProjectAction());
+ this.putValue(DynamicMenuContent.HIDE_WHEN_DISABLED, true);
+ this.setEnabled(enable);
+ this.project = project;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent evt) {
+ String query = askQuery();
+ if (query == null) {
+ return;
+ }
+ LearnFix learnFix = new LearnFix(io.github.jeddict.ai.completion.Action.QUERY);
+ learnFix.askQueryForProject(project, query);
+ }
+
+ }
+}
diff --git a/src/main/java/io/github/jeddict/ai/completion/JeddictItem.java b/src/main/java/io/github/jeddict/ai/completion/JeddictItem.java
index 1906666..4dcf678 100644
--- a/src/main/java/io/github/jeddict/ai/completion/JeddictItem.java
+++ b/src/main/java/io/github/jeddict/ai/completion/JeddictItem.java
@@ -4,6 +4,7 @@
*/
package io.github.jeddict.ai.completion;
+import io.github.jeddict.ai.components.AssistantTopComponent;
import io.github.jeddict.ai.util.Utilities;
import static io.github.jeddict.ai.util.Utilities.getHTMLColor;
import io.github.jeddict.ai.util.SourceUtil;
@@ -23,7 +24,6 @@
import org.netbeans.spi.editor.completion.CompletionDocumentation;
import org.netbeans.spi.editor.completion.CompletionResultSet;
import org.netbeans.spi.editor.completion.CompletionTask;
-import org.openide.util.ImageUtilities;
import org.openide.xml.XMLUtil;
/**
@@ -151,10 +151,7 @@ protected String getRightHtmlText() {
@Override
protected ImageIcon getIcon() {
- if (icon == null) {
- icon = ImageUtilities.loadImageIcon(LOCAL_VARIABLE, false);
- }
- return null;
+ return AssistantTopComponent.icon;
}
@Override
diff --git a/src/main/java/io/github/jeddict/ai/components/AssistantTopComponent.java b/src/main/java/io/github/jeddict/ai/components/AssistantTopComponent.java
index b8564dd..82b1b4b 100644
--- a/src/main/java/io/github/jeddict/ai/components/AssistantTopComponent.java
+++ b/src/main/java/io/github/jeddict/ai/components/AssistantTopComponent.java
@@ -20,16 +20,12 @@
import java.awt.BorderLayout;
import java.awt.Desktop;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.net.HttpURLConnection;
-import java.net.URL;
import java.util.prefs.Preferences;
import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
import javax.swing.text.EditorKit;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
@@ -43,6 +39,7 @@
*/
public class AssistantTopComponent extends TopComponent {
+ public static final ImageIcon icon = new ImageIcon(AssistantTopComponent.class.getResource("/icons/logo16.png"));
public static final String PREFERENCE_KEY = "AssistantTopComponentOpen";
private final JPanel parentPanel;
private HTMLEditorKit editorKit;
@@ -50,10 +47,10 @@ public class AssistantTopComponent extends TopComponent {
public AssistantTopComponent(String name) {
setName(name);
setLayout(new BorderLayout());
+ setIcon(icon.getImage());
parentPanel = new JPanel();
parentPanel.setLayout(new BoxLayout(parentPanel, BoxLayout.Y_AXIS));
-
add(parentPanel, BorderLayout.CENTER);
}
diff --git a/src/main/java/io/github/jeddict/ai/hints/LearnFix.java b/src/main/java/io/github/jeddict/ai/hints/LearnFix.java
index 449c30b..8568698 100644
--- a/src/main/java/io/github/jeddict/ai/hints/LearnFix.java
+++ b/src/main/java/io/github/jeddict/ai/hints/LearnFix.java
@@ -29,9 +29,9 @@
import io.github.jeddict.ai.completion.Action;
import io.github.jeddict.ai.JeddictChatModel;
import io.github.jeddict.ai.components.AssistantTopComponent;
+import static io.github.jeddict.ai.util.ProjectUtils.getSourceFiles;
import io.github.jeddict.ai.util.StringUtil;
import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers;
-import static io.github.jeddict.ai.util.UIUtil.askQueryAboutClass;
import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Dimension;
@@ -47,8 +47,12 @@
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
import java.util.prefs.Preferences;
+import java.util.stream.Collectors;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JPanel;
@@ -59,8 +63,15 @@
import org.netbeans.api.java.source.JavaSource;
import org.netbeans.api.java.source.TreePathHandle;
import org.netbeans.api.java.source.WorkingCopy;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.netbeans.api.project.ProjectUtils;
import org.netbeans.spi.java.hints.JavaFix;
+import org.openide.filesystems.FileObject;
+import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
+import static io.github.jeddict.ai.util.UIUtil.askQuery;
/**
*
@@ -68,8 +79,20 @@
*/
public class LearnFix extends JavaFix {
- private final TreePath treePath;
+ private final List acceptedExtensions = Arrays.asList(
+ "java", "php", "jsf", "kt", "groovy", "scala", "xml", "json", "yaml", "yml",
+ "properties", "txt", "md", "js", "ts", "css", "scss", "html", "xhtml", "sh",
+ "bat", "sql", "jsp", "rb", "cs", "go", "swift", "rs", "c", "cpp", "h", "py"
+ );
+
+ private TreePath treePath;
private final Action action;
+ private JButton prevButton, nextButton, saveButton;
+ private AssistantTopComponent topComponent;
+ private final List responseHistory = new ArrayList<>();
+ private int currentResponseIndex = -1;
+ private String javaCode = null;
+ private String projectContent;
public LearnFix(TreePathHandle tpHandle, Action action, TreePath treePath) {
super(tpHandle);
@@ -77,6 +100,11 @@ public LearnFix(TreePathHandle tpHandle, Action action, TreePath treePath) {
this.action = action;
}
+ public LearnFix(Action action) {
+ super(null);
+ this.action = action;
+ }
+
@Override
protected String getText() {
if (action == Action.LEARN) {
@@ -101,13 +129,13 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception
|| leaf.getKind() == INTERFACE
|| leaf.getKind() == ENUM
|| leaf.getKind() == METHOD) {
- String response = null;
+ String response;
if (action == Action.QUERY) {
- String query = askQueryAboutClass();
+ String query = askQuery();
if (query == null) {
return;
}
- response = new JeddictChatModel().generateHtmlDescription(treePath.getCompilationUnit().toString(), null, null, query);
+ response = new JeddictChatModel().generateHtmlDescription(null, treePath.getCompilationUnit().toString(), null, null, query);
} else {
if (leaf instanceof MethodTree) {
response = new JeddictChatModel().generateHtmlDescriptionForMethod(leaf.toString());
@@ -123,17 +151,63 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception
name = ((ClassTree) leaf).getSimpleName().toString();
}
- displayHtmlContent(copy, tc.getPath(), removeCodeBlockMarkers(response), name);
+ displayHtmlContent(removeCodeBlockMarkers(response), name);
}
}
- private JButton prevButton, nextButton, saveButton;
- private AssistantTopComponent topComponent;
- private final List responseHistory = new ArrayList<>();
- private int currentResponseIndex = -1;
- String javaCode = null;
+ public void askQueryForProject(Project project, String userQuery) {
- private void displayHtmlContent(WorkingCopy copy, TreePath tp, final String response, String title) {
+ ProjectInformation info = ProjectUtils.getInformation(project);
+ String projectName = info.getDisplayName();
+ List sourceFiles = getSourceFiles(project);
+
+ StringBuilder inputForAI = new StringBuilder();
+ for (FileObject file : sourceFiles) {
+ try {
+ if (acceptedExtensions.contains(file.getExt())) {
+ inputForAI.append(file.asText());
+ inputForAI.append("\n");
+ }
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+
+ projectContent = inputForAI.toString();
+ String response = new JeddictChatModel().generateHtmlDescriptionForProject(projectContent, userQuery);
+ displayHtmlContent(removeCodeBlockMarkers(response), projectName);
+ }
+
+ public void askQueryForPackage(Collection extends FileObject> selectedPackages, String userQuery) {
+ Iterator extends FileObject> selectedPackagesIterator = selectedPackages.iterator();
+ if (selectedPackagesIterator.hasNext()) {
+ Project project = FileOwnerQuery.getOwner(selectedPackagesIterator.next());
+ ProjectInformation info = ProjectUtils.getInformation(project);
+ String projectName = info.getDisplayName();
+
+ List sourceFiles = selectedPackages.stream()
+ .filter(FileObject::isFolder)
+ .flatMap(packageFolder -> Arrays.stream(packageFolder.getChildren())
+ .filter(FileObject::isData)
+ .filter(file -> acceptedExtensions.contains(file.getExt())))
+ .collect(Collectors.toList());
+
+ StringBuilder inputForAI = new StringBuilder();
+ for (FileObject file : sourceFiles) {
+ try {
+ inputForAI.append(file.asText());
+ inputForAI.append("\n");
+ } catch (Exception ex) {
+ Exceptions.printStackTrace(ex);
+ }
+ }
+ projectContent = inputForAI.toString();
+ String response = new JeddictChatModel().generateHtmlDescriptionForProject(projectContent, userQuery);
+ displayHtmlContent(removeCodeBlockMarkers(response), projectName);
+ }
+ }
+
+ private void displayHtmlContent(final String response, String title) {
SwingUtilities.invokeLater(() -> {
try {
File tempFile = File.createTempFile("tempHtml", ".html");
@@ -158,118 +232,10 @@ private void displayHtmlContent(WorkingCopy copy, TreePath tp, final String resp
JScrollPane scrollPane = new JScrollPane(topComponent.getParentPanel());
topComponent.add(scrollPane, BorderLayout.CENTER);
- // Create a panel for the text field and buttons
- JPanel bottomPanel = new JPanel(new GridBagLayout());
- GridBagConstraints gbc = new GridBagConstraints();
- gbc.insets = new Insets(2, 2, 2, 2);
-
- // Previous Button
- prevButton = new JButton("\u2190"); // Left arrow (←)
- gbc.gridx = 0;
- gbc.gridy = 0;
- gbc.anchor = GridBagConstraints.WEST;
- bottomPanel.add(prevButton, gbc);
-
- // Next Button
- nextButton = new JButton("\u2192");
- gbc.gridx = 1;
- gbc.gridy = 0;
- gbc.anchor = GridBagConstraints.WEST;
- bottomPanel.add(nextButton, gbc);
-
- // Text Field
- JTextField questionField = new JTextField();
- questionField.setPreferredSize(new Dimension(300, questionField.getPreferredSize().height)); // Set preferred size
- gbc.gridx = 2;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.HORIZONTAL;
- gbc.weightx = 1.0; // Allow text field to expand
- bottomPanel.add(questionField, gbc);
-
- // Ask Button
- JButton submitButton = new JButton("Ask");
- gbc.gridx = 3;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.NONE;
- gbc.weightx = 0; // No expansion
- bottomPanel.add(submitButton, gbc);
-
- // Save Button
- saveButton = new JButton("Copy");
- gbc.gridx = 4;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.NONE;
- gbc.weightx = 0; // No expansion
- bottomPanel.add(saveButton, gbc);
-
- saveButton.addActionListener(e -> {
- try {
- StringSelection selection = new StringSelection(javaCode);
- Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
- clipboard.setContents(selection, null);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- });
-
- JButton upButton = new JButton("\u2191"); // Up arrow (↑)
- gbc.gridx = 5;
- gbc.gridy = 0;
- gbc.fill = GridBagConstraints.NONE;
- gbc.weightx = 0; // No expansion
- bottomPanel.add(upButton, gbc);
-
- upButton.addActionListener(e -> {
- try {
- File latestTempFile = File.createTempFile(title, ".html");
- latestTempFile.deleteOnExit();
- try (FileWriter writer = new FileWriter(latestTempFile)) {
- writer.write(responseHistory.get(currentResponseIndex));
- }
- if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
- Desktop.getDesktop().browse(latestTempFile.toURI());
- }
- } catch (IOException ex) {
- ex.printStackTrace();
- }
- });
-
- // Create a common action listener method
- ActionListener submitActionListener = e -> {
- String question = questionField.getText();
- if (!question.isEmpty()) {
- submitButton.setText("Loading...");
- submitButton.setEnabled(false);
- handleQuestion(question, submitButton);
- }
- };
-
- submitButton.addActionListener(submitActionListener);
- questionField.addActionListener(submitActionListener);
-
responseHistory.add(response);
currentResponseIndex = responseHistory.size() - 1;
- prevButton.addActionListener(e -> {
- if (currentResponseIndex > 0) {
- currentResponseIndex--;
- String historyResponse = responseHistory.get(currentResponseIndex);
- updateEditor(historyResponse);
- updateNavigationButtons(prevButton, nextButton);
- }
- });
- nextButton.addActionListener(e -> {
- if (currentResponseIndex < responseHistory.size() - 1) {
- currentResponseIndex++;
- String historyResponse = responseHistory.get(currentResponseIndex);
- updateEditor(historyResponse);
- updateNavigationButtons(prevButton, nextButton);
- }
- });
-
- updateNavigationButtons(prevButton, nextButton);
-
- topComponent.add(bottomPanel, BorderLayout.SOUTH);
+ topComponent.add(createBottomPanel(title), BorderLayout.SOUTH);
topComponent.open();
topComponent.requestActive();
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
@@ -284,10 +250,121 @@ private void displayHtmlContent(WorkingCopy copy, TreePath tp, final String resp
});
}
+ private JPanel createBottomPanel(String title) {
+ // Create a panel for the text field and buttons
+ JPanel bottomPanel = new JPanel(new GridBagLayout());
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.insets = new Insets(2, 2, 2, 2);
+
+ // Previous Button
+ prevButton = new JButton("\u2190"); // Left arrow (←)
+ gbc.gridx = 0;
+ gbc.gridy = 0;
+ gbc.anchor = GridBagConstraints.WEST;
+ bottomPanel.add(prevButton, gbc);
+
+ // Next Button
+ nextButton = new JButton("\u2192");
+ gbc.gridx = 1;
+ gbc.gridy = 0;
+ gbc.anchor = GridBagConstraints.WEST;
+ bottomPanel.add(nextButton, gbc);
+
+ // Text Field
+ JTextField questionField = new JTextField();
+ questionField.setPreferredSize(new Dimension(300, questionField.getPreferredSize().height));
+ gbc.gridx = 2;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ bottomPanel.add(questionField, gbc);
+
+ // Ask Button
+ JButton submitButton = new JButton("Ask");
+ gbc.gridx = 3;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0;
+ bottomPanel.add(submitButton, gbc);
+
+ // Save Button
+ saveButton = new JButton("Copy");
+ gbc.gridx = 4;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0;
+ bottomPanel.add(saveButton, gbc);
+
+ saveButton.addActionListener(e -> {
+ try {
+ StringSelection selection = new StringSelection(javaCode);
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(selection, null);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ });
+
+ JButton upButton = new JButton("\u2191"); // Up arrow (↑)
+ gbc.gridx = 5;
+ gbc.gridy = 0;
+ gbc.fill = GridBagConstraints.NONE;
+ gbc.weightx = 0; // No expansion
+ bottomPanel.add(upButton, gbc);
+
+ upButton.addActionListener(e -> {
+ try {
+ File latestTempFile = File.createTempFile(title, ".html");
+ latestTempFile.deleteOnExit();
+ try (FileWriter writer = new FileWriter(latestTempFile)) {
+ writer.write(responseHistory.get(currentResponseIndex));
+ }
+ if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) {
+ Desktop.getDesktop().browse(latestTempFile.toURI());
+ }
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ });
+
+ // Create a common action listener method
+ ActionListener submitActionListener = e -> {
+ String question = questionField.getText();
+ if (!question.isEmpty()) {
+ submitButton.setText("Loading...");
+ submitButton.setEnabled(false);
+ handleQuestion(question, submitButton);
+ }
+ };
+
+ submitButton.addActionListener(submitActionListener);
+ questionField.addActionListener(submitActionListener);
+
+ prevButton.addActionListener(e -> {
+ if (currentResponseIndex > 0) {
+ currentResponseIndex--;
+ String historyResponse = responseHistory.get(currentResponseIndex);
+ updateEditor(historyResponse);
+ updateNavigationButtons(prevButton, nextButton);
+ }
+ });
+ nextButton.addActionListener(e -> {
+ if (currentResponseIndex < responseHistory.size() - 1) {
+ currentResponseIndex++;
+ String historyResponse = responseHistory.get(currentResponseIndex);
+ updateEditor(historyResponse);
+ updateNavigationButtons(prevButton, nextButton);
+ }
+ });
+
+ updateNavigationButtons(prevButton, nextButton);
+
+ return bottomPanel;
+ }
+
private JEditorPane updateEditor(String response) {
JEditorPane editorPane = null;
String[] parts = response.split("||||
");
-// String[] parts = response.split("|||
");
topComponent.clear();
for (int i = 0; i < parts.length; i++) {
if (i % 2 == 1) {
@@ -312,8 +389,12 @@ private void handleQuestion(String question, JButton submitButton) {
prevChat = null;
}
}
-
- String response = new JeddictChatModel().generateHtmlDescription(treePath.getCompilationUnit().toString(), treePath.getLeaf() instanceof MethodTree ? treePath.getLeaf().toString() : null, prevChat, question);
+ String response;
+ if (treePath == null && projectContent != null) {
+ response = new JeddictChatModel().generateHtmlDescription(projectContent, null, null, prevChat, question);
+ } else {
+ response = new JeddictChatModel().generateHtmlDescription(null, treePath.getCompilationUnit().toString(), treePath.getLeaf() instanceof MethodTree ? treePath.getLeaf().toString() : null, prevChat, question);
+ }
response = removeCodeBlockMarkers(response);
if (responseHistory.isEmpty() || !response.equals(responseHistory.get(responseHistory.size() - 1))) {
responseHistory.add(response);
diff --git a/src/main/java/io/github/jeddict/ai/hints/MethodFix.java b/src/main/java/io/github/jeddict/ai/hints/MethodFix.java
index 9b02bd6..f3352dd 100644
--- a/src/main/java/io/github/jeddict/ai/hints/MethodFix.java
+++ b/src/main/java/io/github/jeddict/ai/hints/MethodFix.java
@@ -15,7 +15,6 @@
import static io.github.jeddict.ai.util.FileUtil.saveOpenEditor;
import static io.github.jeddict.ai.util.SourceUtil.geIndentaion;
import static io.github.jeddict.ai.util.StringUtil.removeCodeBlockMarkers;
-import static io.github.jeddict.ai.util.UIUtil.askQuery;
import javax.lang.model.element.Element;
import org.json.JSONArray;
import org.json.JSONObject;
@@ -26,6 +25,7 @@
import org.netbeans.api.java.source.WorkingCopy;
import org.netbeans.spi.java.hints.JavaFix;
import org.openide.util.NbBundle;
+import static io.github.jeddict.ai.util.UIUtil.queryToEnhance;
/**
*
@@ -85,7 +85,7 @@ protected void performRewrite(JavaFix.TransformationContext tc) throws Exception
} else if (action == Action.ENHANCE) {
content = new JeddictChatModel().enhanceMethodFromMethodContent(treePath.getParentPath().getLeaf().toString(), leaf.toString());
} else {
- String query = askQuery();
+ String query = queryToEnhance();
if (query == null) {
return;
}
diff --git a/src/main/java/io/github/jeddict/ai/util/ProjectUtils.java b/src/main/java/io/github/jeddict/ai/util/ProjectUtils.java
new file mode 100644
index 0000000..dd14594
--- /dev/null
+++ b/src/main/java/io/github/jeddict/ai/util/ProjectUtils.java
@@ -0,0 +1,40 @@
+/*
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
+ * Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
+ */
+package io.github.jeddict.ai.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.SourceGroup;
+import org.openide.filesystems.FileObject;
+
+/**
+ *
+ * @author Shiwani Gupta
+ */
+public class ProjectUtils {
+
+ public static List getSourceFiles(Project project) {
+ List sourceFiles = new ArrayList<>();
+ SourceGroup[] sourceGroups = org.netbeans.api.project.ProjectUtils.getSources(project).getSourceGroups("java");
+ for (SourceGroup sourceGroup : sourceGroups) {
+ if (sourceGroup.getRootFolder().getParent().getName().equals("test")) {
+ continue;
+ }
+ collectFiles(sourceGroup.getRootFolder(), sourceFiles);
+ }
+ return sourceFiles;
+ }
+
+ public static void collectFiles(FileObject folder, List sourceFiles) {
+ for (FileObject file : folder.getChildren()) {
+ if (file.isFolder()) {
+ collectFiles(file, sourceFiles);
+ } else if (file.isData()) {
+ sourceFiles.add(file);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/jeddict/ai/util/UIUtil.java b/src/main/java/io/github/jeddict/ai/util/UIUtil.java
index 64537b9..3102971 100644
--- a/src/main/java/io/github/jeddict/ai/util/UIUtil.java
+++ b/src/main/java/io/github/jeddict/ai/util/UIUtil.java
@@ -4,6 +4,7 @@
*/
package io.github.jeddict.ai.util;
+import io.github.jeddict.ai.components.AssistantTopComponent;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
@@ -15,7 +16,7 @@
*/
public class UIUtil {
- public static String askQuery() {
+ public static String queryToEnhance() {
// Create a JTextArea for multiline input
JTextArea textArea = new JTextArea(10, 30); // 10 rows, 30 columns
textArea.setWrapStyleWord(true);
@@ -34,7 +35,8 @@ public static String askQuery() {
panel,
"Please provide details about what to update in this method:",
JOptionPane.OK_CANCEL_OPTION,
- JOptionPane.PLAIN_MESSAGE
+ JOptionPane.PLAIN_MESSAGE,
+ AssistantTopComponent.icon
);
// Check the user's choice
@@ -56,7 +58,7 @@ public static String askQuery() {
return query;
}
- public static String askQueryAboutClass() {
+ public static String askQuery() {
// Create a JTextArea for multiline input
JTextArea textArea = new JTextArea(10, 30); // 10 rows, 30 columns
textArea.setWrapStyleWord(true);
@@ -73,9 +75,10 @@ public static String askQueryAboutClass() {
int option = JOptionPane.showConfirmDialog(
null,
panel,
- "Please ask the query about this class.",
+ "Please ask the query.",
JOptionPane.OK_CANCEL_OPTION,
- JOptionPane.PLAIN_MESSAGE
+ JOptionPane.PLAIN_MESSAGE,
+ AssistantTopComponent.icon
);
// Check the user's choice
diff --git a/src/main/java/io/github/jeddict/ai/logo.png b/src/main/resources/icons/logo.png
similarity index 100%
rename from src/main/java/io/github/jeddict/ai/logo.png
rename to src/main/resources/icons/logo.png
diff --git a/src/main/resources/icons/logo16.png b/src/main/resources/icons/logo16.png
new file mode 100644
index 0000000..8d6c44f
Binary files /dev/null and b/src/main/resources/icons/logo16.png differ
diff --git a/src/main/resources/icons/logo24.png b/src/main/resources/icons/logo24.png
new file mode 100644
index 0000000..0c67aff
Binary files /dev/null and b/src/main/resources/icons/logo24.png differ