Browse Source

Fixed code-completion bugs.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2507 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 19 years ago
parent
commit
2c68fb0e71
  1. 2
      src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs
  2. 11
      src/AddIns/Misc/UnitTesting/Test/Utils/MockMember.cs
  3. 11
      src/AddIns/Misc/UnitTesting/Test/Utils/MockMethod.cs
  4. 17
      src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs
  5. 2
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs
  6. 33
      src/Main/Base/Test/MemberLookupHelperTests.cs
  7. 27
      src/Main/Base/Test/NRefactoryResolverTests.cs
  8. 10
      src/Main/Base/Test/Utils/MockMethod.cs
  9. 10
      src/Main/Base/Test/Utils/MockProperty.cs
  10. 15
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractMember.cs
  11. 8
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ConstructedReturnType.cs
  12. 19
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IMember.cs
  13. 35
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  14. 15
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

2
src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/ResolveVisitor.cs

@ -490,7 +490,7 @@ namespace Grunwald.BooBinding.CodeCompletion @@ -490,7 +490,7 @@ namespace Grunwald.BooBinding.CodeCompletion
ResolveResult.AddExtensions(callingClass.ProjectContent.Language, list, callingClass, containingType);
foreach (IMethodOrProperty mp in list) {
if (IsSameName(mp.Name, methodName) && mp is IMethod) {
IMethod m = (IMethod)mp.Clone();
IMethod m = (IMethod)mp.CreateSpecializedMember();
m.Parameters.RemoveAt(0);
methods.Add(m);
}

11
src/AddIns/Misc/UnitTesting/Test/Utils/MockMember.cs

@ -232,5 +232,16 @@ namespace UnitTesting.Tests.Utils @@ -232,5 +232,16 @@ namespace UnitTesting.Tests.Utils
throw new NotImplementedException();
}
}
public IMember GenericMember {
get {
throw new NotImplementedException();
}
}
public IMember CreateSpecializedMember()
{
throw new NotImplementedException();
}
}
}

11
src/AddIns/Misc/UnitTesting/Test/Utils/MockMethod.cs

@ -277,5 +277,16 @@ namespace UnitTesting.Tests.Utils @@ -277,5 +277,16 @@ namespace UnitTesting.Tests.Utils
throw new NotImplementedException();
}
}
public IMember GenericMember {
get {
throw new NotImplementedException();
}
}
public IMember CreateSpecializedMember()
{
throw new NotImplementedException();
}
}
}

17
src/Main/Base/Project/Src/Services/RefactoringService/RefactoringService.cs

@ -463,6 +463,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -463,6 +463,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary>
public static bool IsSimilarMember(IMember member1, IMember member2)
{
member1 = GetGenericMember(member1);
member2 = GetGenericMember(member2);
do {
if (IsSimilarMemberInternal(member1, member2))
return true;
@ -470,6 +472,21 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -470,6 +472,21 @@ namespace ICSharpCode.SharpDevelop.Refactoring
return false;
}
/// <summary>
/// Gets the generic member from a specialized member.
/// Specialized members are the result of overload resolution with type substitution.
/// </summary>
static IMember GetGenericMember(IMember member)
{
// e.g. member = string[] ToArray<string>(IEnumerable<string> input)
// result = T[] ToArray<T>(IEnumerable<T> input)
if (member != null) {
while (member.GenericMember != null)
member = member.GenericMember;
}
return member;
}
static bool IsSimilarMemberInternal(IMember member1, IMember member2)
{
if (member1 == member2)

2
src/Main/Base/Project/Src/TextEditor/Gui/Editor/InsightWindow/MethodInsightDataProvider.cs

@ -172,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor @@ -172,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
ResolveResult.AddExtensions(language, list, result.CallingClass, result.ContainingType);
foreach (IMethodOrProperty mp in list) {
if (language.NameComparer.Equals(mp.Name, result.Name) && mp is IMethod) {
DefaultMethod m = (DefaultMethod)mp.Clone();
DefaultMethod m = (DefaultMethod)mp.CreateSpecializedMember();
// for the insight window, remove first parameter and mark the
// method as normal - this is required to show the list of
// parameters the method expects.

33
src/Main/Base/Test/MemberLookupHelperTests.cs

@ -310,30 +310,43 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -310,30 +310,43 @@ namespace ICSharpCode.SharpDevelop.Tests
}
[Test]
public void ConversionExistsFromListOfStringToListOfT()
public void ListOfStringIsApplicableOnListOfT()
{
Assert.IsTrue(MemberLookupHelper.ConversionExists(ListOf(msc.SystemTypes.String),
ListOf(CreateT())));
Assert.IsTrue(MemberLookupHelper.IsApplicable(ListOf(msc.SystemTypes.String),
ListOf(CreateT())));
}
[Test]
public void ConversionExistsFromListOfStringToIEnumerableOfT()
public void ListOfStringIsApplicableOnIEnumerableOfT()
{
Assert.IsTrue(MemberLookupHelper.ConversionExists(ListOf(msc.SystemTypes.String),
EnumerableOf(CreateT())));
Assert.IsTrue(MemberLookupHelper.IsApplicable(ListOf(msc.SystemTypes.String),
EnumerableOf(CreateT())));
}
[Test]
public void ConversionExistsFromArrayOfStringToIListOfT()
public void ArrayOfStringIsApplicableOnIListOfT()
{
Assert.IsTrue(MemberLookupHelper.ConversionExists(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
IListOf(CreateT())));
Assert.IsTrue(MemberLookupHelper.IsApplicable(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
IListOf(CreateT())));
Assert.IsFalse(MemberLookupHelper.ConversionExists(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
IListOf(CreateT())));
}
[Test]
public void ArrayOfStringIsApplicableOnArrayOfT()
{
Assert.IsTrue(MemberLookupHelper.IsApplicable(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
new ArrayReturnType(msc, CreateT(), 1)));
Assert.IsFalse(MemberLookupHelper.ConversionExists(new ArrayReturnType(msc, msc.SystemTypes.String, 1),
new ArrayReturnType(msc, CreateT(), 1)));
}
[Test]
public void ConversionExistsFromAnonymousDelegateToSystemPredicate()
{
Assert.IsTrue(MemberLookupHelper.ConversionExists(
Assert.IsTrue(MemberLookupHelper.IsApplicable(
new AnonymousMethodReturnType(new DefaultCompilationUnit(msc)),
new GetClassReturnType(msc, "System.Predicate", 1)
));

27
src/Main/Base/Test/NRefactoryResolverTests.cs

@ -116,6 +116,33 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -116,6 +116,33 @@ namespace ICSharpCode.SharpDevelop.Tests
Assert.AreEqual(typeof(T), rr.GetType());
return (T)rr;
}
[Test]
public void GenericMethodInstanciation()
{
string program = @"using System;
using System.Collections.Generic;
class TestClass {
void Main() {
}
static T First<T>(IEnumerable<T> input) {
foreach (T e in input) return e;
throw new EmptyCollectionException();
}
}
";
MemberResolveResult mrr = Resolve<MemberResolveResult>(program, "First(new string[0])", 5);
Assert.AreEqual("System.String", mrr.ResolvedType.FullyQualifiedName);
Assert.AreEqual("System.String", mrr.ResolvedMember.ReturnType.FullyQualifiedName);
IMethod genericMethod = mrr.ResolvedMember.DeclaringType.Methods[1];
Assert.AreEqual("T", genericMethod.ReturnType.FullyQualifiedName);
// ensure that the reference pointing to the specialized method is seen as a reference
// to the generic method.
Assert.IsTrue(Refactoring.RefactoringService.IsReferenceToMember(genericMethod, mrr));
}
#endregion
#region Test for old issues (Fidalgo)

10
src/Main/Base/Test/Utils/MockMethod.cs

@ -272,5 +272,15 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils @@ -272,5 +272,15 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
throw new NotImplementedException();
}
public IMember GenericMember {
get {
throw new NotImplementedException();
}
}
public IMember CreateSpecializedMember()
{
throw new NotImplementedException();
}
}
}

10
src/Main/Base/Test/Utils/MockProperty.cs

@ -290,5 +290,15 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils @@ -290,5 +290,15 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
throw new NotImplementedException();
}
public IMember GenericMember {
get {
throw new NotImplementedException();
}
}
public IMember CreateSpecializedMember()
{
throw new NotImplementedException();
}
}
}

15
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/AbstractMember.cs

@ -73,5 +73,20 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -73,5 +73,20 @@ namespace ICSharpCode.SharpDevelop.Dom
{
return this.Clone();
}
IMember genericMember;
public virtual IMember GenericMember {
get { return genericMember; }
}
public virtual IMember CreateSpecializedMember()
{
AbstractMember copy = Clone() as AbstractMember;
if (copy == null)
throw new Exception("Clone() must return an AbstractMember instance, or CreateSpecializedMember must also be overridden.");
copy.genericMember = this;
return copy;
}
}
}

8
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Implementations/ConstructedReturnType.cs

@ -174,7 +174,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -174,7 +174,7 @@ namespace ICSharpCode.SharpDevelop.Dom
List<IMethod> l = baseType.GetMethods();
for (int i = 0; i < l.Count; ++i) {
if (CheckReturnType(l[i].ReturnType) || CheckParameters(l[i].Parameters)) {
l[i] = (IMethod)l[i].Clone();
l[i] = (IMethod)l[i].CreateSpecializedMember();
if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
l[i].DeclaringTypeReference = this;
}
@ -192,7 +192,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -192,7 +192,7 @@ namespace ICSharpCode.SharpDevelop.Dom
List<IProperty> l = baseType.GetProperties();
for (int i = 0; i < l.Count; ++i) {
if (CheckReturnType(l[i].ReturnType) || CheckParameters(l[i].Parameters)) {
l[i] = (IProperty)l[i].Clone();
l[i] = (IProperty)l[i].CreateSpecializedMember();
if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
l[i].DeclaringTypeReference = this;
}
@ -210,7 +210,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -210,7 +210,7 @@ namespace ICSharpCode.SharpDevelop.Dom
List<IField> l = baseType.GetFields();
for (int i = 0; i < l.Count; ++i) {
if (CheckReturnType(l[i].ReturnType)) {
l[i] = (IField)l[i].Clone();
l[i] = (IField)l[i].CreateSpecializedMember();
if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
l[i].DeclaringTypeReference = this;
}
@ -225,7 +225,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -225,7 +225,7 @@ namespace ICSharpCode.SharpDevelop.Dom
List<IEvent> l = baseType.GetEvents();
for (int i = 0; i < l.Count; ++i) {
if (CheckReturnType(l[i].ReturnType)) {
l[i] = (IEvent)l[i].Clone();
l[i] = (IEvent)l[i].CreateSpecializedMember();
if (l[i].DeclaringType == baseType.GetUnderlyingClass()) {
l[i].DeclaringTypeReference = this;
}

19
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Interfaces/IMember.cs

@ -18,13 +18,30 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -18,13 +18,30 @@ namespace ICSharpCode.SharpDevelop.Dom
/// <summary>
/// Gets/Sets the declaring type reference (declaring type incl. type arguments).
/// If set to null, the getter returns the default type reference to the <see cref="DeclaringType"/>.
/// Never returns null, if the property is set to null (e.g. when this is not a specialized member),
/// it should return the default type reference to the <see cref="DeclaringType"/>.
/// </summary>
IReturnType DeclaringTypeReference {
get;
set;
}
/// <summary>
/// Gets the generic member this member is based on.
/// Returns null if this is not a specialized member.
/// Specialized members are the result of overload resolution with type substitution.
/// </summary>
IMember GenericMember {
get;
}
/// <summary>
/// Creates a copy of this member with its GenericMember property set to this member.
/// Use this method to create copies of a member that should be regarded as the "same member"
/// for refactoring purposes.
/// </summary>
IMember CreateSpecializedMember();
/// <summary>
/// Declaration region of the member (without body!)
/// </summary>

35
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs

@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Dom
for (int i = 0; i < list.Count; i++) {
IMethod m = list[i];
if (m.TypeParameters.Count == typeParameters.Length) {
m = (IMethod)m.Clone();
m = (IMethod)m.CreateSpecializedMember();
m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, typeParameters, true);
for (int j = 0; j < m.Parameters.Count; ++j) {
m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, typeParameters, true);
@ -144,7 +144,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -144,7 +144,7 @@ namespace ICSharpCode.SharpDevelop.Dom
for (int i = 0; i < list.Count; i++) {
IReturnType[] inferred = inferredTypeParameters[i];
if (inferred != null && inferred.Length > 0) {
IMethod m = (IMethod)list[i].Clone();
IMethod m = (IMethod)list[i].CreateSpecializedMember();
m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, inferred, true);
for (int j = 0; j < m.Parameters.Count; ++j) {
m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, inferred, true);
@ -524,16 +524,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -524,16 +524,7 @@ namespace ICSharpCode.SharpDevelop.Dom
{
if (argument == null || argument == NullReturnType.Instance)
return true; // "null" can be passed for any argument
if (expected.IsGenericReturnType) {
foreach (IReturnType constraint in expected.CastToGenericReturnType().TypeParameter.Constraints) {
if (!ConversionExists(argument, constraint)) {
return false;
}
}
return true;
} else {
return ConversionExists(argument, expected);
}
return ConversionExistsInternal(argument, expected, true);
}
#endregion
@ -542,6 +533,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -542,6 +533,11 @@ namespace ICSharpCode.SharpDevelop.Dom
/// Checks if an implicit conversion exists from <paramref name="from"/> to <paramref name="to"/>.
/// </summary>
public static bool ConversionExists(IReturnType from, IReturnType to)
{
return ConversionExistsInternal(from, to, false);
}
static bool ConversionExistsInternal(IReturnType from, IReturnType to, bool allowGenericTarget)
{
// ECMA-334, § 13.1 Implicit conversions
@ -584,11 +580,11 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -584,11 +580,11 @@ namespace ICSharpCode.SharpDevelop.Dom
return true; // from any type to object
}
if ((toIsDefault || to.IsConstructedReturnType)
if ((toIsDefault || to.IsConstructedReturnType || to.IsGenericReturnType)
&& (fromIsDefault || from.IsArrayReturnType || from.IsConstructedReturnType))
{
foreach (IReturnType baseTypeOfFrom in GetTypeInheritanceTree(from)) {
if (IsConstructedConversionToGenericReturnType(baseTypeOfFrom, to))
if (IsConstructedConversionToGenericReturnType(baseTypeOfFrom, to, allowGenericTarget))
return true;
}
}
@ -598,7 +594,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -598,7 +594,7 @@ namespace ICSharpCode.SharpDevelop.Dom
ArrayReturnType toArt = to.CastToArrayReturnType();
// from array to other array type
if (fromArt.ArrayDimensions == toArt.ArrayDimensions) {
return ConversionExists(fromArt.ArrayElementType, toArt.ArrayElementType);
return ConversionExistsInternal(fromArt.ArrayElementType, toArt.ArrayElementType, allowGenericTarget);
}
}
@ -622,14 +618,17 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -622,14 +618,17 @@ namespace ICSharpCode.SharpDevelop.Dom
return false;
}
static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to)
static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to, bool allowGenericTarget)
{
if (from.Equals(to))
return true;
if (!allowGenericTarget)
return false;
if (to.IsGenericReturnType) {
foreach (IReturnType constraintType in to.CastToGenericReturnType().TypeParameter.Constraints) {
if (!ConversionExists(from, constraintType)) {
if (!ConversionExistsInternal(from, constraintType, allowGenericTarget)) {
return false;
}
}
@ -642,7 +641,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -642,7 +641,7 @@ namespace ICSharpCode.SharpDevelop.Dom
if (cFrom != null && cTo != null) {
if (cFrom.FullyQualifiedName == cTo.FullyQualifiedName && cFrom.TypeArguments.Count == cTo.TypeArguments.Count) {
for (int i = 0; i < cFrom.TypeArguments.Count; i++) {
if (!IsConstructedConversionToGenericReturnType(cFrom.TypeArguments[i], cTo.TypeArguments[i]))
if (!IsConstructedConversionToGenericReturnType(cFrom.TypeArguments[i], cTo.TypeArguments[i], allowGenericTarget))
return false;
}
return true;

15
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/ResolveResult.cs

@ -124,19 +124,6 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -124,19 +124,6 @@ namespace ICSharpCode.SharpDevelop.Dom
static void TryAddExtension(LanguageProperties language, ArrayList res, IMethodOrProperty ext, IReturnType resolvedType)
{
// accept only extension methods
if (!ext.IsExtensionMethod)
return;
// don't add extension if method with that name already exists
// but allow overloading extension methods
foreach (IMember member in res) {
IMethodOrProperty p = member as IMethodOrProperty;
if (p != null && p.IsExtensionMethod)
continue;
if (language.NameComparer.Equals(member.Name, ext.Name)) {
return;
}
}
// now add the extension method if it fits the type
if (MemberLookupHelper.IsApplicable(resolvedType, ext.Parameters[0].ReturnType)) {
IMethod method = ext as IMethod;
@ -145,7 +132,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -145,7 +132,7 @@ namespace ICSharpCode.SharpDevelop.Dom
MemberLookupHelper.InferTypeArgument(method.Parameters[0].ReturnType, resolvedType, typeArguments);
for (int i = 0; i < typeArguments.Length; i++) {
if (typeArguments[i] != null) {
ext = (IMethod)ext.Clone();
ext = (IMethod)ext.CreateSpecializedMember();
ext.ReturnType = ConstructedReturnType.TranslateType(ext.ReturnType, typeArguments, true);
for (int j = 0; j < ext.Parameters.Count; ++j) {
ext.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(ext.Parameters[j].ReturnType, typeArguments, true);

Loading…
Cancel
Save