json schema, listen config file changes also through the document adapter

This commit is contained in:
irengrig
2017-01-19 11:03:34 +01:00
parent 62d422f7d6
commit 3b6d08da7d
3 changed files with 85 additions and 44 deletions
@@ -20,7 +20,10 @@ import com.intellij.json.JsonFileType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ZipperUpdater;
@@ -30,7 +33,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Alarm;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.jsonSchema.impl.JsonSchemaServiceImpl;
import com.jetbrains.jsonSchema.impl.JsonSchemaServiceEx;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -41,42 +44,16 @@ import java.util.Set;
* @author Irina.Chernushina on 3/30/2016.
*/
public class JsonSchemaVfsListener extends BulkVirtualFileListenerAdapter {
public JsonSchemaVfsListener(Project project, @NotNull final JsonSchemaServiceImpl service) {
super(new VirtualFileAdapter() {
@NotNull private final JsonSchemaServiceImpl myService = service;
private JsonSchemaMappingsProjectConfiguration myMappingsProjectConfiguration = JsonSchemaMappingsProjectConfiguration.getInstance(project);
private final ZipperUpdater myUpdater = new ZipperUpdater(200, Alarm.ThreadToUse.POOLED_THREAD, project);
private final Set<VirtualFile> myDirtySchemas = ContainerUtil.newConcurrentSet();
private final Runnable myRunnable = () -> {
final Set<VirtualFile> scope = new HashSet<>(myDirtySchemas);
myDirtySchemas.removeAll(scope);
if (scope.isEmpty()) return;
public static void startListening(@NotNull Project project, @NotNull final JsonSchemaServiceEx service) {
final MyUpdater updater = new MyUpdater(project, service);
ApplicationManager.getApplication().getMessageBus().connect(project)
.subscribe(VirtualFileManager.VFS_CHANGES, new JsonSchemaVfsListener(updater));
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new MyDocumentListener(updater), project);
}
final DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(project);
final PsiManager psiManager = PsiManager.getInstance(project);
final Editor[] editors = EditorFactory.getInstance().getAllEditors();
for (Editor editor : editors) {
if (editor instanceof EditorEx) {
final VirtualFile file = ((EditorEx)editor).getVirtualFile();
if (file != null && file.isValid() && JsonFileType.INSTANCE.equals(file.getFileType())) {
final Collection<Pair<VirtualFile, String>> collection = myService.getSchemaFilesByFile(file);
if (collection != null && !collection.isEmpty()) {
for (Pair<VirtualFile, String> pair : collection) {
if (scope.contains(pair.getFirst())) {
ApplicationManager.getApplication().runReadAction(() -> {
final PsiFile psiFile = psiManager.findFile(file);
if (psiFile != null) {
analyzer.restart(psiFile);
}
});
break;
}
}
}
}
}
}
};
private JsonSchemaVfsListener(@NotNull MyUpdater updater) {
super(new VirtualFileAdapter() {
private final MyUpdater myUpdater = updater;
@Override
public void contentsChanged(@NotNull VirtualFileEvent event) {
@@ -109,12 +86,74 @@ public class JsonSchemaVfsListener extends BulkVirtualFileListenerAdapter {
}
private void onFileChange(@NotNull final VirtualFile schemaFile) {
if (myMappingsProjectConfiguration.isRegisteredSchemaFile(schemaFile)) {
myService.dropProviderFromCache(schemaFile);
myDirtySchemas.add(schemaFile);
myUpdater.queue(myRunnable);
}
myUpdater.onFileChange(schemaFile);
}
});
}
private static class MyDocumentListener extends DocumentAdapter {
private final MyUpdater myUpdater;
private MyDocumentListener(MyUpdater updater) {
myUpdater = updater;
}
@Override
public void documentChanged(DocumentEvent e) {
final VirtualFile file = FileDocumentManager.getInstance().getFile(e.getDocument());
if (file != null) myUpdater.onFileChange(file);
}
}
private static class MyUpdater {
@NotNull private final JsonSchemaServiceEx myService;
private JsonSchemaMappingsProjectConfiguration myMappingsProjectConfiguration;
private final ZipperUpdater myUpdater;
private final Set<VirtualFile> myDirtySchemas = ContainerUtil.newConcurrentSet();
private final Runnable myRunnable;
protected MyUpdater(@NotNull Project project, @NotNull JsonSchemaServiceEx service) {
myService = service;
myMappingsProjectConfiguration = JsonSchemaMappingsProjectConfiguration.getInstance(project);
myUpdater = new ZipperUpdater(200, Alarm.ThreadToUse.POOLED_THREAD, project);
myRunnable = () -> {
final Set<VirtualFile> scope = new HashSet<>(myDirtySchemas);
myDirtySchemas.removeAll(scope);
if (scope.isEmpty()) return;
final DaemonCodeAnalyzer analyzer = DaemonCodeAnalyzer.getInstance(project);
final PsiManager psiManager = PsiManager.getInstance(project);
final Editor[] editors = EditorFactory.getInstance().getAllEditors();
for (Editor editor : editors) {
if (editor instanceof EditorEx) {
final VirtualFile file = ((EditorEx)editor).getVirtualFile();
if (file != null && file.isValid() && JsonFileType.INSTANCE.equals(file.getFileType())) {
final Collection<Pair<VirtualFile, String>> collection = myService.getSchemaFilesByFile(file);
if (collection != null && !collection.isEmpty()) {
for (Pair<VirtualFile, String> pair : collection) {
if (scope.contains(pair.getFirst())) {
ApplicationManager.getApplication().runReadAction(() -> {
final PsiFile psiFile = psiManager.findFile(file);
if (psiFile != null) {
analyzer.restart(psiFile);
}
});
break;
}
}
}
}
}
}
};
}
protected void onFileChange(@NotNull final VirtualFile schemaFile) {
if (myMappingsProjectConfiguration.isRegisteredSchemaFile(schemaFile)) {
myService.dropProviderFromCache(schemaFile);
myDirtySchemas.add(schemaFile);
myUpdater.queue(myRunnable);
}
}
}
}
@@ -32,6 +32,9 @@ public interface JsonSchemaServiceEx extends JsonSchemaService {
void visitSchemaObject(@NotNull VirtualFile schemaFile, @NotNull Processor<JsonSchemaObject> consumer);
//! the only point for refreshing json schema caches
void dropProviderFromCache(@NotNull VirtualFile schemaFile);
@Nullable
VirtualFile getSchemaFileById(@NotNull String id, VirtualFile referent);
@@ -22,7 +22,6 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiElement;
import com.intellij.util.Consumer;
import com.intellij.util.NotNullFunction;
@@ -57,8 +56,7 @@ public class JsonSchemaServiceImpl implements JsonSchemaServiceEx {
myLock = new Object();
myProject = project;
myDefinitions = new JsonSchemaExportedDefinitions();
ApplicationManager
.getApplication().getMessageBus().connect(project).subscribe(VirtualFileManager.VFS_CHANGES, new JsonSchemaVfsListener(project, this));
JsonSchemaVfsListener.startListening(project, this);
ensureSchemaFiles();
}
@@ -211,6 +209,7 @@ public class JsonSchemaServiceImpl implements JsonSchemaServiceEx {
}
//! the only point for refreshing json schema caches
@Override
public void dropProviderFromCache(@NotNull final VirtualFile schemaFile) {
synchronized (myLock) {
myDefinitions.dropKey(schemaFile);