diff --git a/src/Main/Base/Project/Src/Gui/Components/SideBar/TextEditorSideBar.cs b/src/Main/Base/Project/Src/Gui/Components/SideBar/TextEditorSideBar.cs index 550242c280..665d67d87d 100644 --- a/src/Main/Base/Project/Src/Gui/Components/SideBar/TextEditorSideBar.cs +++ b/src/Main/Base/Project/Src/Gui/Components/SideBar/TextEditorSideBar.cs @@ -84,7 +84,10 @@ namespace ICSharpCode.SharpDevelop.Gui public void PutInClipboardRing(string text) { if (clipboardRing != null) { - clipboardRing.Items.Add("Text:" + text.Trim(), text); + string shortenedText = text.Trim(); + if (shortenedText.Length > 50) + shortenedText = shortenedText.Substring(0, 47) + "..."; + clipboardRing.Items.Add("Text:" + shortenedText, text); if (clipboardRing.Items.Count > 20) { clipboardRing.Items.RemoveAt(0); } diff --git a/src/Main/Base/Test/NRefactoryResolverTests.cs b/src/Main/Base/Test/NRefactoryResolverTests.cs index c2b3eb04ed..e5fe5a3a70 100644 --- a/src/Main/Base/Test/NRefactoryResolverTests.cs +++ b/src/Main/Base/Test/NRefactoryResolverTests.cs @@ -266,6 +266,21 @@ interface IInterface2 { Assert.IsNull(result, "result"); } + [Test] + public void GenericObjectCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + + } +} +"; + MemberResolveResult result = Resolve(program, "new List()", 4); + Assert.AreEqual("System.Collections.Generic.List.#ctor", result.ResolvedMember.FullyQualifiedName); + Assert.AreEqual("System.Collections.Generic.List{System.String}", result.ResolvedType.DotNetName); + } + [Test] public void InvalidConstructorCallTest() { diff --git a/src/Main/Base/Test/OverloadFinding.cs b/src/Main/Base/Test/OverloadFinding.cs index 781a15629d..bc8de3bf68 100644 --- a/src/Main/Base/Test/OverloadFinding.cs +++ b/src/Main/Base/Test/OverloadFinding.cs @@ -59,9 +59,23 @@ namespace ICSharpCode.SharpDevelop.Tests Test("(null)", 1, overloads); } + [Test] public void Generic() + { + string program = "class T {} class T {}"; + string[] overloads = {"(T a)", "(T a)", "(T a)"}; + Test("(new T())", program, 0, overloads); + Test("(new T())", program, 1, overloads); + Test("(new T())", program, 2, overloads); + } + NRefactoryResolverTests nrrt = new NRefactoryResolverTests(); void Test(string callExpr, int num, params string[] signatures) + { + Test(callExpr, "", num, signatures); + } + + void Test(string callExpr, string extraCode, int num, params string[] signatures) { StringBuilder b = new StringBuilder(); int lineNumber = 0; @@ -81,6 +95,7 @@ namespace ICSharpCode.SharpDevelop.Tests ++lineNumber; b.AppendLine(" }"); } b.AppendLine("}"); + b.Append(extraCode); MemberResolveResult mrr = nrrt.Resolve(b.ToString(), "Method" + callExpr, callPosition); string msg = "wrong overload: "; for (int i = 0; i < positions.Length; i++) { diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs index 340edae7c3..eb4f15b62d 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs @@ -210,9 +210,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// Finds the correct overload according to the C# specification. /// - /// List with the methods to check.
- /// Generic methods in the input type are replaced by methods with have the types substituted! - /// + /// List with the methods to check. /// The types of the arguments passed to the method. /// Out parameter. Will be true if the resulting method /// is an acceptable match, false if the resulting method is just a guess and will lead @@ -220,9 +218,12 @@ namespace ICSharpCode.SharpDevelop.Dom /// The method that will be called. public static IMethod FindOverload(IList methods, IReturnType[] arguments, out bool resultIsAcceptable) { + if (methods == null) + throw new ArgumentNullException("methods"); resultIsAcceptable = false; if (methods.Count == 0) return null; + methods = methods.ToArray(); int[] ranking = RankOverloads(methods, arguments, false, out resultIsAcceptable); int bestRanking = -1; int best = 0; @@ -274,6 +275,11 @@ namespace ICSharpCode.SharpDevelop.Dom bool allowAdditionalArguments, out bool acceptableMatch) { + if (list == null) + throw new ArgumentNullException("list"); + if (arguments == null) + throw new ArgumentNullException("arguments"); + acceptableMatch = false; if (list.Count == 0) return new int[] {}; diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs index 3dda47eeb1..56358cdf44 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/ResolveVisitor.cs @@ -69,6 +69,8 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver ResolveResult rr; if (!cachedResults.TryGetValue(expression, out rr)) { rr = (ResolveResult)expression.AcceptVisitor(this, null); + if (rr != null) + rr.Freeze(); cachedResults[expression] = rr; } return rr; @@ -430,11 +432,21 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver if (rt == null) return null; - return ResolveConstructorOverload(rt.GetUnderlyingClass(), objectCreateExpression.Parameters) + return ResolveConstructorOverload(rt, objectCreateExpression.Parameters) ?? CreateResolveResult(rt); } } + internal ResolveResult ResolveConstructorOverload(IReturnType rt, List arguments) + { + if (rt == null) + return null; + ResolveResult rr = ResolveConstructorOverload(rt.GetUnderlyingClass(), arguments); + if (rr != null) + rr.ResolvedType = rt; + return rr; + } + internal ResolveResult ResolveConstructorOverload(IClass c, List arguments) { if (c == null) diff --git a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs index 33f2820238..22d6a969e7 100644 --- a/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs +++ b/src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs @@ -19,7 +19,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// The ResolveResult specified the location where Resolve was called (Class+Member) /// and the type of the resolved expression. /// - public class ResolveResult : ICloneable + public class ResolveResult : AbstractFreezable, ICloneable { IClass callingClass; IMember callingMember; @@ -60,7 +60,10 @@ namespace ICSharpCode.SharpDevelop.Dom /// public IReturnType ResolvedType { get { return resolvedType; } - set { resolvedType = value; } + set { + CheckBeforeMutation(); + resolvedType = value; + } } public virtual ResolveResult Clone() @@ -508,10 +511,10 @@ namespace ICSharpCode.SharpDevelop.Dom #endregion #region MethodResolveResult - public class MethodGroup : IList + public class MethodGroup : AbstractFreezable, IList { - public bool IsExtensionMethodGroup { get; set; } IList innerList; + bool isExtensionMethodGroup; public MethodGroup() : this(new List()) { @@ -524,6 +527,20 @@ namespace ICSharpCode.SharpDevelop.Dom this.innerList = innerList; } + public bool IsExtensionMethodGroup { + get { return isExtensionMethodGroup; } + set { + CheckBeforeMutation(); + isExtensionMethodGroup = value; + } + } + + protected override void FreezeInternal() + { + base.FreezeInternal(); + innerList = FreezeList(innerList); + } + public IMethod this[int index] { get { return innerList[index]; } set { innerList[index] = value; } @@ -636,6 +653,14 @@ namespace ICSharpCode.SharpDevelop.Dom return new MethodGroupResolveResult(this.CallingClass, this.CallingMember, this.ContainingType, this.Name, this.Methods); } + protected override void FreezeInternal() + { + base.FreezeInternal(); + if (possibleMethods != null) { + possibleMethods = FreezeList(possibleMethods); + } + } + /// /// Gets the name of the method. /// @@ -656,11 +681,12 @@ namespace ICSharpCode.SharpDevelop.Dom public IList Methods { get { if (possibleMethods == null) { - possibleMethods = new MethodGroup[] { - new MethodGroup( - containingType.GetMethods().FindAll((IMethod m) => m.Name == this.name) - ) - }; + possibleMethods = FreezeList( + new MethodGroup[] { + new MethodGroup( + containingType.GetMethods().FindAll((IMethod m) => m.Name == this.name) + ) + }); } return possibleMethods; } @@ -689,7 +715,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// /// Is used for "MyBase" or "Me" in VB constructors to show "New" in the completion list. /// - public sealed class VBBaseOrThisReferenceInConstructorResolveResult : ResolveResult + public class VBBaseOrThisReferenceInConstructorResolveResult : ResolveResult { public VBBaseOrThisReferenceInConstructorResolveResult(IClass callingClass, IMember callingMember, IReturnType referencedType) : base(callingClass, callingMember, referencedType) @@ -718,7 +744,7 @@ namespace ICSharpCode.SharpDevelop.Dom /// Is used for "base"/"MyBase" expression. /// The completion list always shows protected members. /// - public sealed class BaseResolveResult : ResolveResult + public class BaseResolveResult : ResolveResult { public BaseResolveResult(IClass callingClass, IMember callingMember, IReturnType baseClassType) : base(callingClass, callingMember, baseClassType)