]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/issues/SCLIssuesContentProvider.java
4772ad5ba7996b89baa875c4cf24db9e70e940e4
[simantics/platform.git] / bundles / org.simantics.scl.ui / src / org / simantics / scl / ui / issues / SCLIssuesContentProvider.java
1 package org.simantics.scl.ui.issues;
2
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.concurrent.atomic.AtomicBoolean;
7
8 import org.eclipse.jface.viewers.IStructuredContentProvider;
9 import org.eclipse.jface.viewers.Viewer;
10 import org.eclipse.swt.widgets.Control;
11 import org.simantics.scl.compiler.errors.CompilationError;
12 import org.simantics.scl.compiler.errors.DoesNotExist;
13 import org.simantics.scl.compiler.errors.Failable;
14 import org.simantics.scl.compiler.errors.Failure;
15 import org.simantics.scl.compiler.module.Module;
16 import org.simantics.scl.compiler.module.repository.ModuleRepository;
17 import org.simantics.scl.compiler.module.repository.UpdateListener;
18
19 import gnu.trove.map.hash.THashMap;
20 import gnu.trove.procedure.TObjectObjectProcedure;
21 import gnu.trove.procedure.TObjectProcedure;
22
23 public class SCLIssuesContentProvider implements IStructuredContentProvider {
24
25     public static final int MAX_ISSUE_COUNT = 1000;
26     
27     Viewer viewer;
28     ModuleRepository repository;
29     boolean disposed = false;
30     AtomicBoolean refreshInProgress = new AtomicBoolean(false);
31     
32     THashMap<String, CompilationError[]> currentFailures = new THashMap<String, CompilationError[]>();
33     THashMap<String, UpdateListener> updateListeners = new THashMap<String, UpdateListener>(); 
34     
35     @Override
36     public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
37         this.viewer = viewer;
38         this.repository = (ModuleRepository)newInput;
39         if(newInput != null)
40             listenIssues();
41     }
42     
43     private UpdateListener getUpdateListener(String moduleName) {
44         UpdateListener listener;
45         synchronized(updateListeners) {
46             listener = updateListeners.get(moduleName);
47             if(listener == null) {
48                 listener = new UpdateListener() {
49                     @Override
50                     public void notifyAboutUpdate() {
51                         if(!disposed)
52                             listenModule(moduleName);
53                     }
54                 };
55                 updateListeners.put(moduleName, listener);
56             }
57         }
58         return listener;
59     }
60     
61     private void listenModule(String moduleName) {
62         if(repository == null)
63             return;
64         Failable<Module> result = repository.getModule(moduleName, getUpdateListener(moduleName));
65         synchronized(currentFailures) {
66             if(result instanceof Failure) {
67                 Failure failure = (Failure)result;
68                 currentFailures.put(moduleName, failure.errors);
69             }
70             else if(result == DoesNotExist.INSTANCE) {
71                 if(currentFailures.remove(moduleName) == null)
72                     return;
73             }
74             else {
75                 CompilationError[] warnings = result.getResult().getWarnings();
76                 if(warnings.length == 0) {
77                     if(currentFailures.remove(moduleName) == null)
78                         return;
79                 }
80                 else {
81                     currentFailures.put(moduleName, warnings);
82                 }
83             }
84         }
85         refresh();
86     }
87     
88     private void refresh() {
89         if(!refreshInProgress.compareAndSet(false, true))
90             return;
91         if(viewer == null)
92             return;
93         Control control = viewer.getControl();
94         if(control.isDisposed() || disposed)
95             return;
96         control.getDisplay().asyncExec(new Runnable() {
97             @Override
98             public void run() {
99                 if(control.isDisposed() || disposed)
100                     return;
101                 refreshInProgress.set(false);
102                 viewer.refresh();
103             }
104         });
105     }
106
107     private void listenIssues() {
108         new Thread() {
109             public void run() {
110                 if(repository == null)
111                     return;
112                 repository.getSourceRepository().forAllModules(new TObjectProcedure<String>() {
113                     @Override
114                     public boolean execute(String moduleName) {
115                         listenModule(moduleName);
116                         return true;
117                     }
118                 });
119             }
120         }.start();
121     }
122
123     @Override
124     public void dispose() {
125         if(this.disposed)
126             return;
127         this.disposed = true;
128         if(repository != null)
129             synchronized(updateListeners) {
130                 updateListeners.forEachEntry(new TObjectObjectProcedure<String, UpdateListener>() {
131                     @Override
132                     public boolean execute(String moduleName, UpdateListener listener) {
133                         listener.stopListening();
134                         return true;
135                     }
136                 });
137                 updateListeners.clear();
138             }
139     }
140
141     @Override
142     public Object[] getElements(Object inputElement) {
143         ArrayList<SCLIssuesTableEntry> result = new ArrayList<SCLIssuesTableEntry>();
144         synchronized(currentFailures) {
145             String[] moduleNames = currentFailures.keySet().toArray(new String[currentFailures.size()]);
146             Arrays.sort(moduleNames);
147             for(String moduleName : moduleNames) {
148                 CompilationError[] errors = currentFailures.get(moduleName);
149                 for(CompilationError error : errors)
150                     result.add(new SCLIssuesTableEntry(moduleName, error));
151                 if(result.size() >= MAX_ISSUE_COUNT)
152                     break;
153             }
154         }
155         Collections.sort(result);
156         return result.toArray();
157     }
158
159 }