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

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.ExtractMethod/VariableLookupVisitor.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// 
2
 
// VariableLookupVisitor.cs
3
 
//  
4
 
// Author:
5
 
//       Mike KrĆ¼ger <mkrueger@novell.com>
6
 
// 
7
 
// Copyright (c) 2009 Novell, Inc (http://www.novell.com)
8
 
// 
9
 
// Permission is hereby granted, free of charge, to any person obtaining a copy
10
 
// of this software and associated documentation files (the "Software"), to deal
11
 
// in the Software without restriction, including without limitation the rights
12
 
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 
// copies of the Software, and to permit persons to whom the Software is
14
 
// furnished to do so, subject to the following conditions:
15
 
// 
16
 
// The above copyright notice and this permission notice shall be included in
17
 
// all copies or substantial portions of the Software.
18
 
// 
19
 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
 
// THE SOFTWARE.
26
 
 
27
 
using System;
28
 
using System.Linq;
29
 
using System.Collections.Generic;
30
 
using ICSharpCode.NRefactory.Visitors;
31
 
using ICSharpCode.NRefactory.Ast;
32
 
using MonoDevelop.Projects.Dom;
33
 
using MonoDevelop.Projects.Dom.Parser;
34
 
using ICSharpCode.NRefactory;
35
 
using Mono.TextEditor;
36
 
 
37
 
namespace MonoDevelop.Refactoring.ExtractMethod
38
 
{
39
 
        public class VariableDescriptor 
40
 
        {
41
 
                public string Name {
42
 
                        get;
43
 
                        set;
44
 
                }
45
 
                
46
 
                public bool GetsChanged {
47
 
                        get;
48
 
                        set;
49
 
                }
50
 
                
51
 
                public bool InitialValueUsed {
52
 
                        get;
53
 
                        set;
54
 
                }
55
 
                
56
 
                public bool GetsAssigned {
57
 
                        get;
58
 
                        set;
59
 
                }
60
 
                
61
 
                public bool IsDefined {
62
 
                        get;
63
 
                        set;
64
 
                }
65
 
                
66
 
                public IReturnType ReturnType {
67
 
                        get;
68
 
                        set;
69
 
                }
70
 
                
71
 
                public DocumentLocation Location {
72
 
                        get;
73
 
                        set;
74
 
                }
75
 
                
76
 
                public VariableDescriptor (string name)
77
 
                {
78
 
                        this.Name = name;
79
 
                        this.GetsChanged = this.IsDefined = this.InitialValueUsed = false;
80
 
                }
81
 
                
82
 
                public override string ToString ()
83
 
                {
84
 
                        return string.Format("[VariableDescriptor: Name={0}, GetsChanged={1}, InitialValueUsed={2}, GetsAssigned={3}, IsDefined={4}, ReturnType={5}, Location={6}]", Name, GetsChanged, InitialValueUsed, GetsAssigned, IsDefined, ReturnType, Location);
85
 
                }
86
 
        }
87
 
        
88
 
        public class VariableLookupVisitor : AbstractAstVisitor
89
 
        {
90
 
                List<KeyValuePair <string, IReturnType>> unknownVariables = new List<KeyValuePair <string, IReturnType>> ();
91
 
                Dictionary<string, VariableDescriptor> variables = new Dictionary<string, VariableDescriptor> ();
92
 
                
93
 
                public bool ReferencesMember {
94
 
                        get;
95
 
                        set;
96
 
                }
97
 
                
98
 
                public List<KeyValuePair <string, IReturnType>> UnknownVariables {
99
 
                        get {
100
 
                                return unknownVariables;
101
 
                        }
102
 
                }
103
 
 
104
 
                public Dictionary<string, VariableDescriptor> Variables {
105
 
                        get {
106
 
                                return variables;
107
 
                        }
108
 
                }
109
 
                
110
 
                public List<VariableDescriptor> VariableList {
111
 
                        get {
112
 
                                return new List<VariableDescriptor> (variables.Values);
113
 
                        }
114
 
                }
115
 
                
116
 
                public Location MemberLocation {
117
 
                        get;
118
 
                        set;
119
 
                }
120
 
                
121
 
                IResolver resolver;
122
 
                DomLocation position;
123
 
                public DomRegion CutRegion {
124
 
                        get;
125
 
                        set;
126
 
                }
127
 
                public VariableLookupVisitor (IResolver resolver, DomLocation position)
128
 
                {
129
 
                        this.resolver = resolver;
130
 
                        this.position = position;
131
 
                        this.MemberLocation = Location.Empty;
132
 
                }
133
 
                
134
 
                static IReturnType ConvertTypeReference (TypeReference typeRef)
135
 
                {
136
 
                        if (typeRef == null)
137
 
                                return null;
138
 
                        DomReturnType result = new DomReturnType (typeRef.Type);
139
 
                        foreach (TypeReference genericArgument in typeRef.GenericTypes) {
140
 
                                result.AddTypeParameter (ConvertTypeReference (genericArgument));
141
 
                        }
142
 
                        result.PointerNestingLevel = typeRef.PointerNestingLevel;
143
 
                        if (typeRef.IsArrayType) {
144
 
                                result.ArrayDimensions = typeRef.RankSpecifier.Length;
145
 
                                for (int i = 0; i < typeRef.RankSpecifier.Length; i++) {
146
 
                                        result.SetDimension (i, typeRef.RankSpecifier[i]);
147
 
                                }
148
 
                        }
149
 
                        return result;
150
 
                }
151
 
                
152
 
                public override object VisitLocalVariableDeclaration (LocalVariableDeclaration localVariableDeclaration, object data)
153
 
                {
154
 
                        if (!CutRegion.Contains (localVariableDeclaration.StartLocation.Line - 1, localVariableDeclaration.StartLocation.Column -1)) {
155
 
                                foreach (VariableDeclaration varDecl in localVariableDeclaration.Variables) {
156
 
                                        variables[varDecl.Name] = new VariableDescriptor (varDecl.Name) {
157
 
                                                IsDefined = true, 
158
 
                                                ReturnType = ConvertTypeReference (localVariableDeclaration.TypeReference),
159
 
                                                Location = new DocumentLocation (MemberLocation.Line + localVariableDeclaration.StartLocation.Line - 1, localVariableDeclaration.StartLocation.Column - 1)
160
 
                                        };
161
 
                                }
162
 
                        }
163
 
                        return base.VisitLocalVariableDeclaration(localVariableDeclaration, data);
164
 
                }
165
 
                
166
 
                public override object VisitIdentifierExpression (ICSharpCode.NRefactory.Ast.IdentifierExpression identifierExpression, object data)
167
 
                {
168
 
                        if (!variables.ContainsKey (identifierExpression.Identifier)) {
169
 
 
170
 
                                ExpressionResult expressionResult = new ExpressionResult (identifierExpression.Identifier);
171
 
 
172
 
                                ResolveResult result = resolver.Resolve (expressionResult, position);
173
 
                                
174
 
                                MemberResolveResult mrr = result as MemberResolveResult;
175
 
                                ReferencesMember |= mrr != null && mrr.ResolvedMember != null && !mrr.ResolvedMember.IsStatic;
176
 
                                
177
 
                                if (!(result is LocalVariableResolveResult || result is ParameterResolveResult))
178
 
                                        return base.VisitIdentifierExpression (identifierExpression, data);
179
 
                                
180
 
                                // result.ResolvedType == null may be true for namespace names or undeclared variables
181
 
                                if (!result.StaticResolve && !variables.ContainsKey (identifierExpression.Identifier)) {
182
 
                                        variables[identifierExpression.Identifier] = new VariableDescriptor (identifierExpression.Identifier) {
183
 
                                                InitialValueUsed = !valueGetsChanged,
184
 
                                                Location = new DocumentLocation (MemberLocation.Line + identifierExpression.StartLocation.Line - 1, identifierExpression.StartLocation.Column - 1)
185
 
 
186
 
                                        };
187
 
                                        variables[identifierExpression.Identifier].ReturnType = result.ResolvedType;
188
 
                                }
189
 
                                if (result != null && !result.StaticResolve && result.ResolvedType != null && !(result is MethodResolveResult) && !(result is NamespaceResolveResult) && !(result is MemberResolveResult))
190
 
                                        unknownVariables.Add (new KeyValuePair <string, IReturnType> (identifierExpression.Identifier, result.ResolvedType));
191
 
                        }
192
 
                        return base.VisitIdentifierExpression (identifierExpression, data);
193
 
                }
194
 
                bool valueGetsChanged = false;
195
 
                public override object VisitAssignmentExpression (ICSharpCode.NRefactory.Ast.AssignmentExpression assignmentExpression, object data)
196
 
                {
197
 
                        assignmentExpression.Right.AcceptVisitor(this, data);
198
 
                                
199
 
                        valueGetsChanged = true;
200
 
                        IdentifierExpression left = assignmentExpression.Left as IdentifierExpression;
201
 
                        bool isInitialUse = left != null && !variables.ContainsKey (left.Identifier);
202
 
                        assignmentExpression.Left.AcceptVisitor(this, data);
203
 
                        valueGetsChanged = false;
204
 
                        
205
 
                        if (left != null && variables.ContainsKey (left.Identifier)) {
206
 
                                variables[left.Identifier].GetsChanged = true;
207
 
                                if (isInitialUse)
208
 
                                        variables[left.Identifier].GetsAssigned = true;
209
 
                        }
210
 
                        return null;
211
 
                }
212
 
                
213
 
                public override object VisitUnaryOperatorExpression (ICSharpCode.NRefactory.Ast.UnaryOperatorExpression unaryOperatorExpression, object data)
214
 
                {
215
 
                        switch (unaryOperatorExpression.Op) {
216
 
                        case UnaryOperatorType.Increment:
217
 
                        case UnaryOperatorType.Decrement:
218
 
                        case UnaryOperatorType.PostIncrement:
219
 
                        case UnaryOperatorType.PostDecrement:
220
 
                                valueGetsChanged = true;
221
 
                                break;
222
 
                        }
223
 
                        object result = base.VisitUnaryOperatorExpression (unaryOperatorExpression, data);
224
 
                        valueGetsChanged = false;
225
 
                        switch (unaryOperatorExpression.Op) {
226
 
                        case UnaryOperatorType.Increment:
227
 
                        case UnaryOperatorType.Decrement:
228
 
                        case UnaryOperatorType.PostIncrement:
229
 
                        case UnaryOperatorType.PostDecrement:
230
 
                                IdentifierExpression left = unaryOperatorExpression.Expression as IdentifierExpression;
231
 
                                if (left != null && variables.ContainsKey (left.Identifier))
232
 
                                        variables[left.Identifier].GetsChanged = true;
233
 
                                break;
234
 
                        }
235
 
                        return result;
236
 
                }
237
 
 
238
 
                public override object VisitDirectionExpression (ICSharpCode.NRefactory.Ast.DirectionExpression directionExpression, object data)
239
 
                {
240
 
                        valueGetsChanged = true;
241
 
                        IdentifierExpression left = directionExpression.Expression as IdentifierExpression;
242
 
                        bool isInitialUse = left != null && !variables.ContainsKey (left.Identifier);
243
 
                        object result = base.VisitDirectionExpression (directionExpression, data);
244
 
                        valueGetsChanged = false;
245
 
                        if (left != null && variables.ContainsKey (left.Identifier)) {
246
 
                                variables[left.Identifier].GetsChanged = true;
247
 
                                if (isInitialUse && directionExpression.FieldDirection == FieldDirection.Out)
248
 
                                        variables[left.Identifier].GetsAssigned = true;
249
 
                        }
250
 
                        
251
 
                        return result;
252
 
                }
253
 
                
254
 
                public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data)
255
 
                {
256
 
                        if (!MemberLocation.IsEmpty && methodDeclaration.StartLocation.Line != MemberLocation.Line)
257
 
                                return null;
258
 
                        return base.VisitMethodDeclaration (methodDeclaration, data);
259
 
                }
260
 
                
261
 
                public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data)
262
 
                {
263
 
                        if (!MemberLocation.IsEmpty && propertyDeclaration.StartLocation.Line != MemberLocation.Line)
264
 
                                return null;
265
 
                        return base.VisitPropertyDeclaration (propertyDeclaration, data);
266
 
                }
267
 
                
268
 
                public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data)
269
 
                {
270
 
                        if (!MemberLocation.IsEmpty && eventDeclaration.StartLocation.Line != MemberLocation.Line)
271
 
                                return null;
272
 
                        return base.VisitEventDeclaration (eventDeclaration, data);
273
 
                }
274
 
        }
275
 
}