~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric-updates

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.DesignerSupport/MonoDevelop.DesignerSupport/BindingService.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-18 08:40:51 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090218084051-gh8m6ukvokbwj7cf
Tags: 1.9.2+dfsg-1ubuntu1
* Merge from Debian Experimental (LP: #330519), remaining Ubuntu changes:
  + debian/control:
    - Update for Gnome# 2.24
    - Add libmono-cairo1.0-cil to build-deps to fool pkg-config check

Show diffs side-by-side

added added

removed removed

Lines of Context:
32
32
using System;
33
33
using System.CodeDom;
34
34
using System.Reflection;
 
35
using System.Collections;
35
36
using System.Collections.Generic;
36
37
 
37
38
using MonoDevelop.Projects;
38
 
using MonoDevelop.Projects.Parser;
 
39
using MonoDevelop.Projects.Dom;
 
40
using MonoDevelop.Projects.Dom.Parser;
39
41
using MonoDevelop.Projects.Text;
40
42
using MonoDevelop.Projects.CodeGeneration;
41
43
using MonoDevelop.Ide.Gui;
44
46
{
45
47
        
46
48
        
47
 
        public class BindingService
 
49
        public static class BindingService
48
50
        {
49
51
                //TODO: currently case-sensitive, so some languages may not like this
50
52
                const bool ignoreCase = false;
51
53
                
52
 
                private BindingService ()
53
 
                {
54
 
                }
55
 
                
56
 
                public static IMember GetCompatibleMemberInClass (IClass cls, CodeTypeMember member)
57
 
                {
58
 
                        IParserContext ctx = IdeApp.ProjectOperations.ParserDatabase.GetProjectParserContext ((MonoDevelop.Projects.Project) cls.SourceProject);
 
54
                public static IMember GetCompatibleMemberInClass (IType cls, CodeTypeMember member)
 
55
                {
 
56
                        ProjectDom ctx = ProjectDomService.GetProjectDom ((MonoDevelop.Projects.Project) cls.SourceProject);
59
57
                        return GetCompatibleMemberInClass (ctx, cls, member);
60
58
                }
61
59
                
62
 
                public static IMember GetCompatibleMemberInClass (IParserContext ctx, IClass cls, CodeTypeMember member)
 
60
                public static IMember GetCompatibleMemberInClass (ProjectDom ctx, IType cls, CodeTypeMember member)
63
61
                {
64
62
                        //check for identical property names
65
63
                        foreach (IProperty prop in cls.Properties) {
66
64
                                if (string.Compare (prop.Name, member.Name, ignoreCase) == 0) {
67
 
                                        EnsureClassExists (ctx, prop.ReturnType.FullyQualifiedName, GetValidRegion (prop));
 
65
                                        EnsureClassExists (ctx, prop.ReturnType.FullName, GetValidRegion (prop));
68
66
                                        CodeMemberProperty memProp = member as CodeMemberProperty;
69
 
                                        if (memProp == null || !IsTypeCompatible (ctx, prop.ReturnType.FullyQualifiedName, memProp.Type.BaseType))
70
 
                                                throw new MemberExistsException (cls.FullyQualifiedName, MemberType.Property, member, GetValidRegion (prop));
 
67
                                        if (memProp == null || !IsTypeCompatible (ctx, prop.ReturnType.FullName, memProp.Type.BaseType))
 
68
                                                throw new MemberExistsException (cls.FullName, MemberType.Property, member, GetValidRegion (prop), cls.CompilationUnit.FileName);
71
69
                                        return prop;
72
70
                                }
73
71
                        }
75
73
                        //check for identical method names
76
74
                        foreach (IMethod meth in cls.Methods) {
77
75
                                if (string.Compare (meth.Name, member.Name, ignoreCase) == 0) {
78
 
                                        EnsureClassExists (ctx, meth.ReturnType.FullyQualifiedName, GetValidRegion (meth));
 
76
                                        EnsureClassExists (ctx, meth.ReturnType.FullName, GetValidRegion (meth));
79
77
                                        CodeMemberMethod memMeth = member as CodeMemberMethod;
80
 
                                        if (memMeth == null || !IsTypeCompatible (ctx, meth.ReturnType.FullyQualifiedName, memMeth.ReturnType.BaseType))
81
 
                                                throw new MemberExistsException (cls.FullyQualifiedName, MemberType.Method, member, GetValidRegion (meth));
 
78
                                        if (memMeth == null || !IsTypeCompatible (ctx, meth.ReturnType.FullName, memMeth.ReturnType.BaseType))
 
79
                                                throw new MemberExistsException (cls.FullName, MemberType.Method, member, GetValidRegion (meth), cls.CompilationUnit.FileName);
82
80
                                        return meth;
83
81
                                }
84
82
                        }
86
84
                        //check for identical event names
87
85
                        foreach (IEvent ev in cls.Events) {
88
86
                                if (string.Compare (ev.Name, member.Name, ignoreCase) == 0) {
89
 
                                        EnsureClassExists (ctx, ev.ReturnType.FullyQualifiedName, GetValidRegion (ev));
 
87
                                        EnsureClassExists (ctx, ev.ReturnType.FullName, GetValidRegion (ev));
90
88
                                        CodeMemberEvent memEv = member as CodeMemberEvent;
91
 
                                        if (memEv == null || !IsTypeCompatible (ctx, ev.ReturnType.FullyQualifiedName, memEv.Type.BaseType))
92
 
                                                throw new MemberExistsException (cls.FullyQualifiedName, MemberType.Event, member, GetValidRegion (ev));
 
89
                                        if (memEv == null || !IsTypeCompatible (ctx, ev.ReturnType.FullName, memEv.Type.BaseType))
 
90
                                                throw new MemberExistsException (cls.FullName, MemberType.Event, member, GetValidRegion (ev), cls.CompilationUnit.FileName);
93
91
                                        return ev;
94
92
                                }
95
93
                        }
97
95
                        //check for identical field names
98
96
                        foreach (IField field in cls.Fields) {
99
97
                                if (string.Compare (field.Name, member.Name, ignoreCase) == 0) {
100
 
                                        EnsureClassExists (ctx, field.ReturnType.FullyQualifiedName, GetValidRegion (field));
 
98
                                        EnsureClassExists (ctx, field.ReturnType.FullName, GetValidRegion (field));
101
99
                                        CodeMemberField memField = member as CodeMemberField;
102
 
                                        if (memField == null || !IsTypeCompatible (ctx, field.ReturnType.FullyQualifiedName, memField.Type.BaseType))
103
 
                                                throw new MemberExistsException (cls.FullyQualifiedName, MemberType.Field, member, GetValidRegion (field));
 
100
                                        if (memField == null || !IsTypeCompatible (ctx, field.ReturnType.FullName, memField.Type.BaseType))
 
101
                                                throw new MemberExistsException (cls.FullName, MemberType.Field, member, GetValidRegion (field), cls.CompilationUnit.FileName);
104
102
                                        return field;
105
103
                                }
106
104
                        }
107
105
                        
108
106
                        //walk down into base classes, if any
109
107
                        foreach (IReturnType baseType in cls.BaseTypes) {
110
 
                                IClass c = ctx.GetClass (baseType.FullyQualifiedName);
 
108
                                IType c = ctx.GetType (baseType);
111
109
                                if (c == null)
112
 
                                        throw new TypeNotFoundException (baseType.FullyQualifiedName, cls.Region);
 
110
                                        throw new TypeNotFoundException (baseType.FullName, cls.BodyRegion, cls.CompilationUnit.FileName);
113
111
                                IMember mem = GetCompatibleMemberInClass (ctx, c, member);
114
112
                                if (mem != null)
115
113
                                        return mem;
119
117
                        return null;
120
118
                }
121
119
                
122
 
                static IRegion GetValidRegion (IMember member)
 
120
                static DomRegion GetValidRegion (IMember member)
123
121
                {
124
 
                        if (member.Region.FileName == null)
125
 
                                member.Region.FileName = member.DeclaringType.Region.FileName;
126
 
                        return member.Region;
 
122
                        if (member.BodyRegion == null || member.DeclaringType.CompilationUnit.FileName == null)
 
123
                                return member.DeclaringType.BodyRegion;
 
124
                        return member.BodyRegion;
127
125
                }
128
126
                
129
 
                static IClass EnsureClassExists (IParserContext ctx, string className, IRegion location)
 
127
                static IType EnsureClassExists (ProjectDom ctx, string className, DomRegion location)
130
128
                {
131
 
                        IClass cls = ctx.GetClass (className);
 
129
                        IType cls = ctx.GetType (className);
132
130
                        if (cls == null)
133
 
                                throw new TypeNotFoundException (className, location);
 
131
                                throw new TypeNotFoundException (className, location, null);
134
132
                        return cls;
135
133
                }
136
134
                
137
 
                static bool IsTypeCompatible (IParserContext ctx, string existingType, string checkType)
 
135
                static bool IsTypeCompatible (ProjectDom ctx, string existingType, string checkType)
138
136
                {
139
137
                        if (existingType == checkType)
140
138
                                return true;
141
 
                        IClass cls = EnsureClassExists (ctx, checkType, null);
 
139
                        IType cls = EnsureClassExists (ctx, checkType, DomRegion.Empty);
142
140
                        foreach (IReturnType baseType in cls.BaseTypes) {
143
 
                                if (IsTypeCompatible (ctx, existingType, baseType.FullyQualifiedName))
 
141
                                if (IsTypeCompatible (ctx, existingType, baseType.FullName))
144
142
                                    return true;
145
143
                        }
146
144
                        return false;
147
145
                }
148
146
                
149
 
                public static IMember AddMemberToClass (CombineEntry entry, IClass cls, CodeTypeMember member, bool throwIfExists)
150
 
                {
151
 
                        return AddMemberToClass (entry, cls, cls.Parts[0], member, throwIfExists);
152
 
                }
153
 
                
154
 
                public static IMember AddMemberToClass (CombineEntry entry, IClass cls, IClass specificPartToAffect, CodeTypeMember member, bool throwIfExists)
 
147
                public static IMember AddMemberToClass (SolutionItem entry, IType cls, IType specificPartToAffect, CodeTypeMember member, bool throwIfExists)
155
148
                {
156
149
                        bool isChildClass = false;
157
 
                        foreach (IClass c in cls.Parts)
 
150
                        foreach (IType c in cls.Parts)
158
151
                                if (c == specificPartToAffect)
159
152
                                        isChildClass = true;
160
153
                        if (!isChildClass)
166
159
                                return GetCodeGenerator (entry).AddMember (specificPartToAffect, member);
167
160
                        
168
161
                        if (throwIfExists)
169
 
                                throw new MemberExistsException (cls.Name, member, MemberType.Method, existingMember.Region);
 
162
                                throw new MemberExistsException (cls.Name, member, MemberType.Method, existingMember.BodyRegion, cls.CompilationUnit.FileName);
170
163
                        
171
164
                        return existingMember;
172
165
                }
173
166
                
174
 
                public static CodeRefactorer GetCodeGenerator (CombineEntry entry)
 
167
                public static CodeRefactorer GetCodeGenerator (SolutionItem entry)
175
168
                {                       
176
 
                        CodeRefactorer cr = new CodeRefactorer (entry.RootCombine, IdeApp.ProjectOperations.ParserDatabase);
 
169
                        CodeRefactorer cr = new CodeRefactorer (entry.ParentSolution);
177
170
                        cr.TextFileProvider = OpenDocumentFileProvider.Instance;
178
171
                        return cr;
179
172
                }
180
173
                
181
174
                //TODO: check accessibility
182
 
                public static string[] GetCompatibleMethodsInClass (IClass cls, CodeMemberMethod testMethod)
 
175
                public static string[] GetCompatibleMethodsInClass (IType cls, CodeMemberMethod testMethod)
183
176
                {
184
177
                        List<string> list = new List<string> ();
185
178
                        
187
180
                                if (method.Parameters.Count != testMethod.Parameters.Count)
188
181
                                        continue;
189
182
                                
190
 
                                if (method.ReturnType.FullyQualifiedName != testMethod.ReturnType.BaseType)
 
183
                                if (method.ReturnType.FullName != testMethod.ReturnType.BaseType)
191
184
                                        continue;
192
185
                                
193
186
                                //compare each parameter
194
187
                                bool mismatch = false;
195
188
                                for (int i = 0; i < testMethod.Parameters.Count; i++)
196
 
                                        if (method.Parameters[i].ReturnType.FullyQualifiedName != testMethod.Parameters[i].Type.BaseType)
 
189
                                        if (method.Parameters[i].ReturnType.FullName != testMethod.Parameters[i].Type.BaseType)
197
190
                                                mismatch = true;
198
191
                                
199
192
                                if (!mismatch)
204
197
                }
205
198
                
206
199
                
207
 
                public static string[] GetCompatibleMembersInClass (IClass cls, CodeTypeMember testMember)
 
200
                public static string[] GetCompatibleMembersInClass (IType cls, CodeTypeMember testMember)
208
201
                {
209
202
                        if (testMember is CodeMemberMethod)
210
203
                                return GetCompatibleMethodsInClass (cls, (CodeMemberMethod) testMember);
213
206
                }
214
207
                
215
208
                
216
 
                public static bool IdentifierExistsInClass (IClass cls, string identifier)
217
 
                {
218
 
                        bool found = false;
219
 
                        
220
 
                        foreach (IMethod method in cls.Methods)
221
 
                                if (method.Name == identifier)
222
 
                                        found = true;
223
 
                        
224
 
                        foreach (IProperty property in cls.Properties)
225
 
                                if (property.Name == identifier)
226
 
                                        found = true;
227
 
                        
228
 
                        foreach (IEvent ev in cls.Events)
229
 
                                if (ev.Name == identifier)
230
 
                                        found = true;
231
 
                        
232
 
                        foreach (IField field in cls.Fields)
233
 
                                if (field.Name == identifier)
234
 
                                        found = true;
235
 
                        
236
 
                        return found;
237
 
                }
238
 
                
239
 
                
240
 
                public static string GenerateIdentifierUniqueInClass (IClass cls, string trialIdentifier)
 
209
                public static bool IdentifierExistsInClass (ProjectDom parserContext, IType cls, string identifier)
 
210
                {
 
211
                        foreach (IMember member in cls.Members)
 
212
                                if (member.Name == identifier)
 
213
                                        return true;
 
214
                        
 
215
                        return VisibleIdentifierExistsInBaseClasses (parserContext.GetInheritanceTree (cls), identifier);
 
216
                }
 
217
                
 
218
                static bool VisibleIdentifierExistsInBaseClasses (IEnumerable<IType> classes, string identifier)
 
219
                {
 
220
                        foreach (IType cls in classes) {
 
221
                                foreach (IEnumerable en in new IEnumerable[] {cls.Methods, cls.Properties, cls.Events, cls.Fields})
 
222
                                        foreach (IMember item in en)
 
223
                                                if (!item.IsPrivate && item.Name == identifier)
 
224
                                                        return true;
 
225
                                foreach (IType innerClass in cls.InnerTypes)
 
226
                                        if (!innerClass.IsPrivate && innerClass.Name == identifier)
 
227
                                                return true;
 
228
                        }
 
229
                        return false;
 
230
                }
 
231
                
 
232
                public static string GenerateIdentifierUniqueInClass (ProjectDom parserContext, IType cls, string trialIdentifier)
241
233
                {
242
234
                        string trialValue = trialIdentifier;
243
235
                        
244
236
                        for (int suffix = 1; suffix <= int.MaxValue; suffix++)
245
237
                        {
246
 
                                if (!IdentifierExistsInClass (cls, trialValue))
 
238
                                if (!IdentifierExistsInClass (parserContext, cls, trialValue))
247
239
                                        return trialValue;
248
240
                                
249
241
                                trialValue = trialIdentifier + suffix.ToString ();
254
246
                
255
247
                
256
248
                //opens the code view with the desired method, creating it if it doesn't already exist
257
 
                public static void CreateAndShowMember (CombineEntry project, IClass cls, CodeTypeMember member)
 
249
                public static void CreateAndShowMember (SolutionItem project, IType cls, IType specificPartToAffect, CodeTypeMember member)
258
250
                {
259
251
                        //only adds the method if it doesn't already exist
260
 
                        IMember mem = AddMemberToClass (project, cls, member, false);
 
252
                        IMember mem = AddMemberToClass (project, cls, specificPartToAffect, member, false);
261
253
                        
262
254
                        //some tests in case code refactorer returns bad values
263
 
                        int beginline = cls.Region.BeginLine;                   
264
 
                        if (mem.Region != null && mem.Region.BeginLine >= beginline && mem.Region.BeginLine <= cls.Region.EndLine)
265
 
                                beginline = mem.Region.BeginLine;
 
255
                        int beginline = specificPartToAffect.Location.Line;                     
 
256
                        if (!mem.BodyRegion.IsEmpty && mem.BodyRegion.Start.Line >= beginline && mem.Location.Line <= specificPartToAffect.BodyRegion.End.Line)
 
257
                                beginline = mem.BodyRegion.Start.Line;
266
258
                        
267
259
                        //jump to the member or class
268
 
                        IdeApp.Workbench.OpenDocument (cls.Region.FileName, beginline, 1, true);
 
260
                        IdeApp.Workbench.OpenDocument (specificPartToAffect.CompilationUnit.FileName, beginline, 1, true);
269
261
                }
270
262
                
271
263
                public static System.CodeDom.CodeTypeMember ReflectionToCodeDomMember (MemberInfo memberInfo)
308
300
                        foreach (ParameterInfo pi in pinfos) {
309
301
                                CodeParameterDeclarationExpression newPar = new CodeParameterDeclarationExpression (pi.ParameterType.FullName, pi.Name);
310
302
                                if (pi.IsIn) newPar.Direction = FieldDirection.In;
311
 
                                if (pi.IsOut) newPar.Direction = FieldDirection.Out;
 
303
                                else if (pi.IsOut) newPar.Direction = FieldDirection.Out;
 
304
                                newMethod.Parameters.Add (newPar);
 
305
                        }
 
306
                        
 
307
                        return newMethod;
 
308
                }
 
309
                
 
310
                public static System.CodeDom.CodeMemberMethod MDDomToCodeDomMethod (IEvent ev, ProjectDom context)
 
311
                {
 
312
                        if (ev.ReturnType == null)
 
313
                                return null;
 
314
                        IType cls = context.GetType (ev.ReturnType);
 
315
                        if (cls == null)
 
316
                                return null;
 
317
                        foreach (IMethod m in cls.Methods)
 
318
                                if (m.Name == "Invoke")
 
319
                                        return MDDomToCodeDomMethod (m);
 
320
                        return null;
 
321
                }
 
322
                
 
323
                public static System.CodeDom.CodeMemberMethod MDDomToCodeDomMethod (IMethod mi)
 
324
                {
 
325
                        CodeMemberMethod newMethod = new CodeMemberMethod ();
 
326
                        newMethod.Name = mi.Name;
 
327
                        newMethod.ReturnType = new System.CodeDom.CodeTypeReference (mi.ReturnType.FullName);
 
328
                        
 
329
                        newMethod.Attributes = System.CodeDom.MemberAttributes.Private;
 
330
                        switch (mi.Modifiers) {
 
331
                        case Modifiers.Internal:
 
332
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.Assembly;
 
333
                                break;
 
334
                        case Modifiers.ProtectedAndInternal:
 
335
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.FamilyAndAssembly;
 
336
                                break;
 
337
                        case Modifiers.Protected:
 
338
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.Family;
 
339
                                break;
 
340
                        case Modifiers.ProtectedOrInternal:
 
341
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.FamilyAndAssembly;
 
342
                                break;
 
343
                        case Modifiers.Public:
 
344
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.Public;
 
345
                                break;
 
346
                        case Modifiers.Static:
 
347
                                newMethod.Attributes |= System.CodeDom.MemberAttributes.Static;
 
348
                                break;
 
349
                        }
 
350
                        
 
351
                        foreach (IParameter p in mi.Parameters) {
 
352
                                CodeParameterDeclarationExpression newPar = new CodeParameterDeclarationExpression (p.ReturnType.FullName, p.Name);
 
353
                                if (p.IsRef) newPar.Direction = FieldDirection.Ref;
 
354
                                else if (p.IsOut) newPar.Direction = FieldDirection.Out;
 
355
                                else newPar.Direction = FieldDirection.In;
 
356
                                
312
357
                                newMethod.Parameters.Add (newPar);
313
358
                        }
314
359