2
// NRefactoryResolver.cs
5
// Mike KrĆ¼ger <mkrueger@novell.com>
7
// Copyright (C) 2008 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
using System.Collections;
32
using System.Collections.ObjectModel;
33
using System.Collections.Generic;
34
using System.Collections.Specialized;
38
using MonoDevelop.Core;
39
using MonoDevelop.Projects.Dom;
40
using MonoDevelop.Projects.Dom.Parser;
41
using MonoDevelop.Projects;
42
using MonoDevelop.Ide.Gui;
43
using MonoDevelop.Ide.Gui.Content;
44
using MonoDevelop.Ide.CodeTemplates;
45
using MonoDevelop.Projects.Gui.Completion;
46
using MonoDevelop.Refactoring;
47
using ICSharpCode.NRefactory.Visitors;
48
using ICSharpCode.NRefactory.Parser;
49
using ICSharpCode.NRefactory.Ast;
50
using ICSharpCode.NRefactory;
51
using MonoDevelop.CSharp.Parser;
52
using MonoDevelop.CSharp.Completion;
54
namespace MonoDevelop.CSharp.Resolver
56
public class NRefactoryResolver : IResolver
59
SupportedLanguage lang;
60
MonoDevelop.Ide.Gui.TextEditor editor;
62
IMember callingMember;
63
ICompilationUnit unit;
64
LookupTableVisitor lookupTableVisitor;
65
DomLocation resolvePosition;
68
public IType CallingType {
74
public IMember CallingMember {
79
callingMember = value;
83
public ProjectDom Dom {
89
public ICompilationUnit Unit {
95
public static IType GetTypeAtCursor (IType outerType, string fileName, DomLocation position)
97
foreach (IType type in outerType.InnerTypes) {
98
if (type.BodyRegion.Contains (position))
99
return GetTypeAtCursor (type, fileName, position);
104
public static IType GetTypeAtCursor (ICompilationUnit unit, string fileName, DomLocation position)
108
foreach (IType type in unit.Types) {
109
if (type.BodyRegion.Contains (position))
110
return GetTypeAtCursor (type, fileName, position);
115
public NRefactoryResolver (ProjectDom dom, ICompilationUnit unit, MonoDevelop.Ide.Gui.TextEditor editor, string fileName) : this (dom, unit, SupportedLanguage.CSharp, editor, fileName)
119
public NRefactoryResolver (ProjectDom dom, ICompilationUnit unit, SupportedLanguage lang, MonoDevelop.Ide.Gui.TextEditor editor, string fileName)
122
throw new ArgumentNullException ("dom");
127
this.editor = editor;
128
this.fileName = fileName;
129
this.lookupTableVisitor = new LookupTableVisitor (lang);
133
ICSharpCode.NRefactory.Ast.CompilationUnit memberCompilationUnit;
134
public ICSharpCode.NRefactory.Ast.CompilationUnit MemberCompilationUnit {
136
return this.memberCompilationUnit;
140
internal static IMember GetMemberAt (IType type, DomLocation location)
142
foreach (IMember member in type.Members) {
143
if (!(member is IMethod || member is IProperty || member is IEvent || member is IField))
145
// Console.WriteLine (member.Location.Line + " --- " + location.Line);
146
if (member.Location.Line == location.Line || member.BodyRegion.Contains (location)) {
153
internal void SetupResolver (DomLocation resolvePosition)
155
this.resolvePosition = resolvePosition;
156
this.resultTable.Clear ();
157
callingType = GetTypeAtCursor (unit, fileName, resolvePosition);
158
if (callingType != null) {
159
callingMember = GetMemberAt (callingType, resolvePosition);
160
if (callingMember == null) {
161
DomLocation posAbove = resolvePosition;
163
callingMember = GetMemberAt (callingType, posAbove);
165
callingType = dom.ResolveType (callingType);
167
//System.Console.WriteLine("CallingMember: " + callingMember);
168
if (callingMember != null && !setupLookupTableVisitor ) {
169
string wrapper = CreateWrapperClassForMember (callingMember, fileName, editor);
170
using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (lang, new StringReader (wrapper))) {
172
memberCompilationUnit = parser.CompilationUnit;
173
lookupTableVisitor.VisitCompilationUnit (parser.CompilationUnit, null);
174
lookupVariableLine = CallingMember.Location.Line - 2;
175
setupLookupTableVisitor = true;
177
} else if (editor != null) {
178
string wrapper = editor.Text;
179
using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (lang, new StringReader (wrapper))) {
181
memberCompilationUnit = parser.CompilationUnit;
182
lookupTableVisitor.VisitCompilationUnit (parser.CompilationUnit, null);
183
lookupVariableLine = 0;
184
setupLookupTableVisitor = true;
188
bool setupLookupTableVisitor = false;
189
int lookupVariableLine = 0;
190
internal void SetupParsedCompilationUnit (ICSharpCode.NRefactory.Ast.CompilationUnit unit)
192
lookupVariableLine = 0; // all compilation unit lines are 1 based
193
memberCompilationUnit = unit;
194
lookupTableVisitor.VisitCompilationUnit (unit, null);
195
setupLookupTableVisitor = true;
198
static void AddParameterList (CSharpTextEditorCompletion.CompletionDataCollector col, IEnumerable<IParameter> parameters)
200
foreach (IParameter p in parameters) {
202
// completionList.Add (p.Name, "md-literal");
206
void AddContentsFromClassAndMembers (ExpressionContext context, CSharpTextEditorCompletion.CompletionDataCollector col)
208
IMethod method = callingMember as IMethod;
209
if (method != null && method.Parameters != null) {
210
AddParameterList (col, method.Parameters);
212
IProperty property = callingMember as IProperty;
213
if (property != null && property.Parameters != null)
214
AddParameterList (col, property.Parameters);
215
if (CallingType == null)
217
AddContentsFromOuterClass (CallingType.DeclaringType, context, col);
218
IType callingType = CallingType is InstantiatedType ? ((InstantiatedType)CallingType).UninstantiatedType : CallingType;
219
//bool isInStatic = CallingMember != null ? CallingMember.IsStatic : false;
221
if (CallingMember == null || !CallingMember.IsStatic) {
222
foreach (TypeParameter parameter in callingType.TypeParameters) {
223
col.Add (parameter.Name, "md-literal");
227
if (context != ExpressionContext.TypeDeclaration && CallingMember != null) {
228
bool includeProtected = DomType.IncludeProtected (dom, CallingType, CallingMember.DeclaringType);
229
foreach (IType type in dom.GetInheritanceTree (CallingType)) {
230
foreach (IMember member in type.Members) {
231
if (!(member is IType) && CallingMember.IsStatic && !(member.IsStatic || member.IsConst))
233
if (member.IsAccessibleFrom (dom, CallingType, CallingMember, includeProtected)) {
234
if (context.FilterEntry (member))
243
void AddContentsFromOuterClass (IType outer, ExpressionContext context, CSharpTextEditorCompletion.CompletionDataCollector col)
247
foreach (IMember member in outer.Members) {
248
if (member is IType || member.IsStatic || member.IsConst) {
252
AddContentsFromOuterClass (outer.DeclaringType, context, col);
255
static readonly IReturnType attributeType = new DomReturnType ("System.Attribute");
256
public CSharpTextEditorCompletion.CompletionDataCollector AddAccessibleCodeCompletionData (ExpressionContext context, CSharpTextEditorCompletion.CompletionDataCollector col)
258
if (context != ExpressionContext.Global && context != ExpressionContext.TypeName) {
259
AddContentsFromClassAndMembers (context, col);
261
if (lookupTableVisitor != null && lookupTableVisitor.Variables != null) {
262
int callingMemberline = CallingMember != null ? CallingMember.Location.Line : 0;
263
// local variables could be outside members (LINQ initializers)
264
foreach (KeyValuePair<string, List<LocalLookupVariable>> pair in lookupTableVisitor.Variables) {
265
if (pair.Value != null && pair.Value.Count > 0) {
266
foreach (LocalLookupVariable v in pair.Value) {
267
if (new DomLocation (callingMemberline + v.StartPos.Line - 2, v.StartPos.Column) <= this.resolvePosition && (v.EndPos.IsEmpty || new DomLocation (callingMemberline + v.EndPos.Line - 2, v.EndPos.Column) >= this.resolvePosition)) {
268
col.Add (new LocalVariable (CallingMember, pair.Key, ConvertTypeReference (v.TypeRef), DomRegion.Empty));
275
if (CallingMember is IProperty) {
276
IProperty property = (IProperty)callingMember;
277
if (property.HasSet && editor != null && property.SetRegion.Contains (resolvePosition.Line, editor.CursorColumn))
281
if (CallingMember is IEvent)
285
List<string> namespaceList = new List<string> ();
286
namespaceList.Add ("");
288
List<string> namespaceDeclList = new List<string> ();
289
namespaceDeclList.Add ("");
291
foreach (IUsing u in unit.Usings) {
292
foreach (string alias in u.Aliases.Keys) {
295
if (u.Namespaces == null)
297
bool isNamespaceDecl = u.IsFromNamespace && u.Region.Contains (this.resolvePosition);
298
if (u.IsFromNamespace && !isNamespaceDecl)
300
foreach (string ns in u.Namespaces) {
301
namespaceList.Add (ns);
303
namespaceDeclList.Add (ns);
307
foreach (object o in dom.GetNamespaceContents (namespaceList, true, true)) {
308
if (context.FilterEntry (o))
310
if (o is Namespace) {
311
Namespace ns = o as Namespace;
313
foreach (string str in namespaceDeclList) {
314
if (dom.NamespaceExists (str.Length > 0 ? str + "." + ns.Name : ns.Name)) {
323
//IMember member = o as IMember;
324
//if (member != null && completionList.Find (member.Name) != null)
326
if (context == ExpressionContext.Attribute) {
327
IType t = o as IType;
328
if (t != null && !t.IsBaseType (attributeType))
331
ICompletionData data = col.Add (o);
332
if (data != null && context == ExpressionContext.Attribute && data.CompletionText != null && data.CompletionText.EndsWith ("Attribute")) {
333
string newText = data.CompletionText.Substring (0, data.CompletionText.Length - "Attribute".Length);
334
data.SetText (newText);
337
CodeTemplateService.AddCompletionDataForMime ("text/x-csharp", col.CompletionList);
342
Expression ParseExpression (ExpressionResult expressionResult)
344
if (expressionResult == null || String.IsNullOrEmpty (expressionResult.Expression))
346
string expr = expressionResult.Expression.Trim ();
347
if (!expr.EndsWith (";"))
349
using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (this.lang, new StringReader (expr))) {
350
Expression result = parser.ParseExpression();
351
if (result is BinaryOperatorExpression) {
352
TypeReference typeRef = ParseTypeReference (expressionResult);
353
if (typeRef != null) {
354
return new TypeReferenceExpression (typeRef);
361
static TypeReference ParseTypeReference (ExpressionResult expressionResult)
363
if (expressionResult == null || String.IsNullOrEmpty (expressionResult.Expression))
365
string expr = expressionResult.Expression.Trim ();
366
using (ICSharpCode.NRefactory.IParser parser = ICSharpCode.NRefactory.ParserFactory.CreateParser (SupportedLanguage.CSharp, new StringReader ("typeof(" + expr + ");"))) {
367
TypeOfExpression typeOfExpression = parser.ParseExpression () as TypeOfExpression;
368
if (typeOfExpression != null)
369
return typeOfExpression.TypeReference;
374
public static IReturnType ParseReturnType (ExpressionResult expressionResult)
376
TypeReference typeReference = ParseTypeReference (expressionResult);
377
if (typeReference == null)
379
return ConvertTypeReference (typeReference);
382
public ResolveResult ResolveIdentifier (string identifier, DomLocation resolvePosition)
384
this.SetupResolver (resolvePosition);
385
ResolveVisitor visitor = new ResolveVisitor (this);
386
ResolveResult result = this.ResolveIdentifier (visitor, identifier);
390
public ResolveResult ResolveExpression (Expression expr, DomLocation resolvePosition)
393
this.SetupResolver (resolvePosition);
394
ResolveVisitor visitor = new ResolveVisitor (this);
395
ResolveResult result = visitor.Resolve (expr);
400
public Expression ResolvedExpression {
406
public DomLocation ResolvePosition {
408
return resolvePosition;
412
public ResolveResult Resolve (ExpressionResult expressionResult, DomLocation resolvePosition)
414
this.SetupResolver (resolvePosition);
415
ResolveVisitor visitor = new ResolveVisitor (this);
416
ResolveResult result;
417
// System.Console.WriteLine("expressionResult:" + expressionResult);
419
if (unit != null && expressionResult.ExpressionContext == ExpressionContext.AttributeArguments) {
420
string attributeName = NewCSharpExpressionFinder.FindAttributeName (editor, unit, unit.FileName);
421
if (attributeName != null) {
422
IType type = dom.SearchType (new SearchTypeRequest (unit, new DomReturnType (attributeName + "Attribute"), CallingType));
424
type = dom.SearchType (new SearchTypeRequest (unit, new DomReturnType (attributeName), CallingType));
426
foreach (IProperty property in type.Properties) {
427
if (property.Name == expressionResult.Expression) {
428
return new MemberResolveResult (property);
435
TypeReference typeRef;
436
if (expressionResult != null && expressionResult.ExpressionContext != null && expressionResult.ExpressionContext.IsObjectCreation) {
437
typeRef = ParseTypeReference (expressionResult);
438
if (typeRef != null) {
439
if (dom.NamespaceExists (typeRef.Type)) {
440
// System.Console.WriteLine("namespace resolve result");
441
result = new NamespaceResolveResult (typeRef.Type);
443
result = visitor.CreateResult (ConvertTypeReference (typeRef));
445
// System.Console.WriteLine("type reference resolve result");
446
result.ResolvedExpression = expressionResult;
447
if (dom.GetType (result.ResolvedType) != null)
451
expr = ParseExpression (expressionResult);
453
// System.Console.WriteLine("parsed expression:" + expr);
455
// System.Console.WriteLine("Can't parse expression");
459
result = visitor.Resolve (expr);
460
// if (CallingMember == null && result != null)
461
// result.StaticResolve = true;
462
// System.Console.WriteLine("result:" + result + "STATIC" + result.StaticResolve);
463
result.ResolvedExpression = expressionResult;
467
public static IReturnType ConvertTypeReference (TypeReference typeRef)
469
return typeRef.ConvertToReturnType ();
472
IReturnType ResolveType (IReturnType type)
474
return ResolveType (unit, type);
477
IReturnType ResolveType (ICompilationUnit unit, IReturnType type)
480
return DomReturnType.Void;
481
if (type.Type != null) // type known (possible anonymous type), no resolving needed
484
return (IReturnType)new TypeResolverVisitor (dom, unit).Visit (type, this.CallingType);
487
ResolveResult GetFunctionParameterType (ResolveResult resolveResult)
489
if (resolveResult == null || resolveResult.ResolvedType == null)
491
IReturnType type = resolveResult.ResolvedType;
492
while (type.GenericArguments.Count > 0) {
493
IType realType = dom.SearchType (new SearchTypeRequest (Unit, type, CallingType));
494
if (realType != null && realType.ClassType == MonoDevelop.Projects.Dom.ClassType.Delegate) {
495
IMethod invokeMethod = realType.SearchMember ("Invoke", true) [0] as IMethod;
496
if (invokeMethod != null && invokeMethod.Parameters.Count > 0) {
497
type = invokeMethod.Parameters[0].ReturnType;
501
if (type.GenericArguments.Count > 0) {
502
type = type.GenericArguments[0];
507
resolveResult.ResolvedType = type;
508
return resolveResult;
513
HashSet<Expression> expressions = new HashSet<Expression> ();
514
Dictionary<string, ResolveResult> returnTypeDictionary = new Dictionary<string, ResolveResult> ();
515
NRefactoryResolver resolver;
517
public LambdaResolver (NRefactoryResolver resolver)
519
this.resolver = resolver;
522
internal ResolveResult ResolveLambda (ResolveVisitor visitor, Expression lambdaExpression)
524
if (expressions.Contains (lambdaExpression)) {
525
Console.WriteLine ("LOOP!!!");
528
expressions.Add (lambdaExpression);
530
if (lambdaExpression.Parent is LambdaExpression)
531
return ResolveLambda (visitor, lambdaExpression.Parent as Expression);
532
if (lambdaExpression.Parent is ParenthesizedExpression)
533
return ResolveLambda (visitor, lambdaExpression.Parent as Expression);
534
if (lambdaExpression.Parent is AssignmentExpression)
535
return visitor.Resolve (((AssignmentExpression)lambdaExpression.Parent).Left);
536
if (lambdaExpression.Parent is CastExpression)
537
return visitor.Resolve (((CastExpression)lambdaExpression.Parent));
538
if (lambdaExpression.Parent is VariableDeclaration) {
539
VariableDeclaration varDec = (VariableDeclaration)lambdaExpression.Parent;
540
return resolver.GetFunctionParameterType (resolver.ResolveIdentifier (visitor, varDec.Name));
542
if (lambdaExpression.Parent is InvocationExpression) {
543
InvocationExpression invocation = (InvocationExpression)lambdaExpression.Parent;
544
MethodResolveResult result = visitor.Resolve (invocation.TargetObject) as MethodResolveResult;
545
if (result == null) {
546
MonoDevelop.Core.LoggingService.LogWarning ("No compatible method found :" + invocation.TargetObject);
549
result.ResolveExtensionMethods ();
551
// todo! - not 100% correct, but it's a best-fit until the dom contains token information
552
// This code assumes that the lambda expression is the first parameter of the method.
553
for (int i = 0; i < invocation.Arguments.Count; i++) {
554
if (invocation.Arguments[i] == lambdaExpression && i < result.MostLikelyMethod.Parameters.Count) {
555
IParameter parameter = result.MostLikelyMethod.Parameters[i];
556
IReturnType returnType = parameter.ReturnType;
558
while (returnType.GenericArguments.Count > 0) {
559
returnType = returnType.GenericArguments[0];
561
string invariantString = returnType.ToInvariantString ();
562
if (returnTypeDictionary.ContainsKey (invariantString))
563
return returnTypeDictionary[invariantString];
564
ResolveResult createdResult = visitor.CreateResult (returnType);
565
returnTypeDictionary[invariantString] = createdResult;
566
return createdResult;
570
LambdaExpression lambda = (LambdaExpression)lambdaExpression;
571
// Console.WriteLine ("lambda:" + lambda);
572
if (!lambda.ExpressionBody.IsNull) {
573
DomLocation old = resolver.resolvePosition;
575
resolver.resolvePosition = new DomLocation (resolver.CallingMember.Location.Line + resolver.lookupVariableLine +
576
lambda.ExpressionBody.StartLocation.Line - 2,
577
lambda.ExpressionBody.StartLocation.Column - 1);
578
// Console.WriteLine ("pos:" + resolvePosition);
579
// result.AddArgument (visitor.GetTypeSafe (lambda.ExpressionBody));
580
// result.ResolveExtensionMethods ();
581
ResolveResult res = visitor.Resolve (lambda.ExpressionBody);
582
// Console.WriteLine (lambda.ExpressionBody);
583
// Console.WriteLine ("RES:" + res.ResolvedType.FullName);
584
if (!string.IsNullOrEmpty (res.ResolvedType.FullName))
587
resolver.resolvePosition = old;
591
foreach (Expression arg in invocation.Arguments) {
592
var argType = arg is LambdaExpression ? DomReturnType.Void : visitor.GetTypeSafe (arg);
593
result.AddArgument (argType);
596
result.ResolveExtensionMethods ();
597
//Console.WriteLine ("maybe method:" + result.MostLikelyMethod);
598
for (int i = 0; i < invocation.Arguments.Count; i++) {
599
if (invocation.Arguments [i] == lambdaExpression && i < result.MostLikelyMethod.Parameters.Count) {
600
IParameter parameterType = result.MostLikelyMethod.Parameters [i];
601
//Console.WriteLine (i + " par: " + parameterType);
602
if (parameterType.ReturnType.Name == "Func" && parameterType.ReturnType.GenericArguments.Count > 0) {
603
return visitor.CreateResult (parameterType.ReturnType.GenericArguments[0]);
610
if (lambdaExpression.Parent is ObjectCreateExpression) {
611
ObjectCreateExpression objectCreateExpression = (ObjectCreateExpression)lambdaExpression.Parent;
612
int index = objectCreateExpression.Parameters.IndexOf (lambdaExpression);
615
MemberResolveResult resolvedCreateExpression = visitor.Resolve (objectCreateExpression) as MemberResolveResult;
617
if (resolvedCreateExpression != null) {
618
IMethod method = resolvedCreateExpression.ResolvedMember as IMethod;
619
if (method!= null && index < method.Parameters.Count) {
620
return new ParameterResolveResult (method.Parameters[index]);
631
public ResolveResult ResolveLambda (ResolveVisitor visitor, Expression lambdaExpression)
633
return new LambdaResolver (this).ResolveLambda (visitor, lambdaExpression);
636
Dictionary<string, ResolveResult> resultTable = new Dictionary<string, ResolveResult> ();
637
public ResolveResult ResolveIdentifier (ResolveVisitor visitor, string identifier)
639
ResolveResult result = null;
640
if (resultTable.TryGetValue (identifier, out result))
642
resultTable[identifier] = result;
644
foreach (KeyValuePair<string, List<LocalLookupVariable>> pair in this.lookupTableVisitor.Variables) {
645
if (identifier == pair.Key) {
646
LocalLookupVariable var = null;
647
// Console.WriteLine ("--- RP:" + this.resolvePosition + "/" + pair.Value.Count);
648
foreach (LocalLookupVariable v2 in pair.Value) {
649
DomLocation varStartPos = new DomLocation (lookupVariableLine + v2.StartPos.Line, v2.StartPos.Column - 1);
650
DomLocation varEndPos = new DomLocation (lookupVariableLine + v2.EndPos.Line, v2.EndPos.Column - 1);
651
// Console.WriteLine (v2.Name + ":" + varStartPos + " <> " + varEndPos);
652
if (varStartPos > this.resolvePosition || (!v2.EndPos.IsEmpty && varEndPos < this.resolvePosition))
656
// Console.WriteLine ("var:" + var);
659
IReturnType varType = null;
660
IReturnType varTypeUnresolved = null;
661
if (var.IsQueryContinuation) {
662
QueryExpression query = var.Initializer as QueryExpression;
664
QueryExpressionGroupClause grouBy = query.SelectOrGroupClause as QueryExpressionGroupClause;
665
DomLocation old = resolvePosition;
667
resolvePosition = new DomLocation (lookupVariableLine + grouBy.Projection.StartLocation.Line,
668
grouBy.Projection.StartLocation.Column);
669
ResolveResult initializerResolve = visitor.Resolve (grouBy.Projection);
670
ResolveResult groupByResolve = visitor.Resolve (grouBy.GroupBy);
671
DomReturnType resolved = new DomReturnType (dom.GetType ("System.Linq.IGrouping", new IReturnType [] {
672
DomType.GetComponentType (dom, initializerResolve.ResolvedType), groupByResolve.ResolvedType}));
673
varTypeUnresolved = varType = resolved;
675
resolvePosition = old;
678
} else if ((var.TypeRef == null || var.TypeRef.Type == "var" || var.TypeRef.IsNull)) {
679
if (var.ParentLambdaExpression != null) {
680
ResolveResult lambdaResolve = ResolveLambda (visitor, var.ParentLambdaExpression);
681
if (lambdaResolve != null) {
682
varType = lambdaResolve.ResolvedType;
683
varTypeUnresolved = lambdaResolve.UnresolvedType;
685
varType = varTypeUnresolved = DomReturnType.Void;
688
if (var.Initializer != null) {
689
ResolveResult initializerResolve = visitor.Resolve (var.Initializer);
690
// Console.WriteLine ("initializer : "+ var.Initializer + " result:" + initializerResolve);
691
varType = var.IsLoopVariable ? DomType.GetComponentType (dom, initializerResolve.ResolvedType) : initializerResolve.ResolvedType;
692
varTypeUnresolved = var.IsLoopVariable ? DomType.GetComponentType (dom, initializerResolve.UnresolvedType) : initializerResolve.UnresolvedType;
693
// Console.WriteLine ("resolved type:" + initializerResolve.ResolvedType + " is loop : " + var.IsLoopVariable);
694
// Console.WriteLine (varType);
695
// Console.WriteLine ("----------");
698
varTypeUnresolved = varType = ConvertTypeReference (var.TypeRef);
700
// Console.WriteLine ("-----");
701
// Console.WriteLine (varType);
702
varType = ResolveType (varType);
703
result = new LocalVariableResolveResult (
704
new LocalVariable (CallingMember, identifier, varType,
705
new DomRegion (lookupVariableLine + var.StartPos.Line - 1, var.StartPos.Column - 1,
706
lookupVariableLine + var.StartPos.Line - 1, var.EndPos.Column - 1)),
709
result.ResolvedType = varType;
710
result.UnresolvedType = varTypeUnresolved;
714
if (this.callingMember != null) {
715
// special handling of property or field return types, they can have the same name as the return type
716
// ex.: MyType MyType { get; set; } Type1 Type1;
717
if ((callingMember is IProperty || callingMember is IField) && identifier == callingMember.Name) {
718
int pos = editor.GetPositionFromLineColumn (resolvePosition.Line, resolvePosition.Column);
719
while (pos < editor.TextLength && !Char.IsWhiteSpace (editor.GetCharAt (pos)))
721
while (pos < editor.TextLength && Char.IsWhiteSpace (editor.GetCharAt (pos)))
723
StringBuilder memberName = new StringBuilder ();
724
while (pos < editor.TextLength && (Char.IsLetterOrDigit (editor.GetCharAt (pos)) || editor.GetCharAt (pos) == '_') ) {
725
memberName.Append (editor.GetCharAt (pos));
728
//Console.WriteLine ("id: '" + identifier + "' : '" + memberName.ToString () +"'" + (memberName.ToString () == identifier));
729
if (memberName.ToString () == identifier) {
730
result = visitor.CreateResult (callingMember.ReturnType);
735
if (identifier == "value" && this.callingMember is IProperty) {
736
result = new MemberResolveResult (this.callingMember);
737
result.UnresolvedType = ((IProperty)this.callingMember).ReturnType;
738
result.ResolvedType = ResolveType (((IProperty)this.callingMember).ReturnType);
741
if (this.callingMember is IMethod || this.callingMember is IProperty) {
742
ReadOnlyCollection<IParameter> prms = this.callingMember is IMethod
743
? ((IMethod)this.callingMember).Parameters
744
: ((IProperty)this.callingMember).Parameters;
746
foreach (IParameter para in prms) {
747
if (para.Name == identifier) {
748
result = new ParameterResolveResult (para);
749
result.UnresolvedType = para.ReturnType;
750
result.ResolvedType = ResolveType (para.ReturnType);
757
IType searchedType = dom.SearchType (new SearchTypeRequest (unit, this.CallingType, identifier));
758
if (this.callingType != null && dom != null) {
759
List<IMember> members = new List <IMember> ();
760
foreach (IType type in dom.GetInheritanceTree (callingType)) {
761
members.AddRange (type.SearchMember (identifier, true));
763
bool includeProtected = true;
765
if (this.CallingMember != null) {
766
for (int i = 0; i < members.Count; i++) {
767
if (this.CallingMember.IsStatic && !members[i].IsStatic
768
|| !members[i].IsAccessibleFrom (dom, callingType, this.CallingMember, includeProtected))
770
members.RemoveAt (i);
777
if (members.Count > 0) {
778
if (members[0] is IMethod) {
779
result = new MethodResolveResult (members);
780
if (CallingMember != null)
781
result.StaticResolve = CallingMember.IsStatic;
782
} else if (members[0] is IType) {
783
result = new MemberResolveResult (null, true);
784
result.UnresolvedType = result.ResolvedType = new DomReturnType ((IType)members[0]);
787
result = new MemberResolveResult (members[0]);
789
result.UnresolvedType = members[0].ReturnType;
790
result.ResolvedType = ResolveType (members[0].ReturnType);
791
if (members[0] is IProperty && searchedType != null && result.ResolvedType.FullName == searchedType.FullName) {
792
result = new AggregatedResolveResult (result, new MemberResolveResult (null, true) {
793
UnresolvedType = new DomReturnType (searchedType),
794
ResolvedType = new DomReturnType (searchedType)
804
if (searchedType != null) {
805
result = new MemberResolveResult (null, true);
806
result.UnresolvedType = result.ResolvedType = new DomReturnType (searchedType);
810
if (dom.NamespaceExists (identifier, true)) {
811
result = new NamespaceResolveResult (identifier);
815
if (unit != null && unit.Usings != null) {
816
foreach (IUsing u in unit.Usings) {
817
if (u.IsFromNamespace && u.Region.Contains (resolvePosition)) {
818
foreach (string ns in u.Namespaces) {
819
if (dom.NamespaceExists (ns + "." + identifier, true)) {
820
result = new NamespaceResolveResult (ns + "." + identifier);
825
foreach (KeyValuePair<string, IReturnType> alias in u.Aliases) {
826
if (alias.Key == identifier || alias.Key + ".?" == identifier) {
827
result = new NamespaceResolveResult (alias.Value.FullName);
835
if (result != null) {
836
result.CallingType = CallingType;
837
result.CallingMember = CallingMember;
839
resultTable[identifier] = result;
843
internal static string CreateWrapperClassForMember (IMember member, string fileName, TextEditor editor)
847
StringBuilder result = new StringBuilder ();
848
int startLine = member.Location.Line;
849
int endLine = member.Location.Line;
850
if (!member.BodyRegion.IsEmpty)
851
endLine = member.BodyRegion.End.Line + 1;
853
result.Append ("class " + member.DeclaringType.Name + " {");
854
if (editor != null) {
856
editor.GetLineColumnFromPosition (editor.TextLength - 1, out col, out maxLine);
857
endLine = System.Math.Max (endLine, maxLine);
859
int endPos = editor.GetPositionFromLineColumn (endLine, editor.GetLineLength (endLine));
861
endPos = editor.TextLength;
862
text = editor.GetText (editor.GetPositionFromLineColumn (startLine, 0), endPos);
864
Mono.TextEditor.Document doc = new Mono.TextEditor.Document ();
865
doc.Text = File.ReadAllText (fileName) ?? "";
866
startLine = Math.Min (doc.LineCount, Math.Max (1, startLine));
867
endLine = Math.Min (doc.LineCount, Math.Max (1, endLine));
868
int startOffset = doc.LocationToOffset (startLine - 1, 0);
869
text = doc.GetTextAt (startOffset, doc.LocationToOffset (endLine - 1, doc.GetLine (endLine - 1).EditableLength) - startOffset);
871
if (!string.IsNullOrEmpty (text))
872
result.Append (text);
875
return result.ToString ();
878
static class HelperMethods
880
public static void SetText (this ICompletionData data, string text)
882
if (data is CompletionData) {
883
((CompletionData)data).CompletionText = text;
884
} else if (data is MemberCompletionData) {
885
((MemberCompletionData)data).CompletionText = text;
887
System.Console.WriteLine("Unknown completion data:" + data);