Skip to content

Commit

Permalink
Merge pull request #422 from samkerr4coding/fix/issue-413
Browse files Browse the repository at this point in the history
FIX: Chat memory is not cleared when opening new project #413
  • Loading branch information
stephanj authored Dec 28, 2024
2 parents 5fde0d4 + 76e40a2 commit c12db64
Show file tree
Hide file tree
Showing 11 changed files with 76 additions and 61 deletions.
10 changes: 5 additions & 5 deletions src/main/java/com/devoxx/genie/action/AddDirectoryAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ private void addDirectoryToContext(Project project, @NotNull VirtualFile directo
List<VirtualFile> filesToAdd = new ArrayList<>();
DevoxxGenieSettingsService settings = DevoxxGenieStateService.getInstance();

addFilesRecursively(directory, fileListManager, filesToAdd, settings);
addFilesRecursively(project, directory, fileListManager, filesToAdd, settings);

if (!filesToAdd.isEmpty()) {
fileListManager.addFiles(filesToAdd);
fileListManager.addFiles(project, filesToAdd);

ModelProvider selectedProvider = ModelProvider.fromString(settings.getSelectedProvider(project.getLocationHash()));
String selectedModel = settings.getSelectedLanguageModel(project.getLocationHash());
Expand All @@ -86,15 +86,15 @@ private void addDirectoryToContext(Project project, @NotNull VirtualFile directo
}
}

private void addFilesRecursively(@NotNull VirtualFile directory, FileListManager fileListManager,
private void addFilesRecursively(Project project, @NotNull VirtualFile directory, FileListManager fileListManager,
List<VirtualFile> filesToAdd, DevoxxGenieSettingsService settings) {
VirtualFile[] children = directory.getChildren();
for (VirtualFile child : children) {
if (child.isDirectory()) {
if (!settings.getExcludedDirectories().contains(child.getName())) {
addFilesRecursively(child, fileListManager, filesToAdd, settings);
addFilesRecursively(project, child, fileListManager, filesToAdd, settings);
}
} else if (shouldIncludeFile(child, settings) && !fileListManager.contains(child)) {
} else if (shouldIncludeFile(child, settings) && !fileListManager.contains(project, child)) {
filesToAdd.add(child);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/devoxx/genie/action/AddFileAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ public void actionPerformed(@NotNull AnActionEvent e) {
if (selectedFiles != null && selectedFiles.length > 0) {
List<VirtualFile> filesToAdd = new ArrayList<>();
for (VirtualFile file : selectedFiles) {
if (!file.isDirectory() && !fileListManager.contains(file)) {
if (!file.isDirectory() && !fileListManager.contains(project, file)) {
filesToAdd.add(file);
}
}

if (!filesToAdd.isEmpty()) {
fileListManager.addFiles(filesToAdd);
fileListManager.addFiles(project, filesToAdd);
NotificationUtil.sendNotification(project, "Added " + filesToAdd.size() + " file(s) to prompt context");
} else {
NotificationUtil.sendNotification(project, "No new files to add or only directories selected");
Expand Down
17 changes: 10 additions & 7 deletions src/main/java/com/devoxx/genie/action/AddSnippetAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightVirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static com.devoxx.genie.ui.util.WindowPluginUtil.ensureToolWindowVisible;

Expand Down Expand Up @@ -45,10 +47,10 @@ public void actionPerformed(@NotNull AnActionEvent e) {
SelectionModel selectionModel = editor.getSelectionModel();
String selectedText = selectionModel.getSelectedText();
if (selectedText != null) {
createAndAddVirtualFile(selectedFile, selectionModel, selectedText);
createAndAddVirtualFile(e.getProject(), selectedFile, selectionModel, selectedText);
} else {
// No text selected, add complete file
addSelectedFile(selectedFile);
addSelectedFile(e.getProject(), selectedFile);
}
}
}
Expand All @@ -58,22 +60,23 @@ public void actionPerformed(@NotNull AnActionEvent e) {
*
* @param selectedFile the selected file
*/
private static void addSelectedFile(VirtualFile selectedFile) {
private static void addSelectedFile(Project project, VirtualFile selectedFile) {
FileListManager fileListManager = FileListManager.getInstance();
if (fileListManager.contains(selectedFile)) {
if (fileListManager.contains(project, selectedFile)) {
return;
}
fileListManager.addFile(selectedFile);
fileListManager.addFile(project, selectedFile);
}

/**
* Create a virtual file and add it to the file list manager.
*
* @param project
* @param originalFile the original file
* @param selectionModel the selection model
* @param selectedText the selected text
*/
private void createAndAddVirtualFile(@NotNull VirtualFile originalFile,
private void createAndAddVirtualFile(@Nullable Project project, @NotNull VirtualFile originalFile,
@NotNull SelectionModel selectionModel,
String selectedText) {
LightVirtualFile virtualFile = new LightVirtualFile(originalFile.getName(), selectedText);
Expand All @@ -82,7 +85,7 @@ private void createAndAddVirtualFile(@NotNull VirtualFile originalFile,
virtualFile.putUserData(SELECTED_TEXT_KEY, selectedText);
virtualFile.putUserData(SELECTION_START_KEY, selectionModel.getSelectionStart());
virtualFile.putUserData(SELECTION_END_KEY, selectionModel.getSelectionEnd());
FileListManager.getInstance().addFile(virtualFile);
FileListManager.getInstance().addFile(project, virtualFile);
}


Expand Down
69 changes: 39 additions & 30 deletions src/main/java/com/devoxx/genie/service/FileListManager.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
package com.devoxx.genie.service;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.*;

public class FileListManager {

private final List<VirtualFile> files = new ArrayList<>();
private final List<FileListObserver> observers = new ArrayList<>();
private final Map<String, List<VirtualFile>> filesMap = new HashMap<>();
private final Map<String, List<FileListObserver>> observersMap = new HashMap<>();
@Getter
private int totalFileCount = 0;

Expand All @@ -28,68 +26,79 @@ public static FileListManager getInstance() {
return instance;
}

public void addFile(VirtualFile file) {
files.add(file);
notifyObservers(file);
public void addFile(Project project, VirtualFile file) {
List<VirtualFile> currentFiles = filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
currentFiles.add(file);
notifyObservers(project, file);
}

public void addFiles(@NotNull List<VirtualFile> newFiles) {
public void addFiles(Project project, @NotNull List<VirtualFile> newFiles) {
List<VirtualFile> actuallyAddedFiles = new ArrayList<>();
List<VirtualFile> currentFiles = filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
Set<VirtualFile> currentFilesSet = new HashSet<>(currentFiles);

for (VirtualFile file : newFiles) {
if (!files.contains(file)) {
files.add(file);
if (!currentFilesSet.contains(file)) {
currentFiles.add(file);
actuallyAddedFiles.add(file);
currentFilesSet.add(file);
}
}
if (!actuallyAddedFiles.isEmpty()) {
actuallyAddedFiles.sort(Comparator.comparing(VirtualFile::getName, String.CASE_INSENSITIVE_ORDER));
notifyObserversOfBatchAdd(actuallyAddedFiles);
notifyObserversOfBatchAdd(project, actuallyAddedFiles);
}
}

private void notifyObserversOfBatchAdd(@NotNull List<VirtualFile> addedFiles) {

private void notifyObserversOfBatchAdd(Project project, @NotNull List<VirtualFile> addedFiles) {
List<FileListObserver> observers = observersMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
for (FileListObserver observer : observers) {
observer.filesAdded(addedFiles);
}
}

public void removeFile(VirtualFile file) {
files.remove(file);
public void removeFile(Project project, VirtualFile file) {
List<VirtualFile> currentFiles = filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
currentFiles.remove(file);
}

public List<VirtualFile> getFiles() {
return Collections.unmodifiableList(files);
public List<VirtualFile> getFiles(Project project) {
return Collections.unmodifiableList(filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>()));
}

public boolean isEmpty() {
return files.isEmpty();
public boolean isEmpty(Project project) {
return filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>()).isEmpty();
}

public int size() {
return files.size();
public int size(Project project) {
return filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>()).size();
}

public boolean contains(VirtualFile file) {
return files.contains(file);
public boolean contains(Project project, VirtualFile file) {
return filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>()).contains(file);
}

public void addObserver(FileListObserver observer) {
observers.add(observer);
public void addObserver(Project project, FileListObserver observer) {
observersMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>()).add(observer);
}

public void clear() {
public void clear(Project project) {
List<VirtualFile> files = filesMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
files.clear();
totalFileCount = 0;
notifyAllObservers();
notifyAllObservers(project);
}

private void notifyObservers(VirtualFile file) {
private void notifyObservers(Project project, VirtualFile file) {
List<FileListObserver> observers = observersMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
for (FileListObserver observer : observers) {
observer.fileAdded(file);
}
}

private void notifyAllObservers() {
private void notifyAllObservers(Project project) {
List<FileListObserver> observers = observersMap.computeIfAbsent(project.getLocationHash(), k -> new ArrayList<>());
for (FileListObserver observer : observers) {
observer.allFilesRemoved();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private void addExpandablePanelIfNeeded() {
if (chatMessageContext.hasFiles()) {
ApplicationManager.getApplication().invokeLater(() -> {
ExpandablePanel fileListPanel =
new ExpandablePanel(chatMessageContext, FileListManager.getInstance().getFiles());
new ExpandablePanel(chatMessageContext, FileListManager.getInstance().getFiles(chatMessageContext.getProject()));
fileListPanel.setName(chatMessageContext.getId());
promptOutputPanel.addStreamFileReferencesResponse(fileListPanel);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public ChatStreamingResponsePanel(@NotNull ChatMessageContext chatMessageContext
setMaxWidth();

if (chatMessageContext.hasFiles()) {
java.util.List<VirtualFile> files = FileListManager.getInstance().getFiles();
java.util.List<VirtualFile> files = FileListManager.getInstance().getFiles(chatMessageContext.getProject());
ExpandablePanel fileListPanel = new ExpandablePanel(chatMessageContext, files);
add(fileListPanel);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public void onNewConversation(ChatMessageContext chatMessageContext) {
*/
@Override
public void startNewConversation() {
FileListManager.getInstance().clear();
FileListManager.getInstance().clear(project);
ChatMemoryService.getInstance().clear(project);

chatService.startNewConversation("");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ private FileSelectionPanelFactory() {

public static @NotNull JPanel createPanel(Project project, List<VirtualFile> openFiles) {
DefaultListModel<VirtualFile> listModel = new DefaultListModel<>();
JBList<VirtualFile> resultList = createResultList(listModel);
JBList<VirtualFile> resultList = createResultList(project, listModel);
JBTextField filterField = createFilterField(project, listModel, resultList, openFiles);

JPanel mainPanel = new JPanel(new BorderLayout());
Expand All @@ -64,15 +64,16 @@ private FileSelectionPanelFactory() {
/**
* Create the result list
*
* @param project
* @param listModel the list model
* @return the list
*/
private static @NotNull JBList<VirtualFile> createResultList(DefaultListModel<VirtualFile> listModel) {
private static @NotNull JBList<VirtualFile> createResultList(Project project, DefaultListModel<VirtualFile> listModel) {
JBList<VirtualFile> resultList = new JBList<>(listModel);
resultList.setCellRenderer(new FileListCellRenderer());
resultList.setVisibleRowCount(10); // Show 10 rows by default

addMouseListenerToResultList(resultList);
addMouseListenerToResultList(project, resultList);
return resultList;
}

Expand Down Expand Up @@ -201,14 +202,15 @@ public void onSuccess() {
/**
* Add a mouse listener to the result list
*
* @param project
* @param resultList the result list
*/
private static void addMouseListenerToResultList(@NotNull JBList<VirtualFile> resultList) {
private static void addMouseListenerToResultList(Project project, @NotNull JBList<VirtualFile> resultList) {
resultList.addMouseListener(new MouseInputAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == DOUBLE_CLICK) {
addSelectedFile(resultList);
addSelectedFile(project, resultList);
}
}
});
Expand All @@ -217,12 +219,13 @@ public void mouseClicked(MouseEvent e) {
/**
* Add the selected file to the file list
*
* @param project
* @param resultList the result list
*/
private static void addSelectedFile(@NotNull JBList<VirtualFile> resultList) {
private static void addSelectedFile(Project project, @NotNull JBList<VirtualFile> resultList) {
VirtualFile selectedFile = resultList.getSelectedValue();
if (selectedFile != null) {
FileListManager.getInstance().addFile(selectedFile);
FileListManager.getInstance().addFile(project, selectedFile);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class PromptContextFileListPanel extends JPanel
public PromptContextFileListPanel(Project project) {
this.project = project;
fileListManager = FileListManager.getInstance();
fileListManager.addObserver(this);
fileListManager.addObserver(project,this);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

Expand Down Expand Up @@ -75,13 +75,13 @@ public void allFilesRemoved() {
}

private void updateFilesPanelVisibility() {
if (fileListManager.isEmpty()) {
if (fileListManager.isEmpty(project)) {
filesScrollPane.setVisible(false);
filesScrollPane.setPreferredSize(new Dimension(0, 0));
} else {
filesScrollPane.setVisible(true);
int MAX_VISIBLE_FILES = 3;
int fileCount = Math.min(fileListManager.size(), MAX_VISIBLE_FILES);
int fileCount = Math.min(fileListManager.size(project), MAX_VISIBLE_FILES);
int heightPerFile = 30;
int prefHeight = fileCount * heightPerFile;
filesScrollPane.setPreferredSize(new Dimension(getPreferredSize().width, prefHeight));
Expand All @@ -92,7 +92,7 @@ private void updateFilesPanelVisibility() {

@Override
public void onFileRemoved(VirtualFile file) {
fileListManager.removeFile(file);
fileListManager.removeFile(project, file);
removeFromFilesPanel(file);
updateFilesPanelVisibility();
updateUIState();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
public class FileListPanel extends ExpandablePanel {

public FileListPanel(ChatMessageContext chatMessageContext) {
super(chatMessageContext, FileListManager.getInstance().getFiles());
super(chatMessageContext, FileListManager.getInstance().getFiles(chatMessageContext.getProject()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ private ChatMessageContextUtil() {
.userPrompt(userPromptText)
.languageModel(languageModel)
.webSearchRequested(stateService.getWebSearchActivated() && (stateService.isGoogleSearchEnabled() || stateService.isTavilySearchEnabled()))
.totalFileCount(FileListManager.getInstance().size())
.totalFileCount(FileListManager.getInstance().size(project))
.executionTimeMs(0)
.cost(0)
.build();
Expand Down Expand Up @@ -84,7 +84,7 @@ private static void setWindowContext(@NotNull ChatMessageContext chatMessageCont
Editor selectedTextEditor = editorFileButtonManager.getSelectedTextEditor();

// Add files to the context
List<VirtualFile> files = FileListManager.getInstance().getFiles();
List<VirtualFile> files = FileListManager.getInstance().getFiles(chatMessageContext.getProject());
if (!files.isEmpty()) {
addSelectedFiles(chatMessageContext, userPrompt, files);
}
Expand Down

0 comments on commit c12db64

Please sign in to comment.