-package org.simantics.scl.ui.issues;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-import java.util.Collections;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import org.eclipse.jface.viewers.IStructuredContentProvider;\r
-import org.eclipse.jface.viewers.Viewer;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.simantics.scl.compiler.errors.CompilationError;\r
-import org.simantics.scl.compiler.errors.Failable;\r
-import org.simantics.scl.compiler.errors.Failure;\r
-import org.simantics.scl.compiler.module.Module;\r
-import org.simantics.scl.compiler.module.repository.ModuleRepository;\r
-import org.simantics.scl.compiler.module.repository.UpdateListener;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectProcedure;\r
-\r
-public class SCLIssuesContentProvider implements IStructuredContentProvider {\r
-\r
- public static final int MAX_ISSUE_COUNT = 1000;\r
- \r
- Viewer viewer;\r
- ModuleRepository repository;\r
- boolean disposed = false;\r
- AtomicBoolean refreshInProgress = new AtomicBoolean(false);\r
- \r
- THashMap<String, Failure> currentFailures = new THashMap<String, Failure>();\r
- THashMap<String, UpdateListener> updateListeners = new THashMap<String, UpdateListener>(); \r
- \r
- @Override\r
- public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {\r
- this.viewer = viewer;\r
- this.repository = (ModuleRepository)newInput;\r
- if(newInput != null)\r
- listenIssues();\r
- }\r
- \r
- private UpdateListener getUpdateListener(String moduleName) {\r
- UpdateListener listener = updateListeners.get(moduleName);\r
- if(listener == null) {\r
- listener = new UpdateListener() {\r
- @Override\r
- public void notifyAboutUpdate() {\r
- if(!disposed)\r
- listenModule(moduleName);\r
- }\r
- };\r
- updateListeners.put(moduleName, listener);\r
- }\r
- return listener;\r
- }\r
- \r
- private void listenModule(String moduleName) {\r
- if(repository == null)\r
- return;\r
- Failable<Module> result = repository.getModule(moduleName, getUpdateListener(moduleName));\r
- synchronized(currentFailures) {\r
- if(result instanceof Failure) {\r
- Failure failure = (Failure)result;\r
- currentFailures.put(moduleName, failure);\r
- }\r
- else\r
- if(currentFailures.remove(moduleName) == null)\r
- return;\r
- }\r
- refresh();\r
- }\r
- \r
- private void refresh() {\r
- if(!refreshInProgress.compareAndSet(false, true))\r
- return;\r
- if(viewer == null)\r
- return;\r
- Control control = viewer.getControl();\r
- if(control.isDisposed() || disposed)\r
- return;\r
- control.getDisplay().asyncExec(new Runnable() {\r
- @Override\r
- public void run() {\r
- if(control.isDisposed() || disposed)\r
- return;\r
- refreshInProgress.set(false);\r
- viewer.refresh();\r
- }\r
- });\r
- }\r
-\r
- private void listenIssues() {\r
- new Thread() {\r
- public void run() {\r
- if(repository == null)\r
- return;\r
- repository.getSourceRepository().forAllModules(new TObjectProcedure<String>() {\r
- @Override\r
- public boolean execute(String moduleName) {\r
- listenModule(moduleName);\r
- return true;\r
- }\r
- });\r
- }\r
- }.start();\r
- }\r
-\r
- @Override\r
- public void dispose() {\r
- this.disposed = true;\r
- }\r
-\r
- @Override\r
- public Object[] getElements(Object inputElement) {\r
- ArrayList<SCLIssuesTableEntry> result = new ArrayList<SCLIssuesTableEntry>();\r
- synchronized(currentFailures) {\r
- String[] moduleNames = currentFailures.keySet().toArray(new String[currentFailures.size()]);\r
- Arrays.sort(moduleNames);\r
- for(String moduleName : moduleNames) {\r
- Failure failure = currentFailures.get(moduleName);\r
- for(CompilationError error : failure.errors)\r
- result.add(new SCLIssuesTableEntry(moduleName, error));\r
- if(result.size() >= MAX_ISSUE_COUNT)\r
- break;\r
- }\r
- }\r
- Collections.sort(result);\r
- return result.toArray();\r
- }\r
-\r
-}\r
+package org.simantics.scl.ui.issues;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.widgets.Control;
+import org.simantics.scl.osgi.issues.SCLIssueFactoryProvider;
+import org.simantics.scl.osgi.issues.SCLIssueProviderFactory.SCLIssueProvider;
+import org.simantics.scl.osgi.issues.SCLIssuesTableEntry;
+
+public class SCLIssuesContentProvider implements IStructuredContentProvider {
+
+ public static final int MAX_ISSUE_COUNT = 1000;
+
+ private Viewer viewer;
+ boolean disposed = false;
+ private AtomicBoolean refreshInProgress = new AtomicBoolean(false);
+ private List<SCLIssueProvider> issueProviders = new ArrayList<>();
+
+ @Override
+ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+ this.viewer = viewer;
+ if (!issueProviders.isEmpty()) {
+ issueProviders.forEach(p -> p.dispose());
+ issueProviders.clear();
+ }
+ if(newInput != null) {
+ issueProviders = SCLIssueFactoryProvider.getSCLIssueProviderFactories().stream().map(f -> f.getSCLIssueProvider()).collect(Collectors.toList());
+ issueProviders.forEach(p -> p.listenIssues(() -> refresh()));
+ }
+ }
+
+ private void refresh() {
+ if(!refreshInProgress.compareAndSet(false, true))
+ return;
+ if(viewer == null)
+ return;
+ Control control = viewer.getControl();
+ if(control.isDisposed() || disposed)
+ return;
+ control.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if(control.isDisposed() || disposed)
+ return;
+ refreshInProgress.set(false);
+ viewer.refresh();
+ }
+ });
+ }
+
+ public void dispose() {
+ if(this.disposed)
+ return;
+ issueProviders.forEach(p -> p.dispose());
+ issueProviders.clear();
+ this.disposed = true;
+ }
+
+ @Override
+ public Object[] getElements(Object inputElement) {
+ ArrayList<SCLIssuesTableEntry> result = new ArrayList<>();
+ issueProviders.forEach(p -> result.addAll(p.getIssues()));
+ Collections.sort(result);
+ return result.toArray();
+ }
+
+}