]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/issues/SCLModuleIssueProvider.java
SCL expressions to SCL Issues view
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / issues / SCLModuleIssueProvider.java
diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/issues/SCLModuleIssueProvider.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/issues/SCLModuleIssueProvider.java
new file mode 100644 (file)
index 0000000..20a89d4
--- /dev/null
@@ -0,0 +1,147 @@
+package org.simantics.scl.ui.issues;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.simantics.scl.compiler.errors.CompilationError;
+import org.simantics.scl.compiler.errors.DoesNotExist;
+import org.simantics.scl.compiler.errors.Failable;
+import org.simantics.scl.compiler.errors.Failure;
+import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.module.repository.ModuleRepository;
+import org.simantics.scl.compiler.module.repository.UpdateListener;
+import org.simantics.scl.osgi.SCLOsgi;
+import org.simantics.scl.osgi.issues.SCLIssueProviderFactory;
+import org.simantics.scl.osgi.issues.SCLIssueProviderFactory.SCLIssueProvider;
+import org.simantics.scl.osgi.issues.SCLIssuesTableEntry;
+import org.simantics.scl.ui.editor2.OpenSCLDefinition;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectObjectProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+
+public class SCLModuleIssueProvider implements SCLIssueProvider {
+
+    public static class SCLModuleIssueProviderFactory implements SCLIssueProviderFactory {
+
+        @Override
+        public SCLIssueProvider getSCLIssueProvider() {
+            return new SCLModuleIssueProvider();
+        }
+        
+    }
+    
+    ModuleRepository repository = SCLOsgi.MODULE_REPOSITORY;
+
+    THashMap<String, CompilationError[]> currentFailures = new THashMap<>();
+    THashMap<String, UpdateListener> updateListeners = new THashMap<>();
+
+    private boolean disposed;
+    
+    SCLModuleIssueProvider() {
+    }
+
+    private UpdateListener getUpdateListener(String moduleName, Runnable callback) {
+        UpdateListener listener;
+        synchronized(updateListeners) {
+            listener = updateListeners.get(moduleName);
+            if(listener == null) {
+                listener = new UpdateListener() {
+                    @Override
+                    public void notifyAboutUpdate() {
+                        if(!disposed)
+                            listenModule(moduleName, callback);
+                    }
+                };
+                updateListeners.put(moduleName, listener);
+            }
+        }
+        return listener;
+    }
+
+    private void listenModule(String moduleName, Runnable callback) {
+        if(repository == null)
+            return;
+        Failable<Module> result = repository.getModule(moduleName, getUpdateListener(moduleName, callback));
+        synchronized(currentFailures) {
+            if(result instanceof Failure) {
+                Failure failure = (Failure)result;
+                currentFailures.put(moduleName, failure.errors);
+            }
+            else if(result == DoesNotExist.INSTANCE) {
+                if(currentFailures.remove(moduleName) == null)
+                    return;
+            }
+            else {
+                CompilationError[] warnings = result.getResult().getWarnings();
+                if(warnings.length == 0) {
+                    if(currentFailures.remove(moduleName) == null)
+                        return;
+                }
+                else {
+                    currentFailures.put(moduleName, warnings);
+                }
+            }
+        }
+        if (callback != null)
+            callback.run();
+    }
+
+    public void listenIssues(Runnable callback) {
+        new Thread() {
+            public void run() {
+                if(repository == null)
+                    return;
+                repository.getSourceRepository().forAllModules(new TObjectProcedure<String>() {
+                    @Override
+                    public boolean execute(String moduleName) {
+                        listenModule(moduleName, callback);
+                        return true;
+                    }
+                });
+            }
+        }.start();
+    }
+
+    @Override
+    public List<SCLIssuesTableEntry> getIssues() {
+        ArrayList<SCLIssuesTableEntry> result = new ArrayList<>();
+        synchronized(currentFailures) {
+            String[] moduleNames = currentFailures.keySet().toArray(new String[currentFailures.size()]);
+            Arrays.sort(moduleNames);
+            for(String moduleName : moduleNames) {
+                CompilationError[] errors = currentFailures.get(moduleName);
+                for(CompilationError error : errors) {
+                    result.add(new SCLIssuesTableEntry(moduleName, error) {
+                        @Override
+                        public void openLocation() {
+                            OpenSCLDefinition.openDefinition(moduleName, error.location);
+                        }
+                    });
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public void dispose() {
+        if (disposed)
+            return;
+        disposed = true;
+        if(repository != null) {
+            synchronized(updateListeners) {
+                updateListeners.forEachEntry(new TObjectObjectProcedure<String, UpdateListener>() {
+                    @Override
+                    public boolean execute(String moduleName, UpdateListener listener) {
+                        listener.stopListening();
+                        return true;
+                    }
+                });
+                updateListeners.clear();
+            }
+        }
+    }
+
+}