~sschuhmann/scratch/gtk-stack

« back to all changes in this revision

Viewing changes to plugins/outline/ValaSymbolResolver.vala

  • Committer: Steffen Schuhmann
  • Date: 2014-04-14 20:05:11 UTC
  • mfrom: (1253.2.29 scratch)
  • Revision ID: schuhmannsteffen+bazaar@mailbox.org-20140414200511-w5ofz70pm1dvu8pu
Merged upstream to resolve mergingconflicts

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
public class Report : Vala.Report
3
3
{
4
 
        // just mute everything
5
 
        public override void err (Vala.SourceReference? ref, string msg) {}
6
 
        public override void warn (Vala.SourceReference? ref, string msg) {}
7
 
        public override void note (Vala.SourceReference? ref, string msg) {}
8
 
        public override void depr (Vala.SourceReference? ref, string msg) {}
 
4
    // just mute everything
 
5
    public override void err (Vala.SourceReference? ref, string msg) {}
 
6
    public override void warn (Vala.SourceReference? ref, string msg) {}
 
7
    public override void note (Vala.SourceReference? ref, string msg) {}
 
8
    public override void depr (Vala.SourceReference? ref, string msg) {}
9
9
}
10
10
 
11
11
public class Symbol : Granite.Widgets.SourceList.ExpandableItem
12
12
{
13
 
        public Scratch.Services.Document doc { get; construct set; }
14
 
        public Vala.Symbol symbol { get; construct set; }
 
13
    public Scratch.Services.Document doc { get; construct set; }
 
14
    public Vala.Symbol symbol { get; construct set; }
15
15
 
16
 
        public Symbol (Scratch.Services.Document doc, Vala.Symbol symbol)
17
 
        {
18
 
                Object (symbol: symbol, name: symbol.name, doc: doc);
19
 
        }
 
16
    public Symbol (Scratch.Services.Document doc, Vala.Symbol symbol)
 
17
    {
 
18
        Object (symbol: symbol, name: symbol.name, doc: doc);
 
19
    }
20
20
}
21
21
 
22
22
class SymbolIter : Object
23
23
{
24
 
        public Vala.Symbol? symbol { get; construct set; default = null; }
25
 
        public Icon? icon { get; construct set; default = null; }
26
 
        public Gee.LinkedList<SymbolIter> children { get; private set; }
 
24
    public Vala.Symbol? symbol { get; construct set; default = null; }
 
25
    public Icon? icon { get; construct set; default = null; }
 
26
    public Gee.LinkedList<SymbolIter> children { get; private set; }
27
27
 
28
 
        public SymbolIter (Vala.Symbol? symbol = null, Icon? icon = null)
29
 
        {
30
 
                Object(symbol: symbol, icon: icon);
31
 
                children = new Gee.LinkedList<SymbolIter> ();
32
 
        }
 
28
    public SymbolIter (Vala.Symbol? symbol = null, Icon? icon = null)
 
29
    {
 
30
        Object(symbol: symbol, icon: icon);
 
31
        children = new Gee.LinkedList<SymbolIter> ();
 
32
    }
33
33
}
34
34
 
35
35
public class ValaSymbolOutline : Object, SymbolOutline
36
36
{
37
 
        public Scratch.Services.Document doc { get; protected set; }
38
 
        public Granite.Widgets.SourceList store { get; private set; }
39
 
        Granite.Widgets.SourceList.ExpandableItem root;
40
 
        Vala.CodeContext context;
41
 
        Vala.Parser parser;
42
 
        SymbolResolver resolver;
43
 
 
44
 
        SymbolIter cache;
45
 
 
46
 
        Gee.List<Vala.Field> field_blacklist;
47
 
 
48
 
        public ValaSymbolOutline (Scratch.Services.Document _doc)
49
 
        {
50
 
                doc = _doc;
51
 
                doc.doc_closed.connect (doc_closed);
52
 
 
53
 
                field_blacklist = new Gee.LinkedList<Vala.Field> ();
54
 
                cache = new SymbolIter ();
55
 
 
56
 
                store = new Granite.Widgets.SourceList ();
57
 
                store.get_style_context ().add_class ("sidebar");
58
 
                store.item_selected.connect ((selected) => {
59
 
                        if (selected == null) return;
60
 
                        goto (doc, (selected as Symbol).symbol.source_reference.begin.line);
61
 
                        store.selected = null;
62
 
                });
63
 
                root = new Granite.Widgets.SourceList.ExpandableItem (_("Symbols"));
64
 
                store.root.add (root);
65
 
 
66
 
                parser = new Vala.Parser ();
67
 
                resolver = new SymbolResolver ();
68
 
                resolver.add_symbol.connect (add_symbol);
69
 
                resolver.blacklist.connect ((f) => {
70
 
                        field_blacklist.add (f);
71
 
                });
72
 
 
73
 
                init_context ();
74
 
        }
75
 
 
76
 
        void init_context ()
77
 
        {
78
 
                context = new Vala.CodeContext ();
79
 
                context.profile = Vala.Profile.GOBJECT;
80
 
                context.add_source_filename (doc.file.get_path ());
81
 
                context.report = new Report ();
82
 
        }
83
 
        
84
 
        ~ValaSymbolResolver ()
85
 
        {
86
 
                doc.doc_closed.disconnect (doc_closed);
87
 
        }
88
 
 
89
 
        void doc_closed (Scratch.Services.Document doc)
90
 
        {
91
 
                closed ();
92
 
        }
93
 
 
94
 
        public Granite.Widgets.SourceList get_source_list ()
95
 
        {
96
 
                return store;
97
 
        }
98
 
 
99
 
        async void parse_symbols_async ()
100
 
        {
101
 
                field_blacklist.clear ();
102
 
 
103
 
                lock (context)
104
 
                {
105
 
                        Vala.CodeContext.push (context);
106
 
 
107
 
                        parser.parse (context);
108
 
                        resolver.resolve (context);
109
 
 
110
 
                        Vala.CodeContext.pop ();
111
 
                }
112
 
        }
113
 
 
114
 
        public void parse_symbols ()
115
 
        {
116
 
                cache.children.clear ();
117
 
                init_context ();
118
 
                
119
 
                Thread<void*> thread = new Thread<void*>("parse-symbols", () => {
120
 
                        parse_symbols_async ();
121
 
                        return null;
122
 
                });
123
 
 
124
 
                thread.join ();
125
 
 
126
 
                root.clear ();
127
 
                construct_tree (cache, root);
128
 
 
129
 
                filter_generated_fields (root);
130
 
 
131
 
                store.root.expand_all ();
132
 
        }
133
 
 
134
 
        void construct_tree (SymbolIter iter_parent,
135
 
                Granite.Widgets.SourceList.ExpandableItem tree_parent)
136
 
        {
137
 
                foreach (var iter_child in iter_parent.children) {
138
 
                        var tree_child = new Symbol (doc, iter_child.symbol);
139
 
                        tree_child.icon = iter_child.icon;
140
 
                        tree_parent.add (tree_child);
141
 
 
142
 
                        construct_tree (iter_child, tree_child);
143
 
                }
144
 
        }
145
 
 
146
 
        SymbolIter? find_existing (Vala.Symbol symbol, SymbolIter parent = cache)
147
 
        {
148
 
                SymbolIter match = null;
149
 
                foreach (var child in parent.children) {
150
 
                        if (child.symbol== symbol) {
151
 
                                match = child;
152
 
                                break;
153
 
                        } else {
154
 
                                var res = find_existing (symbol, child);
155
 
                                if (res != null)
156
 
                                        return res;
157
 
                        }
158
 
                }
159
 
                return match;
160
 
        }
161
 
 
162
 
        // vala generates for each property a field which we do not want to display
163
 
        void filter_generated_fields (Granite.Widgets.SourceList.ExpandableItem parent)
164
 
        {
165
 
                foreach (var child in parent.children) {
166
 
                        var child_symbol = child as Symbol;
167
 
                        if (field_blacklist.contains (child_symbol.symbol as Vala.Field)) {
168
 
                                parent.remove (child);
169
 
                        }
170
 
                        filter_generated_fields (child_symbol);
171
 
                }
172
 
        }
173
 
 
174
 
        void add_symbol (Vala.Symbol symbol, string icon = "", Icon? real_icon = null)
175
 
        {
176
 
                if (symbol.name == null)
177
 
                        return;
178
 
 
179
 
                SymbolIter parent;
180
 
                if (symbol.scope.parent_scope.owner.name == null)
181
 
                        parent = cache;
182
 
                else
183
 
                        parent = find_existing (symbol.scope.parent_scope.owner);
184
 
 
185
 
                if (parent == null) {
186
 
                        warning ("Could not find parent scope of symbol");
187
 
                        return;
188
 
                }
189
 
 
190
 
                var i = real_icon != null ? real_icon : new ThemedIcon.with_default_fallbacks (icon);
191
 
                var s = new SymbolIter (symbol, i);
192
 
                parent.children.add (s);
193
 
        }
 
37
    public Scratch.Services.Document doc { get; protected set; }
 
38
    public Granite.Widgets.SourceList store { get; private set; }
 
39
    Granite.Widgets.SourceList.ExpandableItem root;
 
40
    Vala.CodeContext context;
 
41
    Vala.Parser parser;
 
42
    SymbolResolver resolver;
 
43
 
 
44
    SymbolIter cache;
 
45
 
 
46
    Gee.List<Vala.Field> field_blacklist;
 
47
 
 
48
    public ValaSymbolOutline (Scratch.Services.Document _doc)
 
49
    {
 
50
        doc = _doc;
 
51
        doc.doc_closed.connect (doc_closed);
 
52
 
 
53
        field_blacklist = new Gee.LinkedList<Vala.Field> ();
 
54
        cache = new SymbolIter ();
 
55
 
 
56
        store = new Granite.Widgets.SourceList ();
 
57
        store.get_style_context ().add_class ("sidebar");
 
58
        store.item_selected.connect ((selected) => {
 
59
            if (selected == null) return;
 
60
            goto (doc, (selected as Symbol).symbol.source_reference.begin.line);
 
61
            store.selected = null;
 
62
        });
 
63
        root = new Granite.Widgets.SourceList.ExpandableItem (_("Symbols"));
 
64
        store.root.add (root);
 
65
 
 
66
        parser = new Vala.Parser ();
 
67
        resolver = new SymbolResolver ();
 
68
        resolver.add_symbol.connect (add_symbol);
 
69
        resolver.blacklist.connect ((f) => {
 
70
            field_blacklist.add (f);
 
71
        });
 
72
 
 
73
        init_context ();
 
74
    }
 
75
 
 
76
    void init_context ()
 
77
    {
 
78
        context = new Vala.CodeContext ();
 
79
        context.profile = Vala.Profile.GOBJECT;
 
80
        context.add_source_filename (doc.file.get_path ());
 
81
        context.report = new Report ();
 
82
    }
 
83
    
 
84
    ~ValaSymbolResolver ()
 
85
    {
 
86
        doc.doc_closed.disconnect (doc_closed);
 
87
    }
 
88
 
 
89
    void doc_closed (Scratch.Services.Document doc)
 
90
    {
 
91
        closed ();
 
92
    }
 
93
 
 
94
    public Granite.Widgets.SourceList get_source_list ()
 
95
    {
 
96
        return store;
 
97
    }
 
98
 
 
99
    async void parse_symbols_async ()
 
100
    {
 
101
        field_blacklist.clear ();
 
102
 
 
103
        lock (context)
 
104
        {
 
105
            Vala.CodeContext.push (context);
 
106
 
 
107
            parser.parse (context);
 
108
            resolver.resolve (context);
 
109
 
 
110
            Vala.CodeContext.pop ();
 
111
        }
 
112
    }
 
113
 
 
114
    public void parse_symbols ()
 
115
    {
 
116
        cache.children.clear ();
 
117
        init_context ();
 
118
        
 
119
        Thread<void*> thread = new Thread<void*>("parse-symbols", () => {
 
120
            parse_symbols_async ();
 
121
            return null;
 
122
        });
 
123
 
 
124
        thread.join ();
 
125
 
 
126
        root.clear ();
 
127
        construct_tree (cache, root);
 
128
 
 
129
        filter_generated_fields (root);
 
130
 
 
131
        store.root.expand_all ();
 
132
    }
 
133
 
 
134
    void construct_tree (SymbolIter iter_parent,
 
135
        Granite.Widgets.SourceList.ExpandableItem tree_parent)
 
136
    {
 
137
        foreach (var iter_child in iter_parent.children) {
 
138
            var tree_child = new Symbol (doc, iter_child.symbol);
 
139
            tree_child.icon = iter_child.icon;
 
140
            tree_parent.add (tree_child);
 
141
 
 
142
            construct_tree (iter_child, tree_child);
 
143
        }
 
144
    }
 
145
 
 
146
    SymbolIter? find_existing (Vala.Symbol symbol, SymbolIter parent = cache)
 
147
    {
 
148
        SymbolIter match = null;
 
149
        foreach (var child in parent.children) {
 
150
            if (child.symbol== symbol) {
 
151
                match = child;
 
152
                break;
 
153
            } else {
 
154
                var res = find_existing (symbol, child);
 
155
                if (res != null)
 
156
                    return res;
 
157
            }
 
158
        }
 
159
        return match;
 
160
    }
 
161
 
 
162
    // vala generates for each property a field which we do not want to display
 
163
    void filter_generated_fields (Granite.Widgets.SourceList.ExpandableItem parent)
 
164
    {
 
165
        foreach (var child in parent.children) {
 
166
            var child_symbol = child as Symbol;
 
167
            if (field_blacklist.contains (child_symbol.symbol as Vala.Field)) {
 
168
                parent.remove (child);
 
169
            }
 
170
            filter_generated_fields (child_symbol);
 
171
        }
 
172
    }
 
173
 
 
174
    void add_symbol (Vala.Symbol symbol, string icon = "", Icon? real_icon = null)
 
175
    {
 
176
        if (symbol.name == null)
 
177
            return;
 
178
 
 
179
        SymbolIter parent;
 
180
        if (symbol.scope.parent_scope.owner.name == null)
 
181
            parent = cache;
 
182
        else
 
183
            parent = find_existing (symbol.scope.parent_scope.owner);
 
184
 
 
185
        if (parent == null) {
 
186
            warning ("Could not find parent scope of symbol");
 
187
            return;
 
188
        }
 
189
 
 
190
        var i = real_icon != null ? real_icon : new ThemedIcon.with_default_fallbacks (icon);
 
191
        var s = new SymbolIter (symbol, i);
 
192
        parent.children.add (s);
 
193
    }
194
194
}
195
195
 
196
196
public class SymbolResolver : Vala.SymbolResolver
197
197
{
198
 
        public signal void add_symbol (Vala.Symbol s, string icon = "", Icon? real_icon = null);
199
 
        public signal void blacklist (Vala.Field f);
 
198
    public signal void add_symbol (Vala.Symbol s, string icon = "", Icon? real_icon = null);
 
199
    public signal void blacklist (Vala.Field f);
200
200
 
201
 
        public override void visit_class (Vala.Class s)
202
 
        {
203
 
                add_symbol (s, "user-home-symbolic",
204
 
                        new ThemedIcon.from_names ({"user-home-symbolic", "go-home-symbolic", "user-home", "go-home", "home"}));
205
 
                base.visit_class (s);
206
 
        }
207
 
        public override void visit_constant (Vala.Constant s)
208
 
        {
209
 
                add_symbol (s, "view-grid-symbolic");
210
 
                base.visit_constant (s);
211
 
        }
212
 
        public override void visit_delegate (Vala.Delegate s)
213
 
        {
214
 
                add_symbol (s);
215
 
                base.visit_delegate (s);
216
 
        }
217
 
        //FIXME both constructor and destructor are currently not added for some reason
218
 
        public override void visit_constructor (Vala.Constructor s)
219
 
        {
220
 
                add_symbol (s, "media-playback-start-symbolic");
221
 
                base.visit_constructor (s);
222
 
        }
223
 
        public override void visit_destructor (Vala.Destructor s)
224
 
        {
225
 
                add_symbol (s, "edit-delete-symbolic");
226
 
                base.visit_destructor (s);
227
 
        }
228
 
        public override void visit_enum (Vala.Enum s)
229
 
        {
230
 
                add_symbol (s, "view-list-compact-symbolic");
231
 
                base.visit_enum (s);
232
 
        }
233
 
        public override void visit_field (Vala.Field s)
234
 
        {
235
 
                add_symbol (s, "view-grid-symbolic");
236
 
                base.visit_field (s);
237
 
        }
238
 
        public override void visit_interface (Vala.Interface s)
239
 
        {
240
 
                add_symbol (s, "", 
241
 
                        new ThemedIcon.from_names ({"dialog-information-symbolic", "help-info-symbolic", "dialog-information", "help-info", "information", "info"}));
242
 
                base.visit_interface (s);
243
 
        }
244
 
        public override void visit_method (Vala.Method s)
245
 
        {
246
 
                add_symbol (s, "document-properties-symbolic");
247
 
                base.visit_method (s);
248
 
        }
249
 
        public override void visit_namespace (Vala.Namespace s)
250
 
        {
251
 
                add_symbol (s, "view-fullscreen-symbolic");
252
 
                base.visit_namespace (s);
253
 
        }
254
 
        public override void visit_property (Vala.Property s)
255
 
        {
256
 
                add_symbol (s, "format-indent-more-symbolic");
257
 
                blacklist (s.field);
258
 
                base.visit_property (s);
259
 
        }
260
 
        public override void visit_signal (Vala.Signal s)
261
 
        {
262
 
                add_symbol (s);
263
 
                base.visit_signal (s);
264
 
        }
265
 
        public override void visit_struct (Vala.Struct s)
266
 
        {
267
 
                add_symbol (s, "user-home-symbolic",
268
 
                        new ThemedIcon.from_names ({"user-home-symbolic", "go-home-symbolic", "user-home", "go-home", "home"}));
269
 
                base.visit_struct (s);
270
 
        }
 
201
    public override void visit_class (Vala.Class s)
 
202
    {
 
203
        add_symbol (s, "user-home-symbolic",
 
204
            new ThemedIcon.from_names ({"user-home-symbolic", "go-home-symbolic", "user-home", "go-home", "home"}));
 
205
        base.visit_class (s);
 
206
    }
 
207
    public override void visit_constant (Vala.Constant s)
 
208
    {
 
209
        add_symbol (s, "view-grid-symbolic");
 
210
        base.visit_constant (s);
 
211
    }
 
212
    public override void visit_delegate (Vala.Delegate s)
 
213
    {
 
214
        add_symbol (s);
 
215
        base.visit_delegate (s);
 
216
    }
 
217
    //FIXME both constructor and destructor are currently not added for some reason
 
218
    public override void visit_constructor (Vala.Constructor s)
 
219
    {
 
220
        add_symbol (s, "media-playback-start-symbolic");
 
221
        base.visit_constructor (s);
 
222
    }
 
223
    public override void visit_destructor (Vala.Destructor s)
 
224
    {
 
225
        add_symbol (s, "edit-delete-symbolic");
 
226
        base.visit_destructor (s);
 
227
    }
 
228
    public override void visit_enum (Vala.Enum s)
 
229
    {
 
230
        add_symbol (s, "view-list-compact-symbolic");
 
231
        base.visit_enum (s);
 
232
    }
 
233
    public override void visit_field (Vala.Field s)
 
234
    {
 
235
        add_symbol (s, "view-grid-symbolic");
 
236
        base.visit_field (s);
 
237
    }
 
238
    public override void visit_interface (Vala.Interface s)
 
239
    {
 
240
        add_symbol (s, "", 
 
241
            new ThemedIcon.from_names ({"dialog-information-symbolic", "help-info-symbolic", "dialog-information", "help-info", "information", "info"}));
 
242
        base.visit_interface (s);
 
243
    }
 
244
    public override void visit_method (Vala.Method s)
 
245
    {
 
246
        add_symbol (s, "document-properties-symbolic");
 
247
        base.visit_method (s);
 
248
    }
 
249
    public override void visit_namespace (Vala.Namespace s)
 
250
    {
 
251
        add_symbol (s, "view-fullscreen-symbolic");
 
252
        base.visit_namespace (s);
 
253
    }
 
254
    public override void visit_property (Vala.Property s)
 
255
    {
 
256
        add_symbol (s, "format-indent-more-symbolic");
 
257
        blacklist (s.field);
 
258
        base.visit_property (s);
 
259
    }
 
260
    public override void visit_signal (Vala.Signal s)
 
261
    {
 
262
        add_symbol (s);
 
263
        base.visit_signal (s);
 
264
    }
 
265
    public override void visit_struct (Vala.Struct s)
 
266
    {
 
267
        add_symbol (s, "user-home-symbolic",
 
268
            new ThemedIcon.from_names ({"user-home-symbolic", "go-home-symbolic", "user-home", "go-home", "home"}));
 
269
        base.visit_struct (s);
 
270
    }
271
271
}
272
272