From 1ed352ca30bd28560ba4c26cb62df2c47cc7ab89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Fri, 14 Sep 2012 08:28:21 +0200 Subject: [PATCH] [Completion] Added a case to prevent recursive constructor calls: 'public A() : this()'. --- .../CSharpParameterCompletionEngine.cs | 46 +++++++++---------- .../IParameterCompletionDataFactory.cs | 5 ++ .../ParameterCompletionTests.cs | 8 ++++ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs index 721c0f0a8f..bf61e27f7b 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpParameterCompletionEngine.cs @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } yield return method; } - + foreach (var extMethods in resolveResult.GetEligibleExtensionMethods (true)) { foreach (var method in extMethods) { yield return method; @@ -152,7 +152,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (invoke.Node is ConstructorInitializer) { var init = (ConstructorInitializer)invoke.Node; if (init.ConstructorInitializerType == ConstructorInitializerType.This) { - return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition); + return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), ctx.CurrentTypeDefinition, init); } else { var baseType = ctx.CurrentTypeDefinition.DirectBaseTypes.FirstOrDefault(bt => bt.Kind != TypeKind.Interface); if (baseType == null) { @@ -167,7 +167,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return null; return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); } - + if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { var attribute = ResolveExpression(invoke); if (attribute == null || attribute.Item1 == null) { @@ -189,22 +189,22 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), new [] { (IMethod)mr.Member }); } } - + if (resolveResult.Type.Kind == TypeKind.Delegate) { return factory.CreateDelegateDataProvider(document.GetOffset(invoke.Node.StartLocation), resolveResult.Type); } - -// -// if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) { -// if (resolveResult is ThisResolveResult) -// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult); -// if (resolveResult is BaseResolveResult) -// return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult); -// } -// IType resolvedType = resolver.SearchType (resolveResult.ResolvedType); -// if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) { -// return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType); -// } + + // + // if (result.ExpressionContext == ExpressionContext.BaseConstructorCall) { + // if (resolveResult is ThisResolveResult) + // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as ThisResolveResult); + // if (resolveResult is BaseResolveResult) + // return new NRefactoryParameterDataProvider (textEditorData, resolver, resolveResult as BaseResolveResult); + // } + // IType resolvedType = resolver.SearchType (resolveResult.ResolvedType); + // if (resolvedType != null && resolvedType.ClassType == ClassType.Delegate) { + // return new NRefactoryParameterDataProvider (textEditorData, result.Expression, resolvedType); + // } break; case ',': invoke = GetInvocationBeforeCursor(true) ?? GetIndexerBeforeCursor(); @@ -217,7 +217,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (typeExpression == null || typeExpression.Item1 == null || typeExpression.Item1.IsError) { return null; } - + return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(typeExpression.Item1.Type)); } return null; @@ -228,7 +228,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion var createType = ResolveExpression(((ObjectCreateExpression)invoke.Node).Type); return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), createType.Item1.Type); } - + if (invoke.Node is ICSharpCode.NRefactory.CSharp.Attribute) { var attribute = ResolveExpression(invoke); if (attribute == null || attribute.Item1 == null) { @@ -236,13 +236,13 @@ namespace ICSharpCode.NRefactory.CSharp.Completion } return factory.CreateConstructorProvider(document.GetOffset(invoke.Node.StartLocation), attribute.Item1.Type); } - + invocationExpression = ResolveExpression(invoke); - + if (invocationExpression == null || invocationExpression.Item1 == null || invocationExpression.Item1.IsError) { return null; } - + resolveResult = invocationExpression.Item1; if (resolveResult is MethodGroupResolveResult) { return factory.CreateMethodDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectMethods(invoke.Node, resolveResult as MethodGroupResolveResult)); @@ -269,7 +269,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion if (tExpr == null || tExpr.Item1 == null || tExpr.Item1.IsError) { return null; } - + return factory.CreateTypeParameterDataProvider(document.GetOffset(invoke.Node.StartLocation), CollectAllTypes(tExpr.Item1.Type)); case '[': invoke = GetIndexerBeforeCursor(); @@ -320,7 +320,7 @@ namespace ICSharpCode.NRefactory.CSharp.Completion return result; } - + } } diff --git a/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs b/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs index 54ebe1c84e..90ecab6261 100644 --- a/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs +++ b/ICSharpCode.NRefactory.CSharp/Completion/IParameterCompletionDataFactory.cs @@ -35,6 +35,11 @@ namespace ICSharpCode.NRefactory.CSharp.Completion { IParameterDataProvider CreateConstructorProvider (int startOffset, IType type); + /// + /// Creates a constructor provider skipping the parent of thisInitializer. + /// + IParameterDataProvider CreateConstructorProvider (int startOffset, IType type, AstNode thisInitializer); + IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable methods); IParameterDataProvider CreateDelegateDataProvider (int startOffset, IType type); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs index 85bfea561a..6cbfc5c57b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeCompletion/ParameterCompletionTests.cs @@ -220,6 +220,14 @@ namespace ICSharpCode.NRefactory.CSharp.CodeCompletion }; } + public IParameterDataProvider CreateConstructorProvider(int startOffset, ICSharpCode.NRefactory.TypeSystem.IType type, AstNode skipNode) + { + Assert.IsTrue(type.Kind != TypeKind.Unknown); + return new Provider () { + Data = type.GetConstructors (m => m.Accessibility == Accessibility.Public) + }; + } + public IParameterDataProvider CreateMethodDataProvider (int startOffset, IEnumerable methods) { return new Provider () {