Lines 11-37
Link Here
|
11 |
|
11 |
|
12 |
package org.eclipse.cdt.debug.internal.ui.views.executables; |
12 |
package org.eclipse.cdt.debug.internal.ui.views.executables; |
13 |
|
13 |
|
|
|
14 |
import java.util.HashMap; |
15 |
import java.util.List; |
16 |
import java.util.Map; |
17 |
|
14 |
import org.eclipse.cdt.core.model.ITranslationUnit; |
18 |
import org.eclipse.cdt.core.model.ITranslationUnit; |
15 |
import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
|
|
16 |
import org.eclipse.cdt.debug.core.executables.Executable; |
19 |
import org.eclipse.cdt.debug.core.executables.Executable; |
|
|
20 |
import org.eclipse.cdt.debug.core.executables.ExecutablesManager; |
21 |
import org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener; |
22 |
import org.eclipse.cdt.debug.internal.ui.views.executables.SourceFilesViewer.TranslationUnitInfo; |
17 |
import org.eclipse.cdt.ui.CElementContentProvider; |
23 |
import org.eclipse.cdt.ui.CElementContentProvider; |
18 |
import org.eclipse.core.runtime.IPath; |
24 |
import org.eclipse.core.runtime.IPath; |
19 |
import org.eclipse.core.runtime.IProgressMonitor; |
25 |
import org.eclipse.core.runtime.IProgressMonitor; |
20 |
import org.eclipse.core.runtime.IStatus; |
26 |
import org.eclipse.core.runtime.IStatus; |
21 |
import org.eclipse.core.runtime.Status; |
27 |
import org.eclipse.core.runtime.Status; |
|
|
28 |
import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
22 |
import org.eclipse.core.runtime.jobs.Job; |
29 |
import org.eclipse.core.runtime.jobs.Job; |
|
|
30 |
import org.eclipse.core.runtime.jobs.JobChangeAdapter; |
31 |
import org.eclipse.jface.viewers.Viewer; |
32 |
import org.eclipse.swt.widgets.Display; |
33 |
|
34 |
public class SourceFilesContentProvider extends CElementContentProvider implements IExecutablesChangeListener { |
35 |
|
36 |
static class QuickParseJob extends Job { |
37 |
final Executable executable; |
38 |
ITranslationUnit[] tus; |
39 |
|
40 |
public QuickParseJob(Executable executable) { |
41 |
super ("Reading Debug Symbol Information: " + executable.getName()); |
42 |
this.executable = executable; |
43 |
this.tus = null; |
44 |
} |
45 |
|
46 |
@Override |
47 |
protected IStatus run(IProgressMonitor monitor) { |
48 |
tus = executable.getSourceFiles(monitor); |
49 |
return Status.OK_STATUS; |
50 |
} |
51 |
} |
52 |
|
53 |
/** contains running jobs */ |
54 |
private Map<IPath, QuickParseJob> pathToJobMap = new HashMap<IPath, SourceFilesContentProvider.QuickParseJob>(); |
55 |
|
56 |
/** those executables for which we asked the question and got a result. |
57 |
* NOTE: this contains a duplicate of into in Executable, because we can't |
58 |
* guarantee or check whether Executable still has the info itself. */ |
59 |
private Map<IPath, ITranslationUnit[]> fetchedExecutables = new HashMap<IPath, ITranslationUnit[]>(); |
23 |
|
60 |
|
24 |
public class SourceFilesContentProvider extends CElementContentProvider { |
61 |
private final SourceFilesViewer viewer; |
25 |
|
62 |
|
26 |
public SourceFilesContentProvider(SourceFilesViewer viewer) { |
63 |
public SourceFilesContentProvider(SourceFilesViewer viewer) { |
27 |
super(true, true); |
64 |
super(true, true); |
|
|
65 |
this.viewer = viewer; |
66 |
ExecutablesManager.getExecutablesManager().addExecutablesChangeListener(this); |
28 |
} |
67 |
} |
29 |
|
68 |
|
|
|
69 |
/* (non-Javadoc) |
70 |
* @see org.eclipse.cdt.ui.CElementContentProvider#dispose() |
71 |
*/ |
72 |
@Override |
73 |
public void dispose() { |
74 |
ExecutablesManager.getExecutablesManager().removeExecutablesChangeListener(this); |
75 |
synchronized (fetchedExecutables) { |
76 |
fetchedExecutables.clear(); |
77 |
} |
78 |
synchronized (pathToJobMap) { |
79 |
pathToJobMap.clear(); |
80 |
} |
81 |
super.dispose(); |
82 |
} |
83 |
|
30 |
@Override |
84 |
@Override |
31 |
public boolean hasChildren(Object element) { |
85 |
public boolean hasChildren(Object element) { |
32 |
if (element instanceof ITranslationUnit) { |
86 |
if (element instanceof ITranslationUnit) { |
33 |
IPath path = ((ITranslationUnit) element).getLocation(); |
87 |
TranslationUnitInfo info = SourceFilesViewer.fetchTranslationUnitInfo( |
34 |
if (path != null && !path.toFile().exists()) |
88 |
(Executable) viewer.getInput(), element, System.currentTimeMillis()); |
|
|
89 |
if (info != null && !info.exists) |
35 |
return false; |
90 |
return false; |
36 |
} |
91 |
} |
37 |
return super.hasChildren(element); |
92 |
return super.hasChildren(element); |
Lines 40-70
Link Here
|
40 |
public Object[] getElements(Object inputElement) { |
95 |
public Object[] getElements(Object inputElement) { |
41 |
if (inputElement instanceof Executable) { |
96 |
if (inputElement instanceof Executable) { |
42 |
final Executable executable = (Executable) inputElement; |
97 |
final Executable executable = (Executable) inputElement; |
43 |
final ITranslationUnit[][] resultHolder = new ITranslationUnit[1][]; |
98 |
final IPath exePath = executable.getPath(); |
44 |
Job quickParseJob = new Job("Reading Debug Symbol Information: " + executable.getName()) { |
99 |
|
45 |
|
100 |
// look for a job that is currently fetching this info |
46 |
@Override |
101 |
QuickParseJob job; |
47 |
protected IStatus run(IProgressMonitor monitor) { |
102 |
synchronized (pathToJobMap) { |
48 |
ITranslationUnit[] sourceFiles = executable.getSourceFiles(monitor); |
103 |
job = pathToJobMap.get(exePath); |
49 |
resultHolder[0] = sourceFiles; |
104 |
} |
50 |
return Status.OK_STATUS; |
105 |
if (job != null) { |
51 |
} |
106 |
// job is still running |
52 |
}; |
107 |
return new String[] { Messages.SourceFilesContentProvider_Refreshing }; |
|
|
108 |
} |
53 |
|
109 |
|
54 |
try { |
110 |
// see if we already checked |
55 |
quickParseJob.schedule(); |
111 |
if (fetchedExecutables.containsKey(exePath)) { |
56 |
quickParseJob.join(); |
112 |
return fetchedExecutables.get(exePath); |
57 |
} catch (InterruptedException e) { |
|
|
58 |
CDebugCorePlugin.log(e); |
59 |
} |
113 |
} |
60 |
|
114 |
|
61 |
ITranslationUnit[] sourceFiles = resultHolder[0]; |
115 |
// start a background job to look for the sources |
62 |
if (sourceFiles.length == 0) |
116 |
job = new QuickParseJob(executable); |
63 |
return new String[] { Messages.SourceFilesContentProvider_NoFilesFound + executable.getName() }; |
117 |
synchronized (pathToJobMap) { |
64 |
else |
118 |
pathToJobMap.put(exePath, job); |
65 |
return sourceFiles; |
119 |
} |
|
|
120 |
|
121 |
// once the job finishes, update the viewer |
122 |
final QuickParseJob theJob = job; |
123 |
job.addJobChangeListener(new JobChangeAdapter() { |
124 |
public void done(IJobChangeEvent event) { |
125 |
Display.getDefault().asyncExec(new Runnable() { |
126 |
public void run() { |
127 |
synchronized (pathToJobMap) { |
128 |
pathToJobMap.remove(exePath); |
129 |
} |
130 |
synchronized (fetchedExecutables) { |
131 |
fetchedExecutables.put(exePath, theJob.tus); |
132 |
} |
133 |
// update the viewer |
134 |
if (!viewer.getControl().isDisposed()) { |
135 |
viewer.getTree().setLayoutDeferred(true); |
136 |
viewer.refresh(executable); |
137 |
viewer.packColumns(); |
138 |
viewer.getTree().setLayoutDeferred(false); |
139 |
} |
140 |
} |
141 |
}); |
142 |
} |
143 |
}); |
144 |
|
145 |
job.schedule(); |
146 |
|
147 |
// while it's running... |
148 |
return new String[] { Messages.SourceFilesContentProvider_Refreshing }; |
66 |
} |
149 |
} |
67 |
return new Object[] {}; |
150 |
return new Object[] {}; |
68 |
} |
151 |
} |
69 |
|
152 |
|
70 |
} |
153 |
|
|
|
154 |
/* (non-Javadoc) |
155 |
* @see org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener#executablesListChanged() |
156 |
*/ |
157 |
public void executablesListChanged() { |
158 |
// Don't clear executables -- closing/opening project doesn't imply |
159 |
// the info is different. But cancel any jobs that might be for closed projects. |
160 |
cancelQuickParseJobs(); |
161 |
} |
162 |
|
163 |
|
164 |
/** |
165 |
* |
166 |
*/ |
167 |
private void cancelQuickParseJobs() { |
168 |
synchronized (pathToJobMap) { |
169 |
for (QuickParseJob job : pathToJobMap.values()) { |
170 |
job.cancel(); |
171 |
} |
172 |
pathToJobMap.clear(); |
173 |
} |
174 |
|
175 |
} |
176 |
|
177 |
/* (non-Javadoc) |
178 |
* @see org.eclipse.cdt.debug.core.executables.IExecutablesChangeListener#executablesChanged(java.util.List) |
179 |
*/ |
180 |
public void executablesChanged(List<Executable> executables) { |
181 |
for (Executable executable : executables) { |
182 |
IPath exePath = executable.getPath(); |
183 |
synchronized (fetchedExecutables) { |
184 |
fetchedExecutables.remove(exePath); |
185 |
} |
186 |
synchronized (pathToJobMap) { |
187 |
QuickParseJob job = pathToJobMap.get(exePath); |
188 |
if (job != null) { |
189 |
job.cancel(); |
190 |
pathToJobMap.remove(exePath); |
191 |
} |
192 |
} |
193 |
} |
194 |
} |
195 |
|
196 |
/* (non-Javadoc) |
197 |
* @see org.eclipse.cdt.ui.CElementContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) |
198 |
*/ |
199 |
@Override |
200 |
public void inputChanged(Viewer viewer, Object oldInput, final Object newInput) { |
201 |
super.inputChanged(viewer, oldInput, newInput); |
202 |
cancelQuickParseJobs(); |
203 |
|
204 |
Display.getDefault().asyncExec(new Runnable() { |
205 |
public void run() { |
206 |
// pack because the quick parse job won't run |
207 |
if (newInput instanceof Executable |
208 |
&& fetchedExecutables.containsKey(((Executable) newInput).getPath())) |
209 |
SourceFilesContentProvider.this.viewer.packColumns(); |
210 |
} |
211 |
}); |
212 |
} |
213 |
} |
214 |
|