source: trunk/org.modelica.mdt.ui/src/org/modelica/mdt/ui/view/ModelicaUnusedPublicFuncionsView.java

Last change on this file was 1879, checked in by mwalther, 9 years ago
  • Some bug fixes for the Susan plugin
  • Changed the Susan file icon name to tpl_file.png
  • Two new views added for MetaModelica? mo-Files, to find unused variables and functions (public and protected)
File size: 28.5 KB
Line 
1package org.modelica.mdt.ui.view;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.Map;
7import java.util.Map.Entry;
8import java.util.regex.Matcher;
9import java.util.regex.Pattern;
10
11import org.eclipse.core.resources.IContainer;
12import org.eclipse.core.resources.IFile;
13import org.eclipse.core.resources.IMarker;
14import org.eclipse.core.resources.IProject;
15import org.eclipse.core.resources.IResource;
16import org.eclipse.core.resources.IWorkspaceRoot;
17import org.eclipse.core.resources.ResourcesPlugin;
18import org.eclipse.core.runtime.CoreException;
19import org.eclipse.core.runtime.IPath;
20import org.eclipse.jface.text.BadLocationException;
21import org.eclipse.jface.text.IDocument;
22import org.eclipse.jface.viewers.DoubleClickEvent;
23import org.eclipse.jface.viewers.IDoubleClickListener;
24import org.eclipse.jface.viewers.TableViewer;
25import org.eclipse.swt.SWT;
26import org.eclipse.swt.custom.StyledText;
27import org.eclipse.swt.events.SelectionAdapter;
28import org.eclipse.swt.events.SelectionEvent;
29import org.eclipse.swt.graphics.Color;
30import org.eclipse.swt.layout.FillLayout;
31import org.eclipse.swt.layout.GridData;
32import org.eclipse.swt.layout.GridLayout;
33import org.eclipse.swt.widgets.Button;
34import org.eclipse.swt.widgets.Composite;
35import org.eclipse.swt.widgets.Event;
36import org.eclipse.swt.widgets.Group;
37import org.eclipse.swt.widgets.Label;
38import org.eclipse.swt.widgets.Listener;
39import org.eclipse.swt.widgets.Table;
40import org.eclipse.swt.widgets.TableColumn;
41import org.eclipse.swt.widgets.TableItem;
42import org.eclipse.ui.IEditorPart;
43import org.eclipse.ui.IFileEditorInput;
44import org.eclipse.ui.ide.IDE;
45import org.eclipse.ui.part.ViewPart;
46import org.eclipse.ui.texteditor.IDocumentProvider;
47import org.modelica.mdt.ui.editor.ModelicaEditor;
48import org.modelica.mdt.ui.text.ModelicaDocumentProvider;
49
50public 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}
Note: See TracBrowser for help on using the repository browser.