From dc6c33595a0807729c94d24fad4b7e3c590d26b7 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 17 May 2005 20:18:35 +0000 Subject: [PATCH] Added constructor overload lookup. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@147 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Implementations/AbstractNamedEntity.cs | 5 ++ .../Src/Dom/Implementations/DefaultClass.cs | 77 +++++++++++-------- .../NRefactoryResolver/NRefactoryResolver.cs | 6 +- .../Src/Dom/NRefactoryResolver/TypeVisitor.cs | 9 +-- .../ICSharpCode.SharpDevelop.Tests.csproj | 1 + src/Main/Base/Test/ReflectionLayerTests.cs | 46 +++++++++++ .../Src/Services/FileUtility/FileUtility.cs | 4 +- 7 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 src/Main/Base/Test/ReflectionLayerTests.cs diff --git a/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs b/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs index ac258c521d..d20b62f789 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/AbstractNamedEntity.cs @@ -96,5 +96,10 @@ namespace ICSharpCode.SharpDevelop.Dom nspace = declaringType.FullyQualifiedName; fullyQualifiedName = nspace + '.' + name; } + + public override string ToString() + { + return String.Format("[{0}: {1}]", GetType().Name, fullyQualifiedName); + } } } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs index a45c5d2218..656a9ec85a 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs @@ -292,7 +292,7 @@ namespace ICSharpCode.SharpDevelop.Dom } return false; } - */ + */ /* public IMember SearchMember(string memberName) { @@ -343,7 +343,7 @@ namespace ICSharpCode.SharpDevelop.Dom } return null; } - */ + */ public IClass GetInnermostClass(int caretLine, int caretColumn) { @@ -438,20 +438,32 @@ namespace ICSharpCode.SharpDevelop.Dom return members; } - */ + */ public class ClassInheritanceEnumerator : IEnumerator, IEnumerable { IClass topLevelClass; IClass currentClass = null; - Queue baseTypeQueue = new Queue(); - + + private struct BaseType { + internal IClass parent; + internal string name; + + internal BaseType(IClass parent, string name) { + this.parent = parent; + this.name = name; + } + } + + Queue baseTypeQueue = new Queue(); + + List finishedClasses = new List(); + public ClassInheritanceEnumerator(IClass topLevelClass) { this.topLevelClass = topLevelClass; - baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName); PutBaseClassesOnStack(topLevelClass); - baseTypeQueue.Enqueue("System.Object"); + baseTypeQueue.Enqueue(new BaseType(null, "System.Object")); } public IEnumerator GetEnumerator() @@ -462,7 +474,7 @@ namespace ICSharpCode.SharpDevelop.Dom void PutBaseClassesOnStack(IClass c) { foreach (string baseTypeName in c.BaseTypes) { - baseTypeQueue.Enqueue(baseTypeName); + baseTypeQueue.Enqueue(new BaseType(c, baseTypeName)); } } @@ -478,42 +490,40 @@ namespace ICSharpCode.SharpDevelop.Dom } } + bool first = true; + public bool MoveNext() { try { + if (first) { + first = false; + currentClass = topLevelClass; + return true; + } if (baseTypeQueue.Count == 0) { return false; } - string baseTypeName = baseTypeQueue.Dequeue().ToString(); - IClass baseType = ParserService.CurrentProjectContent.GetClass(baseTypeName); - - // search through all usings the top level class compilation unit has. - if (baseType == null) { - ICompilationUnit unit = currentClass == null ? null : currentClass.CompilationUnit; - if (unit != null) { - foreach (IUsing u in unit.Usings) { - baseType = u.SearchType(baseTypeName); - if (baseType != null) { - break; - } - } - } - } + BaseType baseTypeStruct = baseTypeQueue.Dequeue(); - // search through all namespaces the top level class is defined in. - if (baseType == null) { - string[] namespaces = topLevelClass.Namespace.Split('.'); - for (int i = namespaces.Length; i > 0 && baseType == null; --i) { - baseType = ParserService.CurrentProjectContent.GetClass(String.Join(".", namespaces, 0, i) + "." + baseTypeName); - } + IClass baseType; + if (baseTypeStruct.parent == null) { + baseType = ProjectContentRegistry.GetMscorlibContent().GetClass(baseTypeStruct.name); + } else { + baseType = baseTypeStruct.parent.ProjectContent.SearchType(baseTypeStruct.name, baseTypeStruct.parent, 1, 1); } - if (baseType != null) { currentClass = baseType; + + // prevent enumerating interfaces multiple times and endless loops when + // circular inheritance is found + if (finishedClasses.Contains(currentClass)) { + return MoveNext(); + } + finishedClasses.Add(currentClass); PutBaseClassesOnStack(currentClass); + return true; } - return baseType != null; } catch (Exception e) { Console.WriteLine(e); } @@ -522,10 +532,11 @@ namespace ICSharpCode.SharpDevelop.Dom public void Reset() { + first = true; baseTypeQueue.Clear(); - baseTypeQueue.Enqueue(topLevelClass.FullyQualifiedName); + finishedClasses.Clear(); PutBaseClassesOnStack(topLevelClass); - baseTypeQueue.Enqueue("System.Object"); + baseTypeQueue.Enqueue(new BaseType(null, "System.Object")); } } } diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index c2305efc56..bad1bb6cd7 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -201,11 +201,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return null; } if (expr is ObjectCreateExpression) { + ArrayList constructors = new ArrayList(); foreach (IMethod m in type.GetMethods()) { if (m.IsConstructor && !m.IsStatic) - return CreateMemberResolveResult(m); + constructors.Add(m); } - return null; + return CreateMemberResolveResult(typeVisitor.FindOverload(constructors, ((ObjectCreateExpression)expr).Parameters, null)); } return new ResolveResult(callingClass, callingMember, type); } @@ -331,6 +332,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver private ResolveResult CreateMemberResolveResult(IMember member) { + if (member == null) return null; return new MemberResolveResult(callingClass, callingMember, member); } diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs index a0d0a78081..e7a2c15753 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs @@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver return m.ReturnType; } - IMethod FindOverload(ArrayList methods, InvocationExpression invocationExpression, object data) + public IMethod FindOverload(ArrayList methods, ArrayList arguments, object data) { if (methods.Count <= 0) { return null; @@ -61,7 +61,6 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (methods.Count == 1) return bestMethod; - ArrayList arguments = invocationExpression.Parameters; IReturnType[] types = new IReturnType[arguments.Count]; for (int i = 0; i < types.Length; ++i) { types[i] = ((Expression)arguments[i]).AcceptVisitor(this, data) as IReturnType; @@ -103,14 +102,14 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver FieldReferenceExpression field = (FieldReferenceExpression)invocationExpression.TargetObject; IReturnType type = field.TargetObject.AcceptVisitor(this, data) as IReturnType; ArrayList methods = resolver.SearchMethod(type, field.FieldName); - return FindOverload(methods, invocationExpression, data); + return FindOverload(methods, invocationExpression.Parameters, data); } else if (invocationExpression.TargetObject is IdentifierExpression) { string id = ((IdentifierExpression)invocationExpression.TargetObject).Identifier; if (resolver.CallingClass == null) { return null; } ArrayList methods = resolver.SearchMethod(resolver.CallingClass.DefaultReturnType, id); - return FindOverload(methods, invocationExpression, data); + return FindOverload(methods, invocationExpression.Parameters, data); } // invocationExpression is delegate call IReturnType t = invocationExpression.AcceptChildren(this, data) as IReturnType; @@ -120,7 +119,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver IClass c = resolver.SearchType(t.FullyQualifiedName, resolver.CallingClass, resolver.CompilationUnit); if (c.ClassType == ClassType.Delegate) { ArrayList methods = resolver.SearchMethod(t, "Invoke"); - return FindOverload(methods, invocationExpression, data); + return FindOverload(methods, invocationExpression.Parameters, data); } return null; } diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index f083fd9706..80f33789c9 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -42,6 +42,7 @@ + diff --git a/src/Main/Base/Test/ReflectionLayerTests.cs b/src/Main/Base/Test/ReflectionLayerTests.cs new file mode 100644 index 0000000000..f46f68a3d7 --- /dev/null +++ b/src/Main/Base/Test/ReflectionLayerTests.cs @@ -0,0 +1,46 @@ +/* + * Created by SharpDevelop. + * User: Daniel Grunwald + * Date: 17.05.2005 + * Time: 21:33 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests +{ + [TestFixture] + public class ReflectionLayerTests + { + IProjectContent pc = ProjectContentRegistry.GetMscorlibContent(); + + [Test] + public void InheritanceTest() + { + IClass c = pc.GetClass("System.SystemException"); + IClass c2 = pc.GetClass("System.Exception"); + Assert.IsNotNull(c, "c is null"); + Assert.IsNotNull(c2, "c2 is null"); + Assert.AreEqual(3, c.BaseTypes.Count); // 2 interfaces + Assert.AreEqual("System.Exception", c.BaseTypes[0]); + Assert.AreSame(c2, c.BaseClass); + + List subClasses = new List(); + foreach (IClass subClass in c.ClassInheritanceTree) { + subClasses.Add(subClass); + } + Assert.AreEqual(5, subClasses.Count, "ClassInheritanceTree length"); + Assert.AreEqual("System.SystemException", subClasses[0].FullyQualifiedName); + Assert.AreEqual("System.Exception", subClasses[1].FullyQualifiedName); + Assert.AreEqual("System.Runtime.Serialization.ISerializable", subClasses[2].FullyQualifiedName); + Assert.AreEqual("System.Runtime.InteropServices._Exception", subClasses[3].FullyQualifiedName); + Assert.AreEqual("System.Object", subClasses[4].FullyQualifiedName); + } + } +} diff --git a/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs b/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs index 47fabba040..656f008569 100644 --- a/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs +++ b/src/Main/Core/Project/Src/Services/FileUtility/FileUtility.cs @@ -172,9 +172,9 @@ namespace ICSharpCode.Core fileName2 = fileName2.Substring(0, fileName2.Length - 1); try { - if (fileName1.Length < 2 || fileName1[1] != ':') + if (fileName1.Length < 2 || fileName1[1] != ':' || fileName1.IndexOf("/.") >= 0 || fileName1.IndexOf("\\.") >= 0) fileName1 = Path.GetFullPath(fileName1); - if (fileName2.Length < 2 || fileName2[1] != ':') + if (fileName2.Length < 2 || fileName2[1] != ':' || fileName2.IndexOf("/.") >= 0 || fileName2.IndexOf("\\.") >= 0) fileName2 = Path.GetFullPath(fileName2); } catch (Exception) { return false;