1 | package org.modelica.mdt.ui.view; |
---|
2 | |
---|
3 | import java.util.ArrayList; |
---|
4 | import java.util.HashMap; |
---|
5 | import java.util.Iterator; |
---|
6 | import java.util.Map; |
---|
7 | import java.util.Map.Entry; |
---|
8 | import java.util.regex.Matcher; |
---|
9 | import java.util.regex.Pattern; |
---|
10 | |
---|
11 | import org.eclipse.core.resources.IContainer; |
---|
12 | import org.eclipse.core.resources.IFile; |
---|
13 | import org.eclipse.core.resources.IMarker; |
---|
14 | import org.eclipse.core.resources.IProject; |
---|
15 | import org.eclipse.core.resources.IResource; |
---|
16 | import org.eclipse.core.resources.IWorkspaceRoot; |
---|
17 | import org.eclipse.core.resources.ResourcesPlugin; |
---|
18 | import org.eclipse.core.runtime.CoreException; |
---|
19 | import org.eclipse.core.runtime.IPath; |
---|
20 | import org.eclipse.jface.text.BadLocationException; |
---|
21 | import org.eclipse.jface.text.IDocument; |
---|
22 | import org.eclipse.jface.viewers.DoubleClickEvent; |
---|
23 | import org.eclipse.jface.viewers.IDoubleClickListener; |
---|
24 | import org.eclipse.jface.viewers.TableViewer; |
---|
25 | import org.eclipse.swt.SWT; |
---|
26 | import org.eclipse.swt.custom.StyledText; |
---|
27 | import org.eclipse.swt.events.SelectionAdapter; |
---|
28 | import org.eclipse.swt.events.SelectionEvent; |
---|
29 | import org.eclipse.swt.graphics.Color; |
---|
30 | import org.eclipse.swt.layout.FillLayout; |
---|
31 | import org.eclipse.swt.layout.GridData; |
---|
32 | import org.eclipse.swt.layout.GridLayout; |
---|
33 | import org.eclipse.swt.widgets.Button; |
---|
34 | import org.eclipse.swt.widgets.Composite; |
---|
35 | import org.eclipse.swt.widgets.Event; |
---|
36 | import org.eclipse.swt.widgets.Group; |
---|
37 | import org.eclipse.swt.widgets.Label; |
---|
38 | import org.eclipse.swt.widgets.Listener; |
---|
39 | import org.eclipse.swt.widgets.Table; |
---|
40 | import org.eclipse.swt.widgets.TableColumn; |
---|
41 | import org.eclipse.swt.widgets.TableItem; |
---|
42 | import org.eclipse.ui.IEditorPart; |
---|
43 | import org.eclipse.ui.IFileEditorInput; |
---|
44 | import org.eclipse.ui.ide.IDE; |
---|
45 | import org.eclipse.ui.part.ViewPart; |
---|
46 | import org.eclipse.ui.texteditor.IDocumentProvider; |
---|
47 | import org.modelica.mdt.ui.editor.ModelicaEditor; |
---|
48 | import org.modelica.mdt.ui.text.ModelicaDocumentProvider; |
---|
49 | |
---|
50 | public class ModelicaUnusedPublicFuncionsView extends ViewPart |
---|
51 | { |
---|
52 | private Button filterButton, fastScanButton; |
---|
53 | private Button completeScanButton; |
---|
54 | private StyledText field, pathField; |
---|
55 | private String filterInput; // input from the textfield |
---|
56 | private static String pathInput; |
---|
57 | private boolean filterActive = false; |
---|
58 | /** |
---|
59 | * [funcName,FileName] , functionpos |
---|
60 | */ |
---|
61 | private HashMap<Tuple<String, String>, functionPos> functionMap; // all |
---|
62 | // functions |
---|
63 | // are |
---|
64 | // listed |
---|
65 | // here |
---|
66 | /** |
---|
67 | * list with all the *.mo files |
---|
68 | */ |
---|
69 | private ArrayList<IResource> res; |
---|
70 | private Table table, funcCallTable, funcGetCalledTable; |
---|
71 | private TableViewer tableViewer; |
---|
72 | private Label functionLabel, functionLabel2; |
---|
73 | private Group functionDetails; |
---|
74 | // private int lastSort = -1; //needed for sorting the table |
---|
75 | private Tuple<String, String> activeFunctionID = new Tuple<String, String>("", ""); |
---|
76 | private int colcount; // needed for sorting the table |
---|
77 | private Button checkBox; |
---|
78 | private boolean showOnlyEmptyFunctions = false; |
---|
79 | |
---|
80 | public ModelicaUnusedPublicFuncionsView() |
---|
81 | { |
---|
82 | |
---|
83 | super(); |
---|
84 | functionMap = new HashMap<Tuple<String, String>, functionPos>(); |
---|
85 | } |
---|
86 | |
---|
87 | private class TableSelectionAdapter extends SelectionAdapter |
---|
88 | { |
---|
89 | private int index; |
---|
90 | private Table table; |
---|
91 | |
---|
92 | public TableSelectionAdapter(Table table, int index) |
---|
93 | { |
---|
94 | this.table = table; |
---|
95 | this.index = index; |
---|
96 | } |
---|
97 | |
---|
98 | public void widgetSelected(SelectionEvent event) |
---|
99 | { |
---|
100 | ModelicaUnusedView.sortTableByColumnIndex(table,index,-1); |
---|
101 | } |
---|
102 | } |
---|
103 | |
---|
104 | @Override |
---|
105 | public void createPartControl(Composite parent) |
---|
106 | { |
---|
107 | // create visible objects like buttons and so on |
---|
108 | parent.setLayout(new GridLayout(1, false)); |
---|
109 | FillLayout fillLayout = new FillLayout(); |
---|
110 | fillLayout.type = SWT.HORIZONTAL; |
---|
111 | parent.setLayout(fillLayout); |
---|
112 | |
---|
113 | Composite composite = new Composite(parent, SWT.BORDER); |
---|
114 | composite.setLayoutData(new FillLayout(SWT.HORIZONTAL | SWT.VERTICAL)); |
---|
115 | composite.setLayout(new GridLayout(1, false)); |
---|
116 | |
---|
117 | Composite leftComposite = new Composite(composite, SWT.BORDER); |
---|
118 | leftComposite.setLayoutData(new GridData(GridData.FILL, SWT.TOP, false, false)); |
---|
119 | leftComposite.setLayout(new GridLayout(3, false)); |
---|
120 | |
---|
121 | Composite leftComposite2 = new Composite(composite, SWT.BORDER); |
---|
122 | GridData tmpGridData = new GridData(GridData.FILL, GridData.FILL, true, true); |
---|
123 | tmpGridData.widthHint = 5000; |
---|
124 | tmpGridData.heightHint = 5000; |
---|
125 | leftComposite2.setLayoutData(tmpGridData); |
---|
126 | leftComposite2.setLayout(new GridLayout(1, false)); |
---|
127 | |
---|
128 | Composite leftComposite3 = new Composite(composite, SWT.BORDER); |
---|
129 | leftComposite3.setLayoutData(new GridData(GridData.FILL, GridData.CENTER, false, false)); |
---|
130 | leftComposite3.setLayout(new GridLayout(3, false)); |
---|
131 | |
---|
132 | functionDetails = new Group(parent, SWT.BORDER); |
---|
133 | functionDetails.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1)); |
---|
134 | |
---|
135 | functionDetails.setLayout(new GridLayout(1, false)); |
---|
136 | functionDetails.setText("Functiondetails"); |
---|
137 | |
---|
138 | //-----------------------------------------------------FilterLabel |
---|
139 | Label filterLabel = new Label(leftComposite, SWT.NONE); |
---|
140 | filterLabel.setText("Filterstring: "); |
---|
141 | |
---|
142 | // ----------------------------------------------------INPUT |
---|
143 | |
---|
144 | field = new StyledText(leftComposite, SWT.BORDER); |
---|
145 | GridData textGrid = new GridData(SWT.BORDER); |
---|
146 | textGrid.widthHint = 85; |
---|
147 | textGrid.heightHint = 20; |
---|
148 | field.setLayoutData(textGrid); |
---|
149 | field.setMargins(2, 2, 2, 0); |
---|
150 | field.setMarginColor(new Color(null, 255, 0, 255)); |
---|
151 | field.setToolTipText("the FilterAttribute"); |
---|
152 | // ----------------------------------------------------PathInput |
---|
153 | |
---|
154 | pathField = new StyledText(leftComposite3, SWT.BORDER); |
---|
155 | GridData pathGrid = new GridData(SWT.BORDER); |
---|
156 | pathGrid.widthHint = 85; |
---|
157 | pathGrid.heightHint = 20; |
---|
158 | pathField.setLayoutData(pathGrid); |
---|
159 | pathField.setMargins(2, 2, 2, 0); |
---|
160 | pathField.setMarginColor(new Color(null, 255, 0, 255)); |
---|
161 | pathField.setToolTipText("restrict the searchpath or all *.mo files in the project will be matched against each other wich will take a lot of time"); |
---|
162 | pathField.setText("Compiler"); |
---|
163 | |
---|
164 | // ----------------------------------------------------BUTTONS |
---|
165 | // ---%%%%%%%%%%%%%%%%%%%%%%---filterButton |
---|
166 | filterButton = new Button(leftComposite, 0); |
---|
167 | GridData filterGridData = new GridData(); |
---|
168 | filterGridData.widthHint = 95; |
---|
169 | filterGridData.heightHint = 25; |
---|
170 | filterButton.setLayoutData(filterGridData); |
---|
171 | filterButton.setText("Refresh"); |
---|
172 | |
---|
173 | Listener filterListener = new Listener() |
---|
174 | { |
---|
175 | public void handleEvent(Event event) |
---|
176 | { |
---|
177 | filterActive = true; |
---|
178 | filterInput = field.getText().trim(); |
---|
179 | refreshTable(); |
---|
180 | } |
---|
181 | }; |
---|
182 | |
---|
183 | filterButton.addListener(SWT.Selection, filterListener); |
---|
184 | |
---|
185 | // ---%%%%%%%%%%%%%%%%%%%%%%---fastScanButton |
---|
186 | fastScanButton = new Button(leftComposite3, 0); |
---|
187 | GridData fastGridData = new GridData(); |
---|
188 | fastGridData.widthHint = 95; |
---|
189 | fastGridData.heightHint = 25; |
---|
190 | fastScanButton.setLayoutData(fastGridData); |
---|
191 | fastScanButton.setText("Fast Scan"); |
---|
192 | fastScanButton.setToolTipText("Performs a fast search of all *.mo Files in the specified Path. A fast search will not check for comments, strings ect. so be careful how to use the results."); |
---|
193 | |
---|
194 | Listener fastListener = new Listener() |
---|
195 | { |
---|
196 | public void handleEvent(Event event) |
---|
197 | { |
---|
198 | // createList(); |
---|
199 | functionMap.clear(); |
---|
200 | pathInput = pathField.getText().trim(); |
---|
201 | searchFiles(); |
---|
202 | fastUpdateFunctionDetails(); |
---|
203 | addFunctionCalls(); |
---|
204 | refreshTable(); |
---|
205 | } |
---|
206 | }; |
---|
207 | |
---|
208 | fastScanButton.addListener(SWT.Selection, fastListener); |
---|
209 | |
---|
210 | // ---%%%%%%%%%%%%%%%%%%%%%%---completeScanButton |
---|
211 | completeScanButton = new Button(leftComposite3, 0); |
---|
212 | GridData completeGridData = new GridData(); |
---|
213 | completeGridData.widthHint = 125; |
---|
214 | completeGridData.heightHint = 25; |
---|
215 | |
---|
216 | completeScanButton.setLayoutData(completeGridData); |
---|
217 | completeScanButton.setText("Complete Scan"); |
---|
218 | completeScanButton.setToolTipText("Performs a complete search of all *.mo Files in the specified Path."); |
---|
219 | |
---|
220 | Listener completeListener = new Listener() |
---|
221 | { |
---|
222 | public void handleEvent(Event event) |
---|
223 | { |
---|
224 | // createList(); |
---|
225 | functionMap.clear(); |
---|
226 | pathInput = pathField.getText().trim(); |
---|
227 | searchFiles(); |
---|
228 | updateFunctionDetails(); |
---|
229 | addFunctionCalls(); |
---|
230 | refreshTable(); |
---|
231 | } |
---|
232 | }; |
---|
233 | |
---|
234 | completeScanButton.addListener(SWT.Selection, completeListener); |
---|
235 | |
---|
236 | // ----------------------------------------------------CheckBox |
---|
237 | |
---|
238 | checkBox = new Button(leftComposite, SWT.CHECK); |
---|
239 | checkBox.setText("show unused functions only"); |
---|
240 | |
---|
241 | Listener checkBoxListener = new Listener() |
---|
242 | { |
---|
243 | public void handleEvent(Event event) |
---|
244 | { |
---|
245 | showOnlyEmptyFunctions = !showOnlyEmptyFunctions; |
---|
246 | } |
---|
247 | }; |
---|
248 | checkBox.addListener(SWT.Selection, checkBoxListener); |
---|
249 | |
---|
250 | |
---|
251 | // ----------------------------------------------------TABLE |
---|
252 | |
---|
253 | Composite composite_1 = new Composite(composite, SWT.NONE); |
---|
254 | composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1)); |
---|
255 | GridLayout gl_composite_1 = new GridLayout(1, false); |
---|
256 | gl_composite_1.horizontalSpacing = 0; |
---|
257 | gl_composite_1.marginHeight = 0; |
---|
258 | gl_composite_1.marginWidth = 0; |
---|
259 | gl_composite_1.verticalSpacing = 0; |
---|
260 | composite_1.setLayout(gl_composite_1); |
---|
261 | |
---|
262 | |
---|
263 | |
---|
264 | tableViewer = new TableViewer(leftComposite2, SWT.BORDER | SWT.FULL_SELECTION ); |
---|
265 | |
---|
266 | tableViewer.addDoubleClickListener(new IDoubleClickListener() |
---|
267 | { |
---|
268 | @Override |
---|
269 | public void doubleClick(DoubleClickEvent event) |
---|
270 | { |
---|
271 | event.getSelection().getClass(); |
---|
272 | TableItem item = null; |
---|
273 | if (table.getSelectionIndex() != -1) |
---|
274 | item = table.getItem(table.getSelectionIndex()); |
---|
275 | else |
---|
276 | return; |
---|
277 | Tuple<String, String> tpl = new Tuple<String, String>(item.getText(0), item.getText(1)); |
---|
278 | functionPos pos = functionMap.get(tpl); |
---|
279 | activeFunctionID = new Tuple<String, String>(item.getText(0), pos.editorFile.getName()); |
---|
280 | // if (pos == null) |
---|
281 | // return; |
---|
282 | jumpToFilePos(pos.editorFile, pos.defStart + 1); |
---|
283 | } |
---|
284 | }); // end doubleClickListener |
---|
285 | |
---|
286 | GridData tableGrid = new GridData(SWT.FILL, SWT.FILL, true, true); |
---|
287 | table = tableViewer.getTable(); |
---|
288 | table.setHeaderVisible(true); |
---|
289 | table.setLinesVisible(true); |
---|
290 | table.setLayoutData(tableGrid); |
---|
291 | |
---|
292 | // listener for onClick-events in the table |
---|
293 | table.addListener(SWT.Selection, new Listener() |
---|
294 | { |
---|
295 | public void handleEvent(Event e) |
---|
296 | { |
---|
297 | TableItem item = (TableItem) e.item; |
---|
298 | String s = item.getText(0); |
---|
299 | if (table.getSelectionIndex() != -1) |
---|
300 | item = table.getItem(table.getSelectionIndex()); |
---|
301 | else |
---|
302 | return; |
---|
303 | Tuple<String, String> tpl = new Tuple<String, String>(item.getText(0), item.getText(1)); |
---|
304 | functionPos pos = functionMap.get(tpl); |
---|
305 | activeFunctionID = new Tuple<String, String>(item.getText(0), pos.editorFile.getName()); |
---|
306 | functionDetails.setText("Functiondetails - " + s); |
---|
307 | |
---|
308 | showFunctionData(pos); |
---|
309 | } |
---|
310 | }); |
---|
311 | |
---|
312 | //tableViewer = new TableViewer(composite_1, SWT.BORDER | SWT.FULL_SELECTION); |
---|
313 | |
---|
314 | // -----------------------------------------------calledFunctions |
---|
315 | functionLabel = new Label(functionDetails, SWT.NONE); |
---|
316 | functionLabel.setText("Functions called:"); |
---|
317 | functionLabel.setToolTipText("The list of all functions that are called in this function"); |
---|
318 | // -----------------------------------------------Table for the functions called |
---|
319 | |
---|
320 | tableViewer = new TableViewer(functionDetails, SWT.FILL | SWT.FULL_SELECTION); |
---|
321 | |
---|
322 | tableViewer.addDoubleClickListener(new IDoubleClickListener() |
---|
323 | { |
---|
324 | @Override |
---|
325 | public void doubleClick(DoubleClickEvent event) |
---|
326 | { |
---|
327 | TableItem item = null; |
---|
328 | if (funcCallTable.getSelectionIndex() != -1) |
---|
329 | item = funcCallTable.getItem(funcCallTable.getSelectionIndex()); |
---|
330 | else |
---|
331 | return; |
---|
332 | |
---|
333 | functionPos pos = functionMap.get(activeFunctionID); |
---|
334 | int line = Integer.valueOf(item.getText(1)); |
---|
335 | if (pos == null) |
---|
336 | return; |
---|
337 | jumpToFilePos(pos.editorFile, line + 1 ); |
---|
338 | |
---|
339 | } |
---|
340 | }); |
---|
341 | funcCallTable = tableViewer.getTable(); |
---|
342 | |
---|
343 | |
---|
344 | funcCallTable.setHeaderVisible(true); |
---|
345 | funcCallTable.setLinesVisible(true); |
---|
346 | funcCallTable.setLayoutData(tableGrid); |
---|
347 | // -----------------------------------------------isCalled |
---|
348 | functionLabel2 = new Label(functionDetails, SWT.NONE); |
---|
349 | functionLabel2.setText("Calls to function:"); |
---|
350 | functionLabel2.setToolTipText("All functions that call this function"); |
---|
351 | // -----------------------------------------------Table for the |
---|
352 | // functions that call this function |
---|
353 | |
---|
354 | tableViewer = new TableViewer(functionDetails, SWT.FILL | SWT.FULL_SELECTION); |
---|
355 | |
---|
356 | tableViewer.addDoubleClickListener(new IDoubleClickListener() |
---|
357 | { |
---|
358 | @Override |
---|
359 | public void doubleClick(DoubleClickEvent event) |
---|
360 | { |
---|
361 | |
---|
362 | event.getSelection().getClass(); |
---|
363 | TableItem item = null; |
---|
364 | if (funcGetCalledTable.getSelectionIndex() != -1) |
---|
365 | item = funcGetCalledTable.getItem(funcGetCalledTable.getSelectionIndex()); |
---|
366 | else |
---|
367 | return; |
---|
368 | |
---|
369 | String[] tmp = item.getText(0).split("\\."); |
---|
370 | Tuple<String, String> tpl; |
---|
371 | if (tmp.length == 1) |
---|
372 | tpl = new Tuple<String, String>(item.getText(0), activeFunctionID.y); |
---|
373 | else |
---|
374 | tpl = new Tuple<String, String>(tmp[tmp.length - 1], tmp[0] + ".mo"); |
---|
375 | functionPos pos = functionMap.get(tpl); |
---|
376 | if (pos == null) |
---|
377 | return; |
---|
378 | int line = Integer.parseInt(item.getText(1)); |
---|
379 | jumpToFilePos(pos.editorFile, line+1); |
---|
380 | } |
---|
381 | }); // end doubleClickListener |
---|
382 | |
---|
383 | funcGetCalledTable = tableViewer.getTable(); |
---|
384 | funcGetCalledTable.setHeaderVisible(true); |
---|
385 | funcGetCalledTable.setLinesVisible(true); |
---|
386 | funcGetCalledTable.setLayoutData(tableGrid); |
---|
387 | |
---|
388 | } |
---|
389 | |
---|
390 | /** |
---|
391 | * jump to the line in the file (has to be a *.mo file) |
---|
392 | * |
---|
393 | * @param file |
---|
394 | * @param line |
---|
395 | */ |
---|
396 | |
---|
397 | private void jumpToFilePos(IFile file, int line) |
---|
398 | { |
---|
399 | if ( (file == null) || (line < 0) ) |
---|
400 | return; |
---|
401 | HashMap<String, Object> map = new HashMap<String, Object>(); |
---|
402 | map.put(IMarker.LINE_NUMBER, line); |
---|
403 | map.put(IDE.EDITOR_ID_ATTR, "org.eclipse.ui.ModellicaEditor"); |
---|
404 | try { |
---|
405 | IMarker marker; |
---|
406 | marker = file.createMarker(IMarker.TEXT); |
---|
407 | marker.setAttributes(map); |
---|
408 | IDE.openEditor(getSite().getWorkbenchWindow().getActivePage(), marker); |
---|
409 | marker.delete(); |
---|
410 | } catch (CoreException e) { |
---|
411 | e.printStackTrace(); |
---|
412 | } |
---|
413 | } |
---|
414 | |
---|
415 | /** |
---|
416 | * search for mo files and then search all files for functions and add them |
---|
417 | * to the functionMap |
---|
418 | */ |
---|
419 | public void searchFiles() |
---|
420 | { |
---|
421 | functionMap.clear(); |
---|
422 | IProject activeProject = null; |
---|
423 | // get all Lines of all Files and search for specific function |
---|
424 | // get Name of active Project |
---|
425 | IEditorPart editorPart = getSite().getWorkbenchWindow().getActivePage().getActiveEditor(); |
---|
426 | if (editorPart != null) { |
---|
427 | IFileEditorInput input = (IFileEditorInput) editorPart.getEditorInput(); |
---|
428 | IFile tmpFile = input.getFile(); |
---|
429 | activeProject = tmpFile.getProject(); |
---|
430 | res = new ArrayList<IResource>(); |
---|
431 | res = getMoFiles(activeProject); |
---|
432 | |
---|
433 | // got all Files from the project, iterate through them |
---|
434 | |
---|
435 | ModelicaEditor edit = new ModelicaEditor(); |
---|
436 | IDocumentProvider provider = new ModelicaDocumentProvider(); |
---|
437 | |
---|
438 | for (int i = 0; i < res.size(); i++) { |
---|
439 | // Start with check if the file is a *.mo file |
---|
440 | if (!res.get(i).getName().endsWith(".mo")) |
---|
441 | continue; |
---|
442 | |
---|
443 | IFile file = ((IFile) res.get(i)); |
---|
444 | // all Lines of the files are loaded in the list |
---|
445 | // start searching for function |
---|
446 | try { |
---|
447 | provider.connect(file); |
---|
448 | } catch (CoreException e) { |
---|
449 | e.printStackTrace(); |
---|
450 | } |
---|
451 | IDocument doc = provider.getDocument(file); |
---|
452 | |
---|
453 | ArrayList<String[]> StringList = edit.getFunctions(doc); |
---|
454 | for (int j = 0; j < StringList.size(); j++) { |
---|
455 | String[] tmpVal = StringList.get(j); |
---|
456 | functionPos func = new functionPos(tmpVal[0], res.get(i).getName(), Integer.valueOf(tmpVal[1]), Integer.valueOf(tmpVal[2])); |
---|
457 | func.editorFile = file; |
---|
458 | try { |
---|
459 | func.text = doc.get(doc.getLineOffset(Integer.valueOf(tmpVal[1])), doc.getLineOffset(Integer.valueOf(tmpVal[2])) - doc.getLineOffset(Integer.valueOf(tmpVal[1]))); |
---|
460 | } catch (NumberFormatException e) { |
---|
461 | e.printStackTrace(); |
---|
462 | } catch (BadLocationException e) { |
---|
463 | e.printStackTrace(); |
---|
464 | } |
---|
465 | // check if only special chars |
---|
466 | if (tmpVal[0].replaceAll("[^a-zA-Z0-9]", "").equals("")) |
---|
467 | continue; |
---|
468 | functionMap.put(new Tuple<String, String>(tmpVal[0], file.getName()), func); |
---|
469 | } |
---|
470 | |
---|
471 | } |
---|
472 | } |
---|
473 | } |
---|
474 | |
---|
475 | /** |
---|
476 | * returns a list with all the .mo files in the project, uses the public |
---|
477 | * variable pathInput to specific the searchpath |
---|
478 | * |
---|
479 | * @param activeProject |
---|
480 | * @return |
---|
481 | */ |
---|
482 | public static ArrayList<IResource> getMoFiles(IProject activeProject) |
---|
483 | { |
---|
484 | ArrayList<IResource> files = new ArrayList<IResource>(); |
---|
485 | IWorkspaceRoot myWorkspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); |
---|
486 | |
---|
487 | IPath path = activeProject.getLocation(); |
---|
488 | |
---|
489 | if (path.toString().contains(pathInput)) |
---|
490 | findFiles(files, path, myWorkspaceRoot, true); |
---|
491 | else |
---|
492 | findFiles(files, path, myWorkspaceRoot, false); |
---|
493 | return files; |
---|
494 | } |
---|
495 | |
---|
496 | /** |
---|
497 | * find all the files in the specific directory that end with .mo |
---|
498 | * |
---|
499 | * @param files |
---|
500 | * @param path |
---|
501 | * @param myWorkspaceRoot |
---|
502 | * @param subPath |
---|
503 | */ |
---|
504 | private static void findFiles(ArrayList<IResource> files, IPath path, IWorkspaceRoot myWorkspaceRoot, boolean subPath) |
---|
505 | { |
---|
506 | IContainer container = myWorkspaceRoot.getContainerForLocation(path); |
---|
507 | |
---|
508 | boolean wasFound = subPath; |
---|
509 | try { |
---|
510 | IResource[] iResources; |
---|
511 | iResources = container.members(); |
---|
512 | for (IResource iR : iResources) { |
---|
513 | |
---|
514 | if (("mo".equalsIgnoreCase(iR.getFileExtension())) && (subPath == true)) |
---|
515 | files.add(iR); |
---|
516 | if (iR.getType() == IResource.FOLDER) { |
---|
517 | IPath tempPath = iR.getLocation(); |
---|
518 | if (tempPath.toString().contains(pathInput)) { |
---|
519 | wasFound = true; |
---|
520 | findFiles(files, tempPath, myWorkspaceRoot, true); |
---|
521 | } else if (wasFound) // when specific folder was already |
---|
522 | // found -> break out of the loop |
---|
523 | break; |
---|
524 | else |
---|
525 | findFiles(files, tempPath, myWorkspaceRoot, false); |
---|
526 | } |
---|
527 | } |
---|
528 | } catch (CoreException e) { |
---|
529 | e.printStackTrace(); |
---|
530 | } |
---|
531 | } |
---|
532 | |
---|
533 | @Override |
---|
534 | public void setFocus() |
---|
535 | { |
---|
536 | |
---|
537 | } |
---|
538 | |
---|
539 | /** |
---|
540 | * shows the data of the function that was clicked on in the function table |
---|
541 | * (the one on the left) the data is displayed in the two small tables on |
---|
542 | * the right side of the view |
---|
543 | * |
---|
544 | * @param func |
---|
545 | */ |
---|
546 | private void showFunctionData(functionPos func) |
---|
547 | { |
---|
548 | funcCallTable.removeAll(); |
---|
549 | String[] titles = { "Function", "Line" }; |
---|
550 | for (int i = 0; i < titles.length; i++) { |
---|
551 | TableColumn column = new TableColumn(funcCallTable, SWT.NONE); |
---|
552 | column.setText(titles[i]); |
---|
553 | TableSelectionAdapter adapt = new TableSelectionAdapter(funcCallTable, i); |
---|
554 | column.addSelectionListener(adapt); |
---|
555 | } |
---|
556 | |
---|
557 | for (int i = 0; i < func.functionCalls.size(); i++) { |
---|
558 | TableItem item = new TableItem(funcCallTable, SWT.NONE); |
---|
559 | item.setText(0, ((String) func.functionCalls.get(i).x)); |
---|
560 | item.setText(1, Integer.toString(func.functionCalls.get(i).y)); |
---|
561 | } |
---|
562 | |
---|
563 | for (int i = 0; i < titles.length; i++) { |
---|
564 | funcCallTable.getColumn(i).pack(); |
---|
565 | } |
---|
566 | |
---|
567 | funcGetCalledTable.removeAll(); |
---|
568 | // other table |
---|
569 | String[] titles2 = { "Function", "Line", "file" }; |
---|
570 | for (int i = 0; i < titles2.length; i++) { |
---|
571 | TableColumn column = new TableColumn(funcGetCalledTable, SWT.NONE); |
---|
572 | column.setText(titles2[i]); |
---|
573 | TableSelectionAdapter adapt = new TableSelectionAdapter(funcGetCalledTable, i); |
---|
574 | column.addSelectionListener(adapt); |
---|
575 | } |
---|
576 | |
---|
577 | Iterator<Entry<String, ArrayList<Integer>>> it = func.occurrencies.entrySet().iterator(); |
---|
578 | while (it.hasNext()) { |
---|
579 | Map.Entry<String, ArrayList<Integer>> pair = it.next(); |
---|
580 | |
---|
581 | for (int i = 0; i < pair.getValue().size(); i++) { |
---|
582 | TableItem item = new TableItem(funcGetCalledTable, SWT.NONE); |
---|
583 | item.setText(0, pair.getKey()); |
---|
584 | |
---|
585 | item.setText(1, Integer.toString(pair.getValue().get(i))); |
---|
586 | |
---|
587 | item.setText(2, pair.getKey().split("\\.")[0] + ".mo"); |
---|
588 | } |
---|
589 | } |
---|
590 | |
---|
591 | for (int i = 0; i < titles2.length; i++) { |
---|
592 | funcGetCalledTable.getColumn(i).pack(); |
---|
593 | } |
---|
594 | } |
---|
595 | |
---|
596 | /** |
---|
597 | * searches for functions that are called in all functions, faster but not |
---|
598 | * as precise |
---|
599 | */ |
---|
600 | private void fastUpdateFunctionDetails() |
---|
601 | { |
---|
602 | if (((functionMap == null) || (functionMap.isEmpty()))) |
---|
603 | return; |
---|
604 | |
---|
605 | Pattern p = Pattern.compile("\n"); |
---|
606 | |
---|
607 | Iterator<Entry<Tuple<String, String>, functionPos>> it = functionMap.entrySet().iterator(); |
---|
608 | while (it.hasNext()) { |
---|
609 | Map.Entry<Tuple<String, String>, functionPos> pair = it.next(); |
---|
610 | int offset = pair.getValue().defStart; |
---|
611 | String text = pair.getValue().text; |
---|
612 | String[] parts = text.split("\\("); |
---|
613 | if (parts != null) |
---|
614 | for (int i = 1; i < parts.length; i++) { |
---|
615 | String tmpPart = parts[i - 1].replaceAll("\\s+", ""); |
---|
616 | |
---|
617 | Matcher m = p.matcher(parts[i - 1]); |
---|
618 | while (m.find()) { |
---|
619 | offset += 1; |
---|
620 | } |
---|
621 | |
---|
622 | // check for keywords |
---|
623 | if ((tmpPart.endsWith(";")) || (tmpPart.endsWith("algorithm")) || (tmpPart.endsWith("case")) || (tmpPart.endsWith("then")) || (tmpPart.endsWith("else")) || (tmpPart.endsWith("if")) || (tmpPart.endsWith("annotation")) || (tmpPart.endsWith("NONE") || (tmpPart.endsWith("SOME"))) || (tmpPart.endsWith("matchcontinue")) || (tmpPart.endsWith("match")) || (tmpPart.endsWith("fail")) || (tmpPart.endsWith("failure"))) |
---|
624 | continue; |
---|
625 | // last word is function, add to list |
---|
626 | String[] tmpParts = parts[i - 1].trim().split("\\s+"); |
---|
627 | |
---|
628 | String funcName = tmpParts[tmpParts.length - 1]; |
---|
629 | if (!funcName.matches("^[a-zA-Z0-9_.-]*$") || (funcName.equals(""))) |
---|
630 | continue; |
---|
631 | |
---|
632 | if (funcName.replaceAll("[^a-zA-Z0-9]", "").equals("")) |
---|
633 | continue; |
---|
634 | |
---|
635 | Matcher matcher = Pattern.compile("//.*" + funcName + "\\n").matcher(text); |
---|
636 | int pos2 = matcher.find() ? matcher.start() : -1; |
---|
637 | |
---|
638 | if ((pos2 != -1)) |
---|
639 | continue; |
---|
640 | |
---|
641 | pair.getValue().functionCalls.add(new Triple<String, Integer, functionPos>(funcName, offset, null)); |
---|
642 | } |
---|
643 | |
---|
644 | } |
---|
645 | } |
---|
646 | |
---|
647 | /** |
---|
648 | * searches for functions that are called in all functions |
---|
649 | */ |
---|
650 | private void updateFunctionDetails() |
---|
651 | { |
---|
652 | if (((functionMap == null) || (functionMap.isEmpty()))) |
---|
653 | return; |
---|
654 | |
---|
655 | Iterator<Entry<Tuple<String, String>, functionPos>> it = functionMap.entrySet().iterator(); |
---|
656 | while (it.hasNext()) { |
---|
657 | Map.Entry<Tuple<String, String>, functionPos> pair = it.next(); |
---|
658 | String text = pair.getValue().text; |
---|
659 | |
---|
660 | // [\.A-Za-z0-9_]+\s*\([^\)]*\) |
---|
661 | Matcher matcher = Pattern.compile("[\\.A-Za-z0-9_]+\\s*\\(").matcher(text); |
---|
662 | while (matcher.find()) { |
---|
663 | |
---|
664 | int offset = pair.getValue().defStart; |
---|
665 | |
---|
666 | String s1 = text.substring(matcher.start(), matcher.end() - 1); |
---|
667 | s1 = s1.trim(); |
---|
668 | if ((s1.equals(";")) || (s1.equals("algorithm")) || (s1.equals("case")) || (s1.equals("then")) || (s1.equals("else")) || (s1.equals("if")) || (s1.equals("annotation")) || (s1.equals("NONE") || (s1.equals("SOME"))) || (s1.equals("matchcontinue")) || (s1.equals("match")) || (s1.equals("fail")) || (s1.equals("failure"))) |
---|
669 | continue; |
---|
670 | |
---|
671 | // check for comments, pattern for multiline comment |
---|
672 | Matcher commentMatcher = Pattern.compile("(//.*|\"[^\"]*\")").matcher(text); |
---|
673 | boolean comment = false; |
---|
674 | while (commentMatcher.find() && (!comment)) { |
---|
675 | if ((commentMatcher.start() < matcher.start()) && (commentMatcher.end() > matcher.end())) |
---|
676 | comment = true; |
---|
677 | } |
---|
678 | if (comment) |
---|
679 | continue; |
---|
680 | |
---|
681 | // get line |
---|
682 | boolean found = false; |
---|
683 | Matcher lineMatcher = Pattern.compile("\n").matcher(text); |
---|
684 | while (lineMatcher.find() && (found == false)) { |
---|
685 | if (lineMatcher.end() > matcher.end()) |
---|
686 | found = true; |
---|
687 | else |
---|
688 | offset++; |
---|
689 | } |
---|
690 | pair.getValue().functionCalls.add(new Triple<String, Integer, functionPos>(s1, offset, null)); |
---|
691 | } |
---|
692 | |
---|
693 | } |
---|
694 | |
---|
695 | } |
---|
696 | |
---|
697 | /** |
---|
698 | * creates the input for the table |
---|
699 | */ |
---|
700 | |
---|
701 | public void refreshTable() |
---|
702 | { |
---|
703 | table.removeAll(); |
---|
704 | |
---|
705 | String[] titles = { "Name", "File" }; |
---|
706 | colcount = titles.length; |
---|
707 | for (int i = 0; i < colcount; i++) { |
---|
708 | TableColumn column = new TableColumn(table, SWT.NONE); |
---|
709 | column.setText(titles[i]); |
---|
710 | TableSelectionAdapter adapt = new TableSelectionAdapter(table, i); |
---|
711 | column.addSelectionListener(adapt); |
---|
712 | } |
---|
713 | |
---|
714 | if (!((functionMap == null) || (functionMap.isEmpty()))) { |
---|
715 | Iterator<Entry<Tuple<String, String>, functionPos>> it = functionMap.entrySet().iterator(); |
---|
716 | while (it.hasNext()) { |
---|
717 | Map.Entry<Tuple<String, String>, functionPos> pair = it.next(); |
---|
718 | if (filterInput != null) |
---|
719 | if (!(filterInput.equals("")) && (filterActive) && (!pair.getValue().name.contains(filterInput)) && (!pair.getValue().defFile.contains(filterInput))) |
---|
720 | continue; |
---|
721 | if (showOnlyEmptyFunctions) { |
---|
722 | if (!pair.getValue().occurrencies.isEmpty()) |
---|
723 | continue; |
---|
724 | } |
---|
725 | TableItem item = new TableItem(table, SWT.NONE); |
---|
726 | item.setText(0, pair.getValue().name); |
---|
727 | item.setText(1, pair.getValue().defFile); |
---|
728 | } |
---|
729 | } |
---|
730 | |
---|
731 | for (int i = 0; i < titles.length; i++) { |
---|
732 | table.getColumn(i).pack(); |
---|
733 | } |
---|
734 | |
---|
735 | filterActive = false; |
---|
736 | } |
---|
737 | |
---|
738 | /** |
---|
739 | * for each function inn the functionMap create the List with from where it |
---|
740 | * is called |
---|
741 | */ |
---|
742 | private void addFunctionCalls() |
---|
743 | { |
---|
744 | |
---|
745 | Iterator<Entry<Tuple<String, String>, functionPos>> it = functionMap.entrySet().iterator(); |
---|
746 | while (it.hasNext()) { |
---|
747 | Map.Entry<Tuple<String, String>, functionPos> pair = it.next(); |
---|
748 | |
---|
749 | // if functions are called |
---|
750 | if (!pair.getValue().functionCalls.isEmpty()) { |
---|
751 | for (int i = 0; i < pair.getValue().functionCalls.size(); i++) { |
---|
752 | String[] tmp = pair.getValue().functionCalls.get(i).x.split("\\."); |
---|
753 | Tuple<String, String> tpl; |
---|
754 | |
---|
755 | if (tmp.length <= 1) |
---|
756 | tpl = new Tuple<String, String>(tmp[0], pair.getValue().editorFile.getName()); |
---|
757 | else |
---|
758 | tpl = new Tuple<String, String>(tmp[tmp.length - 1], tmp[0] + ".mo"); |
---|
759 | |
---|
760 | functionPos calledFunc = functionMap.get(tpl); |
---|
761 | if (calledFunc == null) |
---|
762 | continue; |
---|
763 | |
---|
764 | calledFunc.addOccurrencey(pair.getValue().editorFile.getName().split("\\.")[0] + "." + pair.getValue().name, pair.getValue().functionCalls.get(i).y); |
---|
765 | |
---|
766 | } |
---|
767 | |
---|
768 | } |
---|
769 | } |
---|
770 | } |
---|
771 | |
---|
772 | /** |
---|
773 | * this class will handle all informations about where and how often a |
---|
774 | * function is called. It stores the name, the file where the function is |
---|
775 | * defined and the offests in this file as well as all the occurencies |
---|
776 | */ |
---|
777 | public class functionPos |
---|
778 | { |
---|
779 | /** |
---|
780 | * name of the function |
---|
781 | */ |
---|
782 | public String name; |
---|
783 | /** |
---|
784 | * the file where the function is defined |
---|
785 | */ |
---|
786 | public String defFile; |
---|
787 | /** |
---|
788 | * the offset in the file where the function definition starts |
---|
789 | */ |
---|
790 | public int defStart; |
---|
791 | /** |
---|
792 | * the end of the function definition in the file where the function is |
---|
793 | * defined (offset) |
---|
794 | */ |
---|
795 | public int defEnd; |
---|
796 | /** |
---|
797 | * mapping all occurrencies of the function to the name of the file |
---|
798 | */ |
---|
799 | public HashMap<String, ArrayList<Integer>> occurrencies; |
---|
800 | |
---|
801 | /** |
---|
802 | * a list with all the functions that are called in this function |
---|
803 | * functionPos can be NULL, if a fast search was used or the called |
---|
804 | * function was not found in the searched files |
---|
805 | */ |
---|
806 | public ArrayList<Triple<String, Integer, functionPos>> functionCalls; |
---|
807 | |
---|
808 | public IFile editorFile; |
---|
809 | |
---|
810 | /** |
---|
811 | * The text of the function |
---|
812 | */ |
---|
813 | public String text; |
---|
814 | |
---|
815 | /** |
---|
816 | * initialises a new object for a function |
---|
817 | * |
---|
818 | * @param n |
---|
819 | * - name of the function |
---|
820 | * @param f |
---|
821 | * - name of the file where the function is found |
---|
822 | * @param sOffset |
---|
823 | * - startLine in the file (of the function definition) |
---|
824 | * @param eOffset |
---|
825 | * - endLine in the file (of the function definition) |
---|
826 | */ |
---|
827 | public functionPos(String n, String f, int sLine, int eLine) |
---|
828 | { |
---|
829 | name = n; |
---|
830 | defFile = f; |
---|
831 | defStart = sLine; |
---|
832 | defEnd = eLine; |
---|
833 | occurrencies = new HashMap<String, ArrayList<Integer>>(); |
---|
834 | functionCalls = new ArrayList<Triple<String, Integer, functionPos>>(); |
---|
835 | } |
---|
836 | |
---|
837 | /** |
---|
838 | * adds an occurrence to the list |
---|
839 | * |
---|
840 | * @param file |
---|
841 | * - the name of the file |
---|
842 | * @param offset |
---|
843 | * - the offset |
---|
844 | */ |
---|
845 | public void addOccurrencey(String func, int offset) |
---|
846 | { |
---|
847 | // if the occurence is the definition -> return |
---|
848 | String[] split = func.split("\\."); |
---|
849 | if (split.length > 1) { |
---|
850 | if (name.equals(split[1])) |
---|
851 | return; |
---|
852 | } else if (func.equals(name)) |
---|
853 | return; |
---|
854 | // if not existing, create new key |
---|
855 | if (!occurrencies.containsKey(func)) { |
---|
856 | ArrayList<Integer> tmpColect = new ArrayList<Integer>(); |
---|
857 | tmpColect.add(offset); |
---|
858 | occurrencies.put(func, tmpColect); |
---|
859 | } |
---|
860 | // if existing, add to colection |
---|
861 | else { |
---|
862 | ArrayList<Integer> tmpColect = occurrencies.get(func); |
---|
863 | tmpColect.add(offset); |
---|
864 | } |
---|
865 | } |
---|
866 | } |
---|
867 | |
---|
868 | public class Tuple<X, Y> |
---|
869 | { |
---|
870 | public final X x; |
---|
871 | public final Y y; |
---|
872 | |
---|
873 | public Tuple(X x, Y y) |
---|
874 | { |
---|
875 | this.x = x; |
---|
876 | this.y = y; |
---|
877 | } |
---|
878 | |
---|
879 | public int hashCode() |
---|
880 | { |
---|
881 | |
---|
882 | if ((y.getClass().equals(String.class)) && (x.getClass().equals(String.class))) { |
---|
883 | int r = 0; |
---|
884 | for (int i = 0; i < ((String) x).length(); i++) { |
---|
885 | r += ((String) x).charAt(i); |
---|
886 | } |
---|
887 | for (int j = 0; j < ((String) y).length(); j++) { |
---|
888 | r += ((String) y).charAt(j); |
---|
889 | } |
---|
890 | |
---|
891 | return r; |
---|
892 | } |
---|
893 | return x.hashCode() + y.hashCode(); |
---|
894 | } |
---|
895 | |
---|
896 | public boolean equals(Object o) |
---|
897 | { |
---|
898 | if (!o.getClass().equals(this.getClass())) |
---|
899 | return false; |
---|
900 | |
---|
901 | @SuppressWarnings("unchecked") |
---|
902 | Tuple<X,Y> tpl = ((Tuple<X,Y>) o); |
---|
903 | return (tpl.x.equals(x) && tpl.y.equals(y)); |
---|
904 | |
---|
905 | } |
---|
906 | |
---|
907 | public int compareTo(Object o) |
---|
908 | { |
---|
909 | if (!o.getClass().equals(this.getClass())) |
---|
910 | return -1; |
---|
911 | |
---|
912 | return 1; |
---|
913 | } |
---|
914 | } |
---|
915 | |
---|
916 | public class Triple<X, Y, Z> |
---|
917 | { |
---|
918 | public final X x; |
---|
919 | public final Y y; |
---|
920 | public final Z z; |
---|
921 | |
---|
922 | public Triple(X x, Y y, Z z) |
---|
923 | { |
---|
924 | this.x = x; |
---|
925 | this.y = y; |
---|
926 | this.z = z; |
---|
927 | } |
---|
928 | } |
---|
929 | } |
---|