diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs index ea56d8ef7d..e6bd39063d 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/ExpressionFinder.cs @@ -61,15 +61,21 @@ namespace CSharpBinding.Parser string className = text.Substring(typeStart, typeEnd - typeStart); int pos = className.IndexOf('<'); string nonGenericClassName, genericPart; + int typeParameterCount = 0; if (pos > 0) { nonGenericClassName = className.Substring(0, pos); genericPart = className.Substring(pos); + pos = 0; + do { + typeParameterCount += 1; + pos = genericPart.IndexOf(',', pos + 1); + } while (pos > 0); } else { nonGenericClassName = className; genericPart = null; } ClassFinder finder = new ClassFinder(fileName, text, typeStart); - IReturnType t = finder.SearchType(nonGenericClassName); + IReturnType t = finder.SearchType(nonGenericClassName, typeParameterCount); IClass c = (t != null) ? t.GetUnderlyingClass() : null; if (c != null) { ExpressionContext context = ExpressionContext.TypeDerivingFrom(c, true); diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs index 40629f65e6..f3c00227e0 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/MyNamespaceBuilder.cs @@ -47,21 +47,21 @@ namespace VBNetBinding // we need to use GetClassReturnType instead of DefaultReturnType because we need // a reference to the compound class. c.Properties.Add(new DefaultProperty("Application", - new GetClassReturnType(pc, myApp.FullyQualifiedName), + new GetClassReturnType(pc, myApp.FullyQualifiedName, 0), ModifierEnum.Public | ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, c)); c.Properties.Add(new DefaultProperty("Computer", - new GetClassReturnType(pc, myComp.FullyQualifiedName), + new GetClassReturnType(pc, myComp.FullyQualifiedName, 0), ModifierEnum.Public | ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, c)); if (myForms != null) { c.Properties.Add(new DefaultProperty("Forms", - new GetClassReturnType(pc, myForms.FullyQualifiedName), + new GetClassReturnType(pc, myForms.FullyQualifiedName, 0), ModifierEnum.Public | ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, c)); } c.Properties.Add(new DefaultProperty("User", - new GetClassReturnType(pc, "Microsoft.VisualBasic.ApplicationServices.User"), + new GetClassReturnType(pc, "Microsoft.VisualBasic.ApplicationServices.User", 0), ModifierEnum.Public | ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, c)); cu.Classes.Add(c); @@ -90,7 +90,7 @@ namespace VBNetBinding static IReturnType CreateBaseType(ICompilationUnit cu, string fullName) { - return new GetClassReturnType(cu.ProjectContent, fullName); + return new GetClassReturnType(cu.ProjectContent, fullName, 0); } static IClass CreateMyComputer(ICompilationUnit cu, IProject project, string ns) @@ -128,7 +128,7 @@ namespace VBNetBinding foreach (IClass c in this.ProjectContent.Classes) { if (c.BaseClass == formClass) { properties.Add(new DefaultProperty(c.Name, - new GetClassReturnType(this.ProjectContent, c.FullyQualifiedName), + new GetClassReturnType(this.ProjectContent, c.FullyQualifiedName, 0), ModifierEnum.Public | ModifierEnum.Static, DomRegion.Empty, DomRegion.Empty, c)); } diff --git a/src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs b/src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs index 0b05a36a80..0d68cc61d2 100644 --- a/src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs +++ b/src/AddIns/DisplayBindings/FormDesigner/Project/Src/FormDesigner/DesignerLoader/NRefactoryDesignerLoader.cs @@ -204,7 +204,7 @@ namespace ICSharpCode.FormDesigner FixTypeReference(tref, location, domCu); } ICSharpCode.SharpDevelop.Dom.IClass curType = domCu.GetInnermostClass(location.Y, location.X); - ICSharpCode.SharpDevelop.Dom.IReturnType rt = domCu.ProjectContent.SearchType(type.Type, curType, domCu, location.Y, location.X); + ICSharpCode.SharpDevelop.Dom.IReturnType rt = domCu.ProjectContent.SearchType(type.Type, type.GenericTypes.Count, curType, domCu, location.Y, location.X); if (rt != null) { type.Type = rt.FullyQualifiedName; } diff --git a/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj.user b/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj.user index ef111b3b5e..7ff3943f7c 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj.user +++ b/src/AddIns/DisplayBindings/XmlEditor/Test/XmlEditor.Tests.csproj.user @@ -1,4 +1 @@ - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj.user b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj.user index c439b83dc4..7ff3943f7c 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj.user +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Debugger.Tests.csproj.user @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Dom/ClassFinder.cs b/src/Main/Base/Project/Src/Dom/ClassFinder.cs index d823c3823d..70497efbc6 100644 --- a/src/Main/Base/Project/Src/Dom/ClassFinder.cs +++ b/src/Main/Base/Project/Src/Dom/ClassFinder.cs @@ -60,14 +60,14 @@ namespace ICSharpCode.SharpDevelop.Dom } } - public IClass GetClass(string fullName) + public IClass GetClass(string fullName, int typeParameterCount) { - return projectContent.GetClass(fullName); + return projectContent.GetClass(fullName, typeParameterCount); } - public IReturnType SearchType(string name) + public IReturnType SearchType(string name, int typeParameterCount) { - return projectContent.SearchType(name, callingClass, cu, caretLine, caretColumn); + return projectContent.SearchType(name, typeParameterCount, callingClass, cu, caretLine, caretColumn); } public string SearchNamespace(string name) diff --git a/src/Main/Base/Project/Src/Dom/IReturnType.cs b/src/Main/Base/Project/Src/Dom/IReturnType.cs index 7a1d4c4f90..9bab1ecaf6 100644 --- a/src/Main/Base/Project/Src/Dom/IReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/IReturnType.cs @@ -70,6 +70,13 @@ namespace ICSharpCode.SharpDevelop.Dom get; } + /// + /// Gets the count of type parameters the target class should have. + /// + int TypeParameterCount { + get; + } + /// /// Gets if the return type is a default type, i.e. no array, generic etc. /// diff --git a/src/Main/Base/Project/Src/Dom/IUsing.cs b/src/Main/Base/Project/Src/Dom/IUsing.cs index 57bc059ce7..71fe292ce3 100644 --- a/src/Main/Base/Project/Src/Dom/IUsing.cs +++ b/src/Main/Base/Project/Src/Dom/IUsing.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.SharpDevelop.Dom get; } - IReturnType SearchType(string partitialTypeName); + IReturnType SearchType(string partitialTypeName, int typeParameterCount); string SearchNamespace(string partitialNamespaceName); } } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs index 783c33b9f1..c37c614b78 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/AbstractReturnType.cs @@ -22,11 +22,17 @@ namespace ICSharpCode.SharpDevelop.Dom public abstract List GetFields(); public abstract List GetEvents(); + public virtual int TypeParameterCount { + get { + return 0; + } + } + public override bool Equals(object o) { IReturnType rt = o as IReturnType; if (rt == null) return false; - return rt.IsDefaultReturnType && this.FullyQualifiedName == rt.FullyQualifiedName; + return rt.IsDefaultReturnType && this.FullyQualifiedName == rt.FullyQualifiedName && this.TypeParameterCount == rt.TypeParameterCount; } public override int GetHashCode() diff --git a/src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs index 2f3984799d..7c3f2ac259 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/CombinedReturnType.cs @@ -149,6 +149,12 @@ namespace ICSharpCode.SharpDevelop.Dom } } + public int TypeParameterCount { + get { + return 0; + } + } + public IClass GetUnderlyingClass() { return null; diff --git a/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs index 412d8887ea..21a241916c 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/ConstructedReturnType.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Dom if (!baseType.Equals(rt.baseType)) return false; if (typeParameters.Count != rt.typeParameters.Count) return false; for (int i = 0; i < typeParameters.Count; ++i) { - if (!typeParameters[i].Equals(rt.typeParameters[i])) return false; + if (!object.Equals(typeParameters[i], rt.typeParameters[i])) return false; } return true; } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs index 71c6f72644..00b3e1a833 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultClass.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.SharpDevelop.Dom protected virtual IReturnType CreateDefaultReturnType() { if (IsPartial) { - return new GetClassReturnType(ProjectContent, FullyQualifiedName); + return new GetClassReturnType(ProjectContent, FullyQualifiedName, TypeParameters.Count); } else { return new DefaultReturnType(this); } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultReturnType.cs index ccc7e9f419..5a538cb036 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultReturnType.cs @@ -27,6 +27,12 @@ namespace ICSharpCode.SharpDevelop.Dom this.c = c; } + public override int TypeParameterCount { + get { + return c.TypeParameters.Count; + } + } + public override IClass GetUnderlyingClass() { return c; diff --git a/src/Main/Base/Project/Src/Dom/Implementations/DefaultUsing.cs b/src/Main/Base/Project/Src/Dom/Implementations/DefaultUsing.cs index e37dea54de..ff46e2ec19 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/DefaultUsing.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/DefaultUsing.cs @@ -94,7 +94,7 @@ namespace ICSharpCode.SharpDevelop.Dom return null; } - public IReturnType SearchType(string partitialTypeName) + public IReturnType SearchType(string partitialTypeName, int typeParameterCount) { if (HasAliases) { foreach (KeyValuePair entry in aliases) { @@ -107,7 +107,7 @@ namespace ICSharpCode.SharpDevelop.Dom if (partitialTypeName.Length > aliasString.Length) { if (projectContent.Language.NameComparer.Equals(partitialTypeName.Substring(0, aliasString.Length + 1), aliasString + ".")) { string className = entry.Value.FullyQualifiedName + partitialTypeName.Remove(0, aliasString.Length); - IClass c = projectContent.GetClass(className); + IClass c = projectContent.GetClass(className, typeParameterCount); if (c != null) { return c.DefaultReturnType; } @@ -117,7 +117,7 @@ namespace ICSharpCode.SharpDevelop.Dom } if (projectContent.Language.ImportNamespaces) { foreach (string str in usings) { - IClass c = projectContent.GetClass(str + "." + partitialTypeName); + IClass c = projectContent.GetClass(str + "." + partitialTypeName, typeParameterCount); if (c != null) { return c.DefaultReturnType; } @@ -133,9 +133,9 @@ namespace ICSharpCode.SharpDevelop.Dom subClassName = partitialTypeName.Substring(pos + 1); } foreach (string str in usings) { - IClass c = projectContent.GetClass(str + "." + className); + IClass c = projectContent.GetClass(str + "." + className, typeParameterCount); if (c != null) { - c = projectContent.GetClass(str + "." + partitialTypeName); + c = projectContent.GetClass(str + "." + partitialTypeName, typeParameterCount); if (c != null) { return c.DefaultReturnType; } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs index 9c926d3fd1..8a99c1e426 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/GetClassReturnType.cs @@ -20,10 +20,12 @@ namespace ICSharpCode.SharpDevelop.Dom IProjectContent content; string fullName; string shortName; + int typeParameterCount; - public GetClassReturnType(IProjectContent content, string fullName) + public GetClassReturnType(IProjectContent content, string fullName, int typeParameterCount) { this.content = content; + this.typeParameterCount = typeParameterCount; SetFullyQualifiedName(fullName); } @@ -33,28 +35,34 @@ namespace ICSharpCode.SharpDevelop.Dom } } + public override int TypeParameterCount { + get { + return typeParameterCount; + } + } + public override bool Equals(object o) { GetClassReturnType rt = o as GetClassReturnType; if (rt == null) { IReturnType rt2 = o as IReturnType; if (rt2 != null && rt2.IsDefaultReturnType) - return rt2.FullyQualifiedName == fullName; + return rt2.FullyQualifiedName == fullName && rt2.TypeParameterCount == this.TypeParameterCount; else return false; } - return fullName == rt.fullName; + return fullName == rt.fullName && typeParameterCount == rt.typeParameterCount && content == rt.content; } public override int GetHashCode() { - return content.GetHashCode() ^ fullName.GetHashCode(); + return content.GetHashCode() ^ fullName.GetHashCode() ^ (typeParameterCount * 5); } // TODO: Cache BaseType until a new CompilationUnit is generated (static counter in ParserService) public override IReturnType BaseType { get { - IClass c = content.GetClass(fullName); + IClass c = content.GetClass(fullName, typeParameterCount); return (c != null) ? c.DefaultReturnType : null; } } diff --git a/src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs index 67746683ff..4337b35c69 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/ProxyReturnType.cs @@ -48,6 +48,13 @@ namespace ICSharpCode.SharpDevelop.Dom } } + public virtual int TypeParameterCount { + get { + IReturnType baseType = BaseType; + return (baseType != null) ? baseType.TypeParameterCount : 0; + } + } + /// /// Gets the array ranks of the return type. /// When the return type is not an array, this property returns null. diff --git a/src/Main/Base/Project/Src/Dom/Implementations/SearchClassReturnType.cs b/src/Main/Base/Project/Src/Dom/Implementations/SearchClassReturnType.cs index af415d3900..93533cd98f 100644 --- a/src/Main/Base/Project/Src/Dom/Implementations/SearchClassReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/Implementations/SearchClassReturnType.cs @@ -23,8 +23,9 @@ namespace ICSharpCode.SharpDevelop.Dom int caretColumn; string name; string shortName; + int typeParameterCount; - public SearchClassReturnType(IProjectContent projectContent, IClass declaringClass, int caretLine, int caretColumn, string name) + public SearchClassReturnType(IProjectContent projectContent, IClass declaringClass, int caretLine, int caretColumn, string name, int typeParameterCount) { if (declaringClass == null) throw new ArgumentNullException("declaringClass"); @@ -32,6 +33,7 @@ namespace ICSharpCode.SharpDevelop.Dom this.pc = projectContent; this.caretLine = caretLine; this.caretColumn = caretColumn; + this.typeParameterCount = typeParameterCount; this.name = name; int pos = name.LastIndexOf('.'); if (pos < 0) @@ -40,24 +42,35 @@ namespace ICSharpCode.SharpDevelop.Dom shortName = name.Substring(pos + 1); } + public override int TypeParameterCount { + get { + return typeParameterCount; + } + } + public override bool Equals(object o) { SearchClassReturnType rt = o as SearchClassReturnType; if (rt == null) { IReturnType rt2 = o as IReturnType; if (rt2 != null && rt2.IsDefaultReturnType) - return rt2.FullyQualifiedName == this.FullyQualifiedName; + return rt2.FullyQualifiedName == this.FullyQualifiedName && rt2.TypeParameterCount == this.TypeParameterCount; else return false; } if (declaringClass.FullyQualifiedName != rt.declaringClass.FullyQualifiedName) return false; + if (typeParameterCount != rt.typeParameterCount) return false; + if (caretLine != rt.caretLine) return false; + if (caretColumn != rt.caretColumn) return false; + if (typeParameterCount != rt.typeParameterCount) return false; return name == rt.name; } public override int GetHashCode() { unchecked { - return declaringClass.GetHashCode() ^ name.GetHashCode() ^ caretLine << 8 + caretColumn; + return declaringClass.GetHashCode() ^ name.GetHashCode() + ^ (typeParameterCount << 16 + caretLine << 8 + caretColumn); } } @@ -101,7 +114,7 @@ namespace ICSharpCode.SharpDevelop.Dom return type; try { isSearching = true; - type = pc.SearchType(name, declaringClass, caretLine, caretColumn); + type = pc.SearchType(name, typeParameterCount, declaringClass, caretLine, caretColumn); cache[this] = type; return type; } finally { diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs index 1c5d781ad4..7ad872a3b4 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/NRefactoryResolver.cs @@ -343,7 +343,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (projectContent.NamespaceExists(combinedName)) { return new NamespaceResolveResult(callingClass, callingMember, combinedName); } - c = projectContent.GetClass(combinedName); + c = GetClass(combinedName); if (c != null) { return new TypeResolveResult(callingClass, callingMember, c); } @@ -533,7 +533,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (languageProperties.CanImportClasses) { foreach (IUsing @using in cu.Usings) { foreach (string import in @using.Usings) { - IClass c = projectContent.GetClass(import); + IClass c = GetClass(import); if (c != null) { IMember member = GetMember(c.DefaultReturnType, identifier); if (member != null) { @@ -694,7 +694,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver public IReturnType SearchType(string name) { - return projectContent.SearchType(name, callingClass, cu, caretLine, caretColumn); + return projectContent.SearchType(name, 0, callingClass, cu, caretLine, caretColumn); } #region Helper for TypeVisitor @@ -709,7 +709,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (languageProperties.CanImportClasses) { foreach (IUsing @using in cu.Usings) { foreach (string import in @using.Usings) { - IClass c = projectContent.GetClass(import); + IClass c = projectContent.GetClass(import, 0); if (c != null) { methods = SearchMethod(c.DefaultReturnType, memberName); if (methods.Count > 0) diff --git a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs index 67076a03f3..eeb12b834d 100644 --- a/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs +++ b/src/Main/Base/Project/Src/Dom/NRefactoryResolver/TypeVisitor.cs @@ -260,7 +260,7 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (resolver.ProjectContent.NamespaceExists(combinedName)) { return new NamespaceReturnType(combinedName); } - IClass c = resolver.ProjectContent.GetClass(combinedName); + IClass c = resolver.GetClass(combinedName); if (c != null) { return c.DefaultReturnType; } @@ -510,18 +510,19 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver // keyword-type like void, int, string etc. t = ProjectContentRegistry.Mscorlib.GetClass(reference.SystemType).DefaultReturnType; } else { + int typeParameterCount = reference.GenericTypes.Count; if (useLazyReturnType) { if (reference.IsGlobal) - t = new GetClassReturnType(projectContent, reference.SystemType); + t = new GetClassReturnType(projectContent, reference.SystemType, typeParameterCount); else - t = new SearchClassReturnType(projectContent, callingClass, caretLine, caretColumn, reference.SystemType); + t = new SearchClassReturnType(projectContent, callingClass, caretLine, caretColumn, reference.SystemType, typeParameterCount); } else { IClass c; if (reference.IsGlobal) { - c = projectContent.GetClass(reference.SystemType); + c = projectContent.GetClass(reference.SystemType, typeParameterCount); t = (c != null) ? c.DefaultReturnType : null; } else { - t = projectContent.SearchType(reference.SystemType, callingClass, caretLine, caretColumn); + t = projectContent.SearchType(reference.SystemType, typeParameterCount, callingClass, caretLine, caretColumn); } if (t == null) { if (reference.GenericTypes.Count == 0 && !reference.IsArrayType) { diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs index e18e333e49..08a2b31202 100644 --- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs +++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/DomPersistence.cs @@ -21,7 +21,7 @@ namespace ICSharpCode.SharpDevelop.Dom { public const long FileMagic = 0x11635233ED2F428C; public const long IndexFileMagic = 0x11635233ED2F427D; - public const short FileVersion = 2; + public const short FileVersion = 3; #region Cache management #if DEBUG @@ -160,12 +160,39 @@ namespace ICSharpCode.SharpDevelop.Dom } #endregion + private struct ClassNameTypeCountPair { + public readonly string ClassName; + public readonly byte TypeParameterCount; + + public ClassNameTypeCountPair(IClass c) { + this.ClassName = c.FullyQualifiedName; + this.TypeParameterCount = (byte)c.TypeParameters.Count; + } + + public ClassNameTypeCountPair(IReturnType rt) { + this.ClassName = rt.FullyQualifiedName; + this.TypeParameterCount = (byte)rt.TypeParameterCount; + } + + public override bool Equals(object obj) { + if (!(obj is ClassNameTypeCountPair)) return false; + ClassNameTypeCountPair myClassNameTypeCountPair = (ClassNameTypeCountPair)obj; + if (!ClassName.Equals(myClassNameTypeCountPair.ClassName, StringComparison.InvariantCultureIgnoreCase)) return false; + if (TypeParameterCount != myClassNameTypeCountPair.TypeParameterCount) return false; + return true; + } + + public override int GetHashCode() { + return StringComparer.InvariantCultureIgnoreCase.GetHashCode(ClassName) ^ ((int)TypeParameterCount * 5); + } + } + private sealed class ReadWriteHelper { ReflectionProjectContent pc; readonly BinaryWriter writer; - readonly Dictionary classIndices = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + readonly Dictionary classIndices = new Dictionary(); readonly BinaryReader reader; IReturnType[] types; @@ -236,11 +263,11 @@ namespace ICSharpCode.SharpDevelop.Dom classIndices.Clear(); int i = 0; foreach (IClass c in classes) { - classIndices[c.FullyQualifiedName] = i; + classIndices[new ClassNameTypeCountPair(c)] = i; i += 1; } - List externalTypes = new List(); + List externalTypes = new List(); CreateExternalTypeList(externalTypes, classes.Count, classes); writer.Write(classes.Count); @@ -248,8 +275,9 @@ namespace ICSharpCode.SharpDevelop.Dom foreach (IClass c in classes) { writer.Write(c.FullyQualifiedName); } - foreach (string type in externalTypes) { - writer.Write(type); + foreach (ClassNameTypeCountPair type in externalTypes) { + writer.Write(type.ClassName); + writer.Write(type.TypeParameterCount); } foreach (IClass c in classes) { WriteClass(c); @@ -268,7 +296,8 @@ namespace ICSharpCode.SharpDevelop.Dom types[i] = c.DefaultReturnType; } for (int i = classCount; i < types.Length; i++) { - types[i] = new GetClassReturnType(pc, reader.ReadString()); + string name = reader.ReadString(); + types[i] = new GetClassReturnType(pc, name, reader.ReadByte()); } for (int i = 0; i < classes.Length; i++) { ReadClass(classes[i]); @@ -385,7 +414,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// Finds all return types used in the class collection and adds the unknown ones /// to the externalTypeIndices and externalTypes collections. /// - void CreateExternalTypeList(List externalTypes, + void CreateExternalTypeList(List externalTypes, int classCount, ICollection classes) { foreach (IClass c in classes) { @@ -424,13 +453,13 @@ namespace ICSharpCode.SharpDevelop.Dom } } - void AddExternalType(IReturnType rt, List externalTypes, int classCount) + void AddExternalType(IReturnType rt, List externalTypes, int classCount) { if (rt.IsDefaultReturnType) { - string name = rt.FullyQualifiedName; - if (!classIndices.ContainsKey(name)) { - classIndices.Add(name, externalTypes.Count + classCount); - externalTypes.Add(name); + ClassNameTypeCountPair pair = new ClassNameTypeCountPair(rt); + if (!classIndices.ContainsKey(pair)) { + classIndices.Add(pair, externalTypes.Count + classCount); + externalTypes.Add(pair); } } else if (rt is ArrayReturnType) { AddExternalType(((ArrayReturnType)rt).ElementType, externalTypes, classCount); @@ -465,7 +494,7 @@ namespace ICSharpCode.SharpDevelop.Dom if (name == "System.Void") { writer.Write(VoidRTCode); } else { - writer.Write(classIndices[rt.FullyQualifiedName]); + writer.Write(classIndices[new ClassNameTypeCountPair(rt)]); } } else if (rt is ArrayReturnType) { ArrayReturnType art = (ArrayReturnType)rt; diff --git a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs index a74273cd25..55a8e982cb 100644 --- a/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs +++ b/src/Main/Base/Project/Src/Dom/ReflectionLayer/ReflectionReturnType.cs @@ -152,8 +152,10 @@ namespace ICSharpCode.SharpDevelop.Dom name = name.Substring(0, name.Length - 1); } } + int typeParameterCount = 0; if (name.Length > 2) { if (name[name.Length - 2] == '`') { + typeParameterCount = int.Parse(name[name.Length - 1].ToString()); name = name.Substring(0, name.Length - 2); } } @@ -161,13 +163,13 @@ namespace ICSharpCode.SharpDevelop.Dom name = name.Replace('+', '.'); } if (!createLazyReturnType) { - IClass c = content.GetClass(name); + IClass c = content.GetClass(name, typeParameterCount); if (c != null) return c.DefaultReturnType; // example where name is not found: pointers like System.Char* // or when the class is in a assembly that is not referenced } - return new GetClassReturnType(content, name); + return new GetClassReturnType(content, name, typeParameterCount); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs index 96e0847e29..d3ea251f91 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/DefaultProjectContent.cs @@ -147,7 +147,18 @@ namespace ICSharpCode.Core public ICollection Classes { get { - return ClassLists[0].Values; + lock (namespaces) { + List list = new List(ClassLists[0].Count + 10); + foreach (IClass c in ClassLists[0].Values) { + if (c is GenericClassContainer) { + GenericClassContainer gcc = (GenericClassContainer)c; + list.AddRange(gcc.RealClasses); + } else { + list.Add(c); + } + } + return list; + } } } @@ -212,14 +223,80 @@ namespace ICSharpCode.Core } } + /// + /// Container class that is used when multiple classes with different type parameter + /// count have the same class name. + /// + private class GenericClassContainer : DefaultClass + { + public GenericClassContainer(string fullyQualifiedName) : base(null, fullyQualifiedName) {} + + IClass[] realClasses = new IClass[4]; + + public IEnumerable RealClasses { + get { + foreach (IClass c in realClasses) { + if (c != null) yield return c; + } + } + } + + public int RealClassCount { + get { + int count = 0; + foreach (IClass c in realClasses) { + if (c != null) count += 1; + } + return count; + } + } + + public IClass Get(int typeParameterCount) + { + if (realClasses.Length > typeParameterCount) + return realClasses[typeParameterCount]; + else + return null; + } + + public IClass GetBest(int typeParameterCount) + { + IClass c; + for (int i = typeParameterCount; i < realClasses.Length; i++) { + c = Get(i); + if (c != null) return c; + } + for (int i = typeParameterCount - 1; i >= 0; i--) { + c = Get(i); + if (c != null) return c; + } + return null; + } + + public void Set(IClass c) + { + int typeParameterCount = c.TypeParameters.Count; + if (realClasses.Length <= typeParameterCount) { + IClass[] newArray = new IClass[typeParameterCount + 2]; + realClasses.CopyTo(newArray, 0); + realClasses = newArray; + } + realClasses[typeParameterCount] = c; + } + + public void Remove(int typeParameterCount) + { + if (realClasses.Length > typeParameterCount) + realClasses[typeParameterCount] = null; + } + } + protected void AddClassToNamespaceListInternal(IClass addClass) { + string fullyQualifiedName = addClass.FullyQualifiedName; if (addClass.IsPartial) { LoggingService.Debug("Adding partial class " + addClass.Name + " from " + Path.GetFileName(addClass.CompilationUnit.FileName)); - Dictionary classes = GetClasses(language); - CompoundClass compound = null; - if (classes.ContainsKey(addClass.FullyQualifiedName)) - compound = classes[addClass.FullyQualifiedName] as CompoundClass; + CompoundClass compound = GetClassInternal(fullyQualifiedName, addClass.TypeParameters.Count, language) as CompoundClass; if (compound != null) { // possibly replace existing class (look for CU with same filename) for (int i = 0; i < compound.Parts.Count; i++) { @@ -240,6 +317,20 @@ namespace ICSharpCode.Core } } + IClass oldDictionaryClass; + if (GetClasses(language).TryGetValue(fullyQualifiedName, out oldDictionaryClass)) { + GenericClassContainer gcc = oldDictionaryClass as GenericClassContainer; + if (gcc != null) { + gcc.Set(addClass); + return; + } else if (oldDictionaryClass.TypeParameters.Count != addClass.TypeParameters.Count) { + gcc = new GenericClassContainer(fullyQualifiedName); + gcc.Set(addClass); + gcc.Set(oldDictionaryClass); + addClass = gcc; + } + } + foreach (Dictionary classes in ClassLists) { classes[addClass.FullyQualifiedName] = addClass; } @@ -355,13 +446,11 @@ namespace ICSharpCode.Core void RemoveClass(IClass @class) { - string fullClassName = @class.FullyQualifiedName; - if (!GetClasses(language).ContainsKey(fullClassName)) { - return; - } + string fullyQualifiedName = @class.FullyQualifiedName; if (@class.IsPartial) { // remove a part of a partial class - CompoundClass compound = (CompoundClass)GetClasses(language)[fullClassName]; + CompoundClass compound = (CompoundClass)GetClassInternal(fullyQualifiedName, @class.TypeParameters.Count, language); + if (compound == null) return; compound.Parts.Remove(@class); if (compound.Parts.Count > 0) { compound.UpdateInformationFromParts(); @@ -370,23 +459,33 @@ namespace ICSharpCode.Core @class = compound; // all parts removed, remove compound class } } - string nSpace = @class.Namespace; - if (nSpace == null) { - nSpace = String.Empty; + + IClass classInDictionary; + if (!GetClasses(language).TryGetValue(fullyQualifiedName, out classInDictionary)) { + return; } - RemoveClass(fullClassName, nSpace); - } - - void RemoveClass(string fullyQualifiedName, string nSpace) - { + + GenericClassContainer gcc = classInDictionary as GenericClassContainer; + if (gcc != null) { + gcc.Remove(@class.TypeParameters.Count); + if (gcc.RealClassCount > 0) { + return; + } + } + foreach (Dictionary classes in ClassLists) { classes.Remove(fullyQualifiedName); } + string nSpace = @class.Namespace; + if (nSpace == null) { + nSpace = String.Empty; + } + // Remove class from namespace lists List classList = GetNamespaces(this.language)[nSpace].Classes; for (int i = 0; i < classList.Count; i++) { - if (classList[i].FullyQualifiedName == fullyQualifiedName) { + if (language.NameComparer.Equals(classList[i].FullyQualifiedName, fullyQualifiedName)) { classList.RemoveAt(i); break; } @@ -399,38 +498,64 @@ namespace ICSharpCode.Core #region Default Parser Layer dependent functions public IClass GetClass(string typeName) { - return GetClass(typeName, language, true); + return GetClass(typeName, 0); + } + + public IClass GetClass(string typeName, int typeParameterCount) + { + return GetClass(typeName, typeParameterCount, language, true); + } + + protected IClass GetClassInternal(string typeName, int typeParameterCount, LanguageProperties language) + { + IClass c; + if (GetClasses(language).TryGetValue(typeName, out c)) { + GenericClassContainer gcc = c as GenericClassContainer; + if (gcc != null) { + return gcc.GetBest(typeParameterCount); + } + return c; + } + return null; } - public IClass GetClass(string typeName, LanguageProperties language, bool lookInReferences) + public IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences) { - Dictionary classes = GetClasses(language); - if (classes.ContainsKey(typeName)) { - return classes[typeName]; + IClass c = GetClassInternal(typeName, typeParameterCount, language); + if (c != null && c.TypeParameters.Count == typeParameterCount) { + return c; } // Search in references: if (lookInReferences) { foreach (IProjectContent content in referencedContents) { - IClass classFromContent = content.GetClass(typeName, language, false); - if (classFromContent != null) { - return classFromContent; + IClass contentClass = content.GetClass(typeName, typeParameterCount, language, false); + if (contentClass != null) { + if (contentClass.TypeParameters.Count == typeParameterCount) { + return contentClass; + } else { + c = contentClass; + } } } } + if (c != null) { + return c; + } + // not found -> maybe nested type -> trying to find class that contains this one. int lastIndex = typeName.LastIndexOf('.'); if (lastIndex > 0) { string outerName = typeName.Substring(0, lastIndex); - if (classes.ContainsKey(outerName)) { - IClass upperClass = classes[outerName]; + IClass upperClass = GetClassInternal(outerName, typeParameterCount, language); + if (upperClass != null) { List innerClasses = upperClass.InnerClasses; if (innerClasses != null) { string innerName = typeName.Substring(lastIndex + 1); - foreach (IClass c in innerClasses) { - if (language.NameComparer.Equals(c.Name, innerName)) { - return c; + foreach (IClass innerClass in innerClasses) { + if (language.NameComparer.Equals(innerClass.Name, innerName)) { + return innerClass; } } } @@ -468,29 +593,12 @@ namespace ICSharpCode.Core if (list.Capacity < newCapacity) list.Capacity = newCapacity; foreach (IClass c in ns.Classes) { - if (c.IsInternal && !lookInReferences) { - // internal class and we are looking at it from another project content - continue; - } - if (language.ShowInNamespaceCompletion(c)) - list.Add(c); - if (language.ImportModules && c.ClassType == ClassType.Module) { - foreach (IMember m in c.Methods) { - if (m.IsAccessible(null, false)) - list.Add(m); - } - foreach (IMember m in c.Events) { - if (m.IsAccessible(null, false)) - list.Add(m); - } - foreach (IMember m in c.Fields) { - if (m.IsAccessible(null, false)) - list.Add(m); - } - foreach (IMember m in c.Properties) { - if (m.IsAccessible(null, false)) - list.Add(m); + if (c is GenericClassContainer) { + foreach (IClass realClass in ((GenericClassContainer)c).RealClasses) { + AddNamespaceContentsClass(list, realClass, language, lookInReferences); } + } else { + AddNamespaceContentsClass(list, c, language, lookInReferences); } } foreach (string subns in ns.SubNamespaces) { @@ -500,6 +608,34 @@ namespace ICSharpCode.Core } } + void AddNamespaceContentsClass(ArrayList list, IClass c, LanguageProperties language, bool lookInReferences) + { + if (c.IsInternal && !lookInReferences) { + // internal class and we are looking at it from another project content + return; + } + if (language.ShowInNamespaceCompletion(c)) + list.Add(c); + if (language.ImportModules && c.ClassType == ClassType.Module) { + foreach (IMember m in c.Methods) { + if (m.IsAccessible(null, false)) + list.Add(m); + } + foreach (IMember m in c.Events) { + if (m.IsAccessible(null, false)) + list.Add(m); + } + foreach (IMember m in c.Fields) { + if (m.IsAccessible(null, false)) + list.Add(m); + } + foreach (IMember m in c.Properties) { + if (m.IsAccessible(null, false)) + list.Add(m); + } + } + } + public bool NamespaceExists(string name) { return NamespaceExists(name, language, true); @@ -570,25 +706,27 @@ namespace ICSharpCode.Core return null; } - public IReturnType SearchType(string name, IClass curType, int caretLine, int caretColumn) + public IReturnType SearchType(string name, int typeParameterCount, IClass curType, int caretLine, int caretColumn) { if (curType == null) { - return SearchType(name, null, null, caretLine, caretColumn); + return SearchType(name, typeParameterCount, null, null, caretLine, caretColumn); } - return SearchType(name, curType, curType.CompilationUnit, caretLine, caretColumn); + return SearchType(name, typeParameterCount, curType, curType.CompilationUnit, caretLine, caretColumn); } - public IReturnType SearchType(string name, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn) + public IReturnType SearchType(string name, int typeParameterCount, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn) { if (name == null || name.Length == 0) { return null; } // Try if name is already the full type name - IClass c = GetClass(name); + IClass c = GetClass(name, typeParameterCount); if (c != null) { return c.DefaultReturnType; } + // fallback-class if the one with the right type parameter count is not found. + IReturnType fallbackClass = null; if (curType != null) { // Try parent namespaces of the current class string fullname = curType.FullyQualifiedName; @@ -599,9 +737,12 @@ namespace ICSharpCode.Core curnamespace.Append('.'); curnamespace.Append(name); - c = GetClass(curnamespace.ToString()); + c = GetClass(curnamespace.ToString(), typeParameterCount); if (c != null) { - return c.DefaultReturnType; + if (c.TypeParameters.Count == typeParameterCount) + return c.DefaultReturnType; + else + fallbackClass = c.DefaultReturnType; } // remove class name again to try next namespace curnamespace.Length -= name.Length; @@ -621,20 +762,28 @@ namespace ICSharpCode.Core // Combine name with usings foreach (IUsing u in unit.Usings) { if (u != null) { - IReturnType r = u.SearchType(name); + IReturnType r = u.SearchType(name, typeParameterCount); if (r != null) { - return r; + if (r.TypeParameterCount == typeParameterCount) { + return r; + } else { + fallbackClass = r; + } } } } } if (defaultImports != null) { - IReturnType r = defaultImports.SearchType(name); + IReturnType r = defaultImports.SearchType(name, typeParameterCount); if (r != null) { - return r; + if (r.TypeParameterCount == typeParameterCount) { + return r; + } else { + fallbackClass = r; + } } } - return null; + return fallbackClass; } /// @@ -643,7 +792,7 @@ namespace ICSharpCode.Core /// Fully qualified member name (always case sensitive). public Position GetPosition(string fullMemberName) { - IClass curClass = GetClass(fullMemberName, LanguageProperties.CSharp, false); + IClass curClass = GetClass(fullMemberName, 0, LanguageProperties.CSharp, false); if (curClass != null) { return new Position(curClass.CompilationUnit, curClass.Region.BeginLine, curClass.Region.BeginColumn); } @@ -651,7 +800,7 @@ namespace ICSharpCode.Core if (pos > 0) { string className = fullMemberName.Substring(0, pos); string memberName = fullMemberName.Substring(pos + 1); - curClass = GetClass(className, LanguageProperties.CSharp, false); + curClass = GetClass(className, 0, LanguageProperties.CSharp, false); if (curClass != null) { IMember member = curClass.SearchMember(memberName, LanguageProperties.CSharp); if (member != null) { diff --git a/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs index 9d65d28125..c66109203d 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/IProjectContent.cs @@ -74,10 +74,11 @@ namespace ICSharpCode.Core void UpdateCompilationUnit(ICompilationUnit oldUnit, ICompilationUnit parserOutput, string fileName, bool updateCommentTags); IClass GetClass(string typeName); + IClass GetClass(string typeName, int typeParameterCount); bool NamespaceExists(string name); ArrayList GetNamespaceContents(string nameSpace); - IClass GetClass(string typeName, LanguageProperties language, bool lookInReferences); + IClass GetClass(string typeName, int typeParameterCount, LanguageProperties language, bool lookInReferences); bool NamespaceExists(string name, LanguageProperties language, bool lookInReferences); /// /// Adds the contents of the specified to the . @@ -85,8 +86,8 @@ namespace ICSharpCode.Core void AddNamespaceContents(ArrayList list, string subNameSpace, LanguageProperties language, bool lookInReferences); string SearchNamespace(string name, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn); - IReturnType SearchType(string name, IClass curType, int caretLine, int caretColumn); - IReturnType SearchType(string name, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn); + IReturnType SearchType(string name, int typeParameterCount, IClass curType, int caretLine, int caretColumn); + IReturnType SearchType(string name, int typeParameterCount, IClass curType, ICompilationUnit unit, int caretLine, int caretColumn); Position GetPosition(string fullMemberName); } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs index e97a38a508..0d0db2b45c 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ReflectionProjectContent.cs @@ -91,7 +91,7 @@ namespace ICSharpCode.SharpDevelop.Dom public void InitializeSpecialClasses() { - if (ClassLists[0].ContainsKey(VoidClass.VoidName)) { + if (GetClassInternal(VoidClass.VoidName, 0, Language) != null) { AddClassToNamespaceList(new VoidClass(assemblyCompilationUnit)); } } diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs index 49a32ba3ca..42da46eada 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs +++ b/src/Main/Base/Project/Src/TextEditor/Commands/CodeGenerators/EqualsCodeGenerator.cs @@ -69,7 +69,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands foreach (IField field in currentClass.Fields) { Indent(); - IClass cName = ParserService.CurrentProjectContent.GetClass(field.ReturnType.FullyQualifiedName); + IClass cName = field.ReturnType.GetUnderlyingClass(); if (cName == null || cName.ClassType == ClassType.Struct || cName.ClassType == ClassType.Enum) { editActionHandler.InsertString("if (" + field.Name + " != " + className + "." + field.Name + ") return false;");++numOps; } else { @@ -97,7 +97,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands editActionHandler.InsertString("return ");++numOps; for (int i = 0; i < currentClass.Fields.Count; ++i) { IField field = currentClass.Fields[i]; - IClass cName = ParserService.CurrentProjectContent.GetClass(field.ReturnType.FullyQualifiedName); + IClass cName = field.ReturnType.GetUnderlyingClass(); if (cName == null || cName.ClassType == ClassType.Struct || cName.ClassType == ClassType.Enum) { editActionHandler.InsertString(field.Name + ".GetHashCode()");++numOps; } else { diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs index 31de363784..b5ca3d9470 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/QuickClassBrowserPanel.cs @@ -336,7 +336,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor bool partialMode = false; IClass currentPart = c; if (c.IsPartial) { - CompoundClass cc = c.ProjectContent.GetClass(c.FullyQualifiedName) as CompoundClass; + CompoundClass cc = c.DefaultReturnType.GetUnderlyingClass() as CompoundClass; if (cc != null && cc.Parts.Count > 0) { partialMode = true; c = cc; diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj index 7891ac8c12..c7f16f2b31 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj @@ -50,6 +50,7 @@ + diff --git a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj.user b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj.user index c439b83dc4..7ff3943f7c 100644 --- a/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj.user +++ b/src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj.user @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/Main/Base/Test/ReflectionLayerTests.cs b/src/Main/Base/Test/ReflectionLayerTests.cs index 0d4a692838..27cc56db6b 100644 --- a/src/Main/Base/Test/ReflectionLayerTests.cs +++ b/src/Main/Base/Test/ReflectionLayerTests.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Tests public void ParameterComparisonTest() { DefaultParameter p1 = new DefaultParameter("a", pc.GetClass("System.String").DefaultReturnType, DomRegion.Empty); - DefaultParameter p2 = new DefaultParameter("b", new GetClassReturnType(pc, "System.String"), DomRegion.Empty); + DefaultParameter p2 = new DefaultParameter("b", new GetClassReturnType(pc, "System.String", 0), DomRegion.Empty); List a1 = new List(); List a2 = new List(); a1.Add(p1); diff --git a/src/Main/Base/Test/SearchClassTests.cs b/src/Main/Base/Test/SearchClassTests.cs index 6b31301be7..4ff99ab2fa 100644 --- a/src/Main/Base/Test/SearchClassTests.cs +++ b/src/Main/Base/Test/SearchClassTests.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.SharpDevelop.Tests IReturnType SearchType(string type) { ICompilationUnit cu = Prepare(LanguageProperties.CSharp); - IReturnType c = cu.ProjectContent.SearchType(type, null, cu, 1, 1); + IReturnType c = cu.ProjectContent.SearchType(type, 0, null, cu, 1, 1); Assert.IsNotNull(c, type + "not found"); return c; } @@ -48,7 +48,7 @@ namespace ICSharpCode.SharpDevelop.Tests IReturnType SearchTypeVB(string type) { ICompilationUnit cu = Prepare(LanguageProperties.VBNet); - IReturnType c = cu.ProjectContent.SearchType(type, null, cu, 1, 1); + IReturnType c = cu.ProjectContent.SearchType(type, 0, null, cu, 1, 1); Assert.IsNotNull(c, type + "not found"); return c; } @@ -116,7 +116,7 @@ namespace ICSharpCode.SharpDevelop.Tests public void SearchArrayList() { ICompilationUnit cu = Prepare(LanguageProperties.CSharp); - IReturnType c = cu.ProjectContent.SearchType("Collections.ArrayList", null, cu, 1, 1); + IReturnType c = cu.ProjectContent.SearchType("Collections.ArrayList", 0, null, cu, 1, 1); Assert.IsNull(c, "Namespaces should not be imported in C#"); } diff --git a/src/Main/Base/Test/SearchGenericClassTests.cs b/src/Main/Base/Test/SearchGenericClassTests.cs new file mode 100644 index 0000000000..d40bcf5890 --- /dev/null +++ b/src/Main/Base/Test/SearchGenericClassTests.cs @@ -0,0 +1,99 @@ +// +// 2002-2005 AlphaSierraPapa +// GNU General Public License +// +// $Revision$ +// + +using System; +using System.Collections.Generic; +using NUnit.Framework; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; + +namespace ICSharpCode.SharpDevelop.Tests +{ + [TestFixture] + public class SearchGenericClassTests + { + #region Helper methods + ICompilationUnit Prepare(LanguageProperties language) + { + DefaultProjectContent pc = new DefaultProjectContent(); + pc.ReferencedContents.Add(ProjectContentRegistry.Mscorlib); + pc.Language = language; + DefaultCompilationUnit cu = new DefaultCompilationUnit(pc); + if (language == LanguageProperties.VBNet) { + cu.Usings.Add(CreateUsing(pc, "syStEm.coLLectIons")); + pc.DefaultImports = new DefaultUsing(pc); + pc.DefaultImports.Usings.Add("syStEm"); + pc.DefaultImports.Usings.Add("syStEm.coLLEctionS.GeNeRic"); + } else { + cu.Usings.Add(CreateUsing(pc, "System")); + cu.Usings.Add(CreateUsing(pc, "System.Collections")); + cu.Usings.Add(CreateUsing(pc, "System.Collections.Generic")); + } + return cu; + } + + IUsing CreateUsing(IProjectContent pc, string @namespace) + { + DefaultUsing @using = new DefaultUsing(pc); + @using.Usings.Add(@namespace); + return @using; + } + + IReturnType SearchType(string type, int typeParameterCount) + { + ICompilationUnit cu = Prepare(LanguageProperties.CSharp); + IReturnType c = cu.ProjectContent.SearchType(type, typeParameterCount, null, cu, 1, 1); + Assert.IsNotNull(c, type + "not found"); + return c; + } + + IReturnType SearchTypeVB(string type, int typeParameterCount) + { + ICompilationUnit cu = Prepare(LanguageProperties.VBNet); + IReturnType c = cu.ProjectContent.SearchType(type, typeParameterCount, null, cu, 1, 1); + Assert.IsNotNull(c, type + "not found"); + return c; + } + + void CheckType(string shortName, string vbShortName, string fullType, int typeParameterCount) + { + IReturnType type = SearchType(shortName, typeParameterCount); + Assert.AreEqual(fullType, type.FullyQualifiedName); + Assert.AreEqual(typeParameterCount, type.TypeParameterCount); + type = SearchTypeVB(vbShortName, typeParameterCount); + Assert.AreEqual(fullType, type.FullyQualifiedName); + Assert.AreEqual(typeParameterCount, type.TypeParameterCount); + } + #endregion + + // EventHandler vs. EventHandler + // both mscorlib, both namespace System + [Test] public void FindEventHandler() { + CheckType("EventHandler", "EvEnThAndler", "System.EventHandler", 0); + } + [Test] public void FindGenericEventHandler() { + CheckType("EventHandler", "EvEnThAndler", "System.EventHandler", 1); + } + + + [Test] public void FindNullableClass() { + CheckType("Nullable", "NuLLable", "System.Nullable", 0); + } + [Test] public void FindNullableStruct() { + CheckType("Nullable", "NuLLable", "System.Nullable", 1); + } + + // ICollection vs. ICollection + // both mscorlib, different namespaces + [Test] public void FindCollection() { + CheckType("ICollection", "IColLEction", "System.Collections.ICollection", 0); + } + [Test] public void FindGenericCollection() { + CheckType("ICollection", "IColLEction", "System.Collections.Generic.ICollection", 1); + } + } +}