diff --git a/json/src/com/jetbrains/jsonSchema/JsonSchemaVfsListener.java b/json/src/com/jetbrains/jsonSchema/JsonSchemaVfsListener.java index 7cbf1a2aacac..7aec08a89601 100644 --- a/json/src/com/jetbrains/jsonSchema/JsonSchemaVfsListener.java +++ b/json/src/com/jetbrains/jsonSchema/JsonSchemaVfsListener.java @@ -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 myDirtySchemas = ContainerUtil.newConcurrentSet(); - private final Runnable myRunnable = () -> { - final Set 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> collection = myService.getSchemaFilesByFile(file); - if (collection != null && !collection.isEmpty()) { - for (Pair 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 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 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> collection = myService.getSchemaFilesByFile(file); + if (collection != null && !collection.isEmpty()) { + for (Pair 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); + } + } + } } diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceEx.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceEx.java index 722b7f40b32f..ab79b19f5a51 100644 --- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceEx.java +++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceEx.java @@ -32,6 +32,9 @@ public interface JsonSchemaServiceEx extends JsonSchemaService { void visitSchemaObject(@NotNull VirtualFile schemaFile, @NotNull Processor consumer); + //! the only point for refreshing json schema caches + void dropProviderFromCache(@NotNull VirtualFile schemaFile); + @Nullable VirtualFile getSchemaFileById(@NotNull String id, VirtualFile referent); diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceImpl.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceImpl.java index 9a89b9d84332..8153f4c61ba5 100644 --- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceImpl.java +++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaServiceImpl.java @@ -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);