Browse Source

Fixed SD2-1528: Stack overflow in code completion when using FluentValidation

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@3825 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 17 years ago
parent
commit
2d0d749425
  1. 19
      src/Main/Base/Test/GenericResolverTests.cs
  2. 8
      src/Main/Base/Test/MemberLookupHelperTests.cs
  3. 19
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/MemberLookupHelper.cs
  4. 19
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs
  5. 32
      src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/NRefactoryAstConverterTests.cs

19
src/Main/Base/Test/GenericResolverTests.cs

@ -475,6 +475,25 @@ class D : Program { @@ -475,6 +475,25 @@ class D : Program {
Assert.AreEqual("ExtensionMethods.OfType", mrr.ResolvedMember.FullyQualifiedName);
Assert.AreEqual("System.Collections.Generic.IEnumerable{System.String}", mrr.ResolvedType.DotNetName);
}
[Test]
public void SD2_1528()
{
string program = @"using System;
class TestClass {
static void Test(IRuleBuilder<TestClass, string> ruleBuilder) {
}
}
delegate R Func<T, R>(T arg);
interface IRuleBuilder<T> { }
interface IRuleBuilder<T, P> : IRuleBuilder<T> { }
static class ExtensionMethods {
public static IRuleBuilderOptions<T, TProperty> LessThan<T, TProperty>(this IRuleBuilder<T, TProperty> ruleBuilder, Func<T, TProperty> valueToCompare) where TProperty: IComparable<TProperty> {}
}";
var rr = Resolve<LocalResolveResult>(program, "ruleBuilder", 4);
rr.GetCompletionData(rr.CallingClass.ProjectContent);
}
#endregion
#region C# 3.0 Type Inference

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

@ -319,11 +319,13 @@ namespace ICSharpCode.SharpDevelop.Tests @@ -319,11 +319,13 @@ namespace ICSharpCode.SharpDevelop.Tests
[Test]
public void NoConversionExistsFromStringToDisposableT()
{
Assert.IsFalse(IsApplicable(msc.SystemTypes.String,
CreateTWithDisposableConstraint()));
// no conversion exists
Assert.IsFalse(MemberLookupHelper.ConversionExists(msc.SystemTypes.String,
CreateTWithDisposableConstraint()));
// but it is applicable (applicability ignores constraints)
Assert.IsTrue(IsApplicable(msc.SystemTypes.String,
CreateTWithDisposableConstraint()));
}
[Test]

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

@ -470,7 +470,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -470,7 +470,7 @@ namespace ICSharpCode.SharpDevelop.Dom
static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod)
{
// null could be passed when type arguments could not be resolved/inferred
if (from == null && to == null)
if (from == to) // both are null or
return true;
if (from == null || to == null)
return false;
@ -483,14 +483,15 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -483,14 +483,15 @@ namespace ICSharpCode.SharpDevelop.Dom
if (to.IsGenericReturnType) {
ITypeParameter typeParameter = to.CastToGenericReturnType().TypeParameter;
if (typeParameter.Method != allowGenericTargetsOnThisMethod)
return false;
foreach (IReturnType constraintType in typeParameter.Constraints) {
if (!ConversionExistsInternal(from, constraintType, allowGenericTargetsOnThisMethod)) {
return false;
}
}
return true;
if (typeParameter.Method == allowGenericTargetsOnThisMethod)
return true;
// applicability ignores constraints
// foreach (IReturnType constraintType in typeParameter.Constraints) {
// if (!ConversionExistsInternal(from, constraintType, allowGenericTargetsOnThisMethod)) {
// return false;
// }
// }
return false;
}
// for conversions like from IEnumerable<string> to IEnumerable<T>, where T is a GenericReturnType

19
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/NRefactoryResolver/NRefactoryASTConvertVisitor.cs

@ -422,8 +422,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -422,8 +422,13 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (templateList.Count == 0) {
c.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList;
} else {
Debug.Assert(c.TypeParameters.Count == 0);
foreach (AST.TemplateDefinition template in templateList) {
c.TypeParameters.Add(ConvertConstraints(template, new DefaultTypeParameter(c, template.Name, index++)));
c.TypeParameters.Add(new DefaultTypeParameter(c, template.Name, index++));
}
// converting the constraints requires that the type parameters are already present
for (int i = 0; i < templateList.Count; i++) {
ConvertConstraints(templateList[i], (DefaultTypeParameter)c.TypeParameters[i]);
}
}
}
@ -434,13 +439,18 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -434,13 +439,18 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
if (templateList.Count == 0) {
m.TypeParameters = DefaultTypeParameter.EmptyTypeParameterList;
} else {
Debug.Assert(m.TypeParameters.Count == 0);
foreach (AST.TemplateDefinition template in templateList) {
m.TypeParameters.Add(ConvertConstraints(template, new DefaultTypeParameter(m, template.Name, index++)));
m.TypeParameters.Add(new DefaultTypeParameter(m, template.Name, index++));
}
// converting the constraints requires that the type parameters are already present
for (int i = 0; i < templateList.Count; i++) {
ConvertConstraints(templateList[i], (DefaultTypeParameter)m.TypeParameters[i]);
}
}
}
DefaultTypeParameter ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter)
void ConvertConstraints(AST.TemplateDefinition template, DefaultTypeParameter typeParameter)
{
foreach (AST.TypeReference typeRef in template.Bases) {
if (typeRef == AST.TypeReference.NewConstraint) {
@ -450,13 +460,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver @@ -450,13 +460,12 @@ namespace ICSharpCode.SharpDevelop.Dom.NRefactoryResolver
} else if (typeRef == AST.TypeReference.StructConstraint) {
typeParameter.HasValueTypeConstraint = true;
} else {
IReturnType rt = CreateReturnType(typeRef);
IReturnType rt = CreateReturnType(typeRef, typeParameter.Method, TypeVisitor.ReturnTypeOptions.None);
if (rt != null) {
typeParameter.Constraints.Add(rt);
}
}
}
return typeParameter;
}
public override object VisitDelegateDeclaration(AST.DelegateDeclaration delegateDeclaration, object data)

32
src/Main/ICSharpCode.SharpDevelop.Dom/Tests/ICSharpCode.SharpDevelop.Dom.Tests/NRefactoryAstConverterTests.cs

@ -119,5 +119,37 @@ namespace X @@ -119,5 +119,37 @@ namespace X
");
Assert.AreEqual(SurroundWithSummaryTags("This is the comment"), cu.Classes[0].Documentation);
}
[Test]
public void GenericMethodWithConstraintsTest()
{
// Test that constaints can reference other type parameters.
ICompilationUnit cu = Parse(@"
using System;
class X {
public static A Method<A, B>(A p1, B p2) where A : IComparable<B> where B : IComparable<A> { }
}
");
IMethod method = cu.Classes[0].Methods[0];
Assert.AreEqual(2, method.TypeParameters.Count);
ITypeParameter a = method.TypeParameters[0];
ITypeParameter b = method.TypeParameters[1];
Assert.AreSame(a, method.ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreSame(a, method.Parameters[0].ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreSame(b, method.Parameters[1].ReturnType.CastToGenericReturnType().TypeParameter);
Assert.AreEqual(1, a.Constraints.Count);
ConstructedReturnType crt = a.Constraints[0].CastToConstructedReturnType();
Assert.AreEqual("IComparable", crt.Name);
Assert.AreSame(b, crt.TypeArguments[0].CastToGenericReturnType().TypeParameter);
Assert.AreEqual(1, b.Constraints.Count);
crt = b.Constraints[0].CastToConstructedReturnType();
Assert.AreEqual("IComparable", crt.Name);
Assert.AreSame(a, crt.TypeArguments[0].CastToGenericReturnType().TypeParameter);
}
}
}

Loading…
Cancel
Save