Skip to content

Commit

Permalink
fix: debounce classpath/source change events (#916)
Browse files Browse the repository at this point in the history
Fixes #916

Signed-off-by: azerr <[email protected]>
  • Loading branch information
angelozerr committed Jun 16, 2023
1 parent ce55178 commit 6a64f58
Show file tree
Hide file tree
Showing 9 changed files with 443 additions and 175 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*******************************************************************************
* Copyright (c) 2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
* Copyright (c) 2020 Red Hat Inc. and others.
* All rights reserved. This program and the accompanying materials
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package com.redhat.devtools.intellij.lsp4mp4ij.psi.core.project;

import com.intellij.ProjectTopics;
Expand All @@ -33,94 +33,114 @@

/**
* {@link PsiMicroProfileProject} manager.
*
*
* @author Angelo ZERR
* @see <a href="https://github.com/redhat-developer/quarkus-ls/blob/master/microprofile.jdt/com.redhat.microprofile.jdt.core/src/main/java/com/redhat/microprofile/jdt/core/project/JDTMicroProfileProjectManager.java">https://github.com/redhat-developer/quarkus-ls/blob/master/microprofile.jdt/com.redhat.microprofile.jdt.core/src/main/java/com/redhat/microprofile/jdt/core/project/JDTMicroProfileProjectManager.java</a>
*
*/
@Service
public final class PsiMicroProfileProjectManager {

public static PsiMicroProfileProjectManager getInstance(Project project) {
return ServiceManager.getService(project, PsiMicroProfileProjectManager.class);
}

private Project project;

private final Map<Module, PsiMicroProfileProject> projects;
private MicroProfileProjectListener microprofileProjectListener;

private class MicroProfileProjectListener implements ModuleListener, BulkFileListener {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
for(VFileEvent event : events) {
if ((event instanceof VFileDeleteEvent || event instanceof VFileContentChangeEvent ||
event instanceof VFileCreateEvent) && isConfigSource(event.getFile())) {
Module javaProject = PsiUtilsLSImpl.getInstance(project).getModule(event.getFile());
if (javaProject != null) {
PsiMicroProfileProject mpProject = getJDTMicroProfileProject(javaProject);
if (mpProject != null) {
mpProject.evictConfigSourcesCache();
}
}

}
}
}

@Override
public void beforeModuleRemoved(@NotNull Project project, @NotNull Module module) {
evict(module);
}

private void evict(Module javaProject) {
if (javaProject != null) {
// Remove the JDTMicroProfile project instance from the cache.
projects.remove(javaProject);
}
}
}

private PsiMicroProfileProjectManager(Project project) {
this.project = project;
this.projects = new HashMap<>();
initialize();
}

public PsiMicroProfileProject getJDTMicroProfileProject(Module project) {
return getJDTMicroProfileProject(project, true);
}

private PsiMicroProfileProject getJDTMicroProfileProject(Module project, boolean create) {
Module javaProject = project;
PsiMicroProfileProject info = projects.get(javaProject);
if (info == null) {
if (!create) {
return null;
}
info = new PsiMicroProfileProject(javaProject);
projects.put(javaProject, info);
}
return info;
}

public boolean isConfigSource(VirtualFile file) {
String fileName = file.getName();
for (IConfigSourceProvider provider : IConfigSourceProvider.EP_NAME.getExtensions()) {
if (provider.isConfigSource(fileName)) {
return true;
}
}
return false;
}

public void initialize() {
if (microprofileProjectListener != null) {
return;
}
microprofileProjectListener = new MicroProfileProjectListener();
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(project);
connection.subscribe(VirtualFileManager.VFS_CHANGES, microprofileProjectListener);
project.getMessageBus().connect(project).subscribe(ProjectTopics.MODULES, microprofileProjectListener);
}
private static final String JAVA_FILE_EXTENSION = "java";

public static PsiMicroProfileProjectManager getInstance(Project project) {
return ServiceManager.getService(project, PsiMicroProfileProjectManager.class);
}

private Project project;

private final Map<Module, PsiMicroProfileProject> projects;
private MicroProfileProjectListener microprofileProjectListener;

private class MicroProfileProjectListener implements ModuleListener, BulkFileListener {
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
for (VFileEvent event : events) {
if ((event instanceof VFileDeleteEvent || event instanceof VFileContentChangeEvent ||
event instanceof VFileCreateEvent) && isConfigSource(event.getFile())) {
Module javaProject = PsiUtilsLSImpl.getInstance(project).getModule(event.getFile());
if (javaProject != null) {
PsiMicroProfileProject mpProject = getJDTMicroProfileProject(javaProject);
if (mpProject != null) {
mpProject.evictConfigSourcesCache();
}
}

}
}
}

@Override
public void beforeModuleRemoved(@NotNull Project project, @NotNull Module module) {
evict(module);
}

private void evict(Module javaProject) {
if (javaProject != null) {
// Remove the JDTMicroProfile project instance from the cache.
projects.remove(javaProject);
}
}
}

private PsiMicroProfileProjectManager(Project project) {
this.project = project;
this.projects = new HashMap<>();
initialize();
}

public PsiMicroProfileProject getJDTMicroProfileProject(Module project) {
return getJDTMicroProfileProject(project, true);
}

private PsiMicroProfileProject getJDTMicroProfileProject(Module project, boolean create) {
Module javaProject = project;
PsiMicroProfileProject info = projects.get(javaProject);
if (info == null) {
if (!create) {
return null;
}
info = new PsiMicroProfileProject(javaProject);
projects.put(javaProject, info);
}
return info;
}

/**
* Returns true if the given file is a MicroProfile config properties file (microprofile-config.properties, application.properties, application.yaml, etc) and false otherwise.
*
* @param file the file to check.
* @return true if the given file is a MicroProfile config properties file (microprofile-config.properties, application.properties, application.yaml, etc) and false otherwise.
*/
public boolean isConfigSource(VirtualFile file) {
if (file == null) {
return false;
}
String fileName = file.getName();
for (IConfigSourceProvider provider : IConfigSourceProvider.EP_NAME.getExtensions()) {
if (provider.isConfigSource(fileName)) {
return true;
}
}
return false;
}

/**
* Returns true if the given file is a Java file and false otherwise.
*
* @param file the file to check.
* @return true if the given file is a Java file and false otherwise.
*/
public boolean isJavaFile(VirtualFile file) {
return file != null && JAVA_FILE_EXTENSION.equals(file.getExtension());
}

public void initialize() {
if (microprofileProjectListener != null) {
return;
}
microprofileProjectListener = new MicroProfileProjectListener();
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(project);
connection.subscribe(VirtualFileManager.VFS_CHANGES, microprofileProjectListener);
project.getMessageBus().connect(project).subscribe(ProjectTopics.MODULES, microprofileProjectListener);
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
/*******************************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.intellij.quarkus;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import org.jetbrains.annotations.NotNull;

public class QuarkusPostStartupActivity implements StartupActivity, DumbAware {
@Override
public void runActivity(@NotNull Project project) {
QuarkusProjectService.getInstance(project);
}
}
/*******************************************************************************
* Copyright (c) 2019-2020 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v2.0 which accompanies this distribution,
* and is available at https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package com.redhat.devtools.intellij.quarkus;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.redhat.devtools.intellij.quarkus.classpath.ClasspathResourceChangeManager;
import org.jetbrains.annotations.NotNull;

public class QuarkusPostStartupActivity implements StartupActivity, DumbAware {
@Override
public void runActivity(@NotNull Project project) {
ClasspathResourceChangeManager.getInstance(project);
QuarkusProjectService.getInstance(project);
}
}
Loading

0 comments on commit 6a64f58

Please sign in to comment.